Matthew HurleySam Freeze
Published © GPL3+

BeeO Terminal

A simple bee monitoring system that uses sensors and AI vision to facilitate bee care

IntermediateFull instructions provided5 hours405
BeeO Terminal

Things used in this project

Hardware components

SenseCAP K1100 - The Sensor Prototype Kit with LoRa® and AI
Seeed Studio SenseCAP K1100 - The Sensor Prototype Kit with LoRa® and AI
×1
solar battery pack
×1

Software apps and online services

Blynk
Blynk
Roboflow Universe
YOLOv5
Google Colab

Story

Read more

Schematics

BeeO Terminal Block Diagram

General connections and upload startegies

WIO Terminal Pinouts

Code

BeeO_code

Arduino
Basic code for the BeeO Terminal
#include "Seeed_Arduino_GroveAI.h"
#include "Wire.h"
#include "TFT_eSPI.h" //TFT LCD library 
#include "SensirionI2CSht4x.h"


//Initializations
TFT_eSPI tft; //Initializing TFT LCD
TFT_eSprite spr = TFT_eSprite(&tft); //Initializing buffer

GroveAI ai(Wire);
uint8_t state = 0;

SensirionI2CSht4x sht4x;

volatile bool pageState = false;
volatile bool hiveChecked = false;
int checkPeriod = 86400000; //ms
int start;

//interrupt function for hive check confirmation
void hive_check() {

  hiveChecked = true;
  start = millis();
}

//interrupt function for hive check cancellations
void hive_uncheck() {

  hiveChecked = false;
}

//interrupt function for the first page selection
void page_b() {

  pageState = true;
}

//interrupt function for the second page selection
void page_c() {

  pageState = false;
}



void setup() {


  Serial.begin(9600);

//Initialize both I2C ports
  Wire.begin();
  Wire1.begin();
  sht4x.begin(Wire1);

//Initialize the AI module
  Serial.println("begin");
  if (ai.begin(ALGO_OBJECT_DETECTION, MODEL_EXT_INDEX_1)) // Object detection and pre-trained model 1
  {

    Serial.print("Version: ");
    Serial.println(ai.version());
    Serial.print("ID: ");
    Serial.println( ai.id());
    Serial.print("Algo: ");
    Serial.println( ai.algo());
    Serial.print("Model: ");
    Serial.println(ai.model());
    Serial.print("Confidence: ");
    Serial.println(ai.confidence());
    state = 1;
  } else {

    Serial.println("Algo begin failed.");
  }

  uint16_t error;
  char errorMessage[256];
 
 //Check the connection of the temperature and humidity module
  uint32_t serialNumber;
  error = sht4x.serialNumber(serialNumber);
  if (error) {
      Serial.print("Error trying to execute serialNumber(): ");
      errorToString(error, errorMessage, 256);
      Serial.println(errorMessage);
  } else {
      Serial.print("sht4x Serial Number: ");
      Serial.println(serialNumber);
  }


  pinMode(WIO_LIGHT, INPUT); //Set light sensor pin as INPUT
  pinMode(WIO_MIC, INPUT); //Set mic pin as INPUT
  pinMode(WIO_BUZZER, OUTPUT); //Set the buzzer pin as an output

  pinMode(WIO_5S_PRESS, INPUT_PULLUP);
  pinMode(WIO_KEY_B, INPUT_PULLUP);
  pinMode(WIO_KEY_C, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(WIO_5S_PRESS), hive_check, FALLING); //Button for marking the hive as checked
  attachInterrupt(digitalPinToInterrupt(WIO_KEY_A), hive_uncheck, FALLING); //Button for "unchecking" the hive
  attachInterrupt(digitalPinToInterrupt(WIO_KEY_B), page_b, FALLING); //Button for the first page on the terminal
  attachInterrupt(digitalPinToInterrupt(WIO_KEY_C), page_c, FALLING); //Button for the second page on the terminal


  //Power up tune
  for (int i = 0; i < 100; i++){

    digitalWrite(WIO_BUZZER, HIGH);
    delayMicroseconds(1000);
    digitalWrite(WIO_BUZZER, LOW);
    delayMicroseconds(1000);
  }

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

    digitalWrite(WIO_BUZZER, HIGH);
    delayMicroseconds(400);
    digitalWrite(WIO_BUZZER, LOW);
    delayMicroseconds(400);
  }

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

    digitalWrite(WIO_BUZZER, HIGH);
    delayMicroseconds(125);
    digitalWrite(WIO_BUZZER, LOW);
    delayMicroseconds(125);
  }
  

  tft.begin(); //Start TFT LCD
  tft.setRotation(3); //Set TFT LCD rotation
  spr.createSprite(TFT_HEIGHT,TFT_WIDTH); //Create buffer
}

