Pages: [1]   Go Down
Author Topic: First line of serial communication distorted  (Read 1099 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,


I'm trying to communicate with my arduino  through the posix serial library.

It kind of works  but the first line is distorted.
It should print "flamingo:" in the console
but most of the time I get stuff like

flamflamingo
or
fflamingo


that's for the first line
the other lines seem to work well.

I've seen this happening in the arduino serial monitor too but only on rare occasions...


Here is the code I'm using
Code:
#include <stdio.h>    /* Standard input/output definitions */
#include <stdlib.h>
#include <stdint.h>   /* Standard types */
#include <string.h>   /* String function definitions */
#include <unistd.h>   /* UNIX standard function definitions */
#include <fcntl.h>    /* File control definitions */
#include <errno.h>    /* Error number definitions */
#include <termios.h>  /* POSIX terminal control definitions */
#include <sys/ioctl.h>
#include <getopt.h>


int serialport_init(void);

int main()
{

   int fd = 0;
   char buf[256];
   int n;
   int i;

    char b[1];
    int wloopc=0;


  fd = serialport_init();


   while(wloopc<1){

    i=0;
    while( b[0]!='\n' ) {


         n = read(fd, b, 1);  // read a char at a time
        if( n==-1) break;    // couldn't read
        if( n==0 ) {

            usleep( 10 * 1000 ); // wait 10 msec try again
            continue;
        }


        buf[i]=b[0];
        i++;

    }
    buf[i]=0;   // 0 terminate the string
   
    fputs(buf,stdout);
    b[0]=0;    // reset b[0] so while loop can start over


   }





}


int serialport_init(void)
{
    struct termios toptions;
    int fd;
    int baud=B9600;

    //fprintf(stderr,"init_serialport: opening port %s @ %d bps\n",
    //        serialport,baud);

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)  {
        perror("init_serialport: Unable to open port ");
        return -1;
    }

    if (tcgetattr(fd, &toptions) < 0) {
        perror("init_serialport: Couldn't get term attributes");
        return -1;
    }
    speed_t brate = baud; // let you override switch below if needed

   brate=baud;

    cfsetispeed(&toptions, B9600);
    cfsetospeed(&toptions, B9600);

    // 8N1
    toptions.c_cflag &= ~PARENB;
    toptions.c_cflag &= ~CSTOPB;
    toptions.c_cflag &= ~CSIZE;
    toptions.c_cflag |= CS8;
    // no flow control
    toptions.c_cflag &= ~CRTSCTS;

    toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
    toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl

    toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    toptions.c_oflag &= ~OPOST; // make raw

    // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
    toptions.c_cc[VMIN]  = 0;
    toptions.c_cc[VTIME] = 20;

    if( tcsetattr(fd, TCSAFLUSH, &toptions) < 0) {   //Was TCSANOW
        perror("init_serialport: Couldn't set term attributes");
        return -1;
    }

    return fd;
}




Any ideas?
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 654
Posts: 50931
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I've seen this happening in the arduino serial monitor too but only on rare occasions...
The usual solution is a small delay() after the Serial.begin() in the Arduino sketch, to allow the port time to be opened, before sending data.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you Paul
I've thought the same and already tried that  but that didn't help.

Normally the first line isn't that important since it's just a hello line  in setup();
I'd just like to know why it happens to make sure it's  just the first line and not something that's going to repeat itself throughout the code.

I've noticed that it depends on how fast I run the program again after terminating it  how much distortion there will be.






Logged

0
Offline Offline
Full Member
***
Karma: 4
Posts: 218
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

You asked any ideas?

If it puts "    flamflamingo   "  it might be it is doing a reset after "flam" so maybe its doing a double reset or init
If it puts "    fflamingo   "  it might be it is doing a reset after "f"

The devices are very fast and you probably would not notice this apart from the extra start characters
« Last Edit: September 19, 2012, 04:10:44 pm by april » Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you April.

I think that might explain it.
When I press the reset button manually the thing resets and prints everything just fine.
I'm using a mega 2560

Can't come up with a way to solve it for now.
Except maybe adding a special character before every new word then removing it later.
Wonder how the serial monitor handles this, I've looked through the source and found a couple read functions,  not so familiar with Java though.

Anyways thanks for the suggestions ^^
Logged

Chile
Offline Offline
Edison Member
*
Karma: 35
Posts: 1251
Arduino rocks?
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you April.

I think that might explain it.
When I press the reset button manually the thing resets and prints everything just fine.
I'm using a mega 2560

Can't come up with a way to solve it for now.
Except maybe adding a special character before every new word then removing it later.
Wonder how the serial monitor handles this, I've looked through the source and found a couple read functions,  not so familiar with Java though.

Anyways thanks for the suggestions ^^

Can you check if the same happens with my tweaked version? http://arduino.cc/forum/index.php/topic,118440.0.html

IDE flushes the serial port, but I removed that and the winavr wrapper handles that flush, also you can press Ctrl when clicking upload to auto-open the serial monitor, maybe solves your issue.

Can you post all the related files to your sketch? I can test it locally to research what is happening
Logged

My website: http://ried.cl

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello eried

Thanks but I'm on Linux so your Win prog won't work here.

Anyways If someone can benefit from the source here it is.
I'm not familiar with the library but everything seems okay except for the first line issue.

Just change the name of the serial port in the serialport_init function(fd=open...)  to the one your adruino is on in /dev
The baud rate is 9600

It will listen on that port and print whatever the arduino sent in the console.


Code:


