Showing posts with label Code.C. Show all posts
Showing posts with label Code.C. Show all posts

Tuesday, January 28, 2014

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

In this example, we are going to develop a GUI program on Ubuntu Linux using C with GTK+3, select color to set LCD screen and LED on Arduino Esplora via USB serial.


In order to program with GTK+3, we have to install it on our PC, read last post "Install GTK+3 and compile with gcc in Linux". For the USB Serial communication part, refer to the post "Serial communication between Arduino and PC using C with termios".

Here is the code combine the termios and GTK+3 GtkColorChooser to build GUI for user to choice color, and send to Arduino Esplora via USB serial.

GtkEsploraColor.c:
#include <gtk/gtk.h>

#include <string.h>
#include <fcntl.h>
#include <termios.h>

int tty_fd;
struct termios old_stdio;

static void 
chooser_color_activated(GtkColorChooser *chooser, 
 GdkRGBA *color, gpointer user_data)
{
 GtkWidget *window = user_data;
 
 int intR = (int)((color->red)*65535);
 int intG = (int)((color->green)*65535);
 int intB = (int)((color->blue)*65535);
 GdkColor gColor = {
  0,
  intR, 
  intG, 
  intB};
 gtk_widget_modify_bg(GTK_WIDGET(window), GTK_STATE_NORMAL, &gColor);
 
 char bytes[] = {
  (char)(intB>>8), 
  (char)(intG>>8), 
  (char)(intR>>8)};
 
 write(tty_fd, bytes, 3);
}

void destroy( GtkWidget *widget,
              gpointer   data )
{
 close(tty_fd);
 tcsetattr(STDOUT_FILENO,TCSANOW,&old_stdio);
 
 g_print ("Bye!\n");
    gtk_main_quit();
}

int main( int argc, char *argv[])
{
 //Prepare for termios
 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/ttyACM0 (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,B9600); // 9600 baud
 cfsetispeed(&tio,B9600); // 9600 baud
 
 tcsetattr(tty_fd,TCSANOW,&tio);
 //---
 
    GtkWidget *window;
    GtkWidget *box;
    GtkWidget *label;
    GtkWidget *chooser;

    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(window), 400, 250);
    gtk_window_set_title(GTK_WINDOW(window), "arduino-er.blogspot.com");

    box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);

 label = gtk_label_new("GtkColorChooser to Arduino Esplora");
    gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 3);

 //Create GtkColorChooser
    chooser = gtk_color_chooser_widget_new();
    gtk_box_pack_start(GTK_BOX(box), chooser, FALSE, FALSE, 3);
    g_signal_connect (GTK_COLOR_CHOOSER(chooser),
                    "color-activated", 
                    G_CALLBACK (chooser_color_activated), 
                    window);

    g_signal_connect(G_OBJECT(window), "destroy", 
        G_CALLBACK(destroy), NULL);

    gtk_container_add(GTK_CONTAINER(window), box);
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}

Compile it with command:
$ gcc GtkEsploraColor.c -o GtkEsploraColor `pkg-config --cflags --libs gtk+-3.0`

Arduino Esplora code, SerialColor.ino:
It's same as in the post "Serial communication between Arduino Esplora and PC")
#include <Esplora.h>
#include <TFT.h>
#include <SPI.h>

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() {
    
    if(Serial.available()){
      char bytesIn[3] = {0x00, 0x00, 0x00};
      int i = 0;
      while(Serial.available()){
        bytesIn[i] = Serial.read();
        i++;
        if(i==3)
          break;
      }
      
      EsploraTFT.background(bytesIn[0], bytesIn[1], bytesIn[2]);
      Esplora.writeRGB(bytesIn[0], bytesIn[1], bytesIn[2]);
    }
}


Before run GtkEsploraColor, determine the connect USB port with dmesg:
- Insert Arduino Esploar to USB port
- Enter the command to check the port
$ dmesg
- The attached port should be listed in last lines. It's ttyACM0 in my setup
- Enter the command to run:
$ ./GtkEsploraColor /dev/ttyACM0
- Double Click on the color buttons to set color. The LCD screen and LED on Arduino Esplora should be changed accordingly.

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