Serial Communication doesn't work sometimes.

Hi,

i'm trying to communicate with an Arduino Mega 2560 via serial port /dev/ttyACM0 using C++ and <termios> and <fcntl.h>. I got it running very well including bidirectional communication and some kind of handshaking. The only trouble i have is that it doesn't work all the time. Sometimes i'm experiencing some issus while working with the arduino. I can't reproduce the error because i'm not sure what causes it.

Error description:
I wait for the Arduino to be initialized for 3 to 4 seconds. After that i usually communicate on an request/response model. I write some commands to it and await response from the arduino. Most of the time it works very well. But sometimes it seems the arduino isn't initialized properly. When i write some data to it, it doesn't react nor respond although the TX/RX-LEDs are flashing.

This error occures irregularly and it can't be reproduced. The only thing which's steady is that when the error occured it will occure every time i try to reconnect.

Solution to get it back working:
The only way i can "reset" this error and get the arduino working again is to open the Arduino IDE and start the Serial Monitor and close it again. After that everything works fine again for some time.

Could it be that there are some issues when i try to connect to it? Maybe some kind of "handshaking" when initializing?

I can't understand why it does work most of the time and then it doesn't.

Thanks for your help!

Greets,

Smokehead

you could be loosing the handshaking synchronisation between the devices which will cause the communication to hang and require reset
what handshaking are you using software XON/OFF or hardware RTS/CTS ?

any particular reason for using handshaking? were you loosing data without it?

I have never used C/C++ for PC programming - I don't have the patience. But my Python programs will communicate with my Arduino for as long as I want without any problems.

Is there any possibility that your PC program is closing the serial port before you have finished using the Arduino?

...R
Python - Arduino demo

horace:
you could be loosing the handshaking synchronisation between the devices which will cause the communication to hang and require reset
what handshaking are you using software XON/OFF or hardware RTS/CTS ?

any particular reason for using handshaking? were you loosing data without it?

