0

I got a C# WPF application wich communcates with my arduino uno over serial port. Everything works fine for 3 to 20 seconds then i can not send or receive anything from/to the arduino.

What im trying to archieve: Connected a arduino uno to an optical sensor of a mouse to read from its registers, now i want to process the data on my pc.

I tried using another arduino uno and also some other mouse optical sensor, wich did not change anything. Opening and closing the serialport after each communication did not work for me. I have seen a few questions here on stack exchange, i looked through everyone but they could not help me. Serial.flush() seems to be not working, or its some kind of overflow i cant figure out.

I would really appreciate it if someone could explain me what the root of this problem is.

For completeness, here is my C# code:

 public class SerialCommunication
 {
 public SerialPort serialPort = new SerialPort();
 public SerialCommunication()
 {
 string[] ports = SerialPort.GetPortNames();
 if (ports.Count() == 1)
 {
 MessageBox.Show("No serialport is available");
 return;
 }
 serialPort.PortName = ports[1];
 serialPort.BaudRate = 115200;
 serialPort.Parity = Parity.None;
 serialPort.DataBits = 8;
 serialPort.Handshake = Handshake.None;
 serialPort.StopBits = StopBits.One;
 serialPort.NewLine = "\r\n";
 serialPort.WriteTimeout = 2000;
 serialPort.ReadTimeout = -1;
 serialPort.Open();
 }
 }
public partial class MainWindow : Window
 {
 public static readonly object _lock = new object();
 private SerialCommunication serialCommunication = new SerialCommunication();
 public MainWindow()
 {
 InitializeComponent();
 GetWindow(this).KeyDown += HandelKeyDown;
 serialCommunication.serialPort.DataReceived += (sender, args) =>
 {
 string bufferstring = ((SerialPort)sender).ReadLine();
 OnMessageReceived(bufferstring);
 //serialCommunication.serialPort.DiscardOutBuffer();
 //serialCommunication.serialPort.DiscardInBuffer();
 //Thread.Sleep(3);
 //byte[] buffer = new byte[15];
 //((SerialPort)sender).Read(buffer, 0, buffer.Length);
 //string bufferstring = Encoding.UTF8.GetString(buffer);
 };
 serialCommunication.serialPort.WriteLine("OK");
 }
 private void OnMessageReceived(string message)
 {
 if (message.Length != 15 || message.Contains('O') || message.Contains('K') || message.Contains('\n') || message.Contains('\r'))
 {
 serialCommunication.serialPort.DiscardInBuffer();
 serialCommunication.serialPort.DiscardOutBuffer();
 serialCommunication.serialPort.WriteLine("OK");
 return;
 }
 //Format: "y: 0x%02X,x: 0x%02X"
 string x = message.Substring(3, 4);
 string y = message.Substring(11, 4);
 int offsetX = (Convert.ToInt32(x, 16) - 128);
 int offsetY = (Convert.ToInt32(y, 16) - 128);
 // the next three lines only visualize the received data but do not change it 
 MoveX(offsetX / 50);
 MoveY(offsetY / 50);
 ShowMessage(message);
 Thread.Sleep(2);
 serialCommunication.serialPort.WriteLine("OK");
 }
}

Foto of how the application and data it receives look like: On the right side is the data, at the top the current position

Here is my arduino code:

