Monitoring Station with ESP32

Hey!

I am designing a monitoring station that includes cameras and meteorological data. I consider myself a beginner, and so I would like to have some tips on how I can improve my code and logic to be a more reliable system. I am using an ESP32 to gather the data and a Raspberry Pi Zero 2W to send the data to my Onedrive. The communication is made via UART. The key points of the data acquisition are:

What I am more doubtful about is the way that I am measuring the wind and rain. I am using a pulse counter to count pulses for a time range of 10 minutes. After those 10 minutes, a flag is set, and the other sensors measure the other data. I don't know if this is the best way to do it or the more reliable. I would like to know your advice!

The code is shown below:

#include "M5UnitENV.h"
#include <driver/pcnt.h>
#include <HardwareSerial.h>

// Data Transmission
#define TX 1 
#define RX 3 
// Sensor
#define RAIN 25
#define WINDS 18 


#define RECORD_TIME 20.0f // seconds
#define WIND_SPEED_ARRAY_SIZE 30 // 30 moments of data acquisition == 10-minute period
#define WIND_SPEED_CONVERSION 2.4f 

// Temperature, pressure and humidity sensor library constants
SHT3X sht3x;
QMP6988 qmp;

// Sensor variables
float pSum=0;
float pRead=0;
int pCountSums=0;
int pNoSums=10;
float pAvg=0;
float pAvgHist=0;
float tRead=0;
float hRead=0;

// Data 
bool dataSent = false;

// Configuration for the counters
void configurePCNT(int pulsePin, pcnt_unit_t unit, pcnt_channel_t channel);

// Wind
void Windspeed(void *pvParameters) {
  int16_t count = 0; 
  float windSpeedValues[WIND_SPEED_ARRAY_SIZE] = {0}; 
  int windSpeedIndex = 0;

  for (;;) {

    pcnt_counter_clear(PCNT_UNIT_0); 
    vTaskDelay(RECORD_TIME * 1000 / portTICK_PERIOD_MS); 
    pcnt_get_counter_value(PCNT_UNIT_0, &count); 
    
    float kph = WIND_SPEED_CONVERSION * ((float)count / 2 / RECORD_TIME); 
    windSpeedValues[windSpeedIndex++] = kph; 

    if (windSpeedIndex >= WIND_SPEED_ARRAY_SIZE) {
      float maxWindSpeed = 0;
      float sumWindSpeed = 0;

      for (int i = 0; i < WIND_SPEED_ARRAY_SIZE; i++) {

        if (windSpeedValues[i] > maxWindSpeed) {
          maxWindSpeed = windSpeedValues[i];
        }

        sumWindSpeed += windSpeedValues[i];
      }

      Serial2.print(maxWindSpeed); 
      Serial2.print(",");
      Serial2.print(sumWindSpeed / WIND_SPEED_ARRAY_SIZE); 
      Serial2.print(",");
      windSpeedIndex = 0; 
    }
  }
}

// Rain
void Rain(void *pvParameters) {
  int16_t rain_count = 0;
  pcnt_counter_clear(PCNT_UNIT_1); 
  while (true) {
    uint32_t start_time = millis();
    uint32_t end_time = start_time + (10 * 60 * 1000); // 10 minutes
    //uint32_t end_time = start_time + (40 * 1000); 

    
    while (millis() < end_time) {
      pcnt_get_counter_value(PCNT_UNIT_1, &rain_count);
      vTaskDelay(1000 / portTICK_PERIOD_MS); 
    }

    float volume = rain_count * 0.3f; 
    Serial2.print(volume); 
    Serial2.print(",");
    
    dataSent = true; 
  }
}

void setup() {
  Serial.begin(9600); 
  Serial2.begin(115200, SERIAL_8N1, RX, TX); 

  pinMode(WINDS, INPUT);
  pinMode(RAIN, INPUT);

  configurePCNT(WINDS, PCNT_UNIT_0, PCNT_CHANNEL_0); // contador do vento
  configurePCNT(RAIN, PCNT_UNIT_1, PCNT_CHANNEL_1); // contador da chuva


  // Humidity sensor (I2C)
  if (!qmp.begin(&Wire, QMP6988_SLAVE_ADDRESS_L, 26, 13, 400000U)) {
    Serial.println("Couldn't find QMP6988");
    while (1) delay(1);
  }
  // Temperature and pressure sensor (I2C)
  if (!sht3x.begin(&Wire, SHT3X_I2C_ADDR, 26, 13, 400000U)) {
    Serial.println("Couldn't find SHT3X");
    while (1) delay(1);
  }

  xTaskCreatePinnedToCore(Windspeed, "Windspeed", 10000, NULL, 2, NULL, 1); // Higher priority
  xTaskCreatePinnedToCore(Rain, "Rain", 10000, NULL, 1, NULL, 1); // Lower priority

}

void loop() {
  // Other sensor readings
  if (dataSent) {
    Pressure();
    Serial2.print(",");
    Temperature();
    Serial2.print(",");
    Humidity();
    Serial2.print(",");
    Winddirection();
    Serial2.print(",");
    Soilmoisture();
    Serial2.println();
    dataSent = false;
  }
}

void configurePCNT(int pulsePin, pcnt_unit_t unit, pcnt_channel_t channel) {
  int16_t PCNT_H_LIM_VAL = 3000;
  int16_t PCNT_L_LIM_VAL = -10;

  pcnt_config_t pcnt_config = {};
  pcnt_config.pulse_gpio_num = pulsePin;
  pcnt_config.ctrl_gpio_num = PCNT_PIN_NOT_USED;
  pcnt_config.channel = channel;
  pcnt_config.unit = unit;
  pcnt_config.pos_mode = PCNT_COUNT_INC;
  pcnt_config.neg_mode = PCNT_COUNT_DIS;
  pcnt_config.lctrl_mode = PCNT_MODE_KEEP;
  pcnt_config.hctrl_mode = PCNT_MODE_KEEP;
  pcnt_config.counter_h_lim = PCNT_H_LIM_VAL;
  pcnt_config.counter_l_lim = PCNT_L_LIM_VAL;

  pcnt_unit_config(&pcnt_config);
  pcnt_filter_enable(unit);
  pcnt_counter_clear(unit);

} 

Thank you in advance!

Cheers!

using the PCNT (Pulse Counter) module to measure wind speed etc seems a good idea - do you get accurate results?
not sure what the Raspberry Pi Zero 2W is doing that the ESP32 could not do

So far, they have seemed accurate. Sometimes, I have a peak on windspeed, but I think it is because of the sensor's inaccuracy.

As for the Raspberry Pi to create a CSV of the data from that day and send it to my Onedrive. I don't know if ESP32 can send data this way. As far as I know, I can have my ESP32 create a website, but I don't know if it will be too much to have one ESP32 doing all of this, and I need the data on a CSV.

Thank you!

what software are you using on the RPi zero to transmit the CSV data - is it transmitted over WiFi?

The ESP32 has WiFi and is a powerful microcontroller (although not as powerful as the RPi zero) which should be capable of running a website (or other TCP application) and reading the sensors concurrently etc
probably worth a try - saves the serial connection between the devices

or connect the sensors to the RPi zero?

It's transmitted via UART.

At the start of the project, I considered only using the ESP32, but for this project, I needed to save the data in a CSV each day to do data processing, so I found this solution.

That could be a good idea. I need to see the trade-off if the circuit doesn't get too complex in order to do it.

Thank you for the advice! I will study it!

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.