Read in string from serial and parse in C
cosmosfood
Posts: 2
in Propeller 1
BLUF: Arduino is sending in values of 9 potentiometers over serial to prop. I need to parse them and do math against the values. All in C, no SPIN.
Really have no idea where's left to go on this one.. I have an arduino program printing as ASCII potentiometer values from its serial port to the prop. The values vary from 0 to 299 and the output format is: 0,5,89,4,54,202,3,25,180
On the prop side, I've gotten it to see that values are coming in but I can't parse them, or read them as whole numbers (89 comes in as two separate characters). This is all the more infuriating since I've gotten it to work with C# code in Unity, but the prop is a non starter.
I really don't have the time to learn SPIN to make this all work, and really feel it can be done in C, I'm just at the end of my rope.. Any suggestions?
ARDUINO CODE
PROP CODE
Really have no idea where's left to go on this one.. I have an arduino program printing as ASCII potentiometer values from its serial port to the prop. The values vary from 0 to 299 and the output format is: 0,5,89,4,54,202,3,25,180
On the prop side, I've gotten it to see that values are coming in but I can't parse them, or read them as whole numbers (89 comes in as two separate characters). This is all the more infuriating since I've gotten it to work with C# code in Unity, but the prop is a non starter.
I really don't have the time to learn SPIN to make this all work, and really feel it can be done in C, I'm just at the end of my rope.. Any suggestions?
ARDUINO CODE
void loop()
{
//Read analog inputs on IO1
pots[0] = map(muxShield.analogReadMS(1,0), 0, 1023, 0, 300); //IO1, pin 0
pots[1] = map(muxShield.analogReadMS(1,1), 0, 1023, 0, 300); //IO1, pin 1
pots[2] = map(muxShield.analogReadMS(1,2), 0, 1023, 0, 300); //IO1, pin 2
pots[3] = map(muxShield.analogReadMS(1,3), 0, 1023, 0, 300); //IO1, pin 3
pots[4] = map(muxShield.analogReadMS(1,4), 0, 1023, 0, 300); //IO1, pin 4
pots[5] = map(muxShield.analogReadMS(1,5), 0, 1023, 0, 300); //IO1, pin 5
pots[6] = map(muxShield.analogReadMS(1,6), 0, 1023, 0, 300); //IO1, pin 6
pots[7] = map(muxShield.analogReadMS(1,7), 0, 1023, 0, 300); //IO1, pin 7
pots[8] = map(muxShield.analogReadMS(1,8), 0, 1023, 0, 300); //IO1, pin 8
//Print the results
Serial.print(pots[0]); Serial.print(",");
Serial.print(pots[1]); Serial.print(",");
Serial.print(pots[2]); Serial.print(",");
Serial.print(pots[3]); Serial.print(",");
Serial.print(pots[4]); Serial.print(",");
Serial.print(pots[5]); Serial.print(",");
Serial.print(pots[6]); Serial.print(",");
Serial.print(pots[7]); Serial.print(",");
Serial.println(pots[8]);
// Give Unity time to read lines
delay(27);
}
PROP CODE
#include "simpletools.h" // Include simple tools
#include "fdserial.h"
fdserial *unity;
fdserial *disp;
int main()
{
// (RX, TX, 0, Baud)
unity = fdserial_open(1, 0, 0, 57600);
disp = fdserial_open(31,30,0,57600);
char seps[] = (" ,\t\n");
char store[8];
writeChar(disp, CLS);
dprint(disp, "Click this terminal, \n");
dprint(disp, "and type on keyboard...\n\n");
char c;
while(1)
{
c = fdserial_rxChar(unity);
//Cycle through string
for(int i = 0; i <8; i++){
//Test for start of input--- Result: Confirmed good
if(c = "!"){
i = 0;
//dprint(disp,"Start.\n");
}
store = c;
//Test for end of input--- Result: Confirmed good
if(c = "#"){
// Reached the end, so print the results of storage
for(int j = 0; j < 8; j++){
dprint(disp,store[j]);
}
dprint(disp," END\n");
i = 8;
break;
}
}
}
}
Comments
It can be done on the prop in C. The ascii characters the arduino is sending need to be converted to integers or floats, and the result used for the math.
You can try this parser (quickly put together, but tested as working)... i.e. may not be the best 'C' code but provides a working example. You may need to test with real data input...
Note: The C tab on this website's input field provides proper 'code' formatting.
dgately
char *strtok(char *str, const char *delim)
Parameters
str − The contents of this string are modified and broken into smaller strings (tokens).
delim − This is the C string containing the delimiters. These may vary from one call to another.
https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm
You would still need to turn it in to integer.
a while loop maybe x=x*10 +ascII byte -48;
The strtok function cannot be used on constant strings
The identity of the delimiting character is lost
The strtok() function uses a static buffer while parsing, so it's not thread safe
The solution I chose seemed to give a more "insteructable" path for a new C user...
But, if you know what you are doing with strtok, and test for possible problems, by all means, use it!
dgately
It will change the token you looking for to a zero, so the returned pointer will now point to a smaller chunk of text that is zero terminated.
This could work after strtok inserted the zero:
pnt = strtok(NULL, ",");
while (*pnt) x=x*10+*pnt++ -48;
Thus,
should be:
or:
Although, I do agree with Tony regarding the use of strtok if you are looking to add the 'string.h' lib to the code.
However, I would do something like:
// Declare a delimiter
const char s[4] = ",";
Then you could read in the first token as
char* token;
token = strtok(str,s);
if token is not 0, then read in the rest of the string as:
token = strtok(0, s);
You would only need to compare for the "#" to get the end of the input:
int ret;
ret = strcmp(token, "#");
Ex:
fdserial_rxFlush(ble);
Also, I like to check whether or not there is anything in the buffer before reading in the data:
Ex:
fdserial_rxPeek(ble)
This will not remove a character from the buffer like fdserial_rxChar does.
dgately
while (*s++ = *t++); // string copy until zero
me too!
Understood. It's just a matter of style. However, I have to correct myself since 'NULL' typically in C is defined as "((void *)0)" or 0 if '__cplusplus' is defined and is used with pointers. 'NUL' with a single 'L' would be the equivalent to '\0'.
In your example you are looking for the end of a string not the end of the array.
If the array string had something like a '\0' in the middle of the string, the loop would stop before the end of the array. Ex: "This is \0 an array" will produce
"This is ".
To be on the safe side you should get the sizeof of the array and used that to parse through the array.
EX: Although this would give the size of the entire array.
Also, I believe you meant :
Yes, thanks for noticing that!
dgately
If it works with C# then why not just use that to run your code in the Unity Engine?
Apologies if this question is stupid, I am just starting out with Unity and am just a little curious to know about the game engine.
0,5,89,4,54,202,3,25,180
... or like this:
!0,5,89,4,54,202,3,25,180#
The latter, of course, is easier to deal with.
Since I find I can write a Spin program faster than the C compiler can compile anything I bash together in C -- and I've been working on a parser today so that the Propeller can connect to a show-control program called VenueMagic -- I'm submitting a Spin example, anyway. Being a C programmer, you should be able to convert this pretty easily as it doesn't rely on any special libraries or conversion functions. I used RealTerm to test because it allows me to build a string and then send it.
It took two hours and a double-shot of Jameson's whiskey, but I got it to work. I'm sure many of the C gurus will point out my ignorant flaws.