So in serial monitor to test this...I'm sending <123,321>
The output from example 6 of that tutorial shows: "This just in (HEX values)... 31 32 33 2C 33 32 31"
But can you please assist with the code to split the numbers either side of the 2c?
I want to end up with integers used for the motor of 123 and 321 from sending the above.
I haven't included the code tags as the code is available on that tutorial, but can if needed.
Thank you so much in advance and apologies if this is covered somewhere...I did a lot of googling before turning her for help.
of course you can read a sequence of characters into a string array up to a line terminator and use something like strtok() to split the string into tokens based on commas.
i usually include the following code in all my projects. it supports single letter commands that can be preceded by a multi-digit value.
// pcRead - debugging using serial monitor
const char version [] = "PcRead 200416a";
int debug = 0;
// ---------------------------------------------------------
// toggle output bit
void
pinToggle (
int pin)
{
static int bits = 0;
int bit = 1 << pin;
if (debug) {
Serial.print ("pinToggle: ");
Serial.println (pin);
}
if (bits & bit) {
digitalWrite (pin, LOW);
bits &= ~bit;
}
else {
digitalWrite (pin, HIGH);
bits |= bit;
}
}
// ---------------------------------------------------------
// toggle output bit
int
readString (
char *s,
int maxChar )
{
int n = 0;
Serial.print ("> ");
do {
if (Serial.available()) {
int c = Serial.read ();
if ('\n' == c)
break;
s [n++] = c;
if (maxChar == n)
break;
}
} while (true);
return n;
}
// -----------------------------------------------------------------------------
// process single character commands from the PC
#define MAX_CHAR 10
char s [MAX_CHAR] = {};
int analogPin = 0;
void
pcRead (void)
{
static int val = 13;
if (Serial.available()) {
int c = Serial.read ();
switch (c) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
val = c - '0' + (10 * val);
break;
case 'A':
analogPin = val;
Serial.print ("analogPin = ");
Serial.println (val);
val = 0;
break;
case 'D':
debug ^= 1;
break;
case 'I':
pinMode (val, INPUT);
Serial.print ("pinMode ");
Serial.print (val);
Serial.println (" INPUT");
val = 0;
break;
case 'O':
pinMode (val, OUTPUT);
Serial.print ("pinMode ");
Serial.print (val);
Serial.println (" OUTPUT");
val = 0;
break;
case 'P':
pinMode (val, INPUT_PULLUP);
Serial.print ("pinMode ");
Serial.print (val);
Serial.println (" INPUT_PULLUP");
val = 0;
break;
case 'a':
Serial.print ("analogRead: ");
Serial.println (analogRead (val));
val = 0;
break;
case 'c':
digitalWrite (val, LOW);
Serial.print ("digitalWrite: LOW ");
Serial.println (val);
val = 0;
break;
case 'p':
#if !defined(ARDUINO_ARCH_ESP32)
analogWrite (analogPin, val);
Serial.print ("analogWrite: pin ");
Serial.print (analogPin);
Serial.print (", ");
Serial.println (val);
val = 0;
#endif
break;
case 'r':
Serial.print ("digitalRead: pin ");
Serial.print (val);
Serial.print (", ");
Serial.println (digitalRead (val));
val = 0;
break;
case 's':
digitalWrite (val, HIGH);
Serial.print ("digitalWrite: HIGH ");
Serial.println (val);
val = 0;
break;
case 't':
Serial.print ("pinToggle ");
Serial.println (val);
pinToggle (val);
val = 0;
break;
case 'v':
Serial.print ("\nversion: ");
Serial.println (version);
break;
case '\n': // ignore
break;
case '"':
while ('\n' != Serial.read ()) // discard linefeed
;
readString (s, MAX_CHAR-1);
Serial.println (s);
break;
case '?':
Serial.println ("\npcRead:\n");
Serial.println (" [0-9] append to #");
Serial.println (" A # - set analog pin #");
Serial.println (" D # - set debug to #");
Serial.println (" I # - set pin # to INPUT");
Serial.println (" O # - set pin # to OUTPUT");
Serial.println (" P # - set pin # to INPUT_PULLUP");
Serial.println (" a # - analogRead (pin #)");
Serial.println (" c # - digitalWrite (pin #, LOW)");
Serial.println (" p # -- analogWrite (analogPin, #)");
Serial.println (" r # - digitalRead (pin #)");
Serial.println (" s - digitalWrite (pin #, HIGH)");
Serial.println (" t -- toggle pin # output");
Serial.println (" v - print version");
Serial.println (" \" - read string");
Serial.println (" ? - list of commands");
break;
default:
Serial.print ("unknown char ");
Serial.println (c,HEX);
break;
}
}
}
// -----------------------------------------------------------------------------
void
loop (void)
{
pcRead ();
}
// -----------------------------------------------------------------------------
void
setup (void)
{
Serial.begin(115200);
Serial.println (version);
#if defined(ARDUINO_ARCH_ESP32)
Serial.println ("esp32");
#endif
}
Message: s - X: 122 - Y: 134
Message: s - X: 1 - Y: 0
Message: s - X: 122 - Y: 14
Message: s - X: 122 - Y: 13122
Message: s - X: 4 - Y: 3434
Message: s - X: 122 - Y: 134
So it looks like a lot of information is not being parsed correctly.
The code I was using for this was....
void recvWithStartEndMarkers() {
static boolean recvInProgress = false;
static byte ndx = 0;
char startMarker = '<';
char endMarker = '>';
char rc;
while (BTserial.available() > 0 && newData == false) {
rc = BTserial.read();
if (recvInProgress == true) {
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
recvInProgress = false;
ndx = 0;
newData = true;
}
}
else if (rc == startMarker) {
recvInProgress = true;
}
}
}
//============
void parseData() { // split the data into its parts
char * strtokIndx; // this is used by strtok() as an index
strtokIndx = strtok(tempChars,","); // get the first part - the string
strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
X = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ",");
Y = atoi(strtokIndx); // convert this part to an integer
}
//============
void showParsedData() {
Serial.print("Message: ");Serial.print(messageFromPC);Serial.print(" - ");Serial.print("X: ");Serial.print(X);Serial.print(" - ");Serial.print("Y: ");Serial.println(Y);
}
But with the garbled receiving data I thought switching to Binary (as per example 6) might be the way forward.... Any help much appreciated.
Added a delay(10) and the garbled message is now not garbled.
I'm still interested in how to split the Binary code as per my original question, though.
Or should I send the motor values (which are from 0-255) as one byte?
Added a delay(10) and the garbled message is now not garbled.
Please post your program. There should be no need for a delay()
I'm still interested in how to split the Binary code as per my original question, though.
As far as I can see you never posted the program in which you tried that. However I suspect your problem is that you are thinking that <123,321> is transmitted as two binary numbers. In fact it is transmitted as 9 characters and my Example 6 does not apply.
Unless it necessary for performance it makes debugging much easier if you send numbers as human-readable text.
atoi() or sscanf() will convert your cString (ascii text) « 123 » to the number 123
If you shoot the data over Bluetooth don’t use a shotgun approach to send the data as fast as possible because you’ll saturate your serial port and if you are using software serial it can behave weirdly esp if you are above 9600 bauds. I assume the delay mentionner was to only send the data 100 times per second ? (That’s still a lot probably at 9600 bauds - will saturate the buffer and create pauses)
stevehaze666:
....but my main question was ...is it possible to combine said bytes to form that numbers I'm trying to received.
So can we make the 3 bytes of 1, 2 and 3 make the number 123?
That is the whole purpose of Example 5 in my Tutorial.
And you have your terminology mixed up. You are not sending 3 bytes with the values 1, 2 and 3. You are sending 3 characters. The actual byte values will be 48, 49 and 50 which are the ASCII codes for the characters. And the C++ function atoi() is short for Ascii TOInt