Pages: [1] 2   Go Down
Author Topic: Serial.read() help  (Read 13809 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 415
MEGA_Stick_II is here
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

SouthEast UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 65
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 415
MEGA_Stick_II is here
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

SouthEast UK
Offline Offline
Jr. Member
**
Karma: 0
Posts: 65
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 415
MEGA_Stick_II is here
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Never mind, it is included.
Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

yeah i'm working with a similar program.... sending values to another arduino and setting pwm accordingly

Code:
#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:
#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:
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?

« Last Edit: January 12, 2009, 09:50:00 pm by thefatmoop » Logged

0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 415
MEGA_Stick_II is here
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It compiles,

The issue is this line here,
Code:
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.
« Last Edit: January 12, 2009, 10:41:30 pm by Jassper » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

that's good because i read it and thought "what is that???
i'll try again and see what happens
« Last Edit: January 13, 2009, 12:51:08 am by thefatmoop » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

could i get a pointer in the right direction?
i'm trying to send variables in one long serial message:
Code:
#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:
#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;
  }
 }
}
Logged

0
Offline Offline
Sr. Member
****
Karma: 1
Posts: 415
MEGA_Stick_II is here
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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;

  }
 }*/
}
« Last Edit: January 13, 2009, 06:43:59 am by Jassper » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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:
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:
   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:
setup

*232230*-29914*

*233230*-28914*

*232230*-29914*

*232230*-29914*

it's getting the right 232230... after atoi it's unusable
« Last Edit: January 13, 2009, 06:47:47 pm by thefatmoop » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
// 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
« Last Edit: January 13, 2009, 09:11:56 pm by thefatmoop » Logged

Austin, TX USA
Offline Offline
God Member
*****
Karma: 5
Posts: 997
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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
« Last Edit: January 14, 2009, 12:41:09 am by mikalhart » Logged

0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 82
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

thanks that does make sense and adds clarity
Logged

0
Offline Offline
Faraday Member
**
Karma: 8
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

-j

Logged

Pages: [1] 2   Go Up
Jump to: