0

I'm trying to build an air pollution sensor for a college project, with an Arduino Due and a series of Spec Sensors digital gas detectors. However, I'm having a little trouble getting the first one of them (Carbon Monoxide, https://www.spec-sensors.com/product/digital-co-sensor/) to behave, before I can run multiple. As they're all the same sensor setup but for different gasses, once I get the first one working, the rest should follow easily.

The code's very simple, as it uses Spec's own command system - sending the letter "c" to the sensor forces it to take one reading per second for as long as the sensor is powered, and then the serial monitor displays whatever comes back:

    void setup() {
      // sensor running via Serial1
      Serial.begin(9600);
      Serial1.begin(9600);
      Serial1.print("c");
    }

    void loop() {
      if(Serial1.available()!=0)
      {
        Serial.write(Serial1.read());
      }
    }

My problem comes with the data that's being returned. The gas reading is present, but so is a lot of superfluous information that I don't need. According to the sensor's tech document, the information returned is: serial number, reading (ppb), temperature, humidity, raw voltages, and amount of time the sensor has been running for. In the serial monitor, it looks like this:

output in serial monitor

Right now, all I want is the reading in ppb (the second value), either as the only data coming through or being stored, so that it can then be used in calculations like averages per hour. The trouble I have is that this information appears to be coming through as a stream of individual bytes, and in this format I'm having difficulty working out an effective way to specify which information I want to store, and which I want to ignore. I've been trying, for example, to come up with a way to specify that the first 14 bytes (serial number, comma, space - as this will always be the same length) should be ignored, and then the next series (up until the next comma - as this reading could be 4-6 digits) be stored as an int, or something, but I just can't seem to get anywhere no matter what I try. Does anyone have any suggestions?

  • note: the 1 second continuous read seems to be undocumented – jsotola May 1 '18 at 23:27
1

Since the length of each data varies, you should extract data using spererator like comma in the stream.

First, get one data line from sensor. Read the string until the "Line feed(LF)" character or "Carriage Return(CR)" character appears. located at the end of line(EOL), these two characters seperates each string by changing line. Without these two characters, the monitor shows the stream like this(no line change).

102617010933, 8486, 22, 35, 13464, 25716, 21962, 00, 00, 20, 06102617010933, 87216, 22, 35, 13576, 25223, 21442, 00, 00, 20, 07

So you can see there are CR, LF characters at the EOL. Utilize CR or LF as a terminator of ReadStringUntil() function. https://www.arduino.cc/en/Serial/ReadStringUntil

Second, parsing process. This process is extracting data you want from strtok() function. strtok() is from C language. It divides string by seperator characters. https://stackoverflow.com/questions/3889992/how-does-strtok-split-the-string-into-tokens-in-c?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

Lastly, utilize the data and repeat whenever sensor sends the data.

I'm not expert at coding. I haven't tested the code below. But this code would be helpful.

int data[12];
int isDataReceived = false;

void setup(){
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial1.write('c');
}

void loop(){
  while(Serial1.available()>0) {
    String inString = Serial1.readStringUntil('\n');
    char * pch = strtok(inString, ","); //Serial number would be ignored
    for(int i=0; pch != NULL; i++) {    //following data are stored in data[12] string
      pch = strtok(NULL, ",");
      data[i] = atoi(pch);
    }
    isDataReceived=true;
  }
  if(isDataReceived) {
    Serial.print("Data:");
    Serial.println(data[0]); //just example code. You may see ppb on the serial monitor.
    isDataReceived=false;
  }

}
0

The best solution would be to send only the data you need. If the sensor can't be made to do that, you could try this code:

char str[] = "102617010933, 8486, 22, 35, 13464, 25716, 21962, 00, 00, 20, 06";
unsigned long ppb = 0;

void setup(){

  Serial.begin(9600);

  int counter = 0;
  char * pch = strtok(str, " ,");

  while(pch != NULL){
    if(counter == 1){
      ppb = atol(pch);
      break;
    }
    pch = strtok(NULL, " ,");
    counter += 1;
  }
  Serial.println(ppb);
}

void loop(){

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.