low power surveillance system for weekend house/ boat/ camping car

Hi together,

My name is Martin and I am new here and in Arduino in general.

I managed to run a raspberry pi based surveillance system on our boat for the last three years, which ran great. The boat is about 1 1/2h driving from my home and it is good to have the feeling everything is o.k. on board.
Now I got the information, that the shore power must be switched off, when I am not on board. I can produce some energy with a solar panel, but the raspberry pi (and the LTE router in the second line) are too battery hungry (1A/h ). As the batteries hold about 150 Ah, I need to find a low power solution with e.g. ESP32.

I guess many weekend hut owners, boaters or campers know well this scenario, so the project could be useful for many users.

Currently I have the following functionality, which I want to maintain as far as possible.

  • motion sensor (intrusion)
  • water intrusion sensor
  • bme 280 sensor (temperature, humidity, pressure)
  • battery voltage
  • camera picture upload in intervals to an ftp server (extra pi zero w)

The data is sent via mqtt to a broker at home and processed via node red.

The plan is to use a e.g. ESP32 to do the tasks and sleep most of the time. The current drain of the LTE router should be replaced by solar power, but if possible, I'd like to switch to a ESP GSM module later.

I tried many days with the ESPEASY software on a ESP32, but could not achieve all functions and did not get the system running stable, so I guess it is the best to write a new sketch.

Unfortunately I have no programming experience, so this will be my first project. I hope there is a sketch available, that already fulfils some functions and I can modify it for my needs.

Shore power is switched off in two weeks :slight_smile:

Any hints, how to start are very welcome!

Update:

I loaded a sketch from Rui Santos (thanks!).

MQTT is publishing temperature and humidity on my broker (Yeah!) (first sketch)
Then I tried to integrate a sketch for PIR motion detection (second sketch). Motion detection is working and putting out a message on the serial console. But if I try to publish a message “Motion detected !!!” via MQTT, the ESP32 crashes.
And in the second sketch, the temperature is not sent any more via MQTT

Where is the fault?
How can I read and publish the state of other GPIOs (for water intrusion sensor e.g.)?

/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com  
*********/

#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

// Replace the next variables with your SSID/Password combination
const char* ssid = "xxx";
const char* password = "xxx";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "xxx";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
float temperature = 0;
float humidity = 0;

// LED Pin
const int ledPin = 4;

void setup() {
Serial.begin(115200);
// default settings
// (you can also pass in a Wire library object like &Wire2)
//status = bme.begin();  
if (!bme.begin(0x76)) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
}
setup_wifi();
client.setServer(mqtt_server, 1882);
client.setCallback(callback);

pinMode(ledPin, OUTPUT);
}

void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
  delay(500);
  Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;

for (int i = 0; i < length; i++) {
  Serial.print((char)message[i]);
  messageTemp += (char)message[i];
}
Serial.println();

// Feel free to add more if statements to control more GPIOs with MQTT

// If a message is received on the topic esp32/output, you check if the message is either "on" or "off". 
// Changes the output state according to the message
if (String(topic) == "esp32/output") {
  Serial.print("Changing output to ");
  if(messageTemp == "on"){
    Serial.println("on");
    digitalWrite(ledPin, HIGH);
  }
  else if(messageTemp == "off"){
    Serial.println("off");
    digitalWrite(ledPin, LOW);
  }
}
}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
  Serial.print("Attempting MQTT connection...");
  // Attempt to connect
  if (client.connect("ESP8266Client")) {
    Serial.println("connected");
    // Subscribe
    client.subscribe("esp32/output");
  } else {
    Serial.print("failed, rc=");
    Serial.print(client.state());
    Serial.println(" try again in 5 seconds");
    // Wait 5 seconds before retrying
    delay(5000);
  }
}
}
void loop() {
if (!client.connected()) {
  reconnect();
}
client.loop();

long now = millis();
if (now - lastMsg > 5000) {
  lastMsg = now;
  
  // Temperature in Celsius
  temperature = bme.readTemperature();   
  
  // Convert the value to a char array
  char tempString[8];
  dtostrf(temperature, 1, 2, tempString);
  Serial.print("Temperature: ");
  Serial.println(tempString);
  client.publish("esp32/temperature", tempString);

  humidity = bme.readHumidity();
  
  // Convert the value to a char array
  char humString[8];
  dtostrf(humidity, 1, 2, humString);
  Serial.print("Humidity: ");
  Serial.println(humString);
  client.publish("esp32/humidity", humString);
}
}

