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

Sunday, October 17, 2010

Ubuntu on the BeagleBoard

Ok so we all know that the Ubuntu works well on the Beagleboard.

The latest version 10.10 (Maverick Meerkat) even has an official OMAP3 build:

http://cdimage.ubuntu.com/ubuntu-netbook/ports/releases/10.10/release/

The issue is that this installation is for a full desktop.  The meager resources of the BB chugg to say the least with this version.

Best bet is to struggle through the slow full gnome desktop, drop to a shell with Ctrl-f5, login, then stop gdm:

 sudo /etc/init.d/gdm stop

then install a lighter window manager:

sudo apt-get install xfce4 gdm xubuntu-gdm-theme xubuntu-artwork 

Best Linux OS for eeePC - Puppy Linux

If you have an original 701 eeePC you need a lean mean and tight OS - Puppy Linux's Puppeee is just that.

I put in 2Gig of ram into my 701 which means Puppy (who loads the OS into RAM) flies.  Even with the limitation of the 900 Mhz CPU.

The Kernel is optimised for the CPU too.

Has Chrome with flash 10 installed by default.  You just need to add OpenOffice (LibreOffice) to the base install.

I'm now trying to work out how to get the Arduino IDE running, processing works fine but it packages its own Java...

Stay tuned.

Sunday, March 21, 2010

Arduino code for 38KHz IR signal (LazerTag)

Below will produce the "fire" 38Khz modulated IR signal for interacting with LazerTag guns.  It was written for the Arduino but easily run on a AVR 328/168 straight away.
//PINS
int trigger = 2;  //digital pin 2 but also known as interrupt 0
int IR_RECV = 0;  //Pin to receive TTL received IR pulses on
int IRLED = 7;    //Drives the sending IR LED
int magazine = 0;  //reads if magazine inserted - active low - held high by 26k ohm resistor
int rumble_motor = 0;

int carrier1 = 0;
int carrier2 = 0;


unsigned long time_delay_usec_elapsed =0;
unsigned long time_delay_usec_start = 0;
int temp_flash = 1;  

boolean shot_firing = false;    //used as a bool for telling whether we are currently in the process of firing a shot or not


void setup()
{
  pinMode(13, OUTPUT);
  pinMode(2, INPUT);
  pinMode(IR_RECV, INPUT);
  pinMode(IRLED, OUTPUT);
  pinMode(rumble_motor, OUTPUT);
  pinMode(carrier1, OUTPUT);
  pinMode(carrier2, OUTPUT);
  
  //set up interrupts
//  attachInterrupt(0, fire_shot, FALLING);    //attaches the fire_shot() function to the interrupt 0 which is on pin 2 
//  attachInterrupt(1, receive_shot, FALLING);  //detects signal from photo diodes on PIN 3

  //initialise pins
  digitalWrite(IRLED, LOW);
  digitalWrite(13, HIGH);
  digitalWrite(rumble_motor, 0);

//Setup 38Khz carrier wave
  pinMode(3, INPUT);  //Don't need it
  pinMode(11, OUTPUT);
//Normal mode
  TCCR2A = 0x00;
  bitWrite(TCCR2A, COM2A0, 1);
  bitWrite(TCCR2A, COM2B1, 1);
  bitWrite(TCCR2A, WGM21, 1);
  bitWrite(TCCR2A, WGM20, 1);

  TCCR2B = 0x00;
  bitWrite(TCCR2B, WGM22, 1);
  bitWrite(TCCR2B, CS20, 1);  

  OCR2A = 209;
  OCR2B = 128;  //Doesn't matter

  

 
 


// analogWrite(rumble_motor, 128); 
 
}

void loop()
{

 pinMode(11, INPUT);
 digitalWrite(11, HIGH);
 
 if(digitalRead(2) == LOW) //trigger pulled
 {
 
      //NEW APPROACH - turn off interrupts and send FIRING signals direct
      
      noInterrupts();
 
 
      //on 3ms
      pinMode(11, OUTPUT);
   
      bitWrite(TCCR2B, CS20, 1);
      delayMicroseconds(3000);

      //off 6ms
      pinMode(11, INPUT);
      digitalWrite(11, HIGH);
      delayMicroseconds(6000);

      //on 3ms
      pinMode(11, OUTPUT);
      delayMicroseconds(3000);
//1 
      //off 2ms
      pinMode(11, INPUT);      
      digitalWrite(11, HIGH);
      delayMicroseconds(2000);
            
      //on 1ms
      pinMode(11, OUTPUT);
      delayMicroseconds(1000);
//2      
      //off 2ms
      pinMode(11, INPUT);      
      digitalWrite(11, HIGH);
      delayMicroseconds(2000);
            
      //on 1ms
      pinMode(11, OUTPUT);
      delayMicroseconds(1000);

//3      
      //off 2ms
      pinMode(11, INPUT);      
      digitalWrite(11, HIGH);
      delayMicroseconds(2000);
            
      //on 1ms
      pinMode(11, OUTPUT);
      delayMicroseconds(1000);
//4      
      //off 2ms
      pinMode(11, INPUT);      
      digitalWrite(11, HIGH);
      delayMicroseconds(2000);
            
      //on 1ms
      pinMode(11, OUTPUT);
      delayMicroseconds(1000);
//5      
      //off 2ms
      pinMode(11, INPUT);      
      digitalWrite(11, HIGH);
      delayMicroseconds(2000);
            
      //on 1ms
      pinMode(11, OUTPUT);
      delayMicroseconds(1000);
//6      
      //off 2ms
      pinMode(11, INPUT);      
      digitalWrite(11, HIGH);
      delayMicroseconds(2000);
            
      //on 1ms
      pinMode(11, OUTPUT);
      delayMicroseconds(1000);
//7      
      //off 2ms
      pinMode(11, INPUT);      
      digitalWrite(11, HIGH);
      delayMicroseconds(2000);
            
      //on 1ms
      pinMode(11, OUTPUT);
      delayMicroseconds(1000);

      
      pinMode(11, INPUT);
      digitalWrite(11, HIGH);
        
      interrupts();
      delay(500);
    
      
 }
 

    
 





}

Monday, February 22, 2010

Accurate Arduino timing code

Code below will accurate blink an led on 13 at Hertz, accurate to 1 microsecond (+ for Xtal drift)

digitalWrite(13,temp_flash);
   
  time_delay_usec_elapsed = micros() - time_delay_usec_start;
  if(time_delay_usec_elapsed > 1000000)
  {
    Serial.write("Got here/n");
      time_delay_usec_start = micros();
     
      if(temp_flash == 1)
      {
        digitalWrite(13,0);
        temp_flash = 0;
      }
      else
      {
          digitalWrite(13,1);
          temp_flash = 1;
      }
     
  }
Save Now