Go Down

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

Jassper

This eludes me so I need some direction.

I am trying to send numerical values to the Arduino, for example the number 123. The Serial.read() receives it as separate ASCII values of 49, 50, and 51.

How do I turn this back into a int value of 123?

wiz

Do a search on this site for 'atoi' , that's  a to (eye) , this question has cropped up before.

Jassper

Thats what I need, but where do I find the lib stdlib.h?

wiz

On a Linux system it is part of the avr-libc package but I don't know about Windows.

Jassper

Never mind, it is included.

thefatmoop

#5
Jan 13, 2009, 03:25 am Last Edit: Jan 13, 2009, 03:50 am by thefatmoop Reason: 1
yeah i'm working with a similar program.... sending values to another arduino and setting pwm accordingly

Code: [Select]
#include <math.h>
#include "Wire.h"
#include "WiiChuck.h"
//#include "nunchuck_funcs.h"

#define MAXANGLE 90
#define MINANGLE -90


WiiChuck chuck = WiiChuck();
int angleStart, currentAngle;
int tillerStart = 0;
double angle;

void setup() {
 //nunchuck_init();
 Serial.begin(1200);
 chuck.begin();
 chuck.update();
 chuck.calibrateJoy();
}


void loop() {
 delay(500);
 chuck.update();

  // Serial.print(",jx ");  
   Serial.print((int)chuck.readJoyX()*-1+100);
  // Serial.print(",jy ");  
   Serial.println((int)chuck.readJoyY()*-1+100);
}


this program simply reads joystick x y on wii nunchuck controller, makes it positive, and adds 100 to each (so that it's always 6 characters long)

example output: 233230

I searched the forum for atoi and found this example program
Code: [Select]
#include <stdlib.h>     // needed for [shighlight]atoi[/shighlight]
char buffer[4];
int received;
int ledPin = 9;
void setup()
{
   Serial.begin(9600);
   received = 0;
   buffer[received] = '\0';
}
void loop()
{
   if (Serial.available())
   {
       buffer[received++] = Serial.read();
       buffer[received] = '\0';
       if (received >= (sizeof(buffer)-1))
       {
           Serial.print(buffer);
int myInt = [shighlight]atoi[/shighlight](buffer);
   analogWrite(ledPin, myInt);
           received = 0;
       }
   }
}   }
}


when i did syntax check i had error:
Code: [Select]
In function 'void loop()':
error: expected primary-expression before '[' token At global scope:
[/color]

i don't have the library #include <stdlib.h>? where would i find this?


Jassper

#6
Jan 13, 2009, 04:40 am Last Edit: Jan 13, 2009, 04:41 am by Jassper Reason: 1
It compiles,

The issue is this line here,
Code: [Select]

int myInt = [shighlight]atoi[/shighlight](buffer);


Note the [ shighlight] and the [ /shighlight] these are inserted into the code block to Highlight the word you are searching for, "atoi", Take that out and get rid of the 2 extra }} at the bottom and it should compile.

The lib should already be there.

thefatmoop

#7
Jan 13, 2009, 06:50 am Last Edit: Jan 13, 2009, 06:51 am by thefatmoop Reason: 1
that's good because i read it and thought "what is that???
i'll try again and see what happens

thefatmoop

could i get a pointer in the right direction?
i'm trying to send variables in one long serial message:
Code: [Select]
#include <math.h>
#include "Wire.h"
#include "WiiChuck.h"
//#include "nunchuck_funcs.h"

#define MAXANGLE 90
#define MINANGLE -90


WiiChuck chuck = WiiChuck();
int angleStart, currentAngle;
int tillerStart = 0;
double angle;

void setup() {
 //nunchuck_init();
 Serial.begin(57600);
 chuck.begin();
 chuck.update();
 chuck.calibrateJoy();
}


void loop() {
 delay(1000);
 chuck.update();


  //Serial.print((int)9);
  // Serial.print(",jx ");  
   Serial.print((int)chuck.readJoyX()*-1+100);
  // Serial.print(",jy ");  
   Serial.println((int)chuck.readJoyY()*-1+100);
}


this sends for example 222232 (222 = joyX, 232=joyY)

how would i isolate the variables and be able to work with them in the program below?

Code: [Select]
#include <stdlib.h>     // needed for [shighlight]atoi[/shighlight]
char buffer[9];
int received;

void setup()
{
   Serial.begin(57600);
   received = 0;
   buffer[received] = '\0';
   Serial.print("setup");
}
void loop()
{
   if (Serial.available())
   {
       buffer[received++] = Serial.read();
       buffer[received] = '\0';
       if (received >= (sizeof(buffer)-1))
       {
     int myInt = atoi(buffer);      
Serial.println(buffer);

Serial.print("1: ");
Serial.println(myInt/10);
Serial.print("2: ");
Serial.println(myInt/100);
Serial.print("3: ");
Serial.println(myInt%10);
Serial.print("4: ");
Serial.println(myInt%100);
received = 0;
 }
}
}

Jassper

#9
Jan 13, 2009, 12:42 pm Last Edit: Jan 13, 2009, 12:43 pm by Jassper Reason: 1
I only know enough to be dangerous, but I'll give it a go.

I assume you mean to send the data "222232" from one to the other?

Maybe something like this
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.print("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.println(buffer);
Serial.print("1: ");
Serial.println(myInt/10);
Serial.print("2: ");
Serial.println(myInt/100);
Serial.print("3: ");
Serial.println(myInt%10);
Serial.print("4: ");
Serial.println(myInt%100);
received = 0;

 }
}*/
}


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