Go Down

Topic: Help for Seral.read() (Read 859 times) previous topic - next topic

stunito0o0

Jun 01, 2012, 04:04 pm Last Edit: Jun 01, 2012, 05:13 pm by stunito0o0 Reason: 1
Hi gyus,
I have a little problem with my code.I found out that when you  send somethng to   "Serial.read () ;" it receives  number's position in ASCII table.For example if i send 1 it receives 49.Do you now  I can make it to receive the number  I send, not its ASCII position?Here is my code:
Code: [Select]
int escPin = 2;
int myAngle;
int pulseWidth;
int keyboardValue=0;
int incomingByte=0;
void setup ()
{
Serial.begin(9600);
pinMode (escPin, OUTPUT);
}
void servoPulse (int escPin, int myAngle)
{
pulseWidth = (myAngle * 10) + 600;
digitalWrite (escPin, HIGH);
delayMicroseconds (pulseWidth);
digitalWrite (escPin, LOW);
}
void loop ()
{
if (Serial.available() > 0) {
               incomingByte = Serial.read();
                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);

}

keyboardValue=incomingByte+70;
for (myAngle = keyboardValue; myAngle <= keyboardValue; myAngle++)
{
servoPulse (escPin, myAngle);
delay (20);
}
}

PS.Sorry for my bad english hope you understand my question. :):)

Grumpy_Mike

Quote
I can make it to receive the number  I send,

Is it a single digit number or a multi digit number?

For a single digit number you can use this function
Code: [Select]

int convertFromHex(int ascii){
  if(ascii > 0x39) ascii -= 7; // adjust for hex letters upper or lower case
  return(ascii & 0xf);
}

call it with the value read from Serial.read and it returns the key as a number. Note this will not only work for decimal numbers but for hex values sent as upper case or lower case.

stunito0o0


Is it a single digit number or a multi digit number?

For a single digit number you can use this function
Code: [Select]

int convertFromHex(int ascii){
 if(ascii > 0x39) ascii -= 7; // adjust for hex letters upper or lower case
 return(ascii & 0xf);
}

call it with the value read from Serial.read and it returns the key as a number. Note this will not only work for decimal numbers but for hex values sent as upper case or lower case.



It wil be from 0 to 100 .O I am sorry ,but can u fix my code i'm bad with english and cant understand you fully.Thx in advance :)

James C4S

It is a bad idea to use incomingByte in the way you did, because it gets used whether it has been updated or not.  Seems like everything should be within the if-statement.
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

stunito0o0


It is a bad idea to use incomingByte in the way you did, because it gets used whether it has been updated or not.  Seems like everything should be within the if-statement.

I'm not sure i uderstand you write,but i need it to be that way because i need to spin the motor without stopping,+ that when incomingbyte is 0 the esc is in neutral possition.But thx for the anser i will have it in mind next time. :):)

James C4S


I'm not sure i uderstand you write,but i need it to be that way because i need to spin the motor without stopping,+ that when incomingbyte is 0 the esc is in neutral possition.But thx for the anser i will have it in mind next time. :):)


Quote
Code: [Select]
if (Serial.available() > 0) {
               incomingByte = Serial.read();
                Serial.print("I received: ");
                Serial.println(incomingByte, DEC);

}
keyboardValue=incomingByte+70;

keyboardvalue will be changed whether there was a new character from serial or not.
Capacitor Expert By Day, Enginerd by night.  ||  Personal Blog: www.baldengineer.com  || Electronics Tutorials for Beginners:  www.addohms.com

stunito0o0

Oh I think I understand you this time.You mean that it has to be someting like this :
Code: [Select]

if (incomingByte!=0)
{
keyboardValue=incomingByte+70;
for (myAngle = keyboardValue; myAngle <= keyboardValue; myAngle++)
{
servoPulse (servoPin, myAngle);
delay (20);
}
}

AWOL

Code: [Select]
for (myAngle = keyboardValue; myAngle <= keyboardValue; myAngle++)
Why?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

stunito0o0


Code: [Select]
for (myAngle = keyboardValue; myAngle <= keyboardValue; myAngle++)
Why?

Actualy I am not sure too.When i started to test it  the motor was spining for a second then stops then spin again.It was setted like this
Code: [Select]
for (myAngle = 10; myAngle <= 170; myAngle++)
and i found out that when i make them eaven 
Code: [Select]
for (myAngle = 170; myAngle <= 170; myAngle++)
it the motor spins without stopping.The speed is controled by changing the numbers from 70 to 170.The only problem i have is that i cant  make  the serial function to reseave what i send not the ASCII table.
I am not sure you understand me :D

michael_x

Quote
For example if i send 1 it receives 49.Do you know how I can make it to receive the number I send, not its ASCII position?

I think one main problem is your idea about ascii / binary and serial transmission.

If you use Serial Monitor , enter a "1" and press Send, the text being sent to Arduino consists of that character '1' which shows up as a decimal number 49. Similarly, cou could send an 'A' and would receive a 65.

You might have different code on the sending side, directly sending a single byte with a value of 0 to 100, but that's not Serial Monitor.
Rather make it to interpret the characters you send: "100"  are 3 ascii characters, plus hopefully a newline character that indicates the end of the number.

