Check out the new project site for Light Attack (IR Paintball) http://www.project.lightattack.com.au

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;
}

No comments: