mDot / Mbed OS Honneywell_Dust_Simple
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Main.cpp Source File

Main.cpp

00001 /* Run Honeywell Dust Sensor in continous Sampling Mode on a mDot or 
00002    Freedom K64 board
00003    Version 2.2
00004    Steve Mylroie Roitronic December 2 2017
00005    @C Copyright 2017 Global Quality Corp
00006 */
00007 
00008 #include "mbed.h"
00009 #include "stdlib.h"
00010 
00011 #define VERSION  "2.2"
00012 
00013 #define TRACE_MODE
00014 
00015 //Turn on trace logging to the PC USB port
00016 #ifdef TRACE_MODE
00017 //Log level need to be set one level higher than the highest level to be output
00018 #define LOG_LEVEL 2
00019 #define DEBUG
00020 #endif
00021 
00022 
00023 const uint8_t* measureCommand = "68014057";
00024 const uint8_t* stopCommand    = "68012077";
00025 
00026 //Sensor command response codes
00027 #define OK   0xA5A5
00028 #define BAD  0x9696
00029 
00030 //Maximum response message lenght
00031 #define MESSAGE_LEN 32
00032 
00033 //sensor measurement cycle in millseconds
00034 #define MEASURE_DELAY 1500 
00035 
00036 Serial pc(USBTX, USBRX, 115200);
00037 
00038 //Use USB debug pott for the debug stream
00039 #ifdef DEBUG
00040 uint32_t debugLevel  = LOG_LEVEL;
00041 #else
00042 uint32_t debugLevel = 0;
00043 #endif
00044 
00045 void logInfo(char* text) {
00046      if ( debugLevel > 0 ) {
00047           pc.printf("\n%s\n", text );
00048      }
00049      return;
00050  }
00051  
00052 void logTrace(uint8_t data) {
00053     if (debugLevel > 2 ){ 
00054         pc.putc( data );
00055     }
00056     return;
00057 } 
00058 
00059 //Board specfic serial port pin definitions
00060 
00061 #ifdef TARGET_Freescale  //Freedom Board
00062 
00063 #define SENSOR_XMT D1
00064 #define SENSOR_RCV D0
00065 
00066 #endif
00067 
00068 #ifdef TARGET_MTS_MDOT_F411RE  //Multi Tech mDot
00069 
00070 #define SENSOR_XMT PA_2
00071 #define SENSOR_RCV PA_3
00072 
00073 #endif
00074 
00075 //Number of character following the 
00076 #define RESPONSE_MSG_LEN 2
00077 #define AUTO_MSG_LEN 32
00078 
00079 //Time required to receive one character at 9600 baud
00080 #define CHAR_TIME (1000 * 10)/9600
00081 
00082 enum MSG_TYPE{  UNKNOWN,
00083                 ACK_MSG,
00084                 NAK_MSG,
00085                 AUTO_MSG,
00086                 READ_ERROR } msgType;
00087 
00088 
00089 uint8_t dataBuffer[AUTO_MSG_LEN];
00090 uint8_t* bufferPtr;
00091 uint32_t msgLen;
00092 
00093        
00094 //Use a boards second UART   to communicate witb the Honneywell sensor
00095 //Default UART setting are 8,N,1
00096 RawSerial sensor( SENSOR_XMT, SENSOR_RCV, 9600);
00097 
00098 //Serial Received chararter interupt handler
00099 
00100 void receiveInterrupt() {
00101     uint8_t data;
00102     if(sensor.readable()) {
00103         data = sensor.getc();
00104         if(msgType == UNKNOWN) {  //Start of a new message
00105             bufferPtr = dataBuffer;
00106             switch(data) { //Switch on message type character
00107                 case 0x42:
00108                     msgType = AUTO_MSG;
00109                     msgLen = AUTO_MSG_LEN;
00110                     break;
00111                 case 0xA5:
00112                     msgType = ACK_MSG;
00113                     msgLen = RESPONSE_MSG_LEN;
00114                     break;
00115                 case 0x69:
00116                     msgType = NAK_MSG;
00117                     msgLen = RESPONSE_MSG_LEN;
00118                     break;
00119             }
00120         }
00121         if(msgLen--  > 0 ) {  //Insert Character into type ahead buffer
00122             *bufferPtr++ = data;
00123         }
00124     }
00125     return;    
00126 }
00127 
00128 //Read last message received from type ahead message buffer
00129 //Mbed 5 Serial class only supports single character read and writes or
00130 // async buffer reads and wrutes
00131 MSG_TYPE readBuffer(uint8_t* buffer, uint16_t count)
00132 {
00133     if(buffer == NULL || count > AUTO_MSG_LEN ) { //Calling without buffer or
00134         return READ_ERROR;                    //asking for too many chars
00135     }                                         //is an error
00136     int counter = 0;
00137     uint8_t* inPointer;
00138     uint8_t* outPointer;
00139     int delay;
00140     logInfo( "Reading last message from sensor\n");
00141     while(msgType == UNKNOWN ) { //No message received since last read
00142         Thread::wait(CHAR_TIME); //Wait for new message
00143         counter++;
00144         if(counter > 40) { //Timeout exit after 40 character 40 Charcter times
00145             break;
00146         }
00147     }
00148     counter = 0;    
00149     while(msgLen > 0 ) { //Wait for complete message to arrive
00150         delay = CHAR_TIME * msgLen;
00151         Thread::wait(delay);
00152         counter++;
00153         if(counter > 40) { //Time out exit after 40 character times
00154             pc.printf("msgLen: %d", msgLen);
00155             break;
00156         }
00157     }
00158     if(counter > 40 ) { //Report timeout error
00159        msgType = UNKNOWN;
00160        return READ_ERROR;
00161      }
00162     else {
00163         //Copy the message minus type flag to the requesters buffer 
00164         inPointer = &dataBuffer[1];
00165         outPointer = buffer;
00166         for(int i = 0; i < count; i++) {
00167             *outPointer++ = *inPointer++;
00168         }
00169     }
00170     MSG_TYPE temp = msgType;
00171     //Start Search for the next message
00172     msgType = UNKNOWN;     
00173     return temp;
00174 }
00175     
00176             
00177 void writeBuffer(const uint8_t* buffer, uint16_t count)
00178 {
00179     logInfo( "Sending Command to sensor\n");
00180     uint8_t* pointer = (uint8_t*)buffer;
00181     uint16_t counter = count;
00182     while(1)
00183     {
00184         if(sensor.writeable())
00185         {
00186             logTrace(*pointer);
00187             sensor.putc(*pointer++);
00188             counter--;
00189         }
00190         if(counter == 0) {
00191             return;
00192         }
00193     }
00194 } 
00195 
00196 //Validate the received mesurements checksum
00197 
00198 bool checkValue(uint8_t *thebuf, uint8_t leng)
00199 {  
00200     bool receiveflag = false;
00201     uint16_t receiveSum = 0;
00202     
00203     //Don't include the checksum bytes in the sum
00204     for(int i=0; i<(leng-3); i++){
00205      receiveSum=receiveSum+thebuf[i];
00206     }
00207     receiveSum=receiveSum + 0x42;
00208     
00209     if(receiveSum == ((thebuf[leng-2]<<8)+thebuf[leng-1]))  //check the debug data 
00210     {
00211         receiveSum = 0;
00212         receiveflag = true;
00213     }
00214     return receiveflag;
00215 }
00216 
00217 //Extract the 1 micron particle count from the messaage
00218 uint16_t transmitPM01(uint8_t *thebuf)
00219 {
00220     uint16_t PM01Val;
00221     PM01Val=((thebuf[3]<<8) + thebuf[4]); //count PM1.0 value of the air detector module
00222     return PM01Val;
00223 }
00224 
00225 //Extract the 2.5 micron particle count from the messaage
00226 uint16_t transmitPM2_5(uint8_t *thebuf)
00227 {
00228     uint16_t PM2_5Val;
00229     PM2_5Val=((thebuf[5]<<8) + thebuf[6]);//count PM2.5 value of the air detector module
00230     return PM2_5Val;
00231 }
00232 
00233 //Extract the 10 micron particle count from the messaage
00234 uint16_t transmitPM10(uint8_t *thebuf)
00235 {
00236     uint16_t PM10Val;
00237     PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module  
00238     return PM10Val;
00239 }
00240 
00241 int main()
00242 {
00243     uint8_t dataBuffer[MESSAGE_LEN];
00244     MSG_TYPE mType;
00245     uint16_t PM01Value=0;     //define PM1.0 value of the air detector module
00246     uint16_t PM2_5Value=0;        //define PM2.5 value of the air detector module
00247     uint16_t PM10Value=0;         //define PM10 value of the air detector module
00248     
00249     pc.printf("Starting Honeywell Dust Sesor App version %\n", VERSION);
00250 
00251     #ifdef DEBIG
00252         pc.printf("Character wait time is %d millseconds", CHAR_TIME);
00253     #endif
00254     //Attach a receive interrupt handler
00255     sensor.attach(receiveInterrupt, Serial::RxIrq);
00256     msgType = UNKNOWN;
00257     //Send start command to the sensor
00258     writeBuffer(measureCommand, 4);
00259  /*
00260  Not geting response from sensor - first characters received are measurement data   
00261     //Wait for sensors response
00262     //while(!sensor.readable());
00263     readBuffer(dataBuffer, 2);
00264     response = dataBuffer[0] << 8 || dataBuffer[1];
00265 
00266     switch(response) {
00267         case OK:
00268         logInfo("Sensor Auto Measurement Started");
00269         break;
00270         case BAD:
00271         logInfo("Sensor rejected Start Measurement Commmand");
00272         return -1;
00273         default:
00274         logInfo("Communication Error: Invalid Sensor Response");
00275         return -2;
00276     }
00277 */    
00278 
00279     //Start continous loop 
00280     while(1) {
00281         if((mType = readBuffer(dataBuffer, MESSAGE_LEN -1)) == AUTO_MSG) {
00282             if(dataBuffer[0] == 0x4d){
00283                 if(checkValue(dataBuffer, MESSAGE_LEN-1)){
00284                     PM01Value = transmitPM01(dataBuffer); //count PM1.0 value of the air detector module
00285                     PM2_5Value = transmitPM2_5(dataBuffer);//count PM2.5 value of the air detector module
00286                     PM10Value = transmitPM10(dataBuffer); //count PM10 value of the air detector module 
00287                 }
00288                 else {
00289                     pc.puts("Message checksum error\n");
00290                 }
00291             }
00292             else {
00293               pc.printf("Error Second Character not 0x4d but #x\n", dataBuffer[0]);
00294               }
00295              //Check for exit request
00296             if(pc.readable()) { // Returning false here
00297                 char input = pc.getc();
00298                 if(input == 'Q' || input == 'q')
00299                 { 
00300                     //Shutdown the sensor
00301                     writeBuffer(stopCommand, 4);
00302                     //Unlink the receive interrupt handler
00303                     sensor.attach(0, Serial::RxIrq);
00304                     pc.puts("Exit request received\n");
00305                     return 0;
00306                 }
00307             }
00308             // Use MBed wait function instead of Arduino delay loop
00309             wait_ms(1000);          
00310                   
00311             pc.printf("PM1.0: %d ug/m3\n", PM01Value);  
00312                 
00313             pc.printf("PM2.5: %d ug/m3\n", PM2_5Value);  
00314                   
00315             pc.printf("PM10: %d ug/m3\n", PM10Value);  
00316         
00317             pc.printf("\n");
00318         }
00319         else {
00320             switch(mType) {
00321                 case ACK_MSG:
00322                     if(dataBuffer[0] == 0xA5) {
00323                         pc.puts("Recived ACK response'\n");
00324                     }
00325                     else {
00326                         pc.puts("Received corrupt ACK Response\n");
00327                     }
00328                     break;
00329                 case NAK_MSG:
00330                     if(dataBuffer[0] == 0x69) {
00331                         pc.puts("Recived NAK response'\n");
00332                     }
00333                     else {
00334                         pc.puts("Received corrupt NAK Response\n");
00335                     }
00336                     break;
00337                 case READ_ERROR:
00338                     pc.puts("Data Reading Error\n");
00339 #ifdef DEBUG
00340                     pc.printf("\nMESSAGE_LEN: %d\n",msgLen);
00341                     for (int index = 0; index < MESSAGE_LEN - msgLen; index++) {
00342                         pc.putc(dataBuffer[index]);
00343                         }
00344                     pc.putc('\n');
00345 #endif
00346                     break;
00347                 }
00348             }
00349         }
00350     }