Dan Tudose
Published © GPL3+

Solar-powered greenhouse monitoring station

A monitoring station for my off-grid greenhouse. Multiple environmental parameters, WiFi, solar-powered, cloud connectivity.

IntermediateFull instructions provided10 hours2,107
Solar-powered greenhouse monitoring station

Things used in this project

Hardware components

SparkFun ESP8266 Thing - Dev Board
SparkFun ESP8266 Thing - Dev Board
×1
Sunny Buddy - MPPT Solar Charger
SparkFun Sunny Buddy - MPPT Solar Charger
×1
DS18B20 Programmable Resolution 1-Wire Digital Thermometer
Maxim Integrated DS18B20 Programmable Resolution 1-Wire Digital Thermometer
Use the waterproof version with cable: https://www.aliexpress.com/item/4000895660165.html
×3
BME680 Breakout
Pimoroni BME680 Breakout
Or use the CJMCU version: https://www.aliexpress.com/item/1005001835950567.html
×1
MAX44009 I2C Light Sensor
×1
LiPo protection circuit
×1

Software apps and online services

Blynk
Blynk
Arduino IDE
Arduino IDE

Story

Read more

Schematics

General schematic of the station

Code

Arduino sketch

C/C++
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Wire.h>
#include "MAX44009.h"
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <OneWire.h>
#include <DallasTemperature.h>

#define DEBUG

#define ONE_WIRE_BUS 4
#define TEMPERATURE_PRECISION 12

#define POWER_PIN 12 //pin used as Vcc to the sensors

MAX44009 light;
Adafruit_BME680 bme; 
float temperature, pressure, humidity, voc, battery, luminosity;
float temperature1, temperature2, temperature3;

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// arrays to hold device addresses
DeviceAddress t1   = { 0x28, 0xB2, 0x2D, 0x94, 0x97, 0x0E, 0x03, 0xE0 };
DeviceAddress t2   = { 0x28, 0xB6, 0x4F, 0x94, 0x97, 0x09, 0x03, 0xC0 };
DeviceAddress t3   = { 0x28, 0xF9, 0x07, 0x94, 0x97, 0x09, 0x03, 0x46 };

// You should get Auth Token in the Blynk App.
// Go to the Project Settings (nut icon).
char auth[] = ""; //Enter the Auth code which was send by Blink

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "";  //Enter your WIFI Name
char pass[] = "";  //Enter your WIFI Password

int BME680init()
{

  if (!bme.begin())
    return 0;
  
  // Set up oversampling and filter initialization
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  bme.setGasHeater(320, 150); // 320*C for 150 ms

  return 1;
}

float readADC()
{
  float val;
  val = ((analogRead(A0)-30) * 0.0063); //some tweaking of the ADC value to convert into Volts  
  return val;
}

void printAddress(DeviceAddress deviceAddress)
{
  for (uint8_t i = 0; i < 8; i++)
  {
    // zero pad the address if necessary
    if (deviceAddress[i] < 16) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
  }
}

// function to print the temperature for a 1-Wire device
void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print("Temp C: ");
  Serial.print(tempC);
  
}

// function to print a 1-Wire device's resolution
void printResolution(DeviceAddress deviceAddress)
{
  Serial.print("Resolution: ");
  Serial.print(sensors.getResolution(deviceAddress));
  Serial.println();
}

// main function to print information about a 1-Wire device
void printData(DeviceAddress deviceAddress)
{
  Serial.print("Device Address: ");
  printAddress(deviceAddress);
  Serial.print(" ");
  printTemperature(deviceAddress);
  Serial.println();
}

