Hello everybody,
I've read the great tutorial about Serial Input Basics and basically based my code on the examples in this thread. I'm using C strings to collect the measurement data from the sensors. The datasheet for the sensor types I'm using is in the attachement,
Reading a single sensor, there is no problem (Measurement String: SN, PPB, T (°C), RH (%), ADC Raw, T Raw, RH Raw, Day, Hour, Minute, Second ):
16:53:15.981 -> Read NO2 Sensor:
16:53:16.015 -> Newdata is collected ...
16:53:16.015 -> This just in ... 061318011256, 23, 23, 47, 32671, 26071, 28118, 00, 00, 00, 10
16:53:16.117 -> Gasconc.: 23
16:53:16.117 -> Temp. : 23
16:53:16.151 -> Humid. : 47
but as soon as I'm reading 2 sensors, my output looks like that:
17:03:01.158 -> Read NO2 Sensor:
17:03:01.158 -> Newdata is collected ...
17:03:01.192 -> This just in ... 012919012048, 5450, 22, 53, 13253, 25725, 31014, 00, 00, 09, 22061318011256, 2, 22, 49, 32685, 25746, 28858, 00, 00, 10, 15
17:03:01.331 -> Gasconc.: 5450
17:03:01.365 -> Temp. : 22
17:03:01.365 -> Humid. : 53
17:03:01.399 -> Read CO Sensor:
17:03:01.399 -> -----------------------------------
17:03:03.164 -> Read NO2 Sensor:
17:03:03.164 -> Newdata is collected ...
17:03:03.198 -> This just in ... 012919012048, 5450, 22, 53, 13253, 25725, 31006, 00, 00, 09, 23061318011256, 2, 22, 49, 32685, 25745, 28862, 00, 00, 10, 17
17:03:03.334 -> Gasconc.: 5450
17:03:03.368 -> Temp. : 22
17:03:03.368 -> Humid. : 53
17:03:03.402 -> Read CO Sensor:
17:03:03.402 -> -----------------------------------
I would think, that old data in the C string named receivedChars gets overwritten with every new function call of ReadSPECSensor(), but it doesnt seem to be the case, but I'm not sure..... ndx gets set to 0 so I would think after receiving \n - the newline character - the array would be filled from the beginning again, when I read the sensor again.
I use the same function for both sensors. According to the datasheet, it can take up to 1 second, till a measurement string arrives. I'm not sure, if a speed issue in regards of the serial port is the problem. Would it be better, if I use a C string for every sensor instead of only using one for saving the data? My code is below and thanks for any input!
/*
* Datasheet for commands and for format of the output string:
* http://www.spec-sensors.com/wp-content/uploads/2017/01/DG-SDK-968-045_9-6-17.pdf
*
Script is used for the following objectives:
- Putting out a stream of continous measurements
- saving the measurements in variables
*/
// Simulated measurement intervall
unsigned long startMillis;
const unsigned long measurementPeriod = 2000;
HardwareSerial& no2Port = Serial1;
HardwareSerial& coPort = Serial2;
const byte numChars = 128;
char receivedChars[numChars];
char tempChars[numChars]; // temporary array for use when parsing
// variables to hold the parsed data
int no2;
int no2temp;
int no2hum;
int co;
int cotemp;
int cohum;
boolean newData = false;
//============
void setup() {
Serial.begin(9600);
no2Port.begin(9600);
coPort.begin(9600);
Serial.println("Demo for collecting and parsing measurement string from a SPEC sensor.");
Serial.println("Based on the Serial Input Basics tutorial in the Arduino forum.");
Serial.println();
flush_serial(no2Port);
flush_serial(coPort);
}
//============
void loop() {
if (millis() - startMillis >= measurementPeriod) {
startMillis = millis();
Serial.println("Read NO2 Sensor:");
ReadSPECSensor(no2, no2temp, no2hum, no2Port);
Serial.println("Read CO Sensor:");
ReadSPECSensor(co, cotemp, cohum, coPort);
Serial.println("-----------------------------------");
}
}
//============
void recvWithEndMarker(HardwareSerial& gasPort) {
static byte ndx = 0;
char endMarker = '\n';
char rc;
while (gasPort.available() > 0 && newData == false) {
rc = gasPort.read();
if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
Serial.println("Newdata is collected ...");
}
}
}
//============
void parseData(int &sensorGas, int &sensorTemp, int &sensorHum) { // 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 // http://www.c-howto.de/tutorial/strings-zeichenketten/string-funktionen/string-zerteilen/
strtokIndx = strtok(NULL, ",");
sensorGas = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ",");
sensorTemp = atoi(strtokIndx); // convert this part to an integer
strtokIndx = strtok(NULL, ",");
sensorHum = atoi(strtokIndx); // convert this part to an integer
}
//============
void showParsedData(int gas, int temp, int hum) {
Serial.print("Gasconc.: ");
Serial.println(gas);
Serial.print("Temp. : ");
Serial.println(temp);
Serial.print("Humid. : ");
Serial.println(hum);
if (gas > 10000 || temp > 1000 || hum > 1000) { // in the case received string was wrongly read (mixed up)
Serial.println("Stop exexcution");
stop();
}
}
void showNewData() {
Serial.print("This just in ... ");
Serial.println(receivedChars);
}
void ReadSPECSensor(int &gas, int &temp, int &hum, HardwareSerial& gasPort) {
gasPort.print('\r'); // print to gasport to get single measurement string
recvWithEndMarker(gasPort);
if (newData == true) {
strcpy(tempChars, receivedChars);
// this temporary copy is necessary to protect the original data
// because strtok() used in parseData() replaces the commas with \0
showNewData();
parseData(gas, temp, hum);
showParsedData(gas, temp, hum);
newData = false;
}
}
void flush_serial(HardwareSerial& serialPort) {
// Do we have data in the serial input buffer?
// If so, flush it
Serial.println("Flush the serial input buffer!");
while (serialPort.available() > 0) {
serialPort.read();
Serial.println("in while loop!");
}
Serial.println("Serial flushed! ");
}
void stop() {
while(1);
}
EDIT (08.11.2020):
MORE ABOUT THE TOPIC HERE:
https://forum.arduino.cc/index.php?topic=712737.0
DG-SDK-968-045_9-6-17.pdf (565 KB)