The same with motion detection (crashes)

/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com  
*********/

#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>

// Replace the next variables with your SSID/Password combination
const char* ssid = "xxx";
const char* password = "xxx";

// Add your MQTT Broker IP address, example:
const char* mqtt_server = "xxx";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

// PIR Sensor
#define timeSeconds 10

// Set GPIO for PIR Motion Sensor
const int motionSensor = 27;

// Timer: Auxiliary variables
unsigned long now = millis();
unsigned long lastTrigger = 0;
boolean startTimer = false;

// Checks if motion was detected, sets LED HIGH and starts a timer
void IRAM_ATTR detectsMovement() {
Serial.println("MOTION DETECTED!!!");
// Send "Motion" to MQTT broker
// crashes ESP32 if uncommented  client.publish("esp32/motion", "MOTION DETECTED!!!");
startTimer = true;
lastTrigger = millis();
}

Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
float temperature = 0;
float humidity = 0;

// LED Pin for MQTT message arrived
const int ledPin = 4;

void setup() {
Serial.begin(115200);

// PIR Motion Sensor mode INPUT_PULLUP
pinMode(motionSensor, INPUT_PULLUP);
// Set motionSensor pin as interrupt, assign interrupt function and set RISING mode
attachInterrupt(digitalPinToInterrupt(motionSensor), detectsMovement, RISING);

// default settings
// (you can also pass in a Wire library object like &Wire2)
//status = bme.begin();  
if (!bme.begin(0x76)) {
 Serial.println("Could not find a valid BME280 sensor, check wiring!");
 while (1);
}
setup_wifi();
client.setServer(mqtt_server, 1882);
client.setCallback(callback);

pinMode(ledPin, OUTPUT);
}

void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;

for (int i = 0; i < length; i++) {
 Serial.print((char)message[i]);
 messageTemp += (char)message[i];
}
Serial.println();

// Feel free to add more if statements to control more GPIOs with MQTT

// If a message is received on the topic esp32/output, you check if the message is either "on" or "off". 
// Changes the output state according to the message
if (String(topic) == "esp32/output") {
 Serial.print("Changing output to ");
 if(messageTemp == "on"){
   Serial.println("on");
   digitalWrite(ledPin, HIGH);
 }
 else if(messageTemp == "off"){
   Serial.println("off");
   digitalWrite(ledPin, LOW);
 }
}
}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
 Serial.print("Attempting MQTT connection...");
 // Attempt to connect
 if (client.connect("ESP8266Client")) {
   Serial.println("connected");
   // Subscribe
   client.subscribe("esp32/output");
 } else {
   Serial.print("failed, rc=");
   Serial.print(client.state());
   Serial.println(" try again in 5 seconds");
   // Wait 5 seconds before retrying
   delay(5000);
 }
}
}
void loop() {
if (!client.connected()) {
 reconnect();
}
client.loop();

long now = millis();
if (now - lastMsg > 5000) {
 lastMsg = now;
 
 // Temperature in Celsius
 temperature = bme.readTemperature();   
 
 // Convert the value to a char array
 char tempString[8];
 dtostrf(temperature, 1, 2, tempString);
 Serial.print("Temperature: ");
 Serial.println(tempString);
 

 humidity = bme.readHumidity();
 
 // Convert the value to a char array
 char humString[8];
 dtostrf(humidity, 1, 2, humString);
 Serial.print("Humidity: ");
 Serial.println(humString);
 client.publish("esp32/humidity", humString);

 // Current time
now = millis();
// "motion stopped" after the number of seconds defined in the timeSeconds variable
if(startTimer && (now - lastTrigger > (timeSeconds*1000))) {
 Serial.println("Motion stopped...");
 startTimer = false;
}
}
}

