Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[General] UART communication protocol read with Arduino

Status
Not open for further replies.

RobertoPasic

Newbie level 6
Joined
Dec 2, 2009
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
Macedonia
Activity points
1,390
Hi there,
I have this part of code for read data from PM sensor (model SDS011 from Inova) via UART, according UART communication protocol from SDS011 manual (attach no:1):
Code:
void ProcessSerialData(){
  uint8_t mData = 0;
  uint8_t i = 0;
  uint8_t mPkt[10] = {0};
  uint8_t mCheck = 0;
  while (Serial.available() > 0){    
    // packet format: AA   C0   PM25_Low   PM25_High   PM10_Low   PM10_High   0   0   CRC   AB
    mData = Serial.read();     
    delay(2);                                   // wait until packet is received
       if (mData == 0xAA){               // head1 ok
       mPkt[0] =  mData;
           mData = Serial.read();
           if (mData == 0xc0){           // head2 ok
           mPkt[1] =  mData;
    mCheck = 0;
       for (i = 0; i < 6; i++){           // data recv and crc calc
       mPkt[i + 2] = Serial.read();
       delay(2);
       mCheck += mPkt[i + 2];
     }
        mPkt[8] = Serial.read();
        delay(1);
        mPkt[9] = Serial.read();
        if (mCheck == mPkt[8]){        // crc ok
          Serial2.flush();
          
        Pm25 = (uint16_t)mPkt[2] | (uint16_t)(mPkt[3] << 8);
        Pm10 = (uint16_t)mPkt[4] | (uint16_t)(mPkt[5] << 8);
        return;
        }
      }
    }
  }
}

Code work OK,
Can somebody help with advice about code arrange for read other sensor (exactly ZE07-CO gas sensor), according UART communication protocol from ZE07 manual (attach no:2)
thanks in advance
best regards
 

Attachments

  • attach_no1.pdf
    190.7 KB · Views: 78
  • attach_no2.pdf
    292.6 KB · Views: 72

To read data from the Serial object you first need to check that there is something there to read - typically you spin on the 'Serial.available()' function until it returns a number greater than 0. There is no need for delay functions - which make the process very error prone and also are not working as I think you expect them to i this case. However you need to check this for EACH call to the 'read' function, not just once at the start.
As to your question, I don't really understand why you cannot read the data from the gas sensor in a very similar way to the code you already have. Both have a header value that you can use to synchronise the start of the byte stream, both have a checksum that you can use to validate that the data has been received correctly and both have data that you can read and process.
If what you are asking is how to read in the byte streams from the 2 sensors where they might be sent simultaneously, then you need to tell us a lot more about the Arduino you are using. If there is only one serial device then you have a major problem and you cannot have two devices sending on the same lines at the same time. However many Arduinos allow multiple serial connections in which case you can then set up each to call the 'SerialEvent' function when a character is received.
Susan
 
Aussie, thanks for reply,
I use Arudino DUE, with 3 serial channels, so I can read total 3 serial sensors,
but I don't need to read both sensors simultaneously,
I don't have enough experiences to arrange previous code in this new case,
I will try to solve my problem,
thanks again
best regards
 

I try with:
Code:
void setup() {
  winsenBegin();
  Serial.begin(9600);
}

void loop() {
  float result = winsenRead();
  Serial.println(result, DEC);
}
/**
   Setup the Winsen sensor
*/
void winsenBegin() {
  Serial1.begin(9600);
  byte setConfig[] = {0xFF, 0x01, 0x78, 0x41, 0x00, 0x00, 0x00, 0x00, 0x46}; //Set 1 Q/A configuration
  Serial1.write(setConfig, sizeof(setConfig)); //
  delay(1000);// Wait for a response
  while (Serial1.available() > 0) { // Flush the response
    byte c = Serial1.read();
  }
}
/**
   Read the sensor
   @return {float} sensor [C]
*/
float winsenRead() {
  byte petition[] = {0xFF, 0x01, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79}; // Petition to get a single result
  byte measure[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Space for the response
  float ppm;
  Serial1.write(petition, sizeof(petition));
  delay(2000);
  if (Serial1.available() > 0) {
    Serial1.readBytes(measure, 9);
    if (measure[0] == 0xff && measure[1] == 0x78) {
      Serial1.readBytes(measure, 9);
    }

    if (measure[0] == 0xff && measure[1] == 0x86) {
      ppm = (measure[2] * 256 + measure[3]) * 0.1; // this formula depends of the sensor is in the dataSheet
    } else {
      ppm = -1;
    }
  }
  return ppm;
}

but something is not ok,
I receive strange result (see attached image),
can somebody advice where is the problem?
thanks
unnamed.jpg
 

I'm not sure what you are expecting to see and therefore what is the problem.
You will be getting a buffer overrun in that you declare 'measure' to be 8 bytes long but tell 'readbytes' to read in 9 values!
Looking at (what I think might be the) data sheet, it shows the device sending 10 bytes which are numbered from 0 to 9. This means that you may be not reading in the last character which will then be picked up as the first character the next time.
One thing that may or may not be an issue is that the 'readbytes' function will read up to the number of bytes you specify but it could be less if the timeout (set to a default of 1 second - and I can't see where you change that) occurs. Therefore is may be a source of error if you don't check that you have actually received all the bytes you expect.
Also I'm not sure of the serial interface has its own buffer. If so then things can eb made to work, but if not then having a delay of 2 seconds in the 'winsenRead' function, when the device sends a packet every second, can cause characters to be dropped.
Perhaps a better approach is something like this:
Code:
packetReceived = 0;
while(!packetReceived)
{
    readIndex = 0;
    while(readIndex == 0)
    {
        if(Serial1.available())  // Wait until a character is available
        {
            measure[readIndex] = Serial1.read();  // Read it in
            if( 0xAA == measure[readIndex])         // Is it the start of a header
            {
                 readIndex++;                             // Yes - increment the pointer
                 break;                                       // Break out of the while loop
            }
        }     // Still not seen a valid header so keep on looking
    }
    // We have a valid header character - read in the rest of the packet
    while( readIndex < 10)
    {
        if( Serial1.available())    // Wait until the character is available
        {
            message[readIndex] = Serial1.read();   // Read the character
            if( readIndex == 1)
            {
                // Check that the second character is the expected command ID
                if( message[readIndex] != 0xc0)
                { break; }   // It is not the expected character - something is wrong so dump this packet
            }
            if( readIndex == 9)
            {
                // Check that the end of the packet marker has been read
                if( message[readIndex] != 0xAB)
                { break; }        // Not the expected message tail - dump the packet
                else
                { packetReceived = 1; }  // Show that we have a complete packet
            }
            readIndex++;
        }
    }
}
// When you get here you know you have a complete and valid packet
Susan
 
Susan, thanks again for your advice,
you say: "Looking at (what I think might be the) data sheet, it shows the device sending 10 bytes which are numbered from 0 to 9."
Probably you read manual from my first sensor (PM sensor SDS011), but I have a problem with other sensor (ZE07-CO from Winsen), I attach for your reference manual from ZE07-CO. You can see CO gas sensor can work in two modes, initial upload (sensor send data every second) and Question and Answer mode. I use Question and Answer mode. I will try to implement your peace of code to try to receive whole byte's packet on a correct way,
thanks again
 

Attachments

  • ZE07 CO Module 1.3V.pdf
    442.3 KB · Views: 76

You are correct - I was looking at the SDS011 data sheet so I'm sorry for the misdirection.
However the principle of my code should still apply and certainly my comment about the size of the 'measure' array does - it should be 'measure[9]' so that it can be indexed from 0 to 8.
Susan
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top