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 Controllers

Die Programmierung erfolgt mit Hilfe eines Arduino UNO Boards, welches Adruino als ISP.

Eigentliche Schaltung

Diese besteht aus der Stromversorgung (3,3V)
aus dem Tiny,
und aus demFunkmodul

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. WinkenSoweit 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);
}
   
© ALLROUNDER