semin ahn / PMS
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PMS.cpp Source File

PMS.cpp

00001 #include "PMS.h"
00002 
00003 PMS::PMS(RawSerial& stream)
00004 {
00005   this->_stream = &stream;
00006   _data = new DATA;
00007 }
00008 
00009 PMS::PMS(PinName tx, PinName rx) {
00010     this->_stream = new RawSerial(tx,rx,BAUD_RATE);
00011     _data = new DATA;
00012 }
00013 
00014 void PMS::begin(DATA& data) {
00015     _stream -> baud(BAUD_RATE);
00016     _tmr.start();
00017     _stream -> attach(callback(this,&PMS::RxInterrupt), Serial::RxIrq);
00018     _data = &data;
00019 }
00020 
00021 // Active mode. Default mode after power up. In this mode sensor would send serial data to the host automatically.
00022 void PMS::activeMode()
00023 {
00024   const char command[] = { 0x42, 0x4D, 0xE1, 0x00, 0x01, 0x01, 0x71 };
00025   for(int i = 0; i < sizeof(command); i++)
00026   {
00027     // bug: mcu stop after this transmitt
00028     //_stream -> putc(command[i]);
00029   }
00030   _mode = MODE_ACTIVE;
00031 }
00032 
00033 void PMS::passiveMode()
00034 {
00035   const char command[] = { 0x42, 0x4D, 0xE1, 0x00, 0x00, 0x01, 0x70 };
00036   for(int i = 0; i < sizeof(command); i++)
00037   {
00038     //_stream -> putc(command[i]);
00039   }
00040   _mode = MODE_PASSIVE;
00041 }
00042 
00043 // Request read in Passive Mode.
00044 void PMS::requestRead()
00045 {
00046   if (_mode == MODE_PASSIVE)
00047   {
00048     const char command[] = { 0x42, 0x4D, 0xE2, 0x00, 0x00, 0x01, 0x71 };
00049     for(int i = 0; i < sizeof(command); i++)
00050     {
00051          _stream -> putc(command[i]);
00052     }
00053   }
00054 }
00055 
00056 // Non-blocking function for parse response.
00057 bool PMS::available()
00058 {
00059     Caculate();
00060     return _status;
00061 }
00062 
00063 void PMS::Caculate()
00064 {
00065     _status = STATUS_WAITING;
00066     for(int i = 0; i < 32; i++)
00067     {
00068       uint8_t ch = buf[i];
00069       switch (i)
00070       {
00071       case 0:
00072         if (ch != 0x42)
00073         {
00074           return;
00075         }
00076         _calculatedChecksum = ch;
00077         break;
00078 
00079       case 1:
00080         if (ch != 0x4D)
00081         {
00082 
00083           return;
00084         }
00085         _calculatedChecksum += ch;
00086         break;
00087         
00088       case 2:
00089         _calculatedChecksum += ch;
00090         _frameLen = ch << 8;
00091         break;
00092 
00093       case 3:
00094         _frameLen |= ch;
00095       // Unsupported sensor, different frame length, transmission error e.t.c.
00096         if (_frameLen != 2 * 9 + 2 && _frameLen != 2 * 13 + 2)
00097         {
00098 
00099           return;
00100         }
00101         _calculatedChecksum += ch;
00102         break;
00103 
00104       default:
00105         if (i == _frameLen + 2)
00106         {
00107           _checksum = ch << 8;
00108         }
00109         else if (i == _frameLen + 2 + 1)
00110         {
00111           _checksum |= ch;
00112           if (_calculatedChecksum == _checksum)
00113           {
00114             _status = STATUS_OK;
00115 
00116           // Standard Particles, CF=1.
00117             _data->PM_SP_UG_1_0 = makeWord(_payload[0], _payload[1]);
00118             _data->PM_SP_UG_2_5 = makeWord(_payload[2], _payload[3]);
00119             _data->PM_SP_UG_10_0 = makeWord(_payload[4], _payload[5]);
00120           // Atmospheric Environment.
00121             _data->PM_AE_UG_1_0 = makeWord(_payload[6], _payload[7]);
00122             _data->PM_AE_UG_2_5 = makeWord(_payload[8], _payload[9]);
00123             _data->PM_AE_UG_10_0 = makeWord(_payload[10], _payload[11]);
00124           }
00125           return;
00126           }
00127           else
00128           {
00129             _calculatedChecksum += ch;
00130             uint8_t payloadIndex = i - 4;
00131         // Payload is common to all sensors (first 2x6 bytes).
00132             if (payloadIndex < sizeof(_payload))
00133             {
00134               _payload[payloadIndex] = ch;
00135             }
00136           }
00137           break;
00138         }
00139     }
00140 }
00141 
00142 uint16_t PMS::makeWord(uint8_t high, uint8_t low) {
00143     return (high << 8) | low;
00144 }
00145 
00146 void PMS::RxInterrupt()
00147 {
00148     int cnt = 0;
00149     while(_stream -> readable() || cnt < 32)
00150     {
00151         //if(cnt >= DUST_BUFFER) break;
00152         buf[cnt++] = _stream -> getc();
00153     }
00154 }