mDot / Mbed OS Honneywell_Dust_Simple
Committer:
Roietronics
Date:
Sun Aug 13 06:09:03 2017 +0000
Revision:
8:494f6fcecfbc
Parent:
7:5f612ed18852
Child:
10:43337cc2ac79
Revised version of Honeywell_Dust_Sample using a Serial Receive Interrupt Handler and a in memory message data buffer
; Initial CheckIn

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Roietronics 1:8cad8f7852d4 1 /* Run Honeywell Dust Sensor in continous Sampling Mode on a mDot
Roietronics 3:1ba96949e2fd 2 Version 1.1
Roietronics 0:8326629a1b97 3 Steve Mylroie Roitronic August 1st 2017
Roietronics 0:8326629a1b97 4 @C Copyright Global Quality Corp
Roietronics 0:8326629a1b97 5 */
Roietronics 0:8326629a1b97 6
Roietronics 0:8326629a1b97 7 #include "mbed.h"
Roietronics 0:8326629a1b97 8 #include "stdlib.h"
Roietronics 0:8326629a1b97 9
Roietronics 8:494f6fcecfbc 10 #define VERSION "2.0"
Roietronics 4:12dfd9a8ee76 11
Roietronics 0:8326629a1b97 12 #define TRACE_MODE
Roietronics 0:8326629a1b97 13
Roietronics 0:8326629a1b97 14 //Turn on trace logging to the PC USB port
Roietronics 0:8326629a1b97 15 #ifdef TRACE_MODE
Roietronics 0:8326629a1b97 16 //Log level need to be set one level higher than the high level to be output
Roietronics 5:7cabc36d4352 17 #define LOG_LEVEL 2
Roietronics 0:8326629a1b97 18 #define DEBUG
Roietronics 0:8326629a1b97 19 #endif
Roietronics 0:8326629a1b97 20
Roietronics 3:1ba96949e2fd 21
Roietronics 0:8326629a1b97 22 const uint8_t* measureCommand = "68014057";
Roietronics 0:8326629a1b97 23 const uint8_t* stopCommand = "68012077";
Roietronics 0:8326629a1b97 24
Roietronics 5:7cabc36d4352 25 //Sensor command response codes
Roietronics 0:8326629a1b97 26 #define OK 0xA5A5
Roietronics 0:8326629a1b97 27 #define BAD 0x9696
Roietronics 0:8326629a1b97 28
Roietronics 5:7cabc36d4352 29 //Auto Mode measurement response lenght
Roietronics 0:8326629a1b97 30 #define MESSAGE_LEN 32
Roietronics 5:7cabc36d4352 31
Roietronics 0:8326629a1b97 32 //sensor measurement cycle in millseconds
Roietronics 0:8326629a1b97 33 #define MEASURE_DELAY 1500
Roietronics 0:8326629a1b97 34
Roietronics 3:1ba96949e2fd 35 Serial pc(USBTX, USBRX, 115200);
Roietronics 3:1ba96949e2fd 36
Roietronics 0:8326629a1b97 37 //Use USB debug pott for the debug stream
Roietronics 0:8326629a1b97 38 #ifdef DEBUG
Roietronics 3:1ba96949e2fd 39 uint32_t debugLevel = LOG_LEVEL;
Roietronics 3:1ba96949e2fd 40 #else
Roietronics 3:1ba96949e2fd 41 uint32_t debugLevel = 0;
Roietronics 0:8326629a1b97 42 #endif
Roietronics 0:8326629a1b97 43
Roietronics 3:1ba96949e2fd 44 void logInfo(char* text) {
Roietronics 3:1ba96949e2fd 45 if ( debugLevel > 0 ) {
Roietronics 3:1ba96949e2fd 46 pc.printf("\n%s\n", text );
Roietronics 3:1ba96949e2fd 47 }
Roietronics 3:1ba96949e2fd 48 return;
Roietronics 5:7cabc36d4352 49 }
Roietronics 3:1ba96949e2fd 50
Roietronics 3:1ba96949e2fd 51 void logTrace(uint8_t data) {
Roietronics 3:1ba96949e2fd 52 if (debugLevel > 2 ){ pc.putc( data );
Roietronics 3:1ba96949e2fd 53 }
Roietronics 3:1ba96949e2fd 54 return;
Roietronics 3:1ba96949e2fd 55 }
Roietronics 3:1ba96949e2fd 56
Roietronics 5:7cabc36d4352 57 //Board specfic serial port pin definitions
Roietronics 3:1ba96949e2fd 58
Roietronics 5:7cabc36d4352 59 #ifdef TARGET_Freescale //Freedom Board
Roietronics 5:7cabc36d4352 60
Roietronics 5:7cabc36d4352 61 #define SENSOR_XMT D1
Roietronics 5:7cabc36d4352 62 #define SENSOR_RCV D0
Roietronics 5:7cabc36d4352 63
Roietronics 5:7cabc36d4352 64 #endif
Roietronics 5:7cabc36d4352 65
Roietronics 5:7cabc36d4352 66 #ifdef TARGET_MTS_MDOT_F411RE //Multi Tech mDot
Roietronics 5:7cabc36d4352 67
Roietronics 5:7cabc36d4352 68 #define SENSOR_XMT PA_2
Roietronics 5:7cabc36d4352 69 #define SENSOR_RCV PA_3
Roietronics 5:7cabc36d4352 70
Roietronics 5:7cabc36d4352 71 #endif
Roietronics 5:7cabc36d4352 72
Roietronics 8:494f6fcecfbc 73 #define RESPONSE_MSG_LEN 2
Roietronics 8:494f6fcecfbc 74 #define AUTO_MSG_LEN 32
Roietronics 8:494f6fcecfbc 75
Roietronics 8:494f6fcecfbc 76 //Time required to receive one character at 9600 baud
Roietronics 8:494f6fcecfbc 77 #define CHAR_TIME 1000/9600 & 10
Roietronics 8:494f6fcecfbc 78
Roietronics 8:494f6fcecfbc 79 enum MSG_TYPE{ UNKNOWN,
Roietronics 8:494f6fcecfbc 80 ACK_MSG,
Roietronics 8:494f6fcecfbc 81 NAK_MSG,
Roietronics 8:494f6fcecfbc 82 AUTO_MSG,
Roietronics 8:494f6fcecfbc 83 READ_ERROR } msgType;
Roietronics 8:494f6fcecfbc 84
Roietronics 8:494f6fcecfbc 85
Roietronics 8:494f6fcecfbc 86 uint8_t dataBuffer[AUTO_MSG_LEN];
Roietronics 8:494f6fcecfbc 87 uint8_t* bufferPtr;
Roietronics 8:494f6fcecfbc 88 uint32_t msgLen;
Roietronics 8:494f6fcecfbc 89
Roietronics 8:494f6fcecfbc 90
Roietronics 5:7cabc36d4352 91 //Use a boards second UART to communicate witb the Honneywell sensor
Roietronics 0:8326629a1b97 92 //Default UART setting are 8,N,1
Roietronics 8:494f6fcecfbc 93 RawSerial sensor( SENSOR_XMT, SENSOR_RCV, 9600);
Roietronics 8:494f6fcecfbc 94
Roietronics 8:494f6fcecfbc 95 //Received chararter interupt handler
Roietronics 8:494f6fcecfbc 96
Roietronics 8:494f6fcecfbc 97 void receiveInterrupt() {
Roietronics 8:494f6fcecfbc 98 uint8_t data;
Roietronics 8:494f6fcecfbc 99 if(sensor.readable()) {
Roietronics 8:494f6fcecfbc 100 data = sensor.getc();
Roietronics 8:494f6fcecfbc 101 if(msgType == UNKNOWN) {
Roietronics 8:494f6fcecfbc 102 switch(data) {
Roietronics 8:494f6fcecfbc 103 case 0x42:
Roietronics 8:494f6fcecfbc 104 msgType = AUTO_MSG;
Roietronics 8:494f6fcecfbc 105 msgLen = AUTO_MSG_LEN;
Roietronics 8:494f6fcecfbc 106 bufferPtr = dataBuffer;
Roietronics 8:494f6fcecfbc 107 break;
Roietronics 8:494f6fcecfbc 108 case 0xA5:
Roietronics 8:494f6fcecfbc 109 msgType = ACK_MSG;
Roietronics 8:494f6fcecfbc 110 msgLen = RESPONSE_MSG_LEN;
Roietronics 8:494f6fcecfbc 111 bufferPtr = dataBuffer;
Roietronics 8:494f6fcecfbc 112 break;
Roietronics 8:494f6fcecfbc 113 case 0x69:
Roietronics 8:494f6fcecfbc 114 msgType = NAK_MSG;
Roietronics 8:494f6fcecfbc 115 msgLen = RESPONSE_MSG_LEN;
Roietronics 8:494f6fcecfbc 116 bufferPtr = dataBuffer;
Roietronics 8:494f6fcecfbc 117 break;
Roietronics 8:494f6fcecfbc 118 }
Roietronics 8:494f6fcecfbc 119 }
Roietronics 8:494f6fcecfbc 120 if(msgLen-- > 0 ) {
Roietronics 8:494f6fcecfbc 121 *bufferPtr++ = data;
Roietronics 8:494f6fcecfbc 122 }
Roietronics 8:494f6fcecfbc 123 }
Roietronics 8:494f6fcecfbc 124 return;
Roietronics 8:494f6fcecfbc 125 }
Roietronics 0:8326629a1b97 126
Roietronics 0:8326629a1b97 127 //synchrnous serial read and writes
Roietronics 0:8326629a1b97 128 //Mbed 5 Serial class only supports single character read and writes or
Roietronics 0:8326629a1b97 129 // async buffer reads abd wrutes
Roietronics 8:494f6fcecfbc 130 MSG_TYPE readBuffer(uint8_t* buffer, uint16_t count)
Roietronics 0:8326629a1b97 131 {
Roietronics 8:494f6fcecfbc 132 if(buffer == NULL || count > AUTO_MSG_LEN ) {
Roietronics 8:494f6fcecfbc 133 return READ_ERROR;
Roietronics 8:494f6fcecfbc 134 }
Roietronics 8:494f6fcecfbc 135 int counter = 0;
Roietronics 8:494f6fcecfbc 136 uint8_t* inPointer;
Roietronics 8:494f6fcecfbc 137 uint8_t* outPointer;
Roietronics 8:494f6fcecfbc 138 int delay;
Roietronics 5:7cabc36d4352 139 logInfo( "Receiving Data from sensor\n");
Roietronics 8:494f6fcecfbc 140 while(msgType == UNKNOWN ) {
Roietronics 8:494f6fcecfbc 141 wait(CHAR_TIME);
Roietronics 8:494f6fcecfbc 142 counter++;
Roietronics 8:494f6fcecfbc 143 if(counter > 40) {
Roietronics 8:494f6fcecfbc 144 break;
Roietronics 0:8326629a1b97 145 }
Roietronics 0:8326629a1b97 146 }
Roietronics 8:494f6fcecfbc 147 counter = 9;
Roietronics 8:494f6fcecfbc 148 while(msgLen > 0 ) {
Roietronics 8:494f6fcecfbc 149 delay = CHAR_TIME * msgLen;
Roietronics 8:494f6fcecfbc 150 wait(delay);
Roietronics 8:494f6fcecfbc 151 counter++;
Roietronics 8:494f6fcecfbc 152 if(counter > 40) {
Roietronics 8:494f6fcecfbc 153 break;
Roietronics 8:494f6fcecfbc 154 }
Roietronics 8:494f6fcecfbc 155 }
Roietronics 8:494f6fcecfbc 156 if(counter > 40 ) {
Roietronics 8:494f6fcecfbc 157 msgType = UNKNOWN;
Roietronics 8:494f6fcecfbc 158 return READ_ERROR;
Roietronics 8:494f6fcecfbc 159 }
Roietronics 8:494f6fcecfbc 160 else {
Roietronics 8:494f6fcecfbc 161 //Copy the message to the requesters buffer
Roietronics 8:494f6fcecfbc 162 inPointer = &dataBuffer[1];
Roietronics 8:494f6fcecfbc 163 outPointer = buffer;
Roietronics 8:494f6fcecfbc 164 for(int i = 0; i < count; i++) {
Roietronics 8:494f6fcecfbc 165 *outPointer++ = *inPointer++;
Roietronics 8:494f6fcecfbc 166 }
Roietronics 8:494f6fcecfbc 167 }
Roietronics 8:494f6fcecfbc 168 MSG_TYPE temp = msgType;
Roietronics 8:494f6fcecfbc 169 //Start Search for the next message
Roietronics 8:494f6fcecfbc 170 msgType = UNKNOWN;
Roietronics 8:494f6fcecfbc 171 return temp;
Roietronics 0:8326629a1b97 172 }
Roietronics 0:8326629a1b97 173
Roietronics 8:494f6fcecfbc 174
Roietronics 0:8326629a1b97 175 void writeBuffer(const uint8_t* buffer, uint16_t count)
Roietronics 0:8326629a1b97 176 {
Roietronics 5:7cabc36d4352 177 logInfo( "Sending Data to sensor\n");
Roietronics 0:8326629a1b97 178 uint8_t* pointer = (uint8_t*)buffer;
Roietronics 0:8326629a1b97 179 uint16_t counter = count;
Roietronics 0:8326629a1b97 180 while(1)
Roietronics 0:8326629a1b97 181 {
Roietronics 0:8326629a1b97 182 if(sensor.writeable())
Roietronics 0:8326629a1b97 183 {
Roietronics 3:1ba96949e2fd 184 logTrace(*pointer);
Roietronics 0:8326629a1b97 185 sensor.putc(*pointer++);
Roietronics 0:8326629a1b97 186 counter--;
Roietronics 0:8326629a1b97 187 }
Roietronics 4:12dfd9a8ee76 188 if(counter == 0) {
Roietronics 0:8326629a1b97 189 return;
Roietronics 0:8326629a1b97 190 }
Roietronics 0:8326629a1b97 191 }
Roietronics 0:8326629a1b97 192 }
Roietronics 0:8326629a1b97 193
Roietronics 4:12dfd9a8ee76 194 //Validate the received mesurements checksum
Roietronics 0:8326629a1b97 195
Roietronics 0:8326629a1b97 196 bool checkValue(uint8_t *thebuf, uint8_t leng)
Roietronics 0:8326629a1b97 197 {
Roietronics 0:8326629a1b97 198 bool receiveflag = false;
Roietronics 7:5f612ed18852 199 uint16_t receiveSum = 0;
Roietronics 0:8326629a1b97 200
Roietronics 6:6aa9d16e27bc 201 //Don't include the checksum bytes in the sum
Roietronics 6:6aa9d16e27bc 202 for(int i=0; i<(leng-3); i++){
Roietronics 0:8326629a1b97 203 receiveSum=receiveSum+thebuf[i];
Roietronics 0:8326629a1b97 204 }
Roietronics 0:8326629a1b97 205 receiveSum=receiveSum + 0x42;
Roietronics 0:8326629a1b97 206
Roietronics 0:8326629a1b97 207 if(receiveSum == ((thebuf[leng-2]<<8)+thebuf[leng-1])) //check the debug data
Roietronics 0:8326629a1b97 208 {
Roietronics 0:8326629a1b97 209 receiveSum = 0;
Roietronics 0:8326629a1b97 210 receiveflag = true;
Roietronics 0:8326629a1b97 211 }
Roietronics 0:8326629a1b97 212 return receiveflag;
Roietronics 0:8326629a1b97 213 }
Roietronics 0:8326629a1b97 214
Roietronics 0:8326629a1b97 215 //Extract the 1 micron particle count from the messaage
Roietronics 0:8326629a1b97 216 uint16_t transmitPM01(uint8_t *thebuf)
Roietronics 0:8326629a1b97 217 {
Roietronics 0:8326629a1b97 218 uint16_t PM01Val;
Roietronics 0:8326629a1b97 219 PM01Val=((thebuf[3]<<8) + thebuf[4]); //count PM1.0 value of the air detector module
Roietronics 0:8326629a1b97 220 return PM01Val;
Roietronics 0:8326629a1b97 221 }
Roietronics 0:8326629a1b97 222
Roietronics 0:8326629a1b97 223 //Extract the 2.5 micron particle count from the messaage
Roietronics 0:8326629a1b97 224 uint16_t transmitPM2_5(uint8_t *thebuf)
Roietronics 0:8326629a1b97 225 {
Roietronics 0:8326629a1b97 226 uint16_t PM2_5Val;
Roietronics 0:8326629a1b97 227 PM2_5Val=((thebuf[5]<<8) + thebuf[6]);//count PM2.5 value of the air detector module
Roietronics 0:8326629a1b97 228 return PM2_5Val;
Roietronics 0:8326629a1b97 229 }
Roietronics 0:8326629a1b97 230
Roietronics 0:8326629a1b97 231 //Extract the 10 micron particle count from the messaage
Roietronics 0:8326629a1b97 232 uint16_t transmitPM10(uint8_t *thebuf)
Roietronics 0:8326629a1b97 233 {
Roietronics 0:8326629a1b97 234 uint16_t PM10Val;
Roietronics 0:8326629a1b97 235 PM10Val=((thebuf[7]<<8) + thebuf[8]); //count PM10 value of the air detector module
Roietronics 0:8326629a1b97 236 return PM10Val;
Roietronics 0:8326629a1b97 237 }
Roietronics 0:8326629a1b97 238
Roietronics 0:8326629a1b97 239 int main()
Roietronics 0:8326629a1b97 240 {
Roietronics 5:7cabc36d4352 241 uint8_t dataBuffer[MESSAGE_LEN];
Roietronics 8:494f6fcecfbc 242 MSG_TYPE mType;
Roietronics 0:8326629a1b97 243 uint16_t response;
Roietronics 0:8326629a1b97 244 uint16_t PM01Value=0; //define PM1.0 value of the air detector module
Roietronics 0:8326629a1b97 245 uint16_t PM2_5Value=0; //define PM2.5 value of the air detector module
Roietronics 0:8326629a1b97 246 uint16_t PM10Value=0; //define PM10 value of the air detector module
Roietronics 4:12dfd9a8ee76 247
Roietronics 7:5f612ed18852 248 pc.printf("Starting Honeywell Dust Sesor App version %\n", VERSION);
Roietronics 8:494f6fcecfbc 249 //Attach a receive interrupt handler
Roietronics 8:494f6fcecfbc 250 sensor.attach(receiveInterrupt, Serial::RxIrq);
Roietronics 8:494f6fcecfbc 251 msgType = UNKNOWN;
Roietronics 0:8326629a1b97 252 //Send start command to the sensor
Roietronics 0:8326629a1b97 253 writeBuffer(measureCommand, 4);
Roietronics 5:7cabc36d4352 254 /*
Roietronics 5:7cabc36d4352 255 Not geting response from sensor - first characters received are measurement data
Roietronics 0:8326629a1b97 256 //Wait for sensors response
Roietronics 0:8326629a1b97 257 //while(!sensor.readable());
Roietronics 0:8326629a1b97 258 readBuffer(dataBuffer, 2);
Roietronics 0:8326629a1b97 259 response = dataBuffer[0] << 8 || dataBuffer[1];
Roietronics 0:8326629a1b97 260
Roietronics 0:8326629a1b97 261 switch(response) {
Roietronics 0:8326629a1b97 262 case OK:
Roietronics 0:8326629a1b97 263 logInfo("Sensor Auto Measurement Started");
Roietronics 0:8326629a1b97 264 break;
Roietronics 0:8326629a1b97 265 case BAD:
Roietronics 0:8326629a1b97 266 logInfo("Sensor rejected Start Measurement Commmand");
Roietronics 0:8326629a1b97 267 return -1;
Roietronics 0:8326629a1b97 268 default:
Roietronics 0:8326629a1b97 269 logInfo("Communication Error: Invalid Sensor Response");
Roietronics 0:8326629a1b97 270 return -2;
Roietronics 0:8326629a1b97 271 }
Roietronics 5:7cabc36d4352 272 */
Roietronics 4:12dfd9a8ee76 273
Roietronics 0:8326629a1b97 274 //Start continous loop
Roietronics 8:494f6fcecfbc 275 while(1) {
Roietronics 8:494f6fcecfbc 276 if((mType = readBuffer(dataBuffer,MESSAGE_LEN -1)) == AUTO_MSG) {
Roietronics 0:8326629a1b97 277 if(dataBuffer[0] == 0x4d){
Roietronics 6:6aa9d16e27bc 278 if(checkValue(dataBuffer, MESSAGE_LEN-1)){
Roietronics 7:5f612ed18852 279 PM01Value = transmitPM01(dataBuffer); //count PM1.0 value of the air detector module
Roietronics 7:5f612ed18852 280 PM2_5Value = transmitPM2_5(dataBuffer);//count PM2.5 value of the air detector module
Roietronics 7:5f612ed18852 281 PM10Value = transmitPM10(dataBuffer); //count PM10 value of the air detector module
Roietronics 8:494f6fcecfbc 282 }
Roietronics 6:6aa9d16e27bc 283 else {
Roietronics 8:494f6fcecfbc 284 pc.puts("Message checksum error\n");
Roietronics 8:494f6fcecfbc 285 }
Roietronics 6:6aa9d16e27bc 286 }
Roietronics 7:5f612ed18852 287 else {
Roietronics 7:5f612ed18852 288 pc.printf("Second Character was %x\n", dataBuffer[0]);
Roietronics 7:5f612ed18852 289 }
Roietronics 7:5f612ed18852 290 //Check for exit request
Roietronics 7:5f612ed18852 291 if(pc.readable()) {
Roietronics 7:5f612ed18852 292 char input = pc.getc();
Roietronics 7:5f612ed18852 293 if(input == 'Q' || input == 'q')
Roietronics 7:5f612ed18852 294 {
Roietronics 8:494f6fcecfbc 295 //Shutdown the sensor
Roietronics 7:5f612ed18852 296 writeBuffer(stopCommand, 4);
Roietronics 8:494f6fcecfbc 297 //Unlink the receive interrupt handler
Roietronics 8:494f6fcecfbc 298 sensor.attach(0, Serial::RxIrq);
Roietronics 8:494f6fcecfbc 299 pc.puts("Exit request received\n");
Roietronics 7:5f612ed18852 300 return 0;
Roietronics 8:494f6fcecfbc 301 }
Roietronics 7:5f612ed18852 302 }
Roietronics 8:494f6fcecfbc 303 // Use MBed wait function instead of Arduino delay loop
Roietronics 8:494f6fcecfbc 304 wait_ms(1000);
Roietronics 8:494f6fcecfbc 305
Roietronics 8:494f6fcecfbc 306 pc.printf("PM1.0: %d ug/m3\n", PM01Value);
Roietronics 8:494f6fcecfbc 307
Roietronics 8:494f6fcecfbc 308 pc.printf("PM2.5: %d ug/m3\n", PM2_5Value);
Roietronics 8:494f6fcecfbc 309
Roietronics 8:494f6fcecfbc 310 pc.printf("PM10: %d ug/m3\n", PM10Value);
Roietronics 8:494f6fcecfbc 311
Roietronics 8:494f6fcecfbc 312 pc.printf("\n");
Roietronics 5:7cabc36d4352 313 }
Roietronics 8:494f6fcecfbc 314 else {
Roietronics 8:494f6fcecfbc 315 switch(mType) {
Roietronics 8:494f6fcecfbc 316 case ACK_MSG:
Roietronics 8:494f6fcecfbc 317 if(dataBuffer[0] == 0xA5) {
Roietronics 8:494f6fcecfbc 318 pc.puts("Recived ACK response'\n");
Roietronics 8:494f6fcecfbc 319 }
Roietronics 8:494f6fcecfbc 320 else {
Roietronics 8:494f6fcecfbc 321 pc.puts("Received corrupt ACK Response\n");
Roietronics 8:494f6fcecfbc 322 }
Roietronics 8:494f6fcecfbc 323 break;
Roietronics 8:494f6fcecfbc 324 case NAK_MSG:
Roietronics 8:494f6fcecfbc 325 if(dataBuffer[0] == 0x69) {
Roietronics 8:494f6fcecfbc 326 pc.puts("Recived NAK response'\n");
Roietronics 8:494f6fcecfbc 327 }
Roietronics 8:494f6fcecfbc 328 else {
Roietronics 8:494f6fcecfbc 329 pc.puts("Received corrupt NAK Response\n");
Roietronics 8:494f6fcecfbc 330 }
Roietronics 8:494f6fcecfbc 331 break;
Roietronics 8:494f6fcecfbc 332 case READ_ERROR:
Roietronics 8:494f6fcecfbc 333 puts("Data Reading Error");
Roietronics 8:494f6fcecfbc 334 break;
Roietronics 8:494f6fcecfbc 335 }
Roietronics 8:494f6fcecfbc 336 }
Roietronics 8:494f6fcecfbc 337 }
Roietronics 8:494f6fcecfbc 338 }