Galerie
Der Low Power Node im Überblick
Mein Low Power Node ist ein kleiner, aber effektiver Sensor, der die Temperatur und Luftfeuchtigkeit in einem Raum misst und drahtlos an ein Gateway überträgt. Der Node wurde aus dem Wunsch heraus entwickelt, eine Einzelraum-Temperaturüberwachung in meinen Wohnräumen zu realisieren und dabei mein eigenes Protokoll in mein bestehendes Sensornetzwerk zu integrieren.
Das Gerät wurde mit einem RFM95 LoRa-Modul bei 868MHz im ISM-Band ausgestattet, was eine gute Reichweite und Signalstärke bietet. Der Node kommt mit 2 AAA-Batterien aus und hat eine lange Laufzeit, die je nach Sendezyklen mehrere Monate bis über 1 Jahr betragen kann.
Als Mikrocontroller wurde der Attiny3224 ausgewählt, da er im Vergleich zu anderen 8-Bit-AVRs günstiger ist und mit der UPDI-Schnittstelle programmiert wird, was nur eine Leitung benötigt. Der digitale SHTC3-Sensor von der Firma SENSIRION ist in der Lage, Temperatur und Luftfeuchtigkeit zu messen und bietet eine hohe Genauigkeit und Zuverlässigkeit.
Um die Energie der Batterien optimal zu nutzen, verwende ich einen MAX1724 StepUp-Regler, welcher eine Ausgangsspannung von 3,3V ausgibt und eine gute Effizienz von bis zu 90 % bietet. Er ist für Low Power Batterie Anwendung bestens geeignet, sodass die Batterien lange halten und das Gerät in der Lage ist, kontinuierlich Daten zu senden.
Der Low Power Node wurde in der Arduino IDE programmiert und kann leicht in andere Projekte integriert werden. Die erfassten Daten werden in Node-Red verarbeitet, im Home Assistant visualisiert und bieten eine einfache Möglichkeit, den Raumtemperatur- und Luftfeuchtigkeitsstatus zu überwachen.
Insgesamt ist der Low Power Node eine kostengünstige und effektive Lösung für eine Einzelraum-Temperaturüberwachung, die einfach zu bauen und zu verwenden ist. Mit seiner geringen Größe und geringen Energieanforderungen ist er ideal für den Einsatz in Wohnungen und Häusern geeignet.
Stromaufnahme und Batterielaufzeit im Betrieb mit 2x AAA Batterien
Messung der Stromaufnahme
Das Messen von Strömen im uA-Bereich kann eine Herausforderung sein, da handelsübliche Multimeter in der Regel für höhere Stromstärken ausgelegt sind und nicht die erforderliche Genauigkeit für solch kleine Ströme bieten. Wenn Sie jedoch kleinere Ströme wie uA messen müssen, ist ein spezieller Messadapter wie der CurrentRanger die beste Wahl.
Der CurrentRanger ist ein erschwingliches Strommessgerät, das für die Erfassung schneller Stromtransienten mit hoher Messgenauigkeit ausgelegt ist. Es zeichnet sich durch eine extrem kleine Burden-Spannung aus, was bedeutet, dass es den Stromfluss durch das Messgerät nur minimal beeinflusst und somit sehr genaue Messungen im uA-Bereich ermöglicht.
Mit dem CurrentRanger können Sie nicht nur kleine Ströme genau messen, sondern auch schnell reagierende Stromveränderungen aufzeichnen. Dies macht es zu einem unverzichtbaren Werkzeug für die Entwicklung und Prüfung von elektronischen Schaltungen und Systemen.
Der CurrentRanger arbeitet mit drei verschiedenen Bereichen für die Strommessung, die Nanoampere, Mikroampere und Milliampere umfassen. Je nachdem, welcher Bereich eingestellt ist, wird am Ausgang des Geräts eine bestimmte Spannung ausgegeben. Wenn beispielsweise der Milliampere-Bereich eingestellt ist, wird eine Spannung von 1mV pro mA am Ausgang des Geräts ausgegeben.
Um die gemessenen Stromwerte am besten auswerten zu können, empfiehlt es sich, ein Oszilloskop zu verwenden. Mit einem Oszilloskop können die gemessenen Stromwerte grafisch dargestellt werden, was eine einfache und genaue Analyse ermöglicht. Durch die Verwendung eines Oszilloskops können Sie auch schnell Änderungen im Stromverlauf erkennen und entsprechende Anpassungen vornehmen.
Messung der Stromaufnahme beim Lesen des Sensors und Senden der Daten
Am Oszilloskop kann man das Aufwachen des Low Power Nodes triggern und den Stromverlauf ablesen. In dem Fall habe ich es mir einfach gemacht und den RMS Wert für die Zeit im Wachbetrieb genommen. Die Zeit in dem der Node arbeitet, beträgt 103,6 ms und erhalten dabei 49,3mV, was also 49,3mA entspricht.
Messung der Stromaufnahme im Schlafbetrieb (DeepSleep)
Bei niedrigen Strömen ist ein Boost Converter (StepUp) jedoch möglicherweise nicht so effektiv, da der Wirkungsgrad des Wandlers abnimmt, wenn der Strom durch ihn niedriger wird. Dies liegt daran, dass die Verluste in den Schaltkomponenten des Wandlers relativ konstant bleiben, während der Ausgangsstrom abnimmt. Dadurch wird der Wirkungsgrad des Wandlers verringert, was zu einem höheren Energieverlust führt.
Wenn Sie dennoch auf einen Boost Converter angewiesen sind, können Sie versuchen, den Wirkungsgrad des Wandlers zu verbessern, indem Sie beispielsweise einen hochwertigen, niederohmigen Induktor verwenden und sicherstellen, dass die Schaltfrequenz des Wandlers optimal auf die Eingangsspannung abgestimmt ist. Eine weitere Möglichkeit besteht darin, den Boost Converter so zu dimensionieren, dass er für den maximalen Laststrom ausgelegt ist, den Sie benötigen. Dadurch wird der Wirkungsgrad des Wandlers verbessert, da er für höhere Ströme optimiert ist.
In meinem Fall habe ich dies, mit meinem Wissensstand, auch versucht umzusetzen.
Die Stromaufnahme im DeepSleep habe ich in zwei Schritte unterteilt
Schritt 1: Messung beim Schaltvorgang
Hier kann man sehen, dass die Periode zwischen den Impulsen 177,5ms beträgt, das macht eine Frequenz von 5,63Hz
Schritt 2: Messung ohne Schaltvorgang
Die Stromaufnahme im Nicht-Schaltbetrieb liegt bei 6,81uA, die Dauer errechnet sich aus der Periode von 177,5ms minus die Impulsdauer von 0,5ms, das sind dann 177,1ms.
Der durchschnittliche Stromverbrauch im Schlafbetrieb kann wie folgt berechnet werden:
Stromverbrauch Schlafen = (Impulszeit* Impulsstrom + Ruhezeit* Ruhestrom) / Gesamtschlafzeit
Stromverbrauch Schlafen = (0,5ms * 1160uA + 177,1ms * 6,81uA) / 177,5ms = 10uA
Bestimmung der Effizienz des StepUp-Spannungsreglers (MAX1724EZK33+T)
Für die Bestimmung der durchschnittlichen Effizienz benötigen wir die Betriebszeiten (Schlaf- und Sendebetrieb), sowie die benötigten Lastströme der jeweiligen Betriebszeiten.
Die jeweiligen Effizienzen kann man gut im Datenblatt ablesen.
Man beachtet hier die Eingangsspannung. Da der Sensor mit 2 AAA-Batterien betrieben wird, erhalten wir im Maximum eine Spannung von 3,2V und minimal von 1,6V, die goldene Mitte sind dann quasi 2,4V. Daher werde ich den Bereich der Kennlinie von 2,5V nehmen.
Die Effizienz im Betrieb liegt bei 50mA bei 83 % (rot)
Die Effizienz im Schlaf liegt bei 10uA bei 61 % (orange)
Die durchschnittliche Effizienz kann wie folgt berechnet werden:
Durchschnittliche Effizienz = (Sendezeit* Effizienz Senden+ Schlafzeit* Effizienz Schlaf) / Gesamtzeit
Durchschnittliche Effizienz = (103,6ms * 83 % + 60000ms * 61 %) / 60103,6ms = 61 %
Die Effizienz liegt also bei gerade einmal 61 %, hört sich gar nicht mal so gut an.
Berechnung der Batteriekapazität im Zusammenhang mit der Effizienz
Die Batteriekapazität beträgt 1200mAh, was bedeutet, dass die Batterie eine Ladung von 1200 Milliampere Stunden speichern kann. Wenn wir die Effizienz des StepUp-Spannungsreglers berücksichtigen, können wir die tatsächlich verfügbare Kapazität berechnen:
Verfügbare Kapazität = Batteriekapazität x Effizienz = Verfügbare Kapazität = 1200 mAh x 0,61 = 732 mAh
Bemerkung:
Die Kapazität einer Alkaline-Batterie nimmt bei niedrigeren Temperaturen ab. Dies liegt daran, dass die chemischen Reaktionen in der Batterie bei niedrigeren Temperaturen langsamer ablaufen, was die Freisetzung von Elektronen und damit die Stromabgabe reduziert.
In der Regel ist die Kapazität einer Alkaline-Batterie bei Raumtemperatur (ca. 20-25 °C) am höchsten. Bei Temperaturen unterhalb des Gefrierpunkts (0 °C) kann die Kapazität um bis zu 20 % abnehmen.
Es ist auch zu beachten, dass bei sehr niedrigen Temperaturen der interne Widerstand der Batterie erhöht werden kann, was die Leistung weiter beeinträchtigt. Dies kann dazu führen, dass die Batterie schneller entladen wird, wenn sie bei kaltem Wetter eingesetzt wird.
Elektrische Daten des Sensors und Umgebung
- Kapazität Batterie 1200 mAh (2x AAA-Batterie in Serie), effektiv 732mAh
- Betriebsstrom = 49,3 mA
- Ruhestrom = 10uA
- Effizienz = 61 %
- Umgebungstemperatur = 24 °C
Berechnung der Batterielaufzeit bei einem Sende-Zyklus von 60 Sekunden
Ich verstehe, dass der Sendezyklus von einer Minute für den Sensor möglicherweise nicht sinnvoll ist, da die Lufttemperatur sich normalerweise nicht so schnell ändert. Als Vergleich möchte ich dieses Beispiel trotzdem vorzeigen.
Um die Batterielebensdauer für Ihren Sensor zu berechnen, müssen wir zuerst den durchschnittlichen Stromverbrauch des Sensors berechnen, der sowohl den Stromverbrauch im Betrieb als auch im Ruhemodus berücksichtigt.
Der durchschnittliche Stromverbrauch kann wie folgt berechnet werden:
Durchschnittlicher Stromverbrauch = (Betriebszeit * Betriebsstrom + Ruhemoduszeit * Ruhemodusstrom) / Gesamtzeit
Da der Betriebsstrom 44 mA beträgt und die Betriebszeit 50 ms beträgt, beträgt der Stromverbrauch im Betrieb:
Betriebsstromverbrauch = 44 mA * 50 ms = 0,0022 Ah = 2,2 mAh
Da der Ruhemodusstrom 12 uA beträgt und die Ruhemoduszeit 60 s beträgt, beträgt der Stromverbrauch im Ruhemodus:
Ruhemodusstromverbrauch = 12 uA * 60 s = 0,00072 Ah = 0,72 mAh
Die Gesamtzeit ergibt sich aus der Summe der Betriebszeit und der Ruhemoduszeit:
Gesamtzeit = Betriebszeit + Ruhemoduszeit = 50 ms + 60 s = 60,05s
Daher ergibt sich der durchschnittliche Stromverbrauch zu:
Durchschnittlicher Stromverbrauch = (2,2 mAh + 0,72 mAh) / 60,05 s = 0,048 mAh/s = 48,62 uA
Daher ergibt sich die Batterielebensdauer zu:
Batterielebensdauer = 0,732 Ah / 0,00004862 Ah/s = 22.213 Stunden oder etwa 925Tage bei einer Umgebungstemperatur von ca. 24 °C
Beachten Sie, dass dies eine Schätzung ist und dass die tatsächliche Batterielebensdauer von verschiedenen Faktoren abhängt, wie z. B. der Umgebungstemperatur und der Alterung der Batterie.
Source Code Low Power Node
Benötigte Libraries
Benötigtes Board Core
Core Einstellungen in der Arduino IDE
Cource Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
#include <RadioLib.h> #include "SHTC3.h" #include <avr/sleep.h> #include <avr/wdt.h> #define NSS_Pin 0 #define DIO0_Pin 2 #define RESET_Pin 3 #define DIO1_Pin -1 float freq = 868.4; // carrier frequency 868.4 MHz float bandw = 125.0; // bandwidth 125.0 kHz uint8_t spredf = 7; // spreading 7 uint8_t coder = 5; // coding rate 5 uint8_t syncw = 0x12; // sync word 0x12 int8_t pwrout = 10; // output power 10 dBm uint16_t prel = 8; // preamble length 8 symbols uint8_t ampg = 1; // amplifier gain 1 (maximum gain) #define CRCcheck true #define GatewayID 0xCF // can be changed at the gateway #define NodeID 0xC1 // e.g. C1 = exterior, C2 = bedroom, C3 = kitchen #define SleepTime 60 // Sleep time MCU in seconds #define Vreg 3.30 #define ADCcycles 50 #define ADCpin 1 #define LEDPIN 5 #define SERIAL_BAUD 9600 //#define DEBUG // "Switch" to activate the UART output #ifdef DEBUG #define DEBUG_PRINT(x) Serial.print(x) #define DEBUG_PRINTLN(x) Serial.println(x) #define DEBUG_FLUSH() Serial.flush(); #else #define DEBUG_PRINT(x) #define DEBUG_PRINTLN(x) #define DEBUG_FLUSH() #endif SX1276 radio = new Module(NSS_Pin, DIO0_Pin, RESET_Pin, DIO1_Pin); SHTC3 s(Wire); struct dataObject { uint8_t gatewayId = GatewayID; uint8_t nodeId = NodeID; uint16_t messageId; float temp; float hum; float bat; }; dataObject message; uint8_t messageLen = sizeof(dataObject); void RTC_init(void) { // Initialize RTC while (RTC.STATUS > 0) { ; /* Wait for all register to be synchronized */ } RTC.CLKSEL = RTC_CLKSEL_INT32K_gc; /* 32.768kHz Internal Ultra-Low-Power Oscillator (OSCULP32K) */ RTC.PITINTCTRL = RTC_PI_bm; /* PIT Interrupt: enabled */ RTC.PITCTRLA = RTC_PERIOD_CYC32768_gc /* RTC Clock Cycles 16384, resulting in 32.768kHz/16384 = 2Hz -> 32.768 = 1s, 10s = 327680 */ | RTC_PITEN_bm; /* Enable PIT counter: enabled */ } ISR(RTC_PIT_vect) { RTC.PITINTFLAGS = RTC_PI_bm; /* Clear interrupt flag by writing '1' (required) */ } void setup() { pinMode(ADCpin, INPUT); // ADC #ifdef DEBUG Serial.begin(SERIAL_BAUD); #else pinMode(LEDPIN, OUTPUT); digitalWrite(LEDPIN, HIGH); #endif Wire.begin(); s.begin(true); DEBUG_PRINTLN("#############################################"); DEBUG_PRINT(F("[SX1276] Initializing ... ")); int state = radio.begin(freq, bandw, spredf, coder, syncw, pwrout, prel, ampg); if (state == RADIOLIB_ERR_NONE) { DEBUG_PRINTLN(F("success!")); } else { DEBUG_PRINT(F("failed, code ")); DEBUG_PRINTLN(state); while (true); } radio.setCRC(CRCcheck); //DEBUG_PRINT(F("[SX1276] Chip Version:\t\t")); DEBUG_PRINTLN(radio.getChipVersion(), HEX); DEBUG_PRINT(F("[SX1276] Data Rate:\t\t")); DEBUG_PRINTLN(radio.getDataRate()); DEBUG_PRINT(F("[SX1276] Temp RAW:\t\t")); DEBUG_PRINTLN(radio.getTempRaw()); ADCPowerOptions(LOW_LAT_OFF); ADCPowerOptions(PGA_AUTO_OFF); ADCPowerOptions(ADC_DISABLE); RTC_init(); /* Initialize the RTC timer */ set_sleep_mode(SLEEP_MODE_PWR_DOWN); /* Set sleep mode to POWER DOWN mode */ sleep_enable(); /* Enable sleep mode, but not going to sleep yet */ DEBUG_PRINTLN("#############################################"); } void loop() { DEBUG_PRINTLN(F("[SX1276] Transmitting packet ... ")); message.messageId++; #ifndef DEBUG digitalWrite(LEDPIN, LOW); #endif unsigned long sensorValue = 0; for(int x = 0; x < ADCcycles; x++) { sensorValue += analogRead(ADCpin); delay(1); } #ifndef DEBUG digitalWrite(LEDPIN, HIGH); #endif Serial.println(sensorValue); float voltage= (sensorValue / ADCcycles) * (Vreg / 1023.0); message.bat = voltage; s.sample(); message.temp = s.readTempC(); message.hum = s.readHumidity(); s.sleep(); DEBUG_PRINT(F("[SX1276] Node Temp:\t\t")); DEBUG_PRINTLN(message.temp); DEBUG_PRINT(F("[SX1276] Node Hum:\t\t")); DEBUG_PRINTLN(message.hum); DEBUG_PRINT(F("[SX1276] Node Bat:\t\t")); DEBUG_PRINTLN(message.bat); int state = radio.transmit((uint8_t *)&message, messageLen); if (state == RADIOLIB_ERR_NONE) { DEBUG_PRINTLN(F("[SX1276] success!")); DEBUG_PRINT(F("[SX1276] Datarate:\t")); DEBUG_PRINT(radio.getDataRate()); DEBUG_PRINTLN(F(" bps")); } else if (state == RADIOLIB_ERR_PACKET_TOO_LONG) { DEBUG_PRINTLN(F("too long!")); } else if (state == RADIOLIB_ERR_TX_TIMEOUT) { DEBUG_PRINTLN(F("timeout!")); } else { DEBUG_PRINT(F("failed, code ")); DEBUG_PRINTLN(state); } DEBUG_PRINTLN(); DEBUG_FLUSH(); radio.sleep(); ADCPowerOptions(LOW_LAT_OFF); ADCPowerOptions(PGA_AUTO_OFF); ADCPowerOptions(ADC_DISABLE); for ( uint16_t i = 0 ; i < SleepTime ; ++i ) { sleep_cpu(); } } |
Hallo Martin,
was verwendest Du denn als Gateway und wie greifst Du auf das Gateway von HA zu?
Viele Grüße Markus
Hi Markus,
Aktuell verwende ich ein LoRa TTGO ESP32 als Gateway. Aktuell arbeite ich an der Firmware und werde diese demnächst auf meinem Blog veröffentlichen.
Dies nutzt auch die HA MQTT Discovery Funktion, sodass die empfangenen Nodes direkt in der Geräteliste unter MQTT auftauchen. 🙂
VG Martin