Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 }
Generated on Sat Jul 16 2022 17:20:29 by
1.7.2