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.

No comments:

Post a Comment