groundFungus:
Here is an example to illustrate what I mean by using a software serial port for the Uno to talk to the sensor and hardware (USB) for you to talk to the Uno. Whatever you enter in the serial monitor is passed to the sensor. So, for instance, if "M 4164" is the command, type that into serial monitor and send (without quotes). When the sensor sends data back via software serial port, the data will be displayed and parsed according to the earlier posted code. Connect the sensor TX to the Uno pin 8 and the sensor RX to Uno pin 9.
#include <SoftwareSerial.h>
SoftwareSerial ss(8, 9);
char inputString[] = "H 00345 T 01195 Z 00651";
char *strings[8];
char *ptr = NULL;
// software serial port
const byte numChars_ss = 32;
char receivedChars_ss[numChars_ss];
boolean newData_ss = false;
// hardware serial port
const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;
void setup()
{
Serial.begin(9600);
Serial.println("");
ss.begin(9600);
}
void loop()
{
// watches the hardware serial port (setial monitor)
// enter "M 4164" to enter to request data from sensor
recvWithEndMarker();
// show data from setial monitor and send it out to sensor
showNewData();
// watch the software serial port (sensor)
recvWithEndMarker_ss();
// if the sensor has sent data parse and display it.
if (newData_ss == true)
{
showNewData_ss();
parseData_ss();
}
}
//get data from software serial (sensor)
void recvWithEndMarker_ss()
{
static byte ndx = 0;
char endMarker = '\n';
char rc;
while (ss.available() > 0 && newData_ss == false)
{
rc = ss.read();
if (rc == '\r')
{
return; // ignore carriage return
}
if (rc != endMarker)
{
receivedChars_ss[ndx] = rc;
ndx++;
if (ndx >= numChars_ss)
{
ndx = numChars_ss - 1;
}
}
else
{
receivedChars_ss[ndx] = '\0'; // terminate the string
ndx = 0;
newData_ss = true;
}
}
}
void showNewData_ss()
{
Serial.print("This just in ... ");
Serial.println(receivedChars_ss);
//newData = false;
}
//parse sensor data
void parseData_ss()
{
byte index = 0;
ptr = strtok(receivedChars_ss, " ");
while (ptr != NULL)
{
strings[index] = ptr;
index++;
ptr = strtok(NULL, " ");
}
//Serial.println(index);
//for(int n = 0; n < index; n++)
//{
// Serial.println(strings[n]);
//}
Serial.print("humidity = ");
Serial.print(atoi(strings[1]));
Serial.print(" temperature = ");
Serial.print(atoi(strings[3]));
Serial.print(" CO2 = ");
Serial.println(atoi(strings[5]));
newData_ss = false;
}
//get data from hardware serial (serial monitor)
void recvWithEndMarker()
{
static byte ndx = 0;
char endMarker = '\n';
char rc;
while (Serial.available() > 0 && newData == false)
{
rc = Serial.read();
if (rc == '\r')
{
return; // ignore carriage return
}
if (rc != endMarker)
{
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars)
{
ndx = numChars - 1;
}
}
else
{
receivedChars[ndx] = '\0'; // terminate the string
ndx = 0;
newData = true;
}
}
}
//echo data from serial monitor and send it out to sensor
void showNewData()
{
if (newData == true)
{
Serial.print("This just in ... ");
Serial.println(receivedChars);
ss.println(receivedChars);
Serial.println(receivedChars);
newData = false;
}
}
After some puzzling I figured out that M 4164 apparently just sets the sensor to output T, H and Z. If I send M 4164 and after that Q/r/n (return latest values according to manual) it works!
14:04:16.836 -> This just in ... Q/r/n
14:04:16.883 -> Q/r/n
14:04:16.883 -> This just in ... H 00590 T 01210 Z 01071
14:04:16.930 -> humidity = 590 temperature = 1210 CO2 = 1071
Is it possible to create a function to get these values automatically every time they are updated (every 0.5 seconds) and have them returned as floats? How would I do that?
Maybe we can use the streaming mode for this.
Thank you for helping me, I really appreciate it. Would've never been able to do this on my own I think.