Hallo Neueinsteiger,
hier der Code des Sketches, bis auf die Anpassungen an meine Umgebung (NodeID, Gateway und Frequenz) ist er aus dem github von meigrafd.
// RFM12B Sender for ReedSwitch Sensor with Watchdog (saves much more Power!)
// Detect a normally closed reed switch opening and closing with pin change interrupt to wake from sleep.
//
// Basiert zum Teil auf der Arbeit von Nathan Chantrell
//
// modified by meigrafd @ 31.01.2015
//------------------------------------------------------------------------------
#include <JeeLib.h> // https://github.com/jcw/jeelib
#include <PinChangeInterrupt.h> // http://code.google.com/p/arduino-tiny/downloads/list
// Power-Save-Stuff.
// http://www.surprisingedge.com/low-power-atmegatiny-with-watchdog-timer/
// https://www.sparkfun.com/tutorials/309
// http://jeelabs.org/tag/lowpower/
#include <avr/sleep.h>
volatile int watchdog_counter;
// Watchdog Interrupt Service / is executed when watchdog timed out
ISR(WDT_vect) { watchdog_counter++; }
// 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms
// 6=1sec, 7=2sec, 8=4sec, 9=8sec
// From: http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
int watchdog_wakeup = 9; // Wake up after 8 sec
//------------------------------------------------------------------------------
// You will need to initialize the radio by telling it what ID it has and what network it's on
// The NodeID takes values from 1-127, 0 is reserved for sending broadcast messages (send to all nodes)
// The Network ID takes values from 0-255
// By default the SPI-SS line used is D10 on Atmega328. You can change it by calling .SetCS(pin) where pin can be {8,9,10}
#define NODEID 6 // network ID used for this unit
#define NETWORKID 210 // the network ID we are on
#define GATEWAYID 1 // the node ID we're sending to
#define FREQ RF12_868MHZ // Frequency of RFM12B module
#define ACK_TIME 2000 // # of ms to wait for an ack
#define requestACK false // request ACK? (true/false)
#define SENDDELAY 300000 // wait this many ms between sending packets. 300000ms / 1000 / 8 = 37,5 * 8sec = 5Min.
//------------------------------------------------------------------------------
// PIN-Konfiguration
//------------------------------------------------------------------------------
// SENSOR pins
#define SW_PIN 10 // Reed switch connected from ground to this pin (D10/ATtiny pin 13)
// LED pin
#define LEDpin 8 // D8, PA2 (ATtiny pin 11) - set to 0 to disable LED
//------------------------------------------------------------------------------
/*
+-\/-+
VCC 1| |14 GND
(D0) PB0 2| |13 AREF (D10)
(D1) PB1 3| |12 PA1 (D9)
(PB3) RESET 4| |11 PA2 (D8)
INT0 PWM (D2) PB2 5| |10 PA3 (D7)
PWM (D3) PA7 6| |9 PA4 (D6) SCK
SDA PWM (D4) PA6 7| |8 PA5 (D5) PWM
+----+
*/
//encryption is OPTIONAL
//to enable encryption you will need to:
// - provide a 16-byte encryption KEY (same on all nodes that talk encrypted)
// - to call .Encrypt(KEY) to start encrypting
// - to stop encrypting call .Encrypt(NULL)
//#define KEY "a4gBM69UZ03lQyK4"
// Reed switchState
int switchState;
// Temperatur-String zum Versand per 433 Mhz
char msg[26];
// 7,5 * 8sec = 1 Min. 37,5 * 8sec = 5Min.
int watchdog_limit = SENDDELAY / 1000 / 8;
//##############################################################################
static void activityLed (byte state, byte time = 0) {
if (LEDpin) {
pinMode(LEDpin, OUTPUT);
if (time == 0) {
digitalWrite(LEDpin, state);
} else {
digitalWrite(LEDpin, state);
delay(time);
digitalWrite(LEDpin, !state);
}
}
}
// blink led
static void blink (byte pin, byte n = 3) {
if (LEDpin) {
pinMode(pin, OUTPUT);
for (byte i = 0; i < 2 * n; ++i) {
delay(100);
digitalWrite(pin, !digitalRead(pin));
}
}
}
//--------------------------------------------------------------------------------------------------
// Read current supply voltage (in mV)
//--------------------------------------------------------------------------------------------------
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA,ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high<<8) | low;
//result = 1125300L / result; // Back-Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
result = 1126400L / result; // Back-calculate Vcc in mV
return result;
}
//--------------------------------------------------------------------------------------------------
// Power Save Functions
//--------------------------------------------------------------------------------------------------
// Enable / Disable ADC, saves ~230uA
void enableADC(bool b) {
if (b == true){
bitClear(PRR, PRADC); // power up the ADC
ADCSRA |= bit(ADEN); // enable the ADC
delay(10);
} else {
//ADCSRA &= ~(1<<ADEN); // Disable ADC
ADCSRA &= ~ bit(ADEN); // disable the ADC
bitSet(PRR, PRADC); // power down the ADC
}
}
void goToSleep() {
// SLEEP_MODE_IDLE -the least power savings
// SLEEP_MODE_ADC
// SLEEP_MODE_PWR_SAVE
// SLEEP_MODE_STANDBY
// SLEEP_MODE_PWR_DOWN -the most power savings
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode.
sleep_enable(); // Enable sleep mode.
sleep_mode(); // Enter sleep mode.
// After waking from watchdog interrupt the code continues to execute from this point.
sleep_disable(); // Disable sleep mode after waking.
// Re-enable the peripherals.
//power_all_enable();
}
// 0=16ms, 1=32ms, 2=64ms, 3=128ms, 4=250ms, 5=500ms
// 6=1sec, 7=2sec, 8=4sec, 9=8sec
// From: http://interface.khm.de/index.php/lab/experiments/sleep_watchdog_battery/
void setup_watchdog(int timerPrescaler) {
if (timerPrescaler > 9 ) timerPrescaler = 9; //Correct incoming amount if need be
byte bb = timerPrescaler & 7;
if (timerPrescaler > 7) bb |= (1<<5); //Set the special 5th bit if necessary
//This order of commands is important and cannot be combined
MCUSR &= ~(1<<WDRF); //Clear the watchdog reset
WDTCSR |= (1<<WDCE) | (1<<WDE); //Set WD_change enable, set WD enable
WDTCSR = bb; //Set new watchdog timeout value
WDTCSR |= _BV(WDIE); //Set the interrupt enable, this will keep unit from resetting after each int
}
//--------------------------------------------------------------------------------------------------
// init Setup
void setup() {
// configure RFM12B
rf12_initialize(NODEID, FREQ, NETWORKID);
#ifdef KEY
rf12_encrypt((byte*)KEY); //comment this out to disable encryption
#endif
rf12_control(0xC040); // Adjust low battery voltage to 2.2V
rf12_sleep(0); // sleep right away to save power
pinMode(SW_PIN, INPUT); // set the pin to input
digitalWrite(SW_PIN, HIGH); // use the internal pullup resistor
attachPcInterrupt(SW_PIN,wakeUp,FALLING); // attach a PinChange Interrupt on the falling edge
analogReference(INTERNAL); // Set the aref to the internal 1.1V reference
watchdog_counter = 500; // set to have an initial transmition when starting the sender.
setup_watchdog(watchdog_wakeup);
enableADC(false); // power down/disable the ADC
//ACSR = (1<<ACD); // Disable the analog comparator
//DIDR0 = 0x3F; // Disable digital input buffers on all ADC0-ADC5 pins.
//ADCSRA &= ~ bit(ADEN); bitSet(PRR, PRADC); // Disable the ADC to save power
PRR = bit(PRTIM1); // only keep timer 0 going
if (LEDpin) {
activityLed(1,1000); // LED on
}
}
void wakeUp(){}
// Loop
void loop() {
goToSleep(); // goes to sleep for about 8 seconds and continues to execute code when it wakes up
// 15 * 4 sec = 1 Min , 75 * 4 sec = 5 Min , 225 * 4 sec = 15 min
// 7,5 * 8sec = 1 Min. 37,5 * 8sec = 5Min.
if (watchdog_counter >= watchdog_limit) {
watchdog_counter = 1;
enableADC(true); // power up/enable the ADC
int State = digitalRead(SW_PIN); // Read the state of the reed switch
if (State == LOW) { // Door/window is open
switchState = 1; // 1 indicates open
} else { // Door/window is closed
switchState = 0; // 0 indicates closed
}
if (switchState == 1) {
int supplyV = readVcc(); // Get supply voltage
// msg-Variable mit Daten zum Versand fuellen, die spaeter an das WebScript uebergeben werden
strcpy(msg,"v=");
itoa(supplyV,&msg[strlen(msg)],10);
strcat(msg,"&r=");
itoa(switchState,&msg[strlen(msg)],10);
// Send data via RF
rf12_sleep(-1); // Wake up RF module
while (!rf12_canSend())
rf12_sendStart(GATEWAYID, (uint8_t *)msg, strlen(msg), requestACK);
//radio.Send(GATEWAYID, &msg, sizeof(msg), requestACK);
rf12_sendWait(2); //wait for RF to finish sending (2=standby mode, 3=power down)
rf12_sleep(0);
if (LEDpin) {
blink(LEDpin, 2); // blink LED
}
}
enableADC(false); // power down/disable the ADC
}
}
Display More
Ich Verwende die Gerber-Files von Nathan Chantrell, also TinyTX3 Platinen.
Dort habe ich von GND -> D8 eine LED aufgelötet, und von GND -> D10 den Magnetkontakt.
LED und Magnetkontakt wurden ohne Widerstände aufgelötet. Betrieben wird das Ganze mit 2 x AA Batterien.
Den ATiny84 wurde mit einem USBasp Programmiert, so wie meine Tiny´s für meine Temperatur-Sensoren auch.
Gruß
Harpi