Would it not have been simpler to address the power issue itself based on the 2 week delima? (Simpler. I didn't say cheaper)

Learning and writing code for a fairly complex project as this one in 2 weeks is a very unrealistic goal, IMO.

DangerToMyself:
Would it not have been simpler to address the power issue itself based on the 2 week delima? (Simpler. I didn't say cheaper)

Learning and writing code for a fairly complex project as this one in 2 weeks is a very unrealistic goal, IMO.

Yes, but I have no influence on the shore power. On 30th of Nov the power is shut off. When the raspberry pi is keeps running, the service batteries will last for about 150h (solar power neglected).

My hope is, with some help of the community I can combine some sketches to a running sketch as a compromise.

May be s.o. can have a look on the sketch above?

Have you determined how much power is used by the Raspberry pi and how much is used by the LTE router? I have a feeling that you are optimizing the wrong part of the system.

Could you use an old Android phone as a gateway to uploading information? Some devices can run indefinitely on solar power during the day and internal battery at night, assuming that you don't suffer from too many consecutive cloudy days.

dotancohen:
Have you determined how much power is used by the Raspberry pi and how much is used by the LTE router? I have a feeling that you are optimizing the wrong part of the system.

Could you use an old Android phone as a gateway to uploading information? Some devices can run indefinitely on solar power during the day and internal battery at night, assuming that you don't suffer from too many consecutive cloudy days.

Yes I did :slight_smile:

Raspberry Pi 500 mAh
Raspberry Pi zero with cam 200 mAh
LTE Router 300 mAh

Best case solar charging in winter in this location 15 Ah a day.
Worst case solar charging 0 Ah for a few days.
Battery capacity 150 Ah

If I can get rid of the Raspberrys and the ESPs sleep most of the time the mimic should consume about 350 mAh, means under 10 Ah a day. Gives me 15 days without sun. That should work.

With Raspberrys it is about 24 Ah a day, not possible in winter time.

As I wrote, I want to replace the Router with a ESP32 GSM800 in second line, or maybe with a phone, as you proposed. But the most important thing seem to be the raspberrys.

The first sketch I posted with a sleep cycle would be almost a solution, because the motion sensor could be wired to the router (RUT955), too.

May be I could have attracted some more attention with a picture from the running Pi system. Thats, what I want to use the ESP for.

is you take this apart a bit.

an ESP can send data to any wifi around, if nothing is close, but there is shore power elsewhere, you could use relay stations or a LORA to send the simple data.

if you have other shore power, such as a dock yard or such, you might be able to put a web cam there.

also, since transferring the pictues is the hard part, you could get an ESP up and running and sending data so you can use an RPi to collect the data at your location so you get the nice graphs.

the ESP32 has a camera, not sure of power use, but there are so many wireless web cams and baby monitors that it seems you could buy most of this stuff off the shelf.

Hi Dave,
I just answered you PM.
Last year six boats where on fire and sunk, due to a faulty AC installation.
Therefore AC is cut off completely on the docks.
I guess the router is not the problem, the main power consumption comes from the two raspberries.
The data is already processed at home.

Meanwhile the ESP sends bme280 data and sleeps. Power consumption for 1 message/ h is about 2mAh!
So I think this is the right way.
In far future cameras an even a GSM router could be realized with sleeping ESPs, too. I really prefer a stand alone solution, that works on every place of the world.

But as I posted, the sketch with the PIR sensor cant publish the motion event on mqtt.

Thats the first step to be solved.

The next one is to let an ESP32-CAM sleep and load up pictures in intervals to an ftp server.

I promise, in my next life I become a programmer!

But may be in this life s.o. can have a look an my sketch?

if you have a sketch you want us to review, please
use autoformat
then copy it, and use 'code tags' to post it here
more about code tags HTUTF- code tags
#7 shows to use.

What is wrong with the posted code in #2?