Hi all,
I've seen many posts from people asking how to get data from the serial port and/or get numeric data from the serial port.
The following is some simple code that you can add to your existing HardwareSerial library to provide this functionality:
(add this to the end of HardwareSerial.cpp
)
char *HardwareSerial::readline (const char *prompt)
{
int c, len;
char *buf;
len = 0;
buf = NULL;
this->print (prompt); // print user prompt if any
while (1) { // continuous until end of line
while (! (this->available()));
c = this->read();
buf = (char *) realloc (buf, ((len + 1) * sizeof (char))); // allocate a buffer byte
switch (c) {
case 0x0D:
case 0x0A: { // CR or LF
if (len) { // if there is something in the buffer...
buf[len] = 0; // mark EOL
} else {
free (buf); // empty buffer - return null
buf = NULL;
}
return buf; // return
}
case 0x08:
case 0x7F: { // backspace
if (len > 0) { // if we CAN backspace....
len--; // move pointer back
buf[len] = 0; // invalidate char
this->write ((uint8_t) 0x08); // back up 1
this->write ((uint8_t) 0x20); // blank out char
this->write ((uint8_t) 0x08); // back up again
}
break;
}
default: { // printable characters
if (isprint (c)) {
buf[len] = c; // put char into buffer
len++; // prepare for another char
this->write ((uint8_t) c); // echo char
}
break;
}
}
}
}
long int HardwareSerial::parseInt (const char *arg)
{
size_t n;
size_t len = strlen (arg);
for (n = 0; n < len; n++) {
// allow decimal point
if ((isdigit (arg[n])) || (arg[n] == '.')) {
break;
}
}
if (strncmp ((arg + n), "0x", 2) == 0) {
// parse as hex if it's "0x"
return strtol ((arg + n), NULL, 16);
} else {
// else it must be decimal
return strtol ((arg + n), NULL, 10);
}
}
double HardwareSerial::parseFloat (const char *arg)
{
size_t n;
size_t len = strlen (arg);
for (n = 0; n < len; n++) {
// allow decimal point
if ((isdigit (arg[n])) || (arg[n] == '.')) {
break;
}
}
return strtod ((arg + n), NULL);
}
(add this to HardwareSerial.h
at the bottom of the class definitions [inside the public area])
char *readline (const char *);
long int parseInt (const char *);
double parseFloat (const char *);
Lastly, here's a sketch that shows how it all works:
void setup (void)
{
Serial.begin (115200); // set your baud rate
}
void loop (void)
{
char *buf;
long int i;
double d;
buf = Serial.readline ("\nType something: ");
if (buf) { // must test for non-NULL because blank line returns NULL
Serial.print ("\nYou typed: '");
Serial.print (buf);
Serial.print ("'\n");
i = Serial.parseInt (buf);
d = Serial.parseFloat (buf);
Serial.print ("It's int value is: ");
Serial.print (i);
Serial.print ("\n");
Serial.print ("It's float value is: ");
Serial.print (d);
Serial.print ("\n");
free (buf); // must free buffer after each use (only if not NULL)
}
}
Note that with parseInt, you can prefix the string with "0x" and it will be parsed as HEX.
Typical output of the test sketch:
[b]
Type something: this is a test
You typed: 'this is a test'
It's int value is: 0
It's float value is: 0.00
Type something: .4
You typed: '.4'
It's int value is: 0
It's float value is: 0.40
Type something: 0.45
You typed: '0.45'
It's int value is: 0
It's float value is: 0.45
Type something: 0x1000
You typed: '0x1000'
It's int value is: 4096
It's float value is: 0.00[/b]
Hope this is of some use to you.....