|
| 1 | +// Default sensor sketch for MySensor Micro module |
| 2 | +// Act as a temperature / humidity sensor by default. |
| 3 | +// |
| 4 | +// If A1 is held low while powering on, it will clear eeprom (and thereby the stored nodeid) |
| 5 | +// |
| 6 | +// Battery voltage is repported as child sensorId 199, as well as battery percentage |
| 7 | + |
| 8 | + |
| 9 | +#include <MySensor.h> |
| 10 | +#include <Wire.h> |
| 11 | +#include <SI7021.h> |
| 12 | +#include <SPI.h> |
| 13 | +#include <EEPROM.h> |
| 14 | + |
| 15 | +// Define a static node address, remove if you want auto address assignment |
| 16 | +//#define NODE_ADDRESS 3 |
| 17 | + |
| 18 | +// Child sensor ID's |
| 19 | +#define CHILD_ID_TEMP 1 |
| 20 | +#define CHILD_ID_HUM 2 |
| 21 | +#define CHILD_ID_BATT 199 |
| 22 | + |
| 23 | +//Pin definitions |
| 24 | +#define RESET_CFG_PIN A1 |
| 25 | +#define LED_PIN A2 |
| 26 | + |
| 27 | +#define MEASURE_INTERVAL 60000 |
| 28 | + |
| 29 | +SI7021 humiditySensor; |
| 30 | +MySensor gw; |
| 31 | + |
| 32 | +// Sensor messages |
| 33 | +MyMessage msgHum(CHILD_ID_HUM, V_HUM); |
| 34 | +MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP); |
| 35 | +MyMessage msgBattery(CHILD_ID_BATT, V_VOLTAGE); |
| 36 | + |
| 37 | +// Global settings |
| 38 | +int measureCount = 0; |
| 39 | + |
| 40 | +// Storage of old measurements |
| 41 | +float lastTemperature = -100; |
| 42 | +int lastHumidity = -100; |
| 43 | +long lastBattery = -100; |
| 44 | + |
| 45 | + |
| 46 | +void setup() { |
| 47 | + |
| 48 | + Serial.begin(115200); |
| 49 | + pinMode(LED_PIN, OUTPUT); |
| 50 | + digitalWrite(LED_PIN, LOW); |
| 51 | + |
| 52 | + // First check if we should boot into clear eeprom mode |
| 53 | + pinMode(RESET_CFG_PIN, INPUT); |
| 54 | + digitalWrite(RESET_CFG_PIN, HIGH); // Enable pullup |
| 55 | + if (!digitalRead(RESET_CFG_PIN)) resetEEP(); |
| 56 | + digitalWrite(RESET_CFG_PIN, LOW); |
| 57 | + |
| 58 | + digitalWrite(LED_PIN, HIGH); |
| 59 | + |
| 60 | +#ifdef NODE_ADDRESS |
| 61 | + gw.begin(NULL, NODE_ADDRESS, false); |
| 62 | +#else |
| 63 | + gw.begin(NULL,AUTO,false); |
| 64 | +#endif |
| 65 | + |
| 66 | + digitalWrite(LED_PIN, LOW); |
| 67 | + |
| 68 | + humiditySensor.begin(); |
| 69 | + |
| 70 | + gw.sendSketchInfo("EnvironmentSensor", "1.0"); |
| 71 | + |
| 72 | + gw.present(CHILD_ID_TEMP,S_TEMP); |
| 73 | + gw.present(CHILD_ID_HUM,S_HUM); |
| 74 | + |
| 75 | + gw.present(CHILD_ID_BATT, S_POWER); |
| 76 | +} |
| 77 | + |
| 78 | + |
| 79 | +// Main loop function |
| 80 | +void loop() { |
| 81 | + measureCount ++; |
| 82 | + bool forceTransmit = false; |
| 83 | + |
| 84 | + if (measureCount > 30) {// Every 60th time we wake up, force a transmission on all sensors. |
| 85 | + forceTransmit = true; |
| 86 | + measureCount = 0; |
| 87 | + } |
| 88 | + |
| 89 | + gw.process(); |
| 90 | + sendBattLevel(forceTransmit); |
| 91 | + sendTempHumidityMeasurements(forceTransmit); |
| 92 | + |
| 93 | + gw.sleep(MEASURE_INTERVAL); |
| 94 | +} |
| 95 | + |
| 96 | +/* |
| 97 | + * Sends temperature and humidity from Si7021 sensor |
| 98 | + * |
| 99 | + * Parameters |
| 100 | + * - force : Forces transmission of a value (even if it's the same as previous measurement) |
| 101 | + */ |
| 102 | +void sendTempHumidityMeasurements(bool force) |
| 103 | +{ |
| 104 | + if (force) { |
| 105 | + lastHumidity = -100; |
| 106 | + lastTemperature = -100; |
| 107 | + } |
| 108 | + |
| 109 | + float temperature = humiditySensor.getCelsiusHundredths()/10; |
| 110 | + |
| 111 | + temperature = temperature / 10; |
| 112 | + |
| 113 | + int humidity = humiditySensor.getHumidityPercent(); |
| 114 | + |
| 115 | + if (lastTemperature != temperature) { |
| 116 | + gw.send(msgTemp.set(temperature,1)); |
| 117 | + lastTemperature = temperature; |
| 118 | + Serial.print("temperature "); |
| 119 | + Serial.println(temperature); |
| 120 | + } |
| 121 | + if (lastHumidity != humidity) { |
| 122 | + gw.send(msgHum.set(humidity)); |
| 123 | + lastHumidity = humidity; |
| 124 | + Serial.print("Humidity "); |
| 125 | + Serial.println(humidity); |
| 126 | + } |
| 127 | +} |
| 128 | + |
| 129 | +/* |
| 130 | + * Sends battery information (both voltage, and battery percentage) |
| 131 | + * |
| 132 | + * Parameters |
| 133 | + * - force : Forces transmission of a value |
| 134 | + */ |
| 135 | +void sendBattLevel(bool force) |
| 136 | +{ |
| 137 | + if (force) lastBattery = -1; |
| 138 | + long vcc = readVcc(); |
| 139 | + if (vcc != lastBattery) { |
| 140 | + lastBattery = vcc; |
| 141 | + // Calculate percentage |
| 142 | + gw.send(msgBattery.set(vcc)); |
| 143 | + vcc = vcc - 1900; // subtract 1.9V from vcc, as this is the lowest voltage we will operate at |
| 144 | + |
| 145 | + long percent = vcc / 14; |
| 146 | + gw.sendBatteryLevel(percent); |
| 147 | + } |
| 148 | +} |
| 149 | + |
| 150 | +long readVcc() { |
| 151 | + // Read 1.1V reference against AVcc |
| 152 | + // set the reference to Vcc and the measurement to the internal 1.1V reference |
| 153 | + #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) |
| 154 | + ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); |
| 155 | + #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) |
| 156 | + ADMUX = _BV(MUX5) | _BV(MUX0); |
| 157 | + #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) |
| 158 | + ADMUX = _BV(MUX3) | _BV(MUX2); |
| 159 | + #else |
| 160 | + ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); |
| 161 | + #endif |
| 162 | + |
| 163 | + delay(2); // Wait for Vref to settle |
| 164 | + ADCSRA |= _BV(ADSC); // Start conversion |
| 165 | + while (bit_is_set(ADCSRA,ADSC)); // measuring |
| 166 | + |
| 167 | + uint8_t low = ADCL; // must read ADCL first - it then locks ADCH |
| 168 | + uint8_t high = ADCH; // unlocks both |
| 169 | + |
| 170 | + long result = (high<<8) | low; |
| 171 | + |
| 172 | + result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 |
| 173 | + return result; // Vcc in millivolts |
| 174 | +} |
| 175 | + |
| 176 | + |
| 177 | +/* |
| 178 | + * Resets eeprom to default value (while blinking LED_PIN) |
| 179 | + */ |
| 180 | +void resetEEP() |
| 181 | +{ |
| 182 | + for (int i=0;i<512;i++) { |
| 183 | + digitalWrite(LED_PIN, HIGH); |
| 184 | + delay(100); |
| 185 | + digitalWrite(LED_PIN, LOW); |
| 186 | + delay(100); |
| 187 | + EEPROM.write(i, 0xff); |
| 188 | + } |
| 189 | +} |
| 190 | + |
| 191 | + |
0 commit comments