Go Down

Topic: Serial.read() help (Read 14 times) previous topic - next topic

thefatmoop

#10
Jan 14, 2009, 12:45 am Last Edit: Jan 14, 2009, 12:47 am by thefatmoop Reason: 1
I've been manipulating and rewriting both programs to no avail. In the first program i used i just don't understand why the serial read is "232230", but after atoi it's some oddball negative number.

I tried using this program
Code: [Select]
#include <stdlib.h>    
char X_buffer[3];
char Y_buffer[3];
int received;
int i=0;
int X_pos=0;
int Y_pos=0;

void setup()
{
   Serial.begin(57600);
   received = 0;
   X_buffer[received] = '\0';
   Y_buffer[received] = '\0';
   Serial.println("setup");
}
void loop()
{
   if (Serial.available())
   {
     // Get x cord
       for(i=0; i<3; i++)
         {
         X_buffer[i] = Serial.read();
         }
       // Get y cord
       for(i=0; i<3; i++)
         {
         Y_buffer[i] = Serial.read();
         }
     X_pos = atoi(X_buffer);
     Y_pos = atoi(Y_buffer);



 Serial.print("x:");
 Serial.print(X_pos);
 Serial.print("y:");
 Serial.print(Y_pos);
 Serial.println();

}
}


with output
Code: [Select]
setup

x:2y:0

x:32230y:30

x:2y:0

x:-32306y:30

x:2y:0

x:32230y:30

x:2y:0

x:32230y:30

correct output should have been "232230"


i'm sending the data by:
Code: [Select]
   Serial.print((int)chuck.readJoyX()*-1+100); //make is positive and always 3 digits long
  // Serial.print(",jy ");  
   Serial.print((int)chuck.readJoyY()*-1+100); //make is positive and always 3 digits long

i've tried taking out the (int) makes no difference. I'm sending it as integer ascii?

here's the original program output
Code: [Select]
setup

*232230*-29914*

*233230*-28914*

*232230*-29914*

*232230*-29914*


it's getting the right 232230... after atoi it's unusable

thefatmoop

#11
Jan 14, 2009, 03:10 am Last Edit: Jan 14, 2009, 03:11 am by thefatmoop Reason: 1
If anyone is having the same problems, or wondering if the noob will ever shutup: I found a very good example program from http://rob.faludi.com/itp/clock_decode_with_debug.pde
Here 'rob' is decoding a serial message the same way i wanted to
Code: [Select]
// this program decodes a clock string sent via XBee radio
// the end result is six integer variables that hold the current year, month, day, hour, minute and second
//
// the time string is in the following format:
// *20061003143227
// where the year is 2006, month is October, day is the 3rd, hour is 14 (2 p.m.), minute is 32 and second is 27
//
// by Rob Faludi
// http://www.faludi.com

////// DEBUG OUTPUT IS HANDY, BUT NOT NECESSARY FOR CLOCK DECODING ///////
#include <SoftwareSerial.h>
int rx=6, tx=7; // pins 6 and 7 will have a debug output
SoftwareSerial softSerial(rx, tx); // creates SoftwareSerial on pins 6 and 7
///////////////////////////////////////////////////////////////


int ledPin = 13;
int year;
byte month, day, hour, minute, second;

void setup() {
 pinMode(ledPin, OUTPUT);
 pinMode (rx,INPUT);
 pinMode (tx,OUTPUT);
 // start up the serial connection with 9600-8-n-1-true (non-inverted):
 Serial.begin(9600); // start hardware serial process
 softSerial.begin(9600); // start software serial process
 // blink the status LED
 blinkLED(ledPin, 2, 200);

 softSerial.println();  // do a linefeed on the debug port
 delay(500);
 softSerial.println("starting..."); // show startup on the debug port
 setupXBee();
}


