Я создаю программу UWP для Raspberry Pi. Одной из функций программы является отправка и получение данных от Arduino.
Проблема в том, что когда я пытаюсь отправить данные в Arduino быстро и много раз, я получаю System.Runtime.InteropServices.COMException The operation identifier is not valid.
, исходящий из DataWriter.DetachStream()
.
Быстрая отправка данных работает просто отлично, пока, кажется, до определенного количества, где я получаю исключение.
Под «быстрым» я подразумеваю использование автоматического кликера для нажатия кнопки для отправки данных каждую миллисекунду.
Я не пытался отправлять данные медленно, много раз подряд, чтобы воспроизвести проблему, поскольку это, вероятно, заняло бы много времени (поскольку это занимает около 10-20 секунд с задержкой в 1 мс между передачами.
Я слишком долго искал решение этой проблемы, но, похоже, не могу найти какие-либо связанные вопросы / решения.
public sealed partial class LightControl : Page
{
int Alpha;
int Red;
int Green;
int Blue;
// This is the handler for the button to send data
private void LightButton_Click(object sender, RoutedEventArgs e)
{
if (!(sender is Button button) || button.Tag == null) return;
string tag = button.Tag.ToString();
Alpha = int.Parse(tag.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
Red = int.Parse(tag.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
Green = int.Parse(tag.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
Blue = int.Parse(tag.Substring(6, 2), System.Globalization.NumberStyles.HexNumber);
SendLightData();
}
public async void SendLightData()
{
await ArduinoHandler.Current.WriteAsync(ArduinoHandler.DataEnum.LightArduino,
ArduinoHandler.DataEnum.Light, Convert.ToByte(LightConstants.LightCommand.LightCommand),
Convert.ToByte(Red), Convert.ToByte(Green), Convert.ToByte(Blue), Convert.ToByte(Alpha),
WriteCancellationTokenSource.Token);
}
}
public class ArduinoHandler
{
// Code for singleton behaviour. Included for completeness
#region Singleton behaviour
private static ArduinoHandler arduinoHandler;
private static Object singletonCreationLock = new Object();
public static ArduinoHandler Current
{
get
{
if (arduinoHandler == null)
{
lock (singletonCreationLock)
{
if (arduinoHandler == null)
{
CreateNewArduinoHandler();
}
}
}
return arduinoHandler;
}
}
public static void CreateNewArduinoHandler()
{
arduinoHandler = new ArduinoHandler();
}
#endregion
private DataWriter dataWriter;
private Object WriteCancelLock = new Object();
public async Task WriteAsync(DataEnum receiver, DataEnum sender,
byte commandByte1, byte dataByte1, byte dataByte2, byte dataByte3,
byte dataByte4, CancellationToken cancellationToken)
{
try
{
dataWriter = new DataWriter(arduinos[receiver].OutputStream);
byte[] buffer;
Task<uint> storeAsyncTask;
lock (WriteCancelLock)
{
buffer = new byte[8];
buffer[0] = Convert.ToByte(receiver);
buffer[1] = Convert.ToByte(sender);
buffer[2] = commandByte1;
buffer[3] = dataByte1;
buffer[4] = dataByte2;
buffer[5] = dataByte3;
buffer[6] = dataByte4;
buffer[7] = Convert.ToByte('\n');
cancellationToken.ThrowIfCancellationRequested();
dataWriter.WriteBytes(buffer);
storeAsyncTask = dataWriter.StoreAsync().AsTask(cancellationToken);
}
uint bytesWritten = await storeAsyncTask;
Debug.Write("\nSent: " + BitConverter.ToString(buffer) + "\n");
}
catch (Exception e)
{
Debug.Write(e.Message);
}
finally
{
dataWriter.DetachStream(); // <--- I've located the exception to originate from here, using the debugger in Visual Studio
dataWriter.Dispose();
}
}
public enum DataEnum
{
Light = 0x01,
Piston = 0x02,
PC = 0x03,
LightArduino = 0x04
}
}
Я бы ожидал, что Raspberry Pi отправит данные в Arduino, но через некоторое время при быстрой передаче данных возникнет исключение.
Обновление
Я попытался использовать локальную переменную для dataWriter, как предложено ниже, но через некоторое время это вызывает странное поведение при быстрой передаче данных. Как будто это замедляется. Стоит отметить, что я больше не получаю исключения.
Довольно сложно пытаться объяснить, как он себя ведет, но Debug.Write записывает сообщение, которое я отправляю (что отлично работает). Однако через некоторое время он, похоже, «замедляется», и даже после того, как я перестаю нажимать, данные отправляются раз в секунду или около того. До этого момента он работал совершенно нормально. Так что мне интересно, есть ли какой-то предел, который я бью?
Обновление 2
Кажется, я нашел довольно "странное" и странное решение проблемы.
Если я использую Serial.write () на Arduino для отправки данных обратно в Raspberry Pi, похоже, это как-то решило проблему.
Если кто-нибудь знает, как это работает, мне было бы очень интересно узнать:)
const int payloadSize = 8;
byte payload[payloadSize]
int numBytes;
// Called each time serial data is available
void serialEvent()
{
numBytes = Serial.available();
if (numBytes == payloadSize)
{
for (int i = 0; i < payloadSize; i++)
{
payload[i] = Serial.read();
Serial.write(payload[i]); // <--- This line fixed the issue for whatever reason
}
}
checkData(); // Function to do something with the data
for (int i = 0; i < payloadSize; i++)
{
payload[i] = None;
}
numBytes = 0;
}