I have build an Solar panel-powered Soil moisture sensor.
I bought the lamps on Jula.
Lamp1 Battery 2/3 AAA 100 mAh, 10 SEK, 1 euro
Lamp2 Battery 2/3 AA 200 mAh, 5 SEK, 0,5 euro
Lamp3 Battery LR44 40 mAh, 10 SEK, 1 euro, NOT TESTED YET
I removed all the electronic on the PCB and used the PCB as a connection board.
The solar panel gives around 1,4 V during a very sunny day.
I had to add a step-up(0,8->3,3V) to be able to run a ATMEGA. My first idea was to connect 2 batteries in series, but that was too much work. Now everything fits in the parts that is included.
Lamp1 is using a Pro Mini(fake), glued soil sensor on "arrow"
Lamp2 is using my designed PCB with ATMEGA328p, soil sensor just put in soil, not glued at all.
Both MCU are using Optiboot, https://forum.mysensors.org/topic/3018/tutorial-how-to-burn-1mhz-8mhz-bootloader-using-arduino-ide-1-6-5-r5.
Pro Mini:Power-on LED removed and also step-down. Activity-LED is still in use.
My designed PCB:https://oshpark.com/shared_projects/F7esJEMY, also with LED for startup and send OK
I am using @mfalkvidd sketch, thank you. I have only add a few rows(LED and resend function)
It sends data(Humidity/Volt/VoltPercent every 10 second, just for testing the hardware later on I will send maybe twice an hour or once an hour.
I am measuring the battery voltage on a analog input.
#include <SPI.h>
#include <MySensor.h>
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))
#define N_ELEMENTS(array) (sizeof(array)/sizeof((array)[0]))
#define CHILD_ID_MOISTURE 0
#define CHILD_ID_BATTERY 1
#define SLEEP_TIME 10000 // Sleep time between reads (in milliseconds)
#define THRESHOLD 1.1 // Only make a new reading with reverse polarity if the change is larger than 10%.
#define STABILIZATION_TIME 1000 // Let the sensor stabilize before reading
default BOD settings.
const int SENSOR_ANALOG_PINS[] = {A4, A5}; // Sensor is connected to these two pins. Avoid A3 if using ATSHA204. A6 and A7 cannot be used because they don't have pullups.
MySensor gw;
MyMessage msg(CHILD_ID_MOISTURE, V_HUM);
MyMessage voltage_msg(CHILD_ID_BATTERY, V_VOLTAGE);
long oldvoltage = 0;
byte direction = 0;
int oldMoistureLevel = -1;
float batteryPcnt;
float batteryVolt;
int LED = 5;
void setup()
{
pinMode(LED, OUTPUT);
digitalWrite(LED, HIGH);
delay(200);
digitalWrite(LED, LOW);
delay(200);
digitalWrite(LED, HIGH);
delay(200);
digitalWrite(LED, LOW);
gw.begin();
gw.sendSketchInfo("Plant moisture w solar", "1.0");
gw.present(CHILD_ID_MOISTURE, S_HUM);
delay(250);
gw.present(CHILD_ID_BATTERY, S_MULTIMETER);
for (int i = 0; i < N_ELEMENTS(SENSOR_ANALOG_PINS); i++) {
pinMode(SENSOR_ANALOG_PINS[i], OUTPUT);
digitalWrite(SENSOR_ANALOG_PINS[i], LOW);
}
}
void loop()
{
int moistureLevel = readMoisture();
// Send rolling average of 2 samples to get rid of the "ripple" produced by different resistance in the internal pull-up resistors
// See http://forum.mysensors.org/topic/2147/office-plant-monitoring/55 for more information
if (oldMoistureLevel == -1) { // First reading, save current value as old
oldMoistureLevel = moistureLevel;
}
if (moistureLevel > (oldMoistureLevel * THRESHOLD) || moistureLevel < (oldMoistureLevel / THRESHOLD)) {
// The change was large, so it was probably not caused by the difference in internal pull-ups.
// Measure again, this time with reversed polarity.
moistureLevel = readMoisture();
}
gw.send(msg.set((moistureLevel + oldMoistureLevel) / 2.0 / 10.23, 1));
oldMoistureLevel = moistureLevel;
int sensorValue = analogRead(A0);
Serial.println(sensorValue);
float voltage=sensorValue*(3.3/1023);
Serial.println(voltage);
batteryPcnt = (sensorValue - 248) * 0.72;
batteryVolt = voltage;
gw.sendBatteryLevel(batteryPcnt);
resend((voltage_msg.set(batteryVolt, 3)), 10);
digitalWrite(LED, HIGH);
delay(200);
digitalWrite(LED, LOW);
gw.sleep(SLEEP_TIME);
}
void resend(MyMessage &msg, int repeats)
{
int repeat = 1;
int repeatdelay = 0;
boolean sendOK = false;
while ((sendOK == false) and (repeat < repeats)) {
if (gw.send(msg)) {
sendOK = true;
} else {
sendOK = false;
Serial.print("Error ");
Serial.println(repeat);
repeatdelay += 500;
} repeat++; delay(repeatdelay);
}
}
int readMoisture() {
pinMode(SENSOR_ANALOG_PINS[direction], INPUT_PULLUP); // Power on the sensor
analogRead(SENSOR_ANALOG_PINS[direction]);// Read once to let the ADC capacitor start charging
gw.sleep(STABILIZATION_TIME);
int moistureLevel = (1023 - analogRead(SENSOR_ANALOG_PINS[direction]));
// Turn off the sensor to conserve battery and minimize corrosion
pinMode(SENSOR_ANALOG_PINS[direction], OUTPUT);
digitalWrite(SENSOR_ANALOG_PINS[direction], LOW);
direction = (direction + 1) % 2; // Make direction alternate between 0 and 1 to reverse polarity which reduces corrosion
return moistureLevel;
}