void loop() {

  float temperature;
  float humidity;
  int conf = 0;
  int avgConf = 0;
  uint8_t len = 0;


  uint16_t error;
  char errorMessage[256];

//Temperature and humidity measurements and error check
  error = sht4x.measureHighPrecision(temperature, humidity);
  if (error) {
    Serial.print("Error trying to execute measureHighPrecision(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  }

  if (millis() - start > checkPeriod){
    hiveChecked = false;
  }

//Onboard sensor measurements
  int light = analogRead(WIO_LIGHT); //Assign variable to store light sensor values
  int soundValue = analogRead(WIO_MIC); //Store sound values 
  

//AI vision module data acquisition
  if (state == 1) {

    if (ai.invoke()) { // begin invoke

      while (1) {// wait for invoking finished
      
        CMD_STATE_T ret = ai.state(); 
        if (ret == CMD_STATE_IDLE) {

          break;
        }

        delay(10);
      }
 
      len = ai.get_result_len(); // receive how many people detect
      if(len) {

        object_detection_t data;       //get data
        for (int i = 0; i < len; i++) {

          ai.get_result(i, (uint8_t*)&data, sizeof(object_detection_t)); //get result
          conf = data.confidence + conf; //create a sum of confidence values for averaging

        }

        avgConf = conf/len; //average the confidence values
      } else {

        Serial.println("No identification");
      }
    } else {

      delay(10);
      Serial.println("Invoke Failed.");
    }

  } else {

    state == 0;
  }

//Create the WIO terminal LCD displays
  if (pageState == false){ //First page - for sensor measurements

    //Setting the title header for page 1
    spr.fillSprite(TFT_BLACK); //Fill background
    spr.fillRect(0,0,320,50,TFT_YELLOW); //Rectangle fill
    spr.setTextColor(TFT_BLACK); //Setting text color
    spr.setTextSize(3); //Setting text size 
    spr.drawString("HIVE STATUS",64,15); //Drawing a text string 

    spr.drawFastVLine(150,50,190,TFT_YELLOW); //Drawing verticle line
    spr.drawFastHLine(0,140,320,TFT_YELLOW); //Drawing horizontal line

    //Setting temperature
    spr.setTextColor(TFT_YELLOW);
    spr.setTextSize(2);
    spr.drawString("Temperature",10,65);
    spr.setTextSize(3);
    spr.drawNumber(temperature,50,95); //Display temperature values 
    spr.drawString("C",90,95);

    //Setting humidity
    spr.setTextSize(2);
    spr.drawString("Humidity",25,160);
    spr.setTextSize(3);
    spr.drawNumber(humidity,30,190); //Display humidity values 
    spr.drawString("%RH",70,190);

    //Setting sound level

    soundValue = map(soundValue,0,800,0,100); //Map sound values 
    spr.setTextSize(2);
    spr.drawString("Noise Level",160,65);
    spr.setTextSize(3);
    spr.drawNumber(soundValue,200,95); //Display sound values as percentage  
    spr.drawString("%",240,95);

    //Setting light 
    spr.setTextSize(2);
    spr.drawString("Light",200,160);
    spr.setTextSize(3);
    light = map(light,0,1023,0,100); //Map light sensor values 
    spr.drawNumber(light,205,190); //Display light sensor values as percentage  
    spr.drawString("%",245,190);
  } else {

    //Setting the title header for page 2 - AI vision data and hive check
    spr.fillSprite(TFT_BLACK); //Fill background
    spr.setTextColor(TFT_YELLOW); //Setting text color
    spr.setTextSize(4); //Setting text size 
    spr.drawString("BEE ACTIVITY",18,15); //Drawing a text string 

    spr.drawFastHLine(0,180,320,TFT_YELLOW); //Drawing horizontal line
    spr.drawFastHLine(0,55,320,TFT_YELLOW); //Drawing horizontal line

    spr.setTextSize(2); //Setting text size 
    spr.drawString("BEES COUNTED: ",28,65); //Drawing a text string 
    spr.drawNumber(len,100,90);
    spr.drawString("AVERAGE CONFIDENCE:",28,125); //Drawing a text string
    spr.drawNumber(avgConf,100,150);

    if (hiveChecked == false){

      spr.setTextSize(2); //Setting text size 
      spr.drawString("!! HIVE READY TO BE !!",28,190); //Drawing a text string 
      spr.drawString("CHECKED",117,210); //Drawing a text string
    }
  }


  spr.pushSprite(0,0); //Push to LCD
  delay(30);


}

Wifi_BeeO_code

Arduino
Basic Code for BeeO Terminal WIFI support
// Template ID, Device Name and Auth Token are provided by the Blynk.Cloud
// See the Device Info tab, or Template settings
#define BLYNK_TEMPLATE_ID "TMPLf81e7DoG"
#define BLYNK_DEVICE_NAME "BeeO Terminal"
#define BLYNK_AUTH_TOKEN "gMLwd_WefV4N1fvBM_IOV7A0DqvaiH02"

// Your WiFi credentials.
// Set password to "" for open networks.
char ssid[] = "Default Network";
char pass[] = "StreetNumber11000!";

#define BLYNK_PRINT Serial

#include "rpcWiFi.h"
#include "WiFiClient.h"
#include "BlynkSimpleWioTerminal.h"
#include "Seeed_Arduino_GroveAI.h"
#include "Wire.h"
#include "TFT_eSPI.h" //TFT LCD library 
#include "Arduino.h"
#include "SensirionI2CSht4x.h"


//Initializations
/**
TFT_eSPI tft; //Initializing TFT LCD
TFT_eSprite spr = TFT_eSprite(&tft); //Initializing buffer
**/

GroveAI ai(Wire);
uint8_t state = 0;

SensirionI2CSht4x sht4x;
/**
volatile bool pageState = false;
volatile bool hiveChecked = false;
int checkPeriod = 86400000; //ms
int start;
**/
char auth[] = BLYNK_AUTH_TOKEN;
 
BlynkTimer timer;
/**
void hive_check() {

  hiveChecked = true;
  start = millis();
}

void hive_uncheck() {

  hiveChecked = false;
}

void page_b() {

  pageState = true;
}

void page_c() {

  pageState = false;
}
**/


void myTimerEvent(){

  float temperature;
  float humidity;
  int conf = 0;
  int avgConf = 0;
  uint8_t len = 0;

  int light = analogRead(WIO_LIGHT); //Assign variable to store light sensor values
  light = map(light,0,1023,0,100); //Map light sensor values 
  int soundValue = analogRead(WIO_MIC); //Store sound values 
  soundValue = map(soundValue,0,800,0,100); //Map sound values 

  Blynk.virtualWrite(V0, light);
  Serial.print("Light: ");
  Serial.println(light);
  Blynk.virtualWrite(V1, soundValue);

  uint16_t error;
  char errorMessage[256];

  error = sht4x.measureHighPrecision(temperature, humidity);
  if (error) {
    Serial.print("Error trying to execute measureHighPrecision(): ");
    errorToString(error, errorMessage, 256);
    Serial.println(errorMessage);
  }

  Blynk.virtualWrite(V2, temperature);
  Blynk.virtualWrite(V3, humidity);

  if (state == 1) {

    if (ai.invoke()) { // begin invoke

      while (1) {// wait for invoking finished
      
        CMD_STATE_T ret = ai.state(); 
        if (ret == CMD_STATE_IDLE) {

          break;
        }

        delay(50);
      }
 
      len = ai.get_result_len(); // receive how many people detect
      if(len) {

        object_detection_t data;       //get data
        for (int i = 0; i < len; i++) {

          ai.get_result(i, (uint8_t*)&data, sizeof(object_detection_t)); //get result
          conf = data.confidence + conf;
          Serial.println("Successful Identification");
          Serial.println(i+1);
          Serial.println(data.confidence);
          Serial.println();

        }

        avgConf = conf/len;
        Blynk.virtualWrite(V5, avgConf);
        Blynk.virtualWrite(V4, len);
      } else {

        Serial.println("No identification");
        Blynk.virtualWrite(V4, 0);
        Blynk.virtualWrite(V5, 0);
      }
    } else {

      delay(200);
      Serial.println("Invoke Failed.");
    }

  } else {

    state == 0;
  }
}



void setup() {

  Serial.begin(115200);
  while(!Serial); // Wait for Serial to be ready

  Wire.begin();
  Wire1.begin();
  sht4x.begin(Wire1);

  Serial.println("begin");
  if (ai.begin(ALGO_OBJECT_DETECTION, MODEL_EXT_INDEX_1)) // Object detection and pre-trained model 1
  {

    Serial.print("Version: ");
    Serial.println(ai.version());
    Serial.print("ID: ");
    Serial.println( ai.id());
    Serial.print("Algo: ");
    Serial.println( ai.algo());
    Serial.print("Model: ");
    Serial.println(ai.model());
    Serial.print("Confidence: ");
    Serial.println(ai.confidence());
    state = 1;
  } else {

    Serial.println("Algo begin failed.");
  }

  uint16_t error;
  char errorMessage[256];
 
  uint32_t serialNumber;
  error = sht4x.serialNumber(serialNumber);
  if (error) {
      Serial.print("Error trying to execute serialNumber(): ");
      errorToString(error, errorMessage, 256);
      Serial.println(errorMessage);
  } else {
      Serial.print("sht4x Serial Number: ");
      Serial.println(serialNumber);
  }


  pinMode(WIO_LIGHT, INPUT); //Set light sensor pin as INPUT
  pinMode(WIO_MIC, INPUT); //Set mic pin as INPUT
  pinMode(WIO_BUZZER, OUTPUT); //Set the buzzer pin as an output
/**
  pinMode(WIO_5S_PRESS, INPUT_PULLUP);
  pinMode(WIO_KEY_B, INPUT_PULLUP);
  pinMode(WIO_KEY_C, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(WIO_5S_PRESS), hive_check, FALLING);
  attachInterrupt(digitalPinToInterrupt(WIO_KEY_A), hive_uncheck, FALLING);
  attachInterrupt(digitalPinToInterrupt(WIO_KEY_B), page_b, FALLING);
  attachInterrupt(digitalPinToInterrupt(WIO_KEY_C), page_c, FALLING);
**/

  //Power up tune
  for (int i = 0; i < 100; i++){

    digitalWrite(WIO_BUZZER, HIGH);
    delayMicroseconds(1000);
    digitalWrite(WIO_BUZZER, LOW);
    delayMicroseconds(1000);
  }

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

    digitalWrite(WIO_BUZZER, HIGH);
    delayMicroseconds(400);
    digitalWrite(WIO_BUZZER, LOW);
    delayMicroseconds(400);
  }

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

    digitalWrite(WIO_BUZZER, HIGH);
    delayMicroseconds(125);
    digitalWrite(WIO_BUZZER, LOW);
    delayMicroseconds(125);
  }
  
  Blynk.begin(auth, ssid, pass);
  // You can also specify server:
  //Blynk.begin(auth, ssid, pass, "blynk.cloud", 80);
  //Blynk.begin(auth, ssid, pass, IPAddress(192,168,1,100), 8080);
 
  // Setup a function to be called every second
  timer.setInterval(1000L, myTimerEvent);
/**
  tft.begin(); //Start TFT LCD
  tft.setRotation(3); //Set TFT LCD rotation
  spr.createSprite(TFT_HEIGHT,TFT_WIDTH); //Create buffer
**/
}

