Check out the new projects site for A-i-S www.adventuresinsilicon.com

Tuesday, November 30, 2010

Code: Linux: Sending out strings on a serial port

/*
 * Dingo_aus
 * 
 * Control a servo position via uart on /dev/ttyUSB0
 *
 *
 *
 * /

/* Some code copied from:
 * ser.c
    (C) 2004-5 Captain http://www.captain.at
   
    Sends 3 characters (ABC) via the serial port (/dev/ttyS0) and reads
    them back if they are returned from the PIC.
   
    Used for testing the PIC-MMC test-board
    http://www.captain.at/electronic-index.php

*/
#include    /* Standard input/output definitions */
#include   /* String function definitions */
#include   /* UNIX standard function definitions */
#include    /* File control definitions */
#include    /* Error number definitions */
#include /* POSIX terminal control definitions */

//#include "captain/capser.h"

int writeport(int fd, char *chars);
int readport(int fd, char *result);
int getbaud(int fd);


int fd;

int initport(int fd) {
    struct termios options;
    // Get the current options for the port...
    tcgetattr(fd, &options);
    // Set the baud rates to 9600... (Max 38400)
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);
    // Enable the receiver and set local mode...
    options.c_cflag |= (CLOCAL | CREAD);

    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;

    // Set the new options for the port...
    tcsetattr(fd, TCSANOW, &options);
    return 1;
}

int main(int argc, char **argv) {

    fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);
    if (fd == -1) {
        perror("open_port: Unable to open /dev/ttyUSB0 - ");
        return 1;
    } else {
        fcntl(fd, F_SETFL, 0);
    }
   
    printf("baud=%d\n", getbaud(fd));
    initport(fd);
    printf("baud=%d\n", getbaud(fd));

    char sCmd[254];
    //strcpy(sCmd, "test");
    strcpy(sCmd, "servo1 10");
    //sCmd[0] = 0x74;        //Hex ASCII t
    //sCmd[1] = 0x65;        //Hex ASCII e
    //sCmd[2] = 0x73;        //HEX ASCII s
    //sCmd[3] = 0x74;        //HEX ASCII t
    //sCmd[4] = 0x00;

    if (!writeport(fd, sCmd)) {
        printf("write failed\n");
        close(fd);
        return 1;
    }

    printf("written:%s\n", sCmd);
   
    usleep(500000);
    char sResult[254];
    int counter_i = 0;
    //init array for debugging purposes
    for(counter_i = 0; counter_i <= 253; counter_i++)
    {
        sResult[counter_i] = 0x00;
    }
   
    fcntl(fd, F_SETFL, FNDELAY); // don't block serial read

    if (!readport(fd,sResult)) {
        printf("read failed\n");
        close(fd);
        return 1;
    }
    printf("readport=%s\n", sResult);
   
    close(fd);
    return 0;
}



int writeport(int fd, char *chars) {
    int len = strlen(chars);
    chars[len] = 0x0d; // stick a after the command        (0xd == 13 == ASCII CR)
    chars[len+1] = 0x00; // terminate the string properly
    int n = write(fd, chars, strlen(chars));
    if (n < 0) {
        fputs("write failed!\n", stderr);
        return 0;
    }
    return 1;                                                                                                          
}

int readport(int fd, char *result) {
    int iIn = read(fd, result, 254);
    result[iIn-1] = 0x00;                //Dingo - I think this is unessecary and causing last char to be dropped -can work around by adding a char
    if (iIn < 0) {
        if (errno == EAGAIN) {
            printf("SERIAL EAGAIN ERROR\n");
            return 0;
        } else {
            printf("SERIAL read error %d %s\n", errno, strerror(errno));
            return 0;
        }
    }                   
    return 1;
}

