Monday, January 27, 2014

Serial communication between Arduino and PC using C with termios

This example show how to implement Serial communication using C language with termios.h. It run on Ubuntu, and send and receive data to and from Arduino Esplora connected with USB cable.


The C program, testTermios.c, in Ubuntu side copy from example in http://en.wikibooks.org/wiki/Serial_Programming/Serial_Linux#termios, it is a simple terminal program with termios.h.
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
 
int main(int argc,char** argv)
{
 struct termios tio;
 struct termios stdio;
 struct termios old_stdio;
 int tty_fd;
 
 unsigned char c='D';
 tcgetattr(STDOUT_FILENO,&old_stdio);
 
 printf("Please start with %s /dev/ttyS1 (for example)\n",argv[0]);
 memset(&stdio,0,sizeof(stdio));
 stdio.c_iflag=0;
 stdio.c_oflag=0;
 stdio.c_cflag=0;
 stdio.c_lflag=0;
 stdio.c_cc[VMIN]=1;
 stdio.c_cc[VTIME]=0;
 tcsetattr(STDOUT_FILENO,TCSANOW,&stdio);
 tcsetattr(STDOUT_FILENO,TCSAFLUSH,&stdio);
 fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK); // make the reads non-blocking
 
 memset(&tio,0,sizeof(tio));
 tio.c_iflag=0;
 tio.c_oflag=0;
 tio.c_cflag=CS8|CREAD|CLOCAL; // 8n1, see termios.h for more information
 tio.c_lflag=0;
 tio.c_cc[VMIN]=1;
 tio.c_cc[VTIME]=5;
 
 tty_fd=open(argv[1], O_RDWR | O_NONBLOCK);
 cfsetospeed(&tio,B115200); // 115200 baud
 cfsetispeed(&tio,B115200); // 115200 baud
 
 tcsetattr(tty_fd,TCSANOW,&tio);
 while (c!='q')
 {
  if (read(tty_fd,&c,1)>0)        write(STDOUT_FILENO,&c,1);
  // if new data is available on the serial port, print it out
  if (read(STDIN_FILENO,&c,1)>0)  write(tty_fd,&c,1);
  // if new data is available on the console, send it to the serial port
 }
 
 close(tty_fd);
 tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
 
 return EXIT_SUCCESS;
}

Compile it with the command:
$ gcc testTermios.c -o testTermios

To run it with specified device port, run the command dmesg to check the Arduino Esplora connected post:
$ dmesg

It's ttyACM0 in my case.

Run:
$ ./testTermios /dev/ttyACM0

Press any key will send to ttyACM0, press 'q' to quit.

In Arduino Esplora side, testSerial.ino. (It is same as the example in "Serial communication between Arduino Esplora and PC", using Arduino IDE's Serial Monitor.)
#include <Esplora.h>
#include <TFT.h>
#include <SPI.h>

int prevSw1 = HIGH;
int incomingByte = 0;
String charsIn = "";
char printout[20];  //max char to print: 20
 
void setup() {
  
    EsploraTFT.begin();  
    EsploraTFT.background(0,0,0);
    EsploraTFT.stroke(255,255,255);  //preset stroke color
     
    //Setup Serial Port with baud rate of 9600
    Serial.begin(9600);
    
    //indicate start
    Esplora.writeRGB(255, 255, 255);
    delay(250);
    Esplora.writeRGB(0, 0, 0);
    
}
 
void loop() {
    int sw1 = Esplora.readButton(SWITCH_1);
    if(sw1 != prevSw1){
      if(sw1 == LOW){
        Serial.println("Hello from Arduino Esplora");
      }
      prevSw1 = sw1;
    }
    
    while (Serial.available()) {
      char charRead = Serial.read();
      charsIn.concat(charRead);
    }
    if(charsIn != ""){
      Serial.println("How are you, " + charsIn);
      charsIn.toCharArray(printout, 21);
      EsploraTFT.background(0,0,0);
      EsploraTFT.text(printout, 0, 10);
      charsIn = "";
    }
}


Next:
- Send data to Arduino from Linux PC, program in C with GUI of GTK+3, as ColorChooser

No comments:

Post a Comment