// perfroms a reading of all 3 1-Wire sensors
void getTemperature()
{
 sensors.begin();

  if (!sensors.getAddress(t1, 0)) Serial.println("Unable to find address for Device 0");
  if (!sensors.getAddress(t2, 1)) Serial.println("Unable to find address for Device 1");
  if (!sensors.getAddress(t3, 2)) Serial.println("Unable to find address for Device 2");

  #ifdef DEBUG
  printAddress(t1);
  Serial.println();
  printAddress(t2);
  Serial.println();
  printAddress(t3);
  Serial.println();
  #endif
  
  sensors.setResolution(t1, TEMPERATURE_PRECISION); 
  sensors.setResolution(t2, TEMPERATURE_PRECISION);
  sensors.setResolution(t3, TEMPERATURE_PRECISION);
  
  #ifdef DEBUG
  Serial.print("t1 Resolution: ");
  Serial.print(sensors.getResolution(t1), DEC);
  Serial.println();
  
  Serial.print("t2 Resolution: ");
  Serial.print(sensors.getResolution(t2), DEC);
  Serial.println();
  
  Serial.print("t3 Resolution: ");
  Serial.print(sensors.getResolution(t3), DEC);
  Serial.println();
  #endif
  sensors.requestTemperatures();
  
  temperature1 = sensors.getTempC(t1);
  temperature2 = sensors.getTempC(t2);
  temperature3 = sensors.getTempC(t3);
  
  #ifdef DEBUG
  Serial.println(temperature1);
  Serial.println(temperature2);
  Serial.println(temperature3);
  #endif
  
 }

bool blynkRoutine(void) {
  
    digitalWrite(POWER_PIN, HIGH); //turn on all sensors
  
    luminosity = light.get_lux();
    #ifdef DEBUG
    Serial.print("Lux: ");
    Serial.println(luminosity);
    #endif
    
    battery = readADC();
    #ifdef DEBUG
    Serial.print("Battery = ");
    Serial.print(battery);
    Serial.println(" V");
    #endif
    
    if (!bme.performReading()) 
    {
      Serial.println("Failed to perform reading :(");
      return true;
    }
    if (!bme.performReading()) 
    {
      Serial.println("Failed to perform reading :(");
      return true;
    }

    temperature = bme.temperature;
    pressure = bme.pressure / 100.0;
    humidity = bme.humidity;
    voc = bme.gas_resistance / 1000.0;

    #ifdef DEBUG
    Serial.print("Temperature = ");
    Serial.print(temperature);
    Serial.println(" *C");
    
    Serial.print("Pressure = ");
    Serial.print(pressure);
    Serial.println(" hPa");
    
    Serial.print("Humidity = ");
    Serial.print(humidity);
    Serial.println(" %");
    
    Serial.print("Gas = ");
    Serial.print(voc);
    Serial.println(" KOhms");
    #endif
    
    getTemperature(); // reads all 1-Wire sensors
    
    digitalWrite(POWER_PIN, LOW); //turn off all sensors
    
    Blynk.virtualWrite(V0, temperature1);  
    Blynk.virtualWrite(V1, temperature2);  
    Blynk.virtualWrite(V2, temperature3);  
    Blynk.virtualWrite(V3, luminosity);
    Blynk.virtualWrite(V4, battery);
    Blynk.virtualWrite(V5, temperature);
    Blynk.virtualWrite(V6, pressure);
    Blynk.virtualWrite(V7, humidity);
    Blynk.virtualWrite(V8, voc);
 
  return true; // repeat? true
}

void setup()
{
  Serial.begin(9600);   
 
  pinMode(POWER_PIN, OUTPUT);
  digitalWrite(POWER_PIN, HIGH);
  
  Wire.begin();
  
  delay(500);
 
  
  if(light.begin())
  {
    Serial.println("Could not find a valid MAX44009 sensor, check wiring!");
    while(1);
  }
  if(!BME680init())
  {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while(1);
  }

  delay(1000);
  
  #ifdef DEBUG
  Serial.println("Start auth...");
  #endif
  
  Blynk.begin(auth, ssid, pass);
  
  #ifdef DEBUG
  Serial.println("Done auth, connected...");
  #endif
  
  blynkRoutine(); // main routine for reading sensor data and populating Blynk structure with it
  
  Blynk.run(); // Initiates Blynk & sends data

  #ifdef DEBUG
  Serial.println("Entering sleep...");
  #endif
  
  ESP.deepSleep(300000000, WAKE_RF_DEFAULT); // Sleep for 300 seconds and then resets
 
}

void loop()
{
  delay(10); // execution should never reach this 
}

Credits

Dan Tudose

Dan Tudose

6 projects • 34 followers

Comments