#include <Arduino.h>
// 5v
#define POWER 13
// Serial I/O
#define SDIO 11
// Serial clock
#define SCK 12
// Registers
#define DELTAY 0x02
#define DELTAX 0x03
#define serialInputBufferSize 16
char dataBuffer[serialInputBufferSize];
unsigned short inputBufferLength = 0;
bool sendPosition = true;
char tmp[16];
void InitMouse()
{
 digitalWrite(SCK, HIGH);
 delayMicroseconds(5);
 digitalWrite(SCK, LOW);
 delayMicroseconds(1);
 digitalWrite(SCK, HIGH);
 // Wait for the serial transaction timer to time out:
 delay(1000);
}
byte readRegister(byte addr)
{
 byte r = 0;
 // Set the dataline to output
 pinMode(SDIO, OUTPUT);
 for (int i = 7; i >= 0; i--)
 {
 digitalWrite(SCK, LOW);
 digitalWrite(SDIO, addr & (1 << i));
 digitalWrite(SCK, HIGH);
 }
 // Switch the dataline from output to input
 pinMode(SDIO, INPUT);
 // The datasheet mentions to wait at least 100 μsec
 // when switching from write to read operations.
 // This is needed for the chip to prepare the data
 delayMicroseconds(110);
 // Clock trough the register and read its data
 for (int i = 7; i >= 0; i--)
 {
 digitalWrite(SCK, LOW);
 digitalWrite(SCK, HIGH);
 r |= (digitalRead(SDIO) << i);
 }
 // Delay at the end guarantees >100 μsec before next transaction
 delayMicroseconds(110);
 return r;
}
byte y = 0;
byte x = 0;
void WaitForMovementThenSendPositionOffset()
{
 x = 0;
 y = 0;
 while (((y == 0 && x == 0) || x == NULL || y == NULL) && sendPosition)
 {
 delay(1); // kann eigentlich weg
 y = readRegister(DELTAY);
 x = readRegister(DELTAX);
 }
 if (sprintf(tmp, "y: 0x%02X,x: 0x%02X", y, x) > 0)
 {
 tmp[16] = 0;
 if (!Serial.println(tmp))
 {
 // Serial.end();
 // Serial.begin(9600);
 // Serial.begin(115200);
 Serial.flush();
 }
 sendPosition = false;
 }
}
void serialEvent()
{
 sendPosition = false;
 // Read serial data into the buffer
 while (Serial.available())
 {
 dataBuffer[inputBufferLength++] = Serial.read();
 }
 Serial.flush();
 if (strstr(dataBuffer, "OK"))
 {
 sendPosition = true;
 WaitForMovementThenSendPositionOffset();
 }
}
void setup()
{
 pinMode(SCK, OUTPUT);
 pinMode(SDIO, INPUT);
 pinMode(POWER, OUTPUT);
 digitalWrite(POWER, HIGH);
 Serial.setTimeout(1000);
 // Serial.begin(9600);
 Serial.begin(115200);
 InitMouse();
}
void loop()
{
}
asked Dec 30, 2019 at 0:07
6
  • what troubleshooting have you done? Commented Dec 30, 2019 at 0:14
  • @jsotola as mentioned above: I tried using another arduino uno and also some other mouse optical sensor, wich did not change anything. Opening and closing the serialport after each communication did not work for me. I have seen a few questions here on stack exchange, i looked through everyone but they could not help me. I also tried around with delay() and other useless stuff for 2 days now Commented Dec 30, 2019 at 0:26
  • 1
    start with basics ... lower the baud rate ... use a simple Arduino sketch that sends repeatedly "ABC123" one character at a time with a short pause in between characters ... observe the result on the C# side of the connection Commented Dec 30, 2019 at 0:38
  • @jsotola i tried baudrate 9600 wich did not help, on the c# side i get the results i want. I will add a foto of how my wpf application looks like and the data it receives, but thank you Commented Dec 30, 2019 at 1:02
  • 1
    you need to modify the arduino sketch to the minium code that still exhibits the undesired behavior ... that is why i said to start by sending ABC123 and see if it still happens Commented Dec 30, 2019 at 2:21

2 Answers 2

0

Every time you receives data, it tries to read a full line (SerialPort.ReadLine()). If there's not a full line available, it will block the current thread until there is or until it times out.

These calls will stack up and eventually cause the application to fail.

answered Dec 30, 2019 at 3:07
1
  • If i restart the c# application, it still does not work. I have to restart the arduino, then it works again. I think problem is on the arduino side, but i give it a try and use a buffer with SerialPort.Read() instead. Commented Dec 30, 2019 at 13:37
0

The problem was in the serialEvent() method. I did not rest the bufferindex where i red the received message so it allways stayed there until the arduino ran out of memory and also i did not gave the arduino enough time to receive the message so i added delay(1) there.

Here is my updated code:

void serialEvent()
{
 inputBufferLength = 0;
 sendPosition = false;
 delay(1);
 // Read serial data into the buffer
 while (Serial.available())
 {
 if (inputBufferLength < serialInputBufferSize)
 {
 dataBuffer[inputBufferLength++] = Serial.read();
 }
 else
 {
 Serial.read();
 }
 }
 Serial.flush();
 if (strstr(dataBuffer, "OK"))
 {
 sendPosition = true;
 WaitForMovementThenSendPositionOffset();
 }
}
answered Dec 30, 2019 at 23:15

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.