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.
Dependents: LoRaWAN-demo-72-bootcamp SDS021Test
Diff: Sds021.cpp
- Revision:
- 0:0c1a6a29b8c4
- Child:
- 1:fb3d61ffd503
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Sds021.cpp Sat Jan 28 11:31:02 2017 +0000 @@ -0,0 +1,192 @@ +/*! + * Sds021.cpp + * + * Control the inovafitness particles sensor SDS021 + * + * Copyright (c) 2017 - Alexandre Bouillot github.com/abouillot + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documnetation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + #include "Sds021.h" + +char* SDS21::prepareMessage(SDS21::action_t action, bool set, int address, int value) +{ + // reset command content + memset(outMessage, 0, kOutputLength); + + // Sets common message values + outMessage[0] = head; + outMessage[1] = commandCmd; + outMessage[2] = action; + outMessage[3] = set; + outMessage[4] = value; + outMessage[15] = address >> 8; + outMessage[16] = address & 0xFF; + outMessage[kOutputLength - 1] = tail; + + return outMessage; +} + +char SDS21::calcCheckSum(char* buffer, int start_idx, int stop_idx) +{ + int chk = 0; + for (int i = start_idx; i < stop_idx; i++) + chk += buffer[i]; + chk &= 0xFF; + return (char)chk; +} + +bool SDS21::checkSum(char* buffer, int start_idx, int stop_idx) +{ + return calcCheckSum(buffer, start_idx, stop_idx) == buffer[stop_idx]; +} + +void SDS21::writeMessage(char* buffer) +{ + // Calculates and stores checksum in output buffer + outMessage[17] = calcCheckSum(outMessage, 2, 17); + _sds021.write(outMessage, kOutputLength); + + // Waits for software serial to finish sending message +// delay(20); // (19 bytes * 8 bits * 0.104 ms = 15.808 ms minimum) +// delete[] buffer; + + while (!update()); + +} + +bool SDS21::update() +{ + bool updated = false; + + // Check Serial input buffer for a message + while (_sds021.readable()) { + int bufPos = 0; + + // Clear the local buffer + memset(inMessage, 0, kInputLength); + + do { + while(!_sds021.readable()) ; + inMessage[bufPos] = _sds021.getc(); + } while (inMessage[bufPos] != head); + + + while (++bufPos < kInputLength) { + while(!_sds021.readable()) ; + inMessage[bufPos] = _sds021.getc(); + } + + for (int i=0; i<kInputLength; i++) { + printf("%02x_", inMessage[i]); + } + printf("\n"); + + // Update local values if message is valid + if (checkSum(inMessage)) { + char command_id = inMessage[1]; + + // Parse data frame + if (command_id == dataCmd) { + _PM2_5 = (float)((inMessage[3] << 8) + inMessage[2]) / 10.0; + _PM10 = (float)((inMessage[5] << 8) + inMessage[4]) / 10.0; + } + + // Parse reply frame + else if (command_id == replyCmd) { + char action = inMessage[2]; + + if (action == modeAct) + _mode = inMessage[4]; + else if (action == stateAct) + _state = inMessage[4]; + else if (action == intervalAct) + _interval = inMessage[4]; + else if (action == versionAct) { + _firmware.year = inMessage[3]; + _firmware.month = inMessage[4]; + _firmware.day = inMessage[5]; + } + } + + // Update device ID + _id = (inMessage[6] << 8) + inMessage[7]; + + updated = true; + } else + printf("checksum error %02x %02x\n", calcCheckSum(inMessage, 2, 8), inMessage[8]); + } + + return updated; +} + +void SDS21::setId(int new_id) +{ + // Compiles the message + prepareMessage(idAct, true, _id); + outMessage[13] = new_id >> 8; + outMessage[14] = new_id & 0xFF; + + for (int i=0; i<kOutputLength; i++) + printf("%02x.", outMessage[i]); + printf("\n"); + writeMessage(outMessage); +} + +void SDS21::setPassiveMode(bool passive) +{ + // Compiles the message + prepareMessage(modeAct, true, _id, passive); + writeMessage(outMessage); +} + +void SDS21::readData() +{ + prepareMessage(queryAct, false, _id); + writeMessage(outMessage); +} + + +void SDS21::setInterval(uint8_t minutes) +{ + // Clamps minutes between 0-30 + if (minutes > 30) + minutes = 30; + + // Compiles the message + prepareMessage(intervalAct, true, _id, minutes); + writeMessage(outMessage); +} + +void SDS21::setAwake(bool working) +{ + // Compiles the message + prepareMessage(stateAct, true, _id, working); + writeMessage(outMessage); +} + +SDS21::version_t SDS21::getVersion() +{ + // Compiles the message + prepareMessage(versionAct, true, _id); + writeMessage(outMessage); + + return _firmware; +} \ No newline at end of file