Alexandre Bouillot / Sds021

Dependents:   LoRaWAN-demo-72-bootcamp SDS021Test

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