Retrieving substrings of unknown size string

For learning purposes...

Goals:

  1. Control a RGB LED with 3 numbers wrote in Serial Monitor (done);
  2. Use a BT received string in format "?,?,?" to control the same RGB LED.

Equipment: UNO + HC-05 BT module + Android Phone with MIT inventor app

Achieved: Serial monitor shows that data sent from mobile is ok and I have a string like 255,0,0.

Questions:

  1. If I do work with the whole string, how can I separate each number and assign to a variable? (presumably substring won´t work because I don´t know the size of each number in advance);

  2. Would be a better approach to use an array of char and use "," as a separator in strtok?

What do you reccomend?

Better coding tips are welcome too :slightly_smiling_face:

[code]
#include <SoftwareSerial.h>
#define PinoRX 5
#define PinoTX 6
#define baudrate 9600

int pinoR = 11; 
int pinoG = 10; 
int pinoB = 9; 

int redval, greenval, blueval;

String msg;

SoftwareSerial hc05(PinoRX , PinoTX);

void setup() {
  pinMode(PinoRX, INPUT);
  pinMode(PinoTX, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(3, OUTPUT);
  digitalWrite(4, HIGH);
  digitalWrite(3, LOW);
  Serial.begin(9600);
  hc05.begin(baudrate);
  pinMode(pinoR, OUTPUT); 
  pinMode(pinoG, OUTPUT); 
  pinMode(pinoB, OUTPUT); 
  Serial.begin(9600);
  Serial.println(F("Insira os valores para R G B no formato XXX,XXX,XXX"));
}

void loop() {

  char data;
  msg = "";

  while (hc05.available()) {
    if ((hc05.available() > 0) && data != '.')
    {
      delay(10);
      char data = hc05.read();
      msg += data;
      Serial.println (msg);
    }
  }

  while (Serial.available()) {
    // look for the next valid integer in the incoming serial stream:
    redval = Serial.parseInt();
    greenval = Serial.parseInt();
    blueval = Serial.parseInt();
    analogWrite(pinoR, redval); 
    analogWrite(pinoG, greenval); 
    analogWrite(pinoB, blueval); 
    Serial.print(redval);
    Serial.print(",");
    Serial.print(greenval);
    Serial.print(",");
    Serial.println(blueval);
  }
}
[/code]

See the serial input basics tutorial. Example #5 has code to receive a string and parse the values. The default length of the string in the examples is 32, but that is easily changed.

1 Like

Forget the "String" class, it will most likely cause problems at some point. The most efficient way to do it is to make a custom "parseInt" function for the software serial:

int parseInt(SoftwareSerial &ss, int default = 0)
{
  int result = default;
  while (ss.available())
  {
    char cc = ss.peak();
    if ((cc >= '0') && (cc <= '9'))
    {
      result = (result * 10) + (cc - '0');
      ss.read();
    }
    else break;
  }
  return result;
}
1 Like

consider
(you may want to consider a parallel array with numeric values using atoi())

char s [80];

#define MaxTok  10
char *toks [MaxTok];

// -----------------------------------------------------------------------------
int
tokenize (
    char       *s,
    const char *sep )
{
    unsigned n;
    toks [0] = strtok (s, sep);
    for (n = 1; (toks [n] = strtok (NULL, sep)); n++)
        ;

    return n;
}

// -----------------------------------------------------------------------------
void dispToks (
    char * toks [])
{
    for (unsigned n = 0; toks [n]; n++)
        Serial.println (toks [n]);
}

// -----------------------------------------------------------------------------
void loop ()
{
    if (Serial.available ())  {
        int n = Serial. readBytesUntil ('\n', s, sizeof(s));
        s [n] = 0;      // terminate string

        tokenize (s, ",");
        dispToks (toks);
    }
}

// -----------------------------------------------------------------------------
void setup ()
{
    Serial.begin (9600);
}
1 Like

Is there some reason you don't read from 'hc05' the same way you read then from Serial?

  while (hc05.available()) {
    // look for the next valid integer in the incoming serial stream:
    redval = hc05.parseInt();
    greenval = hc05.parseInt();
    blueval = hc05.parseInt();
    analogWrite(pinoR, redval); 
    analogWrite(pinoG, greenval); 
    analogWrite(pinoB, blueval); 
    Serial.print(redval);
    Serial.print(",");
    Serial.print(greenval);
    Serial.print(",");
    Serial.println(blueval);
  }
1 Like

The only reason is: I didn´t know it was possible.

Now it works! Thanks! @johnwasser