void loop() {
 Serial.flush(); // clear the serial buffer before reading new data
 char timeString[15]; // create a string to hold the time value when it's read
 memset(timeString,'\0',15); // initialize that string to all NULL characters
 boolean timeStringValid = false; // declare and initialize a variable to track whether the string has all valid characters
 Serial.print("GET");
 byte inByte = '\0'; // declare and initialize a byte to read in serial data
 long startTime = millis();//makes the start time = to now
 int timeout = 1000; // timeout after one second
 while(millis() - startTime < timeout && inByte != '*') {
   inByte = Serial.read(); // read data and wait for an asterisk character
 }

 if (inByte == '*') { // if we got the correct start character (instead of a timeout)
   timeStringValid = true; // declare and initialize a variable to track whether the string has all valid characters
   long startTime = millis();//makes the start time = to now
   int timeout = 1000; // timeout after one second
   while(millis() - startTime < timeout && Serial.available() < 14) {
     ; //wait for enough data to be available (14 characters of time string), while doing nothing else
   }
   for (int i=0; i < 14; i++) {
     timeString[i] = Serial.read(); // reach each time string character into a character array
     if(timeString[i] < '0' || timeString[i] > '9') {
       timeStringValid = false;  // if any character is bad then the whole string is bad
     }
   }
   softSerial.print("Time: ");
   softSerial.println(timeString);
 }

 if (timeStringValid == true) {
   char yearString[5];  // create a string to hold the year part of the string
   memset(yearString,'\0',5); // initialize that string to all NULL characters
   strncpy( yearString, timeString, 4); // copy the first four characters of timeString into the year string
   year = atoi(yearString); // convert ASCII year string to integer and store in the year integer variable
   softSerial.print("Year: ");
   softSerial.println(year, DEC);

   char monthString[3]; // create a string to hold the month part of the string
   memset(monthString,'\0',3); // initialize that string to all NULL characters
   strncpy( monthString, timeString+4, 2); // skip four characters, then copy the next two of timeString into the month string
   month = atoi(monthString);  // convert ASCII month string to integer and store in the month integer variable
   softSerial.print("Month: ");
   softSerial.println(month, DEC);

   char dayString[3];
   memset(dayString,'\0',3);
   strncpy( dayString, timeString+6, 2);
   day = atoi(dayString);
   softSerial.print("Day: ");
   softSerial.println(day, DEC);

   char hourString[3];
   memset(hourString,'\0',3);
   strncpy( hourString, timeString+8, 2);
   hour = atoi(hourString);
   softSerial.print("Hour: ");
   softSerial.println(hour, DEC);

   char minuteString[3];
   memset(minuteString,'\0',3);
   strncpy( minuteString, timeString+10, 2);
   minute = atoi(minuteString);
   softSerial.print("Minute: ");
   softSerial.println(minute, DEC);

   char secondString[3];
   memset(secondString,'\0',3);
   strncpy( secondString, timeString+12, 2);
   second = atoi(secondString);
   softSerial.print("Second: ");
   softSerial.println(second, DEC);
 }

 softSerial.println(""); // print a blank line

 delay(1000); // wait for a moment so that output is readable
}



void setupXBee() {
 boolean success = false;
 int ctr = 0;
 while (success == false && ctr < 6) {
   // an arbitrary byte to wake up the XBee
   Serial.print("X");
   delay(1100);
   // put the XBee in command mode
   Serial.print("+++");
   delay(1100);
   Serial.flush(); // clear the serial buffer before sending and reading new data
   // set the PAN (personal area network) ID number
   Serial.print("ATIDC,");
   // set the MY (16 bit address)
   Serial.print("MY1,");
   // set the Destination High to 0x0
   Serial.print("DH0,");
   // set the Destination Low (16 bit address)
   Serial.print("DL0,");
   // exit command mode (note that we use Serial.printLN here to issue a linefeed that completes the command sequence)
   Serial.println("CN");

   if (checkFor("OK", 1000)) {
     // if an OK was received then continue
     //     debugPrintln("setup done");
     softSerial.println("setup done");
     success = true;
   }
   else {
     //     debugPrintln("setup failed");
     softSerial.println("setup failed");
     success = false;
   }
   ctr++;
 }
}




///////////////////////////////// UTILITY FUNCTIONS //////////////////////////////////////////
// this function checks for a specific response on the serial port
// it accepts a string to look for and a timeout in milliseconds
int checkFor(char* desiredResponse, int timeout) {
 int result = 0;
 int length = 40;
 char incomingResponse[41];
 memset(incomingResponse,0,length); // initialize all incomingResponse string positions to null
 char inByte = NULL;
 long startTime = millis();//makes the start time = to now
 char* ptr_incomingResponse = incomingResponse;
 // while we haven't timed out or gotten back the string that we are looking for
 while (millis() - startTime < timeout && strstr(incomingResponse,desiredResponse) == NULL ) { //strstr compares strings
   if (Serial.available() > 0) { // if there are any bytes waiting to be read
     inByte = Serial.read();  // read one byte
     if (incomingResponse > ptr_incomingResponse-length) { // if we haven't read in 80 characters yet
       *ptr_incomingResponse = inByte;  // put the byte into the current position in the string
       ptr_incomingResponse++;  // advance to the next position in the string
     }
     else {
       //move the last char to be next to last, and so forth until we reach the end of the array.
       for (int i = 0; i < length; i++) {
         incomingResponse[i] = incomingResponse[i+1];  
       }
       incomingResponse[length-1] = inByte;  // put the byte into the current position in the string
     }
   }
 }
 softSerial.println(incomingResponse);
 if (strstr(incomingResponse,desiredResponse) != NULL ) { // if the desired string is found
   result = 1;
 }
 else {
   result = 0;
 }
 return result;
}



// this function blinks the an LED light as many times as requested
void blinkLED(int targetPin, int numBlinks, int blinkRate) {
 for (int i=0; i<numBlinks; i++) {
   digitalWrite(targetPin, HIGH);   // sets the LED on
   delay(blinkRate);                     // waits for a blinkRate milliseconds
   digitalWrite(targetPin, LOW);    // sets the LED off
   delay(blinkRate);
 }
}


thank you rob for the excessive commenting

mikalhart

#12
Jan 14, 2009, 03:37 am Last Edit: Jan 14, 2009, 06:41 am by mikalhart Reason: 1
thefatmoop--

The reason that atoi is returning such unexpected numbers for you is that it returns an int, which in Arduino-land is 16-bits and limited to a maximum value of 32767.  If you use atol, which uses long instead, that may improve things.

Mikal

thefatmoop

thanks that does make sense and adds clarity

kg4wsv

Mikal, I think you meant -32768 to 32767 for an int (or 0 - 65535 for an unsigned int).

-j


Go Up