#include <stdio.h>    /* Standard input/output definitions */
#include <stdlib.h>
#include <stdint.h>   /* Standard types */
#include <string.h>   /* String function definitions */
#include <unistd.h>   /* UNIX standard function definitions */
#include <fcntl.h>    /* File control definitions */
#include <errno.h>    /* Error number definitions */
#include <termios.h>  /* POSIX terminal control definitions */
#include <sys/ioctl.h>
#include <getopt.h>


int serialport_init(void);
void clear_string();
int serialport_read_until(int fd,char until);
int serialport_write(int fd, const char* str);



char b[1];
char buf[256];
char sendbuf[256];
int i=0;
int len;
int w;


int main()
{

   int fd = 0;
   int StatusRec=3;

   //sendbuf[0]='2';
  //  sendbuf[0]='9';
   // sendbuf[1]='9';

    //sendbuf[2]='\n';
   // sendbuf[3]='\0';


  fd = serialport_init();
usleep(200);

while(1){

        do{
         StatusRec=serialport_read_until(fd,'\n');
         //usleep(10);

        }while(StatusRec==-1||StatusRec==2);
           //printf("__%d__",StatusRec);
           printf("%s",buf);

/*  Send data to the arduino with this...  If using sketch  below just un-comment this
  
    printf("What shall be sent?");
            scanf("%s",&sendbuf);
            sendbuf[strlen(sendbuf)]='\n';
            sendbuf[strlen(sendbuf)+1]='\0';
            printf("%s\n",sendbuf);
            serialport_write(fd,sendbuf);
  */          clear_string();

        usleep(1000);
        }


}

int serialport_init(void)
{
    struct termios toptions;
    int fd;
    int baud=B9600;


    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1)  {
        perror("init_serialport: Unable to open port ");
        return -1;
    }

    if (tcgetattr(fd, &toptions) < 0) {
        perror("init_serialport: Couldn't get term attributes");
        return -1;
    }
    speed_t brate = baud;

   brate=baud;

    cfsetispeed(&toptions, B9600);
    cfsetospeed(&toptions, B9600);

    // 8N1
    toptions.c_cflag &= ~PARENB;
    toptions.c_cflag &= ~CSTOPB;
    toptions.c_cflag &= ~CSIZE;
    toptions.c_cflag |= CS8;
    // no flow control
    toptions.c_cflag &= ~CRTSCTS;

    toptions.c_cflag |= CREAD | CLOCAL;  // turn on READ & ignore ctrl lines
    toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl

    toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
    toptions.c_oflag &= ~OPOST; // make raw

    // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
    toptions.c_cc[VMIN]  = 0;
    toptions.c_cc[VTIME] = 20;

    if( tcsetattr(fd,TCSANOW , &toptions) < 0) {   //Was TCSAFLUSH
        perror("init_serialport: Couldn't set term attributes");
        return -1;
    }

    return fd;
}




void clear_string()
{
    int f;
     for(f=0;f<256;f++){
      buf[f]=0;

      }
 i=0;
    }


int serialport_read_until(int fd,char until)
{

    do {
        int n = read(fd, b, 1);  // read a char at a time
        if( n==-1) return -1;    // couldn't read
        if( b[0]==0||n==0 ) {
            usleep( 10 * 1000 ); // wait 10 msec try again
            printf("^^");
            continue;
        }
        else{
        buf[i] = b[0]; i++;
        }
    } while( b[0] != until );

   if(b[0]==until){
    buf[i] = 0;  // null terminate the string
    return 0;
    i=0;
    b[0]=0;
   }
   else{
   return 2;
   }
}





int serialport_write(int fd, const char* str)
{
    int len = strlen(str);
    int n = write(fd, str, len);
    if( n!=len )
        return -1;
    return 0;
}



As for the arduino code you can add just a few  Serial.println()'s


The code below will listen for input(int)  when it receives input it will delay that much and then send the input back to the pc.
If you input 99  it will blink led 13  twce and then send back the input
Just make sure to un-comment the send part in the code above.

Code:
#include <HardwareSerial.h>


void init_process_string(void);
char STRING[128];
int serial_count;
int delaytime=0;
int ledpin=13;



void setup(){

  pinMode(ledpin,OUTPUT);
      delay(500);
  Serial.begin(9600);
  delay(700);
  Serial.println("start");
  
    Serial.flush();
      delay(500);

        
}

void loop()
{
   char c;
   if (Serial.available() > 0)
   {
      c = Serial.read();

      if (c != '\n')
      {
         STRING[serial_count] = c;
        
         serial_count++;
      }
   }
   //mark no data.
   else
   {
      delayMicroseconds(100);
   }

   //if theres a pause or we got a real command, do it
   if (serial_count && (c == '\n'))
   {
         delaytime=atoi(STRING);
         delay(delaytime);
         if(delaytime==99){
          
           digitalWrite(ledpin,LOW);
                               delay(1000);
           digitalWrite(ledpin,HIGH);
                    delay(5000);
            digitalWrite(ledpin,LOW);
                                delay(1000);
             digitalWrite(ledpin,HIGH);
                    delay(5000);
            digitalWrite(ledpin,LOW);
                                
         }
          
         Serial.println(delaytime,DEC);
         Serial.flush();
    
    
      //clear command.
      init_process_string();
   }


}



void init_process_string()
{
   //init our command
   for (byte i=0; i<128; i++)
      STRING[i] = 0;
   serial_count = 0;
}
« Last Edit: September 22, 2012, 03:50:34 pm by Tentationem » Logged

Pages: [1]   Go Up
Jump to: