AT Tiny 433Mhz Schneehöhenmessgerät
Energie und Platzsparender Sender für "beliebige" Messwerte oder auch zur Überwachung von Kontakten und Zuständen aller Art
|
Programmierung eines Tiny ControllersDie Programmierung erfolgt mit Hilfe eines Arduino UNO Boards, welches Adruino als ISP. |
|
Eigentliche SchaltungDiese besteht aus der Stromversorgung (3,3V) Ausserdem brauchen wir natürlich noch den Ultraschallsensor zur Entfernungsmessung. Verbesserungen Möglich wäre in diesem Zusammenhang noch die Überwachung der Batteriespannung um den Batteriewechsel frühzeitig zu erkennen. |
Auswertung des Funksignals
Die Auswertung der Funksignale erfolgt derzeit mit einer Erweiterung meines SmartHome Gateways .
Dieses habe ich um einen 433Mhz Empänger erweitert.
Das so empfangene Funksignal wird mit Hilfe der DeviceId (siehe Quellcode) eindeutig einer Messstelle zugeordnet und als UDP Broadcast
auf das LAN-Netz gegeben. Dort lauscht ein Raspberry Pi am entsprechenden Socket, welcher die Werte in eine MySql Datenbank wegschreibt.
Ein Auswerteprozess (WEB Seite) kann dann die Messwerte (Schneehöhe) lesen und als Diaramm oä. darstellen. Soweit bin ich allerdings noch nicht
Software- und Schaltungstricks
Um nun besonders Stromsparend "unterwegs" zu sein, beherscht der Tiny verschiedne Sleep Mode.
In diesem Mode, verbraucht er so gut wie keinen Strom. Die "Kunst" besteht nun darin den Tiny zu definieren Zeitpunkten zu wecken, die Messung und Funkübertragung zu machen und ihn sofort danach wieder "schalfen zu legen".
Da der Tiny nicht durch einen Timer aus dem Sleep erweckt werden kann, muss diese Aufgabe der WatchdogInterrupt erledigen. Da dieser wiederum aber auf max. 8sec. eingestellt werden kann, brachen wir noch eine Schleife "außen rum" (siehe GlobalSleep() im Quellcode ).
Quellcode
Die Funktionen InitWatchdog und GlobalSleep hab ich im Internet als Anregung gesehen und entsprechnd angepasst. Leider weis ich die Herkunft nicht mehr. Sollte sich der Authr wiederfinden, bitte kurze Mail an mich, dann wird dieser selbverständlich genannt!
#include "RCSwitch.h"
#include "xrc.h"
#include
#include
#define PinIn 1 //PulsePin
#define PinTx 4 //Sender
#define PinPing 3 //Trigger
#define DeviceID 10 //Gerätekennung
#define SendDelay 1 //Sendeintervall 8 * 7 = 56s
#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
//Interrupt Flag für WakeUp from Sleep Mode
volatile boolean f_wdt = 1;
ISR(WDT_vect) {f_wdt=1;}
//Sender instanzieren
XRC RC = XRC();
//Hauptprogramm (Initialisierung)
void setup()
{
//Sender Initialisiseren (kein Tx, Sender an Pin 4)
RC.begin(-1,PinTx);
//Sonstige Initialisierung
pinMode(PinPing, OUTPUT);
digitalWrite(PinPing, LOW);
pinMode(PinIn, INPUT);
//Sleep and Watchdog initialisieren
InitWatchdog(); //Watchdog für 8sec Starten
}
//Programmschleife
void loop()
{
//Messwerte besorgen
uint16_t value = GetDistance();
//Wert senden
RC.send(DeviceID, value);
//Deep Sleep! CPU(5V) = 7uA! CPU(3.3V) = 4uA!
//mit Sensor 7mA bei 5V
GlobalSleep();
}
//#################################################################
long GetDistance()
{ // |<-distance->|
// PinPing: __----------__________________________
// PinIn : xxxxxxxxxxxx_____________---------____
digitalWrite(PinPing, HIGH);
delayMicroseconds(10);
digitalWrite(PinPing, LOW);
long pingDuration = pulseIn(PinIn, HIGH);
return (pingDuration / 29 / 2); //Wert in cm
}
//#################################################################
//All Power Off - WakeUp from Watchdog INT (Statment )
void GlobalSleep()
{
for (uint8_t sleepCounter= 0; sleepCounter < SendDelay; sleepCounter++)
{
if (f_wdt==1)
{ // wait for timed out watchdog / flag is set when a watchdog timeout occurs
f_wdt=0; // reset flag
cbi(ADCSRA,ADEN); // switch Analog to Digitalconverter OFF
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // sleep mode is set here
sleep_enable();
sleep_mode(); // SLEEP!
sleep_disable(); // System continues execution here when watchdog timed out
sbi(ADCSRA,ADEN); // switch Analog to Digitalconverter ON
}
}
}
//ii..0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void InitWatchdog()
{
byte bb;
bb = 9 & 7;
bb|= (1<<5);
bb|= (1< MCUSR &= ~(1<
// start timed sequence
WDTCR |= (1<
// set new watchdog timeout value
WDTCR = bb;
WDTCR |= _BV(WDIE);
}