void loop() {
/**
  if (millis() - start > checkPeriod){
    hiveChecked = false;
  }
**/
  Blynk.run();
  timer.run(); // Initiates BlynkTimer
/**
  if (pageState == false){

    //Setting the title header for page 1
    spr.fillSprite(TFT_BLACK); //Fill background with white color
    spr.fillRect(0,0,320,50,TFT_YELLOW); //Rectangle fill with dark green 
    spr.setTextColor(TFT_BLACK); //Setting text color
    spr.setTextSize(3); //Setting text size 
    spr.drawString("HIVE STATUS",64,15); //Drawing a text string 

    spr.drawFastVLine(150,50,190,TFT_YELLOW); //Drawing verticle line
    spr.drawFastHLine(0,140,320,TFT_YELLOW); //Drawing horizontal line

    //Setting temperature
    spr.setTextColor(TFT_YELLOW);
    spr.setTextSize(2);
    spr.drawString("Temperature",10,65);
    spr.setTextSize(3);
    spr.drawNumber(temperature,50,95); //Display temperature values 
    spr.drawString("C",90,95);

    //Setting humidity
    spr.setTextSize(2);
    spr.drawString("Humidity",25,160);
    spr.setTextSize(3);
    spr.drawNumber(humidity,30,190); //Display humidity values 
    spr.drawString("%RH",70,190);

    //Setting sound level

    soundValue = map(soundValue,0,800,0,100); //Map sound values 
    spr.setTextSize(2);
    spr.drawString("Noise Level",160,65);
    spr.setTextSize(3);
    spr.drawNumber(soundValue,200,95); //Display sound values as percentage  
    spr.drawString("%",240,95);

    //Setting light 
    spr.setTextSize(2);
    spr.drawString("Light",200,160);
    spr.setTextSize(3);
    light = map(light,0,1023,0,100); //Map light sensor values 
    spr.drawNumber(light,205,190); //Display light sensor values as percentage  
    spr.drawString("%",245,190);
  } else {

    //Setting the title header for page 2
    spr.fillSprite(TFT_BLACK); //Fill background with white color
    spr.setTextColor(TFT_YELLOW); //Setting text color
    spr.setTextSize(4); //Setting text size 
    spr.drawString("BEE ACTIVITY",18,15); //Drawing a text string 

    spr.drawFastHLine(0,180,320,TFT_YELLOW); //Drawing horizontal line
    spr.drawFastHLine(0,55,320,TFT_YELLOW); //Drawing horizontal line

    spr.setTextSize(2); //Setting text size 
    spr.drawString("BEES COUNTED: ",28,65); //Drawing a text string 
    spr.drawNumber(len,100,90);
    spr.drawString("AVERAGE CONFIDENCE:",28,125); //Drawing a text string
    spr.drawNumber(avgConf,100,150);

    if (hiveChecked == false){

      spr.setTextSize(2); //Setting text size 
      spr.drawString("!! HIVE READY TO BE !!",28,190); //Drawing a text string 
      spr.drawString("CHECKED",117,210); //Drawing a text string
    }
  }


  spr.pushSprite(0,0); //Push to LCD
  delay(30);
**/

}

Bee_Pollen.uf2

Arduino
Trained model using the BeePollen dataset from Roboflow universe - user "beepollen2
No preview (download only).

Credits

Matthew Hurley

Matthew Hurley

5 projects • 4 followers
Sam Freeze

Sam Freeze

0 projects • 2 followers
PhD wildlife biology student and bat researcher working at the intersection of cutting-edge technology and bat conservation.

Comments