It's not a handshaking in the classical sense. It's more like acknowledging of the received command. I need something like that for controlling the flow in my process (it's used for device-testing). On the computer side (master) i trigger an action (send command to the arduino) and need to wait for the action to be processed. After the arduino (slave) processed the command it acknowledges the command or sends an errorcode. Calling it handshaking was misleading. It's more like an request/response type with ACK/NACK.

Robin2:
I have never used C/C++ for PC programming - I don't have the patience. But my Python programs will communicate with my Arduino for as long as I want without any problems.

Is there any possibility that your PC program is closing the serial port before you have finished using the Arduino?

...R
Python - Arduino demo

I don't think the port is closed too early. If that would be the reason behind it the Arduino wouldn't receive any data via RX. Also my code doesn't provide the option to close the port without confirming it twice. That doesn't happen.

When opening the port the arduino is resetted. So i don't think it's a problem with the arudino but more with initializing the port. Is the arduino IDE/SerialMonitor sending some startbytes or initialization bytes when it opens the port?

For further information:

I've started a std::thread for reading the data that the main-thread is free for user-interaction and updating the GUI as well as processing the thread which is used for another USB device. The reading is performed asynchronous.

Smokehead:
It's not a handshaking in the classical sense. It's more like acknowledging of the received command. I need something like that for controlling the flow in my process (it's used for device-testing). On the computer side (master) i trigger an action (send command to the arduino) and need to wait for the action to be processed. After the arduino (slave) processed the command it acknowledges the command or sends an errorcode. Calling it handshaking was misleading. It's mor like an request/response type with ACK/NACK.

can you print on both system the state of your ACK/NACK handshake?
this may indicate if it is locking up

could the communication between your threads be locking up?

horace:
can you print on both system the state of your ACK/NACK handshake?
this may indicate if it is locking up

could the communication between your threads be locking up?

What do you mean with printing? On the Arduino it lights up an LED for some time if there has been an NACK/Error while processing the action. In the PC-Software i'm printing out the received byts via std::cout.

The two threads are running completely independent and don't have any pointers or variables in common. They don't even have to read/write at the same time. So i don't think they are influencing eachother.

on the Arduino can you print to the serial monitor, e.g. what you are transmitting/receiving, the handshaking state, etc

in C++ are you writing to std::cout from both threads? this would cause problems if the IO code is not reentrant

I can't use the SerialMonitor at the same time with my programm. So that woudn't work. Even if it would work, it shouldn't display anything because i'm not writing chars. I'm only writing bytes with values up to 0x10. With the serial monitor i can't send hex values directly nor display received byte values as hex. It's only possible to send chars.

I just use std::cout for debugging and by now only for debugging the arduino communication. After reading a received packaged i write to std::cout as hex-value to see which one i received. That shouldn't be a problem. Later every thread should write the i/o-transmissions to a log file. But each thread gets its own logfile.

Smokehead:
I can't use the SerialMonitor at the same time with my programm.

I understand that. It is very useful to include in your PC program the ability to display debug messages that come from the Arduino.

I guess another option is to use a USB - TTL cable to set up another line of communication with the Arduino for showing debug messages on the Serial Monitor using one the other HardwareSerial ports on your Mega.

...R

I thought you were using an arduino mega which has three serial ports in addition to the one which communicates with the serial monitor

you can print hex values, e.g.

How do i implement some kind of debug - monitor? Then i would need a functioning serial communication to recognize and display these messages. That means that when i can send debug messages correctly my process messages will be transmitted correctly too. Which would lead to obsolete debug messages..

The only way i could think of is an FTDI USB-RS232 TTL cable similar to the cables used for serial terminals with raspberry pis. Are the TX/RX pins for USB-Serial communication the same pins which are accessible on TX/RX pins 18/19 (PD3/PD2)? So i maybe could just look what's happening on the bus similar to sniffing? Or would that be a problem and i should send the debug messages via another serial port on the arduino (serial2 / serial 3) ?

The hex messages i get back can be displayed as hex. Thank you i didn't know that. But how can i send hex values via SerialMonitor? I just thought that wouldn't be possible.

you could connect to the Arduino Mega TX1 and Rx1 using an FTDI TTL-232R-5V or TTL-232RG-VSW5V-WE (note 5volt levls) or similar interface - you then use the Arduino Serial1 communications channel

to print HEX etc

 int  analogValue = 125;
  // print it out in many formats:
  Serial.println(analogValue);       // print as an ASCII-encoded decimal
  Serial.println(analogValue, DEC);  // print as an ASCII-encoded decimal
  Serial.println(analogValue, HEX);  // print as an ASCII-encoded hexadecimal
  Serial.println(analogValue, OCT);  // print as an ASCII-encoded octal
  Serial.println(analogValue, BIN);  // print as an ASCII-encoded binary

prints

125
125
7D
175
1111101

Okay, thank you. I'll try that. Maybe there are some other things going on which i'm not aware of.

Thanks for your help.

have a look on EBAY for FTDI USB to TTL Serial Converter Adapter FT232RL where you can select 3.3 or 5 volt TTL signals

Okay i'll have a look!

is there a way to send hex values like 0x01, 0x02, ... etc. from PC to Arduino vs serial monitor? Your solution is only from arduino to pc which isn't exactly what i want. That was working already. Even without the second parameter which is only needed for the SerialMonitor i think.

In other serial communication the Serial.print is just sending bits which are interpreted as byte/char. So it doesn't matter how it should be displayed but only how it should be processed. I think the Serial.print(0x43, HEX) is just for the SerialMonitor to display it's values which would mean it sends some additional bytes/bits encoding the formatting which would be inappropriate in other applications. Is that right?

in C++ to print in hexadecimal use the hex format flag
http://www.cplusplus.com/reference/ios/hex/

to also show the number base use the showbase flag
http://www.cplusplus.com/reference/ios/showbase/

the method call Serial.print(78, HEX) converts the integer value 78 into characters which represent the value in the hexadecimal base, i.e. it prints 4E

I think we don't talk about the same things. I know how to print formattetd values to cout. I didn't ask anything about C++ or programming or formatting values etc.

I wanted to know if the Arduino IDE Serial Monitor is capable of sending hex values to the arduino.. How to handle datatypes or formatting values in C++ isn't the problem.

If the IDE Serial Monitor can't do that i maybe try another option or maybe write a little serial terminal myself for doing stuff like that. My idea was to send the code manually by typing it to a terminal.

you can type hexadecimal values into the serial monitor - at the arduino you will have to parse the received character string, have a look at examples in
http://forum.arduino.cc/index.php?topic=288234.0

e.g. a program reading hexadecimal values (one per line) from the serial monitor and converting into an integer

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(10000);
}

void loop() 
{
  byte text[100]={0};
  int number =0;
  Serial.readBytesUntil('\r', text, 100) ;
  for(int i=0; text[i]>0;i++)
  {
    // parse text converting into hexadecimal
    text[i]=toupper(text[i]);
    if(text[i]>='0' && text[i] <= '9')
        number = number *16 + text[i]-'0';    // character '0' to '9'
    else
      if(text[i]>='A' && text[i] <= 'F')
          number = number *16 + text[i]-'A' + 10;   // character 'A' to 'F'
  }
  Serial.println(number, DEC);  // print as an ASCII-encoded decimal
  Serial.println(number, HEX);  // print as an ASCII-encoded hexadecimal
  Serial.println(number, OCT);  // print as an ASCII-encoded octal
  Serial.println(number, BIN);  // print as an ASCII-encoded binary
}

if I typed 12ab I would get

4779
12AB
11253
1001010101011

Yes okay so that's absolutely not what i want.

In my C++ program i do something similar like this:

typedef struct {
    uint8_t sof;
    uint8_t cmdId;
    uint8_t payloadLen;
    uint8_t data[];
} serialCmd_header_t 

typedef struct {
    serialCmd_header_t header;
    uint8_t data[];
}

void serialWrite(uint8_t *data, int len); {

    serialCmd_t *cmd;

    cmd = (serialCmd_t*) malloc(sizeof(serialCmd_header_t) + len);
 
    cmd->header.sof = 0xfb;
    cmd->header.cmdId = 0x1c;
    cmd->header.payloadLen = len;

    memcpy(cmd->data, data, len);

    int bytesWritten = write(m_fd, cmd, (sizeof(serialCmd_header_t) + len));

}

Not sure anymore about the details, i have to look for it tomorrow again. But it is similar to this. So i really need to send byte values not formatted as chars. Nor do i want to parse any data. I just want to use byte values. So when i write 0x07 to my console i don't want it to be parsed as '0' 'x' '2' '7'. I want the serial monitor terminal to send the actual value 39 / 0x27 / 0b00100111

Smokehead:
So when i write 0x07 to my console i don't want it to be parsed as '0' 'x' '2' '7'. I want the serial monitor terminal to send the actual value 39 / 0x27 / 0b00100111

as far as I am aware the Arduino Serial Monitor cannot do that
you can write a program (in C++, C#, VB, etc) which when 0x07 is typed it transmits the equivalent byte value