You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
5.7 KiB
170 lines
5.7 KiB
// Enable debug prints to serial monitor |
|
#define MY_DEBUG |
|
#define MY_RADIO_NRF24 |
|
#define MY_RF24_PA_LEVEL RF24_PA_MAX |
|
//#define MY_NODE_ID 7 |
|
|
|
#include <SPI.h> |
|
#include <MySensors.h> |
|
|
|
// Running this in Domoticz stable version 2.5 will not work - upgrade to beta. |
|
|
|
#define DIGITAL_INPUT_SENSOR 3 // The reed switch you attached. (Only 2 and 3 generates interrupt!) |
|
#define INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway) |
|
|
|
#define CHILD_ID 1 // Id of the sensor child |
|
#define SKETCH_NAME "Rain Gauge" // Change to a fancy name you like |
|
#define SKETCH_VERSION "1.1" // Your version |
|
|
|
unsigned long SLEEP_TIME = 20*60000; // Sleep time (in milliseconds). |
|
//unsigned long SLEEP_TIME = 20000; // use this instead for debug |
|
|
|
float hwRainVolume = 0; // Current rainvolume calculated in hardware. |
|
int hwPulseCounter = 0; // Pulsecount recieved from GW |
|
float fullCounter = 0; // Counts when to send counter |
|
float bucketSize = 0.32; // Bucketsize mm, needs to be 1, 0.5, 0.25, 0.2 or 0.1 |
|
boolean pcReceived = false; // If we have recieved the pulscount from GW or not |
|
boolean reedState; // Current state the reedswitch is in |
|
boolean oldReedState; // Old state (last state) of the reedswitch |
|
unsigned long lastSend =0; // Time we last tried to fetch counter. |
|
|
|
MyMessage volumeMsg(CHILD_ID,V_RAIN); |
|
MyMessage lastCounterMsg(CHILD_ID,V_VAR1); |
|
|
|
//========================= |
|
// BATTERY VOLTAGE DIVIDER SETUP |
|
// 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 |
|
// ((100e3+35e3)/35e3)*1.1 = Vmax = 4,24 Volts |
|
// 4,24/1023 = Volts per bit = 0.004144673 |
|
#define VBAT_PER_BITS 0.004144673 |
|
#define VMIN 3.0 // Vmin (radio Min Volt)=1.9V (564v) |
|
#define VMAX 4.2 // Vmax = (2xAA bat)=3.0V (892v) |
|
int batteryPcnt = 0; // Calc value for battery % |
|
int batLoop = 0; // Loop to help calc average |
|
int batArray[3]; // Array to store value for average calc. |
|
int BATTERY_SENSE_PIN = A0; // select the input pin for the battery sense point |
|
//========================= |
|
|
|
void presentation() { |
|
|
|
// Send the Sketch Version Information to the Gateway |
|
sendSketchInfo(SKETCH_NAME, SKETCH_VERSION); |
|
|
|
// Register this device as Rain sensor (will not show in Domoticz until first value arrives) |
|
present(CHILD_ID, S_RAIN); |
|
} |
|
|
|
|
|
void setup() |
|
{ |
|
// use the 1.1 V internal reference |
|
analogReference(INTERNAL); // For battery sensing |
|
|
|
pinMode(DIGITAL_INPUT_SENSOR, INPUT_PULLUP); // sets the reed sensor digital pin as input |
|
|
|
reedState = digitalRead(DIGITAL_INPUT_SENSOR); // Read what state the reedswitch is in |
|
oldReedState = reedState; // Set startup position for reedswitch |
|
|
|
Serial.println("Startup completed"); |
|
} |
|
|
|
void loop() |
|
{ |
|
unsigned long currentTime = millis(); |
|
|
|
//See if we have the counter/pulse from Domoticz - and ask for it if we dont. |
|
if (!pcReceived && (currentTime - lastSend > 5000)) { |
|
request(CHILD_ID, V_VAR1); |
|
lastSend=currentTime; |
|
return; |
|
} |
|
if (!pcReceived) { |
|
return; |
|
} |
|
|
|
//Read if the bucket tipped over |
|
reedState = digitalRead(DIGITAL_INPUT_SENSOR); |
|
boolean tipped = oldReedState != reedState; |
|
|
|
//BUCKET TIPS! |
|
if (tipped==true) { |
|
Serial.println("The bucket has tipped over..."); |
|
oldReedState = reedState; |
|
hwRainVolume = hwRainVolume + bucketSize; |
|
send(volumeMsg.set((float)hwRainVolume,1)); |
|
wait(1000); |
|
fullCounter = fullCounter + bucketSize; |
|
|
|
//Count so we send the counter for every 1mm |
|
if(fullCounter >= 1){ |
|
hwPulseCounter++; |
|
send(lastCounterMsg.set(hwPulseCounter)); |
|
wait(1000); |
|
fullCounter = 0; |
|
} |
|
|
|
} |
|
|
|
if (tipped==false) { |
|
|
|
//No bucket tipped over last sleep-period, check battery then... |
|
batM(); |
|
} |
|
|
|
lastSend=currentTime; |
|
sleep(INTERRUPT, CHANGE, SLEEP_TIME); |
|
//The interupt can be CHANGE or FALLING depending on how you wired the hardware. |
|
} |
|
|
|
//Read if we have a incoming message. |
|
void receive(const MyMessage &msg) { |
|
if (msg.type==V_VAR1) { |
|
hwPulseCounter = msg.getULong(); |
|
hwRainVolume = hwPulseCounter; |
|
pcReceived = true; |
|
Serial.print("Received last pulse count from gw: "); |
|
Serial.println(hwPulseCounter); |
|
} |
|
} |
|
|
|
void batM(){ //The battery calculations |
|
|
|
delay(500); |
|
// Battery monitoring reading |
|
int sensorValue = analogRead(BATTERY_SENSE_PIN); |
|
delay(500); |
|
|
|
// Calculate the battery in % |
|
float Vbat = sensorValue * VBAT_PER_BITS; |
|
int batteryPcnt = static_cast<int>(((Vbat-VMIN)/(VMAX-VMIN))*100.); |
|
|
|
if (batteryPcnt > 100) { |
|
batteryPcnt=100; |
|
} |
|
if (batteryPcnt < 0) { |
|
batteryPcnt=0; |
|
} |
|
|
|
Serial.print("Battery percent: "); Serial.print(batteryPcnt); Serial.println(" %"); |
|
|
|
// Add it to array so we get an average of 3 (3x20min) |
|
batArray[batLoop] = batteryPcnt; |
|
|
|
if (batLoop > 1) { |
|
batteryPcnt = (batArray[0] + batArray[1] + batArray[2]); |
|
batteryPcnt = batteryPcnt / 3; |
|
|
|
Serial.print("Battery Average (Send): "); Serial.print(batteryPcnt); Serial.println(" %"); |
|
sendBatteryLevel(batteryPcnt); |
|
batLoop = 0; |
|
|
|
//Sends 1 per hour as a heartbeat. |
|
send(volumeMsg.set((float)hwRainVolume,1)); |
|
send(lastCounterMsg.set(hwPulseCounter)); |
|
} |
|
else |
|
{ |
|
batLoop++; |
|
} |
|
}
|
|
|