Sorting data coming in from the serial port

Is it possible to sort different data points coming in over the 1 serial port? I want to send multiple sensor readings from an arduino mega over to an ESP via UART and was wondering if its possible to sort the data so that I can store the data in the correct variables e.g. temperature and humidity sensors send data to the esp, esp then stores the temperature values in a temperature variable and the humidity values in a humidity variable. I made a post earlier on the same project that I'm working on but with a different (solved) problem. I believe this link provides enough context. Thanks.
Why does serial2.read break the code?

EDIT: ESP Code

#define RXD2 16
#define TXD2 17

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>

#if defined(ESP32)
  #include <WiFiMulti.h>
  WiFiMulti wifiMulti;
  #define DEVICE "ESP32"
#elif defined(ESP8266)
  #include <ESP8266WiFiMulti.h>
  ESP8266WiFiMulti wifiMulti;
  #define DEVICE "ESP8266"
  #define WIFI_AUTH_OPEN ENC_TYPE_NONE
#endif

#include <InfluxDbClient.h>
#include <InfluxDbCloud.h>

// WiFi AP SSID
#define WIFI_SSID ""
// WiFi password
#define WIFI_PASSWORD ""
// InfluxDB v2 server url, e.g. https://eu-central-1-1.aws.cloud2.influxdata.com (Use: InfluxDB UI -> Load Data -> Client Libraries)
#define INFLUXDB_URL ""
// InfluxDB v2 server or cloud API authentication token (Use: InfluxDB UI -> Load Data -> Tokens -> <select token>)
#define INFLUXDB_TOKEN ""
// InfluxDB v2 organization id (Use: InfluxDB UI -> Settings -> Profile -> <name under tile> )
#define INFLUXDB_ORG ""
// InfluxDB v2 bucket name (Use: InfluxDB UI -> Load Data -> Buckets)
#define INFLUXDB_BUCKET ""
// Set timezone string according to https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
// Examples:
//  Pacific Time:   "PST8PDT"
//  Eastern:        "EST5EDT"
//  Japanesse:      "JST-9"
//  Central Europe: "CET-1CEST,M3.5.0,M10.5.0/3"
#define TZ_INFO ""

// InfluxDB client instance with preconfigured InfluxCloud certificate
InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN, InfluxDbCloud2CACert);
// InfluxDB client instance without preconfigured InfluxCloud certificate for insecure connection 
//InfluxDBClient client(INFLUXDB_URL, INFLUXDB_ORG, INFLUXDB_BUCKET, INFLUXDB_TOKEN);

// Data point
Point sensorReadings("measurements");

float temperature;


void setup() {
  Serial.begin(115200);
  Serial2.begin(9600, SERIAL_8N1, RXD2, TXD2);

  // Setup wifi
  WiFi.mode(WIFI_STA);
  wifiMulti.addAP(WIFI_SSID, WIFI_PASSWORD);

  Serial.print("Connecting to wifi");
  while (wifiMulti.run() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
  Serial.println();
  
  
  // Add tags
  sensorReadings.addTag("ESP32", DEVICE);
  sensorReadings.addTag("TENT", "D1.168");
  sensorReadings.addTag("sensor", "IRTEMP");

  // Accurate time is necessary for certificate validation and writing in batches
  // For the fastest time sync find NTP servers in your area: https://www.pool.ntp.org/zone/
  // Syncing progress and the time will be printed to Serial.
  timeSync(TZ_INFO, "pool.ntp.org", "time.nis.gov");

  // Check server connection
  if (client.validateConnection()) {
    Serial.print("Connected to InfluxDB: ");
    Serial.println(client.getServerUrl());
  } else {
    Serial.print("InfluxDB connection failed: ");
    Serial.println(client.getLastErrorMessage());
  }
}

void loop() {

  Serial.println(Serial2.parseFloat());

 // Get latest sensor readings
  temperature = Serial2.parseFloat();

  // Add readings as fields to point
  sensorReadings.addField("TemperatureTwo", temperature);

  // Print what are we exactly writing
  Serial.print("Writing: ");
  Serial.println(client.pointToLineProtocol(sensorReadings));

  // Write point into buffer
  client.writePoint(sensorReadings);

  // Clear fields for next usage. Tags remain the same.
  sensorReadings.clearFields();

  // If no Wifi signal, try to reconnect it
  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("Wifi connection lost");
  }

  // Wait 10s
  Serial.println("Wait 10s");
  delay(1000);
}

Send each value with a precursor letter. E.g. H 250, T 12, P 101.35
And use those key letters to assign the subsequent value to the correct variable.

Or, simply assign them based on the location in a line - the first variable is always temperature, the second always humidity, the third pressure. Etc.

consider
i use pcRead() to debug programs with single char commands that can be optionally preceded by a val (e.g. 123c)

// pcRead - debugging using serial monitor

const char version [] = "PcRead 201114a";

int debug = 0;

// ---------------------------------------------------------
// 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 = 0;

    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);
            digitalWrite (val, ! digitalRead (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
}

You can get ideas from Robin's Serial Input Basics - updated. The principles apply to communication between two microcontrollers as well; you will have to write the sender side yourself matching the receiver.

Alternatively you could print only when you’ve gathered all the values

I was thinking something like that but I dont know how to go about that in the code

This seems a bit beyond me atm with my coding ability. I'll try to break it down and see if I can fully understand it

I found that post earlier and thought it might be of use to me. Am I correct in saying that example 5 would be the best suited example to try and implement?

How would I sort it on the ESP side? I have the code giving a different sensor reading every 10s from 3 different sensors.

As I said,
Send each value with a precursor letter. E.g. H 250, T 12, P 101.35
Without your ESP code, how can I comment?
Basically, you receive H, you suck in a number and put it in the humidity variable. ditto for T, and whatever else. If you have multiple sensors of the same type, e.g. temperature 1 and 2, just give them different signature characters.

Yes, that was what I was thinking.

yes it's not exactly what you asked for but can certainly be easily modified to do what you ask and more. "123T" could set the temperature, "456H" the humidity.

        case 'T':
            temperature = val;
            val = 0;
            break;

developing a flexible approach is often reusable and can easily be expanded for other purposes

I've updated the post including the ESP code. Also, I referenced a post about another problem yesterday. Essentially the issue was that the sensor values were displayed in ascii code on the ESP serial monitor and the solution was to use Serial2.parseFloat() instead of Serial2.read(). However, this .parsefloat doesnt send the precursor letters you said to use, so I'm not sure what to do now.

hint, look for an incoming character of interest, then parsefloat immediately after that.

are you looking to process a string from the serial port or from a WiFi socket? or is mega sending a string to and esp which is then transmitting it over wifi to some other wifi device that needs to process the string?

once the string from Serial2 is read (parsed) i don't believe it can be read again.

also, code should check if something is available before reading the Serial2 interface

Im trying to get the mega to send data points as floats to the esp and then these data points are then sent to influxdb (an open-source time series database). Also, I never use those two lines of code at the same time. I comment one out when I'm testing different things. Ok, I'll add the check code now then

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.