1

This going to be a difficult to debug problem but I hope some ppl here have C knowledge and idea what's going on. Given an arduino nano which is controlled by a C program from WRT54G.

Here is the relevant part of the arduino code:

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

 int integerValue=0; 

                              // Max value is 65535
char incomingByte;

void loop() {
  if (Serial.available() > 0) {   // something came across serial
    integerValue = 0;         // throw away previous integerValue
    while(1) {            // force into a loop until 'n' is received
      incomingByte = Serial.read();
      if (incomingByte == '\n') break;   // exit the while(1), we're done receiving
      if (incomingByte == -1) continue;  // if no characters are in the buffer read() returns -1
      integerValue *= 10;  // shift left 1 decimal place
      // convert ASCII to integer, add, and shift left 1 decimal place
      integerValue = ((incomingByte - 48) + integerValue);

    }
   Serial.print("Command: ");
   Serial.println(integerValue);

  }
}

Pretty straight forward (it converts serial received ascii chars to numeric format), arduino receives a simple integer and it runs a function. For example 1-> turn on relay1. This work's reliably for sure because I can just do:

echo "1" > /dev/tts/1 

from the terminal.

Now here is the relevant part of the C code:

    int serialport_read_until(int fd, char* buf, char until, int buf_max, int timeout)
    {
        char b[1];  // read expects an array, so we give it a 1-byte array
        int i=0;
        do { 
            int n = read(fd, b, 1);  // read a char at a time
            if( n==-1) return -1;    // couldn't read
            if( n==0 ) {
                usleep( 1 * 1000 );  // wait 1 msec try again
                timeout--;
                continue;
            }
    #ifdef SERIALPORTDEBUG  
            printf("serialport_read_until: i=%d, n=%d b='%c'\n",i,n,b[0]); // debug
    #endif
            buf[i] = b[0]; 
            i++;
        } while( b[0] != until && i < buf_max && timeout>0 );

        buf[i] = 0;  // null terminate the string
        return 0;
    }

    /* Only use integer commands */
    int serialport_write(int fd, int comm_no)
    {
        char command[6];

        sprintf(command,"%d\n",comm_no);
        printf("Sending Command:%s",command);

        int len = strlen(command);
        int n = write(fd, command, len);
        if( n!=len ) 
            return -1;
        return 0;
    }

void *ardu_handler(void *fdfd)
{
  int fd = *(int*)fdfd;
  char buf[256];
  char getback[10];

  while (1)
   {
     memset(buf, 0, sizeof(buf)); 
     serialport_read_until(fd, buf, '\n', 256, 5);
     fprintf(stderr, "Received: %s\n", buf);
   }
}

Then a C thread will be started with the ardu_handler which in this case doesn't do anything else just print's back the response from the ardu.

What's happening is when I send a command I start getting back infinite amount of commands (up until I close the C app and start it again) and to make it worse it is even inconsistent.

For example:

Command: 62143
Command: 7891
Command: 3216
Command: 11287
...
runs forever.

What I asking myself is whether these responses coming out from the arduino or they are just coming out from the bogous C program... It's not possible to connect to see what's coming out on the serial port unfortunately until this program holds the port open.

Although I run the C code on mips this was doing the same thing back on x86 PC with an arduino uno (sometimes it is stable but then it falls into this unstable state and floods the serial port). It was unreliable and I would like to make it reliable.

4
  • Change the type of incomingByte to int. See arduino.cc/en/Serial/read
    – ott--
    Commented Jan 7, 2016 at 20:46
  • 1
    Reading on, the 2nd code block contains a buffer overflow where char b[1]; is defined, but you're trying to null-terminate a string. Where is buf_max defined?
    – ott--
    Commented Jan 7, 2016 at 20:58
  • I assume the results you posted above are the stderr output, though I can't see the Received: part of it. Commented Jan 7, 2016 at 22:48
  • // Max value is 65535 - that isn't true.
    – Nick Gammon
    Commented Jan 8, 2016 at 11:01

1 Answer 1

1

I recommend you change the type of incomingByte to int, like was advised in the comments. Also, your null-termination is occurring past the end of buf; change the condition in the while statement to i < buf_max - 1, so that one byte is left for the null. Also use parentheses to separate those conditions, in the unlikely event there's some issue of precedence.

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.