mDot / Mbed OS Honneywell_Dust_Simple
Revision:
16:6550040fbdf4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Main.cpp.orig	Sun Dec 03 00:24:46 2017 +0000
@@ -0,0 +1,341 @@
+/* Run Honeywell Dust Sensor in continous Sampling Mode on a mDot or 
+   Freedom K64 board
+   Version 2.2
+   Steve Mylroie Roitronic December 2 2017
+   @C Copyright 2017 Global Quality Corp
+*/
+
+#include "mbed.h"
+#include "stdlib.h"
+
+#define VERSION  "2.2"
+
+#define TRACE_MODE
+
+//Turn on trace logging to the PC USB port
+#ifdef TRACE_MODE
+//Log level need to be set one level higher than the highest level to be output
+#define LOG_LEVEL 2
+#define DEBUG
+#endif
+
+
+const uint8_t* measureCommand = "68014057";
+const uint8_t* stopCommand    = "68012077";
+
+//Sensor command response codes
+#define OK   0xA5A5
+#define BAD  0x9696
+
+//Maximum response message lenght
+#define MESSAGE_LEN 32
+
+//sensor measurement cycle in millseconds
+#define MEASURE_DELAY 1500 
+
+Serial pc(USBTX, USBRX, 115200);
+
+//Use USB debug pott for the debug stream
+#ifdef DEBUG
+uint32_t debugLevel  = LOG_LEVEL;
+#else
+uint32_t debugLevel = 0;
+#endif
+
+void logInfo(char* text) {
+     if ( debugLevel > 0 ) {
+          pc.printf("\n%s\n", text );
+     }
+     return;
+ }
+ 
+void logTrace(uint8_t data) {
+     if (debugLevel > 2 ){ pc.putc( data );
+      }
+      return;
+  } 
+
+//Board specfic serial port pin definitions
+
+#ifdef TARGET_Freescale  //Freedom Board
+
+#define SENSOR_XMT D1
+#define SENSOR_RCV D0
+
+#endif
+
+#ifdef TARGET_MTS_MDOT_F411RE  //Multi Tech mDot
+
+#define SENSOR_XMT PA_2
+#define SENSOR_RCV PA_3
+
+#endif
+
+//Number of character following the 
+#define RESPONSE_MSG_LEN 2
+#define AUTO_MSG_LEN 32
+
+//Time required to receive one character at 9600 baud
+#define CHAR_TIME (1000 * 10)/9600
+
+enum MSG_TYPE{  UNKNOWN,
+                ACK_MSG,
+                NAK_MSG,
+                AUTO_MSG,
+                READ_ERROR } msgType;
+
+
+uint8_t dataBuffer[AUTO_MSG_LEN];
+uint8_t* bufferPtr;
+uint32_t msgLen;
+
+       
+//Use a boards second UART   to communicate witb the Honneywell sensor
+//Default UART setting are 8,N,1
+RawSerial sensor( SENSOR_XMT, SENSOR_RCV, 9600);
+
+//Serial Received chararter interupt handler
+
+void receiveInterrupt() {
+    uint8_t data;
+    if(sensor.readable()) {
+        data = sensor.getc();
+        if(msgType == UNKNOWN) {  //Start of a new message
+            bufferPtr = dataBuffer;
+            switch(data) { //Switch on message type character
+                case 0x42:
+                    msgType = AUTO_MSG;
+                    msgLen = AUTO_MSG_LEN;
+                    break;
+                case 0xA5:
+                    msgType = ACK_MSG;
+                    msgLen = RESPONSE_MSG_LEN;
+                    break;
+                case 0x69:
+                    msgType = NAK_MSG;
+                    msgLen = RESPONSE_MSG_LEN;
+                    break;
+                }
+            }
+        if(msgLen--  > 0 ) {  //Insert Character into type ahead buffer
+            *bufferPtr++ = data;
+            }
+        }
+    return;    
+    }    
+
+//Read last message received from type ahead message buffer
+//Mbed 5 Serial class only supports single character read and writes or
+// async buffer reads and wrutes
+MSG_TYPE readBuffer(uint8_t* buffer, uint16_t count)
+{
+    if(buffer == NULL || count > AUTO_MSG_LEN ) { //Calling without buffer or
+            return READ_ERROR;                    //asking for too many chars
+        }                                         //is an error
+    int counter = 0;
+    uint8_t* inPointer;
+    uint8_t* outPointer;
+    int delay;
+    logInfo( "Reading last message from sensor\n");
+    while(msgType == UNKNOWN ) { //No message received since last read
+        Thread::wait(CHAR_TIME); //Wait for new message
+        counter++;
+        if(counter > 40) { //Timeout exit after 40 character 40 Charcter times
+            break;
+            }
+        }
+    counter = 0;    
+    while(msgLen > 0 ) { //Wait for complete message to arrive
+        delay = CHAR_TIME * msgLen;
+        Thread::wait(delay);
+        counter++;
+        if(counter > 40) { //Time out exit after 40 character times
+            break;
+            }
+        }
+    if(counter > 40 ) { //Report timeout error
+       msgType = UNKNOWN;
+       return READ_ERROR;
+         }
+    else {
+        //Copy the message minus type flag to the requesters buffer 
+        inPointer = &dataBuffer[1];
+        outPointer = buffer;
+        for(int i = 0; i < count; i++) {
+            *outPointer++ = *inPointer++;
+            }
+        }
+    MSG_TYPE temp = msgType;
+    //Start Search for the next message
+    msgType = UNKNOWN;     
+    return temp;
+    }
+    
+            
+void writeBuffer(const uint8_t* buffer, uint16_t count)
+{
+    logInfo( "Sending Command to sensor\n");
+    uint8_t* pointer = (uint8_t*)buffer;
+    uint16_t counter = count;
+    while(1)
+    {
+        if(sensor.writeable())
+        {
+            logTrace(*pointer);
+            sensor.putc(*pointer++);
+            counter--;
+            }
+        if(counter == 0) {
+            return;
+            }
+        }
+    } 
+
+//Validate the received mesurements checksum
+
+bool checkValue(uint8_t *thebuf, uint8_t leng)
+{  
+  bool receiveflag = false;
+  uint16_t receiveSum = 0;
+
+  //Don't include the checksum bytes in the sum
+  for(int i=0; i<(leng-3); i++){
+  receiveSum=receiveSum+thebuf[i];
+  }
+  receiveSum=receiveSum + 0x42;
+ 
+  if(receiveSum == ((thebuf[leng-2]<<8)+thebuf[leng-1]))  //check the debug data 
+  {
+    receiveSum = 0;
+    receiveflag = true;
+  }
+  return receiveflag;
+}
+
+//Extract the 1 micron particle count from the messaage
+uint16_t transmitPM01(uint8_t *thebuf)
+{
+  uint16_t PM01Val;
+  PM01Val=((thebuf[3]<<8) + thebuf[4]); //count PM1.0 value of the air detector module
+  return PM01Val;
+}
+
+//Extract the 2.5 micron particle count from the messaage
+uint16_t transmitPM2_5(uint8_t *thebuf)
+{
+  uint16_t PM2_5Val;
+  PM2_5Val=((thebuf[5]<<8) + thebuf[6]);//count PM2.5 value of the air detector module
+  return PM2_5Val;
+  }
+
+//Extract the 10 micron particle count from the messaage
+uint16_t transmitPM10(uint8_t *thebuf)
+{
+  uint16_t PM10Val;
+  PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module  
+  return PM10Val;
+}
+
+int main()
+{
+    uint8_t dataBuffer[MESSAGE_LEN];
+    MSG_TYPE mType;
+    uint16_t PM01Value=0;     //define PM1.0 value of the air detector module
+    uint16_t PM2_5Value=0;        //define PM2.5 value of the air detector module
+    uint16_t PM10Value=0;         //define PM10 value of the air detector module
+    
+    pc.printf("Starting Honeywell Dust Sesor App version %\n", VERSION);
+
+    #ifdef DEBIG
+        pc.printf("Character wait time is %d millseconds", CHAR_TIME);
+    #endif
+    //Attach a receive interrupt handler
+    sensor.attach(receiveInterrupt, Serial::RxIrq);
+    msgType = UNKNOWN;
+    //Send start command to the sensor
+    writeBuffer(measureCommand, 4);
+ /*
+ Not geting response from sensor - first characters received are measurement data   
+    //Wait for sensors response
+    //while(!sensor.readable());
+    readBuffer(dataBuffer, 2);
+    response = dataBuffer[0] << 8 || dataBuffer[1];
+
+    switch(response) {
+        case OK:
+        logInfo("Sensor Auto Measurement Started");
+        break;
+        case BAD:
+        logInfo("Sensor rejected Start Measurement Commmand");
+        return -1;
+        default:
+        logInfo("Communication Error: Invalid Sensor Response");
+        return -2;
+    }
+*/    
+
+    //Start continous loop 
+    while(1) {
+        if((mType = readBuffer(dataBuffer,MESSAGE_LEN -1)) == AUTO_MSG) {
+            if(dataBuffer[0] == 0x4d){
+              if(checkValue(dataBuffer, MESSAGE_LEN-1)){
+                PM01Value = transmitPM01(dataBuffer); //count PM1.0 value of the air detector module
+                PM2_5Value = transmitPM2_5(dataBuffer);//count PM2.5 value of the air detector module
+                PM10Value = transmitPM10(dataBuffer); //count PM10 value of the air detector module 
+                }
+              else {
+                pc.puts("Message checksum error\n");
+                }
+              }
+            else {
+              pc.printf("Error Second Character not 0x4d but #x\n", dataBuffer[0]);
+              }
+             //Check for exit request
+            if(pc.readable()) {
+                char input = pc.getc();
+                if(input == 'Q' || input == 'q')
+                { 
+                    //Shutdown the sensor
+                    writeBuffer(stopCommand, 4);
+                    //Unlink the receive interrupt handler
+                    sensor.attach(0, Serial::RxIrq);
+                    pc.puts("Exit request received\n");
+                    return 0;
+                    }
+                }
+              // Use MBed wait function instead of Arduino delay loop
+            wait_ms(1000);          
+                  
+            pc.printf("PM1.0: %d ug/m3\n", PM01Value);  
+                
+            pc.printf("PM2.5: %d ug/m3\n", PM2_5Value);  
+                  
+            pc.printf("PM10: %d ug/m3\n", PM10Value);  
+        
+            pc.printf("\n");
+            }
+            else {
+                switch(mType) {
+                    case ACK_MSG:
+                    if(dataBuffer[0] == 0xA5) {
+                        pc.puts("Recived ACK response'\n");
+                        }
+                    else {
+                        pc.puts("Received corrupt ACK Response\n");
+                        }
+                    break;
+                    case NAK_MSG:
+                    if(dataBuffer[0] == 0x69) {
+                        pc.puts("Recived NAK response'\n");
+                        }
+                    else {
+                        pc.puts("Received corrupt NAK Response\n");
+                        }
+                    break;
+                    case READ_ERROR:
+                        pc.puts("Data Reading Error\n");
+                    break;
+                    }
+                }
+        }
+    }
\ No newline at end of file