int getbaud(int fd) {
    struct termios termAttr;
    int inputSpeed = -1;
    speed_t baudRate;
    tcgetattr(fd, &termAttr);
    /* Get the input speed.                              */
    baudRate = cfgetispeed(&termAttr);
    switch (baudRate) {
        case B0:      inputSpeed = 0; break;
        case B50:     inputSpeed = 50; break;
        case B110:    inputSpeed = 110; break;
        case B134:    inputSpeed = 134; break;
        case B150:    inputSpeed = 150; break;
        case B200:    inputSpeed = 200; break;
        case B300:    inputSpeed = 300; break;
        case B600:    inputSpeed = 600; break;
        case B1200:   inputSpeed = 1200; break;
        case B1800:   inputSpeed = 1800; break;
        case B2400:   inputSpeed = 2400; break;
        case B4800:   inputSpeed = 4800; break;
        case B9600:   inputSpeed = 9600; break;
        case B19200:  inputSpeed = 19200; break;
        case B38400:  inputSpeed = 38400; break;
    }
    return inputSpeed;
}

Code: Using serial to set servo position (Arduino)

 //Test by Dingo_aus of simple Serial comms 28 Nov 2010


/*
 ---- basic communication example ----
 Control Arduino board functions with the following messages:

 r a -> read analog pins
 r d -> read digital pins
 w d [pin] [value] -> write digital pin
 w a [pin] [value] -> write analog pin
 p m [pin] [value] -> set pin mode


 Base: Thomas Ouellet Fredericks
 Additions: Alexandre Quessy

 */


#include
#include


//GLOBAL VALUES
// Instantiate Messenger object with the message function and the default separator (the space character)
Messenger message = Messenger();
Servo servo1;
int servo1pos = 0;


// Define messenger function
void messageCompleted() {


 
  //serial commands (all need carriage return after them)
  /*  "r a"    -    Read back all analog values
      "r d"    -    Read back all digital values
      "w d [pin] [value]" -> write digital pin
      "w a [pin] [value]" -> write analog pin
       "p m [pin] [value]" -> set pin mode
      "test"    -    Print test message
      "servo1 "  -  Set servo1 to a position in degrees (between 0 and 180)
  



  */

  if(message.checkString("servo1"))
  {
      //Debug
      Serial.print("Setting value for servo1...");
      servo1pos = message.readInt();
      //Clamp values to 0<180
      if(servo1pos < 0)
      {
        servo1pos = 0;
      }
      if(servo1pos > 180)
      {
        servo1pos = 180;
      }
 
      servo1.write(servo1pos);
    
      Serial.print(servo1pos);
      Serial.print("\n\r");
  }
 
  if( message.checkString("test"))
  {
    Serial.print("Test protocol engaged...test successful\n\r");
  }

  if ( message.checkString("r") ) { // Read pins (analog or digital)
    if ( message.checkString("a") ) {
      Serial.print("a ");
      for (char i=0;i<6;i++) { // Read pins 2 to 13
        Serial.print(analogRead(i),DEC); // Send the pin value
        Serial.print(" "); // Add a space separator
      }
      Serial.println(); // Terminate message
    }
    else if ( message.checkString("d") ) {
      Serial.print("d ");
      for (char i=2;i<14;i++) { // Read pins 2 to 13
        Serial.print(digitalRead(i),DEC); // Send the pin value
        Serial.print(" "); // Add a space separator
      }
      Serial.println(); // Terminate message
    }
  }
  else if ( message.checkString("w") ) { // Write pin (analog or digital)
    if ( message.checkString("a") ) {
      int pin = message.readInt();
      int value = message.readInt();
      analogWrite(pin,value); //Sets the PWM of the pin
    }
    else if ( message.checkString("d") ) {
      int pin = message.readInt();
      int state = message.readInt();
      digitalWrite(pin,state); //Sets the state of the pin
    }
  } else if ( message.checkString("p") &&  message.checkString("m") ) { // Pin mode
      int pin = message.readInt();
      int mode = message.readInt();
      pinMode(pin,mode);
  }


}

void setup() {
  // Initiate Serial Communication
  Serial.begin(9600);
  Serial.print("Serial Messenger Test \n");
  message.attach(messageCompleted);
 
  servo1.attach(7);


}

void loop() {
  // The following line is the most effective way of
  // feeding the serial data to Messenger
  while ( Serial.available( ) ) message.process(Serial.read( ) );


}

How to send and receive strings between Arduino and PC

Use the Messeger library:


http://www.arduino.cc/playground/Code/Messenger

Allows for whole strings which can then be cut up for values etc

Ubuntu on BB

Much better to use icewm or jvm on Ubuntu 10.10.

With 256Mb of RAM you still will have ~50 Mb free for apps