Ralph Yamamoto
Created August 19, 2025 © MIT

Pollinator Population Monitor

Protect pollinator population and habitat by monitoring pollinator population count over time

IntermediateWork in progressOver 1 day95

Things used in this project

Hardware components

Seeed Studio XIAO ESP32S3 Sense
Seeed Studio XIAO ESP32S3 Sense
×1
Bosch BME688
×1
Texas Instruments OPT3001
×1
Solar Panel - 6V, 5W
×1
LiPo Battery - 3.7V, 700mAh, 603035
×1
NextPCB  Custom PCB Board
NextPCB Custom PCB Board
×1

Software apps and online services

Arduino IDE
Arduino IDE
Edge Impulse Studio
Edge Impulse Studio
Node-RED
Node-RED
MQTT
MQTT
OpenScad
Ultimaker Cura Slicer
IrfanView

Hand tools and fabrication machines

Anycubic Kobra 2 3D Printer

Story

Read more

Custom parts and enclosures

Pollinator Camera Case Bottom

Case bottom holds all of the camera components

Sketchfab still processing.

Pollinator Camera Case Top

Case top has openings for camera and sensors

Sketchfab still processing.

Schematics

Xiao ESP32S3 Pollinator Camera Schematic v1p0

Schematic for custom PCB from NextPCB

Code

Pollinator Camera Sensor Test

C/C++
Reads BME688 and OPT3001 data and publishes JSON string via MQTT
/***************************************************************************
 * Pollinator_Camera_Sensors.ino
 *
 *  Created on: 09.05.2025
 *  
 *  
 ***************************************************************************/

#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>
#include "arduino_secrets.h"
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <ClosedCube_OPT3001.h>
#include <ArduinoJson.h>

#define SEALEVELPRESSURE_HPA (1013.25)
#define OPT3001_ADDRESS 0x44

Adafruit_BME680 bme(&Wire); // I2C
ClosedCube_OPT3001 opt3001; // I2C

// Add your MQTT Broker IP address

// Set your Static IP address
IPAddress local_IP(10, 0, 0, 206);
// Set your Gateway IP address
IPAddress gateway(10, 0, 0, 1);
IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);   //optional
IPAddress secondaryDNS(8, 8, 4, 4); //optional

WiFiClient espClient;
PubSubClient client(espClient);

void setup() {
  Serial.begin(115200);
  // while (!Serial);
  Serial.println(F("Pollinator Camera Sensors test"));

  setup_wifi();
  client.setServer(mqtt_server, 1883); 

  opt3001.begin(OPT3001_ADDRESS);

  OPT3001_Config newConfig;
	newConfig.RangeNumber = B1100;	
	newConfig.ConvertionTime = B0;
	newConfig.Latch = B1;
	newConfig.ModeOfConversionOperation = B11;
  // Write config
  opt3001.writeConfig(newConfig);

  if (!bme.begin()) {
    Serial.println("Could not find a valid BME680 sensor, check wiring!");
    while (1);
  }

  // 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
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  // Tell BME688 to perform a measurement
  if (!bme.performReading()) {
    Serial.println("Failed to perform reading :(");
    return;
  }

  // Read OPT3001
  OPT3001 light = opt3001.readResult();

  // Create JSON object
  StaticJsonDocument<256> doc;
  doc["temperature"] = bme.temperature; // Celcius
  doc["humidity"] = bme.humidity;
  doc["pressure"] = bme.pressure / 100.0; // hPa
  doc["gas_resistance"] = bme.gas_resistance / 1000.0; // KOhms
  doc["altitude"] = bme.readAltitude(1013.25); // Approx sea-level pressure
  doc["light"] = light.lux; // Ambient light lux

  char jsonBuffer[256];
  serializeJson(doc, jsonBuffer);

  // Publish JSON
  client.publish("sensors/env", jsonBuffer);

  Serial.println(jsonBuffer);

  delay(30000); // adjust publish interval
}

void reconnect() {
  while (!client.connected()) {
    if (client.connect("BME688_Client")) {
      // Connected
    } else {
      delay(5000);
    }
  }
}

void setup_wifi() {
  delay(10);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500);
  }
}

Credits

Ralph Yamamoto
14 projects • 26 followers

Comments