hi @Dirk_H
Great project. I'm looking for a battery powered switch sketch like yours.
Do you have it updated to MySensors v2.x? I tried to convert it but did not manage to get it working.
/*
* Copyright (C) 2015 Dirk H. R.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* DESCRIPTION
* This Program will implement six child sensors, which present one Push Button each.
* The Program is meant to be used in conjunction with the Wall Remote Hardware
* See MySensors for more information
*
* Frequency is 3.6864 MHz to ensure operation at low Voltages
*
*/
#include <MySensors.h>
#include <SPI.h>
#include <PinChangeInt.h> //???
#define MY_DEBUG
#define MY_RADIO_NRF24
#define SKETCH_NAME "Wall Remote"
#define NodeID 2
#define BotLeft_CHILD_ID 0 //Child ID for Bottom Left
#define MidLeft_CHILD_ID 1 //Child ID forMiddle Left
#define TopCornerLeft_CHILD_ID 2 //Child ID for Top Left (Corner Switch)
#define BotRight_CHILD_ID 3 //Child ID for Bottom Left
#define MidRight_CHILD_ID 4 //Child ID forMiddle Left
#define TopCornerRight_CHILD_ID 5 //Child ID for Top Left (Corner Switch)
#define BotLeft_PIN A1//21 //Digital Input for Bottom Left Pin PCInt 11
#define MidLeft_PIN A0//20 //Digital Input for Middle Left Pin PCInt 10
#define TopLeft_PIN A2//19 //Digital Input for Top Left (Corner Switch) Pin PCInt 9
#define BotRight_PIN 8 //Digital Input for Bottom Right Pin
#define MidRight_PIN 5 //Digital Input for Middle Right Pin
#define TopRight_PIN 4 //Digital Input for Top Right (Corner Switch) Pin
int BATTERY_SENSE_PIN = A6; // select the input pin for the battery sense point
int oldBatteryPcnt = 0;
// Change V_LIGHT if you don't use S_LIGHT in presentation below
MyMessage msg_BotLeft(BotLeft_CHILD_ID, V_LIGHT);
MyMessage msg_MidLeft(MidLeft_CHILD_ID, V_LIGHT);
MyMessage msg_TopLeft(TopCornerLeft_CHILD_ID, V_LIGHT);
MyMessage msg_BotRight(BotRight_CHILD_ID, V_LIGHT);
MyMessage msg_MidRight(MidRight_CHILD_ID, V_LIGHT);
MyMessage msg_TopRight(TopCornerRight_CHILD_ID, V_LIGHT);
//The BtnVal and the Btn_xx_ID are used to store the current state of the six buttons into a single uint8
uint8_t BtnVal=0; //idle/start value is 255 because Buttons get pulled up in idle state
uint8_t BtnVal_last=0;
#define Btn_BotLeft_ID 0
#define Btn_MidLeft_ID 1
#define Btn_TopLeft_ID 2
#define Btn_BotRight_ID 3
#define Btn_MidRight_ID 4
#define Btn_TopRight_ID 5
void setup()
{
//begin(NULL,NodeID);
// Setup the buttons
pinMode(BotLeft_PIN, INPUT);
pinMode(MidLeft_PIN, INPUT);
pinMode(TopLeft_PIN, INPUT);
pinMode(BotRight_PIN, INPUT);
pinMode(MidRight_PIN, INPUT);
pinMode(TopRight_PIN, INPUT);
// Activate internal pull-ups
digitalWrite(BotLeft_PIN, HIGH);
digitalWrite(MidLeft_PIN, HIGH);
digitalWrite(TopLeft_PIN, HIGH);
digitalWrite(BotRight_PIN, HIGH);
digitalWrite(MidRight_PIN, HIGH);
digitalWrite(TopRight_PIN, HIGH);
//Use internal 1.1V Reference (for Battery Measurement)
analogReference(INTERNAL);
/*Setup PinChange Interrupt. Unfortunately you must ensure that the "MyGateway.cpp" will not be compiled for this,
i.e. look into your Arduino libraries\MySensors folder and
---> RENAME THE "MyGateway.cpp" to e.g. "MyGateway.cpp.nolib" <---.
Of cause you must undo the renameing when you want to compile a MySensors Gateway!
The reason for this renaming is that the compilter of Arduino compiles also the MyGateway where the PinChange interrupt
Vector is also defined, which will lead to an error because it is only allowed to have it one time in the program.
*/
PCattachInterrupt(BotLeft_PIN,BotLeft_ISR,CHANGE);
PCattachInterrupt(MidLeft_PIN,MidLeft_ISR,CHANGE);
PCattachInterrupt(TopLeft_PIN,TopLeft_ISR,CHANGE);
PCattachInterrupt(BotRight_PIN,BotRight_ISR,CHANGE);
PCattachInterrupt(MidRight_PIN,MidRight_ISR,CHANGE);
PCattachInterrupt(TopRight_PIN,TopRight_ISR,CHANGE);
interrupts();
Serial.begin (115200);
}
void presentation()
{
// Register Wall Remote buttons (they will be created as child devices)
// I decided to take the S_Light parameter as i inteded the WallRemote to switch lights,
// however you can change if you think this is more apropriate, hovwever
// If S_LIGHT is not used, remember to update variable type you send in. See "msg" above.
present(BotLeft_CHILD_ID, S_LIGHT);
present(MidLeft_CHILD_ID, S_LIGHT);
present(TopCornerLeft_CHILD_ID, S_LIGHT);
present(BotRight_CHILD_ID, S_LIGHT);
present(MidRight_CHILD_ID, S_LIGHT);
present(TopCornerRight_CHILD_ID, S_LIGHT);
}
}
void WallRemote_Sleep(){
//Custom Function that puts ATMega and NRF24L01 into sleep mode.
//This was necessary because PinChange Interrupts have been used.
sleep(0xff, 0x00, 0xff, 0x00, 0);
}
void inline BtnPressHandler(uint8_t Button, uint8_t ValPos){
//Handler that just saves state of pressed button into BtnVal variable
//assuming that no debouncing is necessary because of wakeup time (16kCykles @ 4MHz = 4ms)
if (digitalRead(Button)==LOW) BtnVal |= (1<<ValPos);
else BtnVal &= ~(1<<ValPos);
}
//The six following ISRs are used to Wakeup the device and to call the Button Handler routine
void BotLeft_ISR(){
BtnPressHandler(BotLeft_PIN, Btn_BotLeft_ID);
}
void MidLeft_ISR(){
BtnPressHandler(MidLeft_PIN, Btn_MidLeft_ID);
}
void TopLeft_ISR(){
BtnPressHandler(TopLeft_PIN, Btn_TopLeft_ID);
}
void BotRight_ISR(){
BtnPressHandler(BotRight_PIN, Btn_BotRight_ID);
}
void MidRight_ISR(){
BtnPressHandler(MidRight_PIN, Btn_MidRight_ID);
}
void TopRight_ISR(){
BtnPressHandler(TopRight_PIN, Btn_TopRight_ID);
}
void BtnSender(MyMessage Btn_Msg, uint8_t Btn_ID){
uint8_t temp=0;
temp = (BtnVal & (1<<Btn_ID));
if ( (BtnVal_last & (1<<Btn_ID)) != temp){
if (temp) send(Btn_Msg.set(HIGH));
else send(Btn_Msg.set(LOW));
}
}
//loop only checks the ButtonState Variable and transmits changes if necessary
void loop()
{
// get the battery Voltage (note: we only get here at restart of the node or after Interrupt from the Buttons)
int BatVal = analogRead(BATTERY_SENSE_PIN);
// 1M, 470K divider across battery and using internal ADC ref of 1.1V
// Sense point is bypassed with 0.1 uF cap to reduce noise at that point
// ((1e6+470e3)/470e3)*1.1 = Vmax = 3.44 Volts
// 3.44/1023 = Volts per bit = 0.003363075
float batteryV = BatVal * 0.003363075;
int batteryPcnt = BatVal / 10;
if (oldBatteryPcnt != batteryPcnt) {
// Power up radio after sleep
sendBatteryLevel(batteryPcnt);
oldBatteryPcnt = batteryPcnt;
}
//check if something has changed
if (BtnVal != BtnVal_last){
BtnSender(msg_BotLeft, Btn_BotLeft_ID);
BtnSender(msg_MidLeft, Btn_MidLeft_ID);
BtnSender(msg_TopLeft, Btn_TopLeft_ID);
BtnSender(msg_BotRight, Btn_BotRight_ID);
BtnSender(msg_MidRight, Btn_MidRight_ID);
BtnSender(msg_TopRight, Btn_TopRight_ID);
}
BtnVal_last = BtnVal;
//Go back to sleep (custom function, see above)
WallRemote_Sleep();
}
thx