See Nick Gammon's hints on dealing with Serial input ( He prefers visible markers to indicate start and end of numbers like "<100>"  )

Quote
Oh I think I understand you this time.You mean that it has to be someting like this :
  if (incomingByte!=0)

You're on the way. Unfortunately, incomingByte is not 0 any more after you received anything. You might set it to 0 whenever your loop restarts, or in an else { } banch of if( Serial.available() )

Arrch

#10
Jun 01, 2012, 05:13 pm Last Edit: Jun 01, 2012, 05:44 pm by Arrch Reason: 1
The only problem i have is that i cant  make  the serial function to reseave what i send not the ASCII table.

You have a couple options. Since you're not sure exactly how many digits the user is going to send, the most common is to use a start and/or stop byte. Everything between is processed as part of the number. Simple example:

Code: [Select]
const char STOP_BYTE = '\n'; // In the serial monitor, you will need to select the appropriate drop down to append the newline char
char buffer[20]; // stores the characters to be converted to an int
...
void loop() {
 static byte i=0;
 if (Serial.available() > 0) {
   char inByte = Serial.read();
   if (inByte==STOP_BYTE) { // We've received the end of our input
     buffer[i] = '\0'; // null terminate the string
     int data = atoi(buffer);
     // Do something with the data int
     i=0; // reset the index
   } else {
     buffer[i++] = inByte; // add character to buffer and increment index
   }
 }
}


What this does is stores every character received into a char array. When it received the newline character it null terminates the array (making it a string) and calls the atoi function which converts a string to an int. You then do what you want with the int and reset the index. The important thing to note is that you need to send a newline after you're done inputting the number. If using the Arduino serial monitor, change the appropriate drop down in the bottom right.

stunito0o0

Hey again guys I hope i am not too cheeky,but can u help a little bit more i am not sure what i do wrong.
Code: [Select]
int escPin = 2;
int myAngle;
int pulseWidth;
int keyboardValue=0;
int incomingByte=0;
const char STOP_BYTE = '\n'; // In the serial monitor, you will need to select the appropriate drop down to append the newline char
char buffer[20]; // stores the characters to be converted to an int
void setup ()
{
Serial.begin(9600);
pinMode (escPin, OUTPUT);
}
void servoPulse (int escPin, int myAngle)
{
pulseWidth = (myAngle * 10) + 600;
digitalWrite (escPin, HIGH);
delayMicroseconds (pulseWidth);
digitalWrite (escPin, LOW);
}

void loop() {
  static byte i=0;
  if (Serial.available() > 0)
  {
    char inByte = Serial.read();
    if (inByte=='\n') // We've received the end of our input
    {
      buffer[i] = '\0'; // null terminate the string
      int data = atoi(buffer);
      // Do something with the data int
      i=0; // reset the index
    }
    else {
      buffer[i++] = inByte; // add character to buffer and increment index
    }
  }
}
keyboardValue=data+70;
for (myAngle = keyboardValue; myAngle <= keyboardValue; myAngle++)
{
servoPulse (escPin, myAngle);
delay (20);
}
}

errors:
1 expected constructor,destructor,or type of conversion before '='token
2 expected unqualified-id befor 'for'
3 expected constructor,destructor,or type of conversion  before '<=' token
4 expected constructor,destructor,or type of conversion  before '++' token
5 expected declaration before '}' token
Thx in advance. :)

Arrch


Hey again guys I hope i am not too cheeky,but can u help a little bit more i am not sure what i do wrong.

Too many/too little curly braces. This is where proper formatting helps a great deal. Do yourself a favor and use the auto format tool in the Arduino IDE (Tools > Auto Format) and it should be more apparent.

dxw00d

Unfortunately, Auto-format just tells you that there are too many close braces.

I think this one is superfluous:
Code: [Select]
}
keyboardValue=data+70;


You are then left with data being out of scope on that line.

stunito0o0

i fixed it  :smiley-roll-sweat:
Code: [Select]
int escPin = 2;
int myAngle;
int pulseWidth;
int keyboardValue=0;
int incomingByte=0;
const char STOP_BYTE = '\n'; // In the serial monitor, you will need to select the appropriate drop down to append the newline char
char buffer[20]; // stores the characters to be converted to an int
void setup ()
{
Serial.begin(9600);
pinMode (escPin, OUTPUT);
}
void servoPulse (int escPin, int myAngle)
{
pulseWidth = (myAngle * 10) + 600;
digitalWrite (escPin, HIGH);
delayMicroseconds (pulseWidth);
digitalWrite (escPin, LOW);
}

void loop() {
 static byte i=0;
 if (Serial.available() > 0)
 {
   char inByte = Serial.read();
   if (inByte=='\n') // We've received the end of our input
   {
     buffer[i] = '\0'; // null terminate the string
     int data = atoi(buffer);
     // Do something with the data int
     i=0; // reset the index
      keyboardValue=data+70;
     
for (myAngle = keyboardValue; myAngle <= keyboardValue; myAngle++)
{
servoPulse (escPin, myAngle);
delay (20);
}
   }
   else {
     buffer[i++] = inByte; // add character to buffer and increment index
   }
 }
}

but the esc doesnt even arm  :( what am i doing wrong now

Go Up