VodhelVouauxHugoMathieuSemenzatoCestClaireTaWu
Published © MIT

BeeHave - Bee monitor

Student project aiming to make a hive monitor, measuring frequency, temperature, humidity as well as enlightenment.

IntermediateFull instructions provided380
BeeHave - Bee monitor

Things used in this project

Hardware components

Solar Cell
×1
Lithium battery
×1
LiPo Rider Pro
×1
Homemade weigh scale HX711
×1
DHT22 Temperature Sensor
DHT22 Temperature Sensor
×2
Grove temperature sensor
×1
Nano 33 BLE Sense
Arduino Nano 33 BLE Sense
×1
Lora-E5 Grove
×1
Microphone
×1
Audio amplifier
×1
Embase jack femelle
×1
Box
×1

Software apps and online services

KiCad
KiCad
Arduino IDE
Arduino IDE
The Things Stack
The Things Industries The Things Stack
Ubidots
Ubidots
BeepMonitor

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
PCB Milling Machine (Generic)
Computer

Story

Read more

Schematics

Ampli Micro PCB

Main PCB

Code

Arduino code

Arduino
//Partie temp et hum
//Serial1(6, 7); // (RX, TX)le port fait partie de la carte il est directement relié par les branchements 
#define SHDN 2 //D21.
#define LED 11 //déclaration de la LED

#include <DHT.h>
#define brocheDeBranchementDHT_1 7    // La ligne de communication du DHT22 sera donc branchée sur la pin D7 de l'Arduino
#define typeDeDHT DHT22             // Ici, le type de DHT utilisé est un DHT22 (que vous pouvez changer en DHT11, DHT21, ou autre, le cas échéant)
  // Instanciation de la librairie DHT
DHT dht1(brocheDeBranchementDHT_1, typeDeDHT);

#define brochedeBranchementDHT_2 6
DHT dht2(brochedeBranchementDHT_2, typeDeDHT);

//Partie poids
#include "HX711.h"
#define LOADCELL_DOUT_PIN  8
#define LOADCELL_SCK_PIN  9
HX711 scale;
short pds=0;

//Partie Lora
static char recv_buf[512];
static bool is_exist = false;
static bool is_join = false;
static int led = 0;
int ret=0;

//Variable temp et hum
short tmp1;
short hum1;
float tauxHumidite1;              // Lecture du taux d'humidité (en %)
float temperatureEnCelsius1;   // Lecture de la température, exprimée en degrés Celsius

short tmp2;
short hum2;
float tauxHumidite2;
float temperatureEnCelsius2;

//Partie temp seule
#define MAXIMWIRE_EXTERNAL_PULLUP
#include <MaximWire.h>
#define PIN_BUS 10 //D10
MaximWire::Bus bus(PIN_BUS);
MaximWire::DS18B20 device;

//partie mesure du courant et de la tension pour calculer la luminosité et l'état de la batterie
#include <Wire.h>
#include "DFRobot_INA219.h"
DFRobot_INA219_IIC     ina219(&Wire, INA219_I2C_ADDRESS4);
float ina219Reading_mA = 1000;
float extMeterReading_mA = 1000;
//bool etat = false, etat_avant = false;
short tauxluminosite;              // Lecture du taux de liminosite (en %)
short batterie;   // état de la batterie (en %)

//partie FFT
#include "arduinoFFT.h"
//Variables gloabeles nécessaires
#define SAMP_FREQ 2048
#define NUM_SAMP 256
unsigned int samp_period;
unsigned long timing;
// Vectors to hold samples
double real[NUM_SAMP];
double imag[NUM_SAMP];
double freq_imp;
double freq[(NUM_SAMP>>1)+1];
short fft;

arduinoFFT FFT = arduinoFFT();



//fonction Lora
static int at_send_check_response(char *p_ack, int timeout_ms, char *p_cmd, ...){
  int ch;
  int num = 0;
  int index = 0;
  int startMillis = 0;
  memset(recv_buf, 0, sizeof(recv_buf));
  Serial1.write(p_cmd);
  Serial.write(p_cmd);
  delay(200);
  startMillis = millis();
  do{
    while (Serial1.available() > 0){
      ch = Serial1.read();
      recv_buf[index++] = ch;
      Serial.write(ch);
      delay(2);
    }

  }
  while (millis() - startMillis < timeout_ms);
  if (strstr(recv_buf, p_ack) != NULL){
    return 1;
  }
  else return 0;
  }

void setup() {
  //paramétrage de la led pour qu'elle s'allume 3 secondes si on allume l'interrupteur
  
  // 2 lignes suivantes en +
  pinMode(SHDN, OUTPUT);
  digitalWrite(SHDN,HIGH);
  
  pinMode(LED_PWR, OUTPUT);
  delay(1000);
  digitalWrite(LED_PWR, LOW);
  pinMode(LED, OUTPUT);
  delay(1000);
  digitalWrite(LED, HIGH);
  delay(3000);
  digitalWrite(LED, LOW);
  delay(3000);
// put your setup code here, to run once:
  Serial.begin(9600);
  Serial1.begin(9600);
  Serial.print("Serial1 LORAWAN TEST\r\n");
  if(at_send_check_response("+AT: OK", 100, "AT\r\n"))
  {
    is_exist = true;
    at_send_check_response("+ID: AppEui", 1000, "AT+ID\r\n");
    at_send_check_response("+MODE: LWOTAA", 1000, "AT+MODE=LWOTAA\r\n");
    at_send_check_response("+DR: EU868", 1000, "AT+DR=EU868\r\n");

    at_send_check_response("+DR: DR0", 1000, "AT+DR=DR0\r\n"); //ligne ajoutéé!

    at_send_check_response("+CH: NUM", 1000, "AT+CH=NUM,0-2\r\n");
    at_send_check_response("+KEY: APPKEY", 1000,"AT+KEY=APPKEY,\"D65874A71B9E99229F2D43C9D3C6E000\"\r\n");
    at_send_check_response("+KEY: DEVEUI", 1000, "AT+ID=DEVEUI,\"2CF7F1203230C97C\"\r\n");
    at_send_check_response("+KEY: APPEUI", 1000, "AT+ID=APPEUI,\"8000000000000006\"\r\n");
    at_send_check_response("+CLASS: C", 1000, "AT+CLASS=A\r\n");
    ret=at_send_check_response("+PORT: 8", 1000, "AT+PORT=8\r\n");
    delay(200);
    is_join = true;
  }
  else
  {
    is_exist = false;
    Serial.print("No Serial1 module found.\r\n");
  }

// Initialisation de la liaison série (pour retourner les infos au moniteur série de l'ordi)
  //Serial.begin(9600);
  //Serial.println("Programme de test du DHT22");
  //Serial.println("==========================");
  //Serial.println();

  // Initialisation du DHT22;
  dht1.begin();
  dht2.begin();

//Partie balance
  scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);

//partie mesure courant et tension
Serial.println();
    while(ina219.begin() != true)
    {
        Serial.println("INA219 begin failed");
        delay(2000);
    }
    ina219.linearCalibrate(ina219Reading_mA, extMeterReading_mA);
    Serial.println();


//Partie FFT
samp_period = round(1000000 * (1.0 / SAMP_FREQ));
}

void loop() {
  if (is_exist){
    int ret = 0;
    if (is_join){
      ret = at_send_check_response("+JOIN: Network joined", 12000, "AT+JOIN\r\n");
      if (ret){
        is_join = false;
        Serial.println();
        Serial.print("Network JOIN !\r\n\r\n");
        
        // Lecture des données
        tauxHumidite1 = dht1.readHumidity();
        Serial.println(tauxHumidite1);
        temperatureEnCelsius1 = dht1.readTemperature();
        Serial.println(temperatureEnCelsius1);
        tauxHumidite2 = dht2.readHumidity();
        Serial.println(tauxHumidite2);
        temperatureEnCelsius2 = dht2.readTemperature();      
        Serial.println(temperatureEnCelsius2);
        
        //lecture des données de courant et de tension 
        Serial.print("Batterie chargée à ");
        Serial.print(analogRead(A7)*0.1538); // *100 / 650
        Serial.println("%");
        //batterie = analogRead(A7)*0.1538*100;

        Serial.print("Current:      ");
        Serial.print(abs(ina219.getCurrent_mA()), 1);
        Serial.print("mA -> ");
        Serial.print(abs(ina219.getCurrent_mA()/4), 1);
        Serial.println(" pourcent de luminosité");
        //tauxluminosite = abs(ina219.getCurrent_mA()/4)*100;
        
        // Vérification si données bien reçues
        if (isnan(tauxHumidite1) || isnan(temperatureEnCelsius1) || isnan(tauxHumidite2) || isnan(temperatureEnCelsius2)) {
          Serial.println("Aucune valeur retournée par le DHT22. Est-il bien branché ?");
          delay(2000);
          return;         // Si aucune valeur n'a été reçue par l'Arduino, on attend 2 secondes, puis on redémarre la fonction loop()
        }        
      
        // Calcul de la température ressentie
        //float temperatureRessentieEnCelsius = dht.computeHeatIndex(temperatureEnCelsius, tauxHumidite, false); // Le "false" est là pour dire qu'on travaille en °C, et non en °F
        
        // Affichage des valeurs
        //Serial.print("Humidité = "); Serial.print(tauxHumidite); Serial.println(" %");
        //Serial.print("Température = "); Serial.print(temperatureEnCelsius); Serial.println(" °C");
        //Serial.print("Température ressentie = "); Serial.print(temperatureRessentieEnCelsius); Serial.println(" °C");
        //Serial.println();
      
        // Temporisation de 2 secondes (pour rappel : il ne faut pas essayer de faire plus d'1 lecture toutes les 2 secondes, avec le DHT22, selon le fabricant)
        delay(2000);
        
      } 
      else{
        at_send_check_response("+ID: AppEui", 1000, "AT+ID\r\n");
        Serial.println();
        Serial.print("JOIN failed!\r\n\r\n");
        delay(5000);
      } 
    }
    else{ 
      char cmd[128];

    
      //poids + sleep mode
      scale.power_up();
      pds = ((scale.get_units()-333857)/29661)*100;
      scale.power_down();

      //partie batterie
      //important : a 100% de batterie, analogRead vaut 642, a 0%, il vaut 512
      //(analogRead(A7)-512)doit donner une valeur entre 130 et 0 -> /130 * 100 = pourcentage
      batterie = analogRead(A7); //510 pour avoir une marge -> pas de valeurs négatives
      tauxluminosite = abs(ina219.getCurrent_mA()/4)*100;

      
      digitalWrite(SHDN,HIGH);

      dht1.begin();
      dht2.begin();
      delay(10000);//histoire de laisser le temps de s'init bien
      
      //Partie FFT
      // Sampling 
      for (int i=0; i<NUM_SAMP; i++) {
        // Time since Arduino began script 
        timing = micros();
        // Take in ADC measurement from pin A0 
        real[i] = analogRead(A3);
        //Set imaginary term of sample to 0 
        imag[i] = 0;
        // Pause to set frequency
        while((samp_period + timing) > micros()){
        }
      }
      // FFT 
      FFT.Windowing(real, NUM_SAMP, FFT_WIN_TYP_HAMMING, FFT_FORWARD);
      FFT.Compute(real, imag, NUM_SAMP, FFT_FORWARD);
      FFT.ComplexToMagnitude(real, imag, NUM_SAMP);
      // Calculate most prominant frequency 
      freq_imp = FFT.MajorPeak(real, NUM_SAMP, SAMP_FREQ)-15;
      Serial.print("frequence :");
      Serial.println(freq_imp);
      fft=freq_imp*100;


      freq[0]=0;
      for(int i=1; i<((NUM_SAMP>>1)+1); i++){
        double delta = 0.5 * ((real[i-1] - real[i+1]) / (real[i-1] - (2.0 * real[i]) + real[i+1]));
        double interpolatedX = ((i + delta)  * SAMP_FREQ) / (NUM_SAMP-1);
        if(i==(NUM_SAMP>> 1)) //To improve calculation on edge values
          interpolatedX = ((i + delta)  * SAMP_FREQ) / (NUM_SAMP);
      
        freq[i]=interpolatedX-15;    
      }

      double val[10]={0,0,0,0,0,0,0,0,0,0};
      int cpt[10]={0,0,0,0,0,0,0,0,0,0};

      for(int i=0; i<((NUM_SAMP>>1)+1); i++){
        if(freq[i]>98 && freq[i]<=146){
          val[0]+=real[i]*(3.3/1024)*1000;
          cpt[0]++;
        }

        else if(freq[i]>146 && freq[i]<=195){
          val[1]+=real[i]*(3.3/1024)*1000;
          cpt[1]++;
        }

        else if(freq[i]>195 && freq[i]<=244){
          val[2]+=real[i]*(3.3/1024)*1000;
          cpt[2]++;
        }

        else if(freq[i]>244 && freq[i]<=293){
          val[3]+=real[i]*(3.3/1024)*1000;
          cpt[3]++;
        }

        else if(freq[i]>293 && freq[i]<=342){
          val[4]+=real[i]*(3.3/1024)*1000;
          cpt[4]++;
        }

        else if(freq[i]>342 && freq[i]<=391){
          val[5]+=real[i]*(3.3/1024)*1000;
          cpt[5]++;
        }

        else if(freq[i]>391 && freq[i]<=439){
          val[6]+=real[i]*(3.3/1024)*1000;
          cpt[6]++;
        }

        else if(freq[i]>439 && freq[i]<=488){
          val[7]+=real[i]*(3.3/1024)*1000;
          cpt[7]++;
        }

        else if(freq[i]>488 && freq[i]<=537){
          val[8]+=real[i]*(3.3/1024)*1000;
          cpt[8]++;
        }

        else if(freq[i]>537 && freq[i]<=586){
          val[9]+=real[i]*(3.3/1024)*1000;
          cpt[9]++;
        }
      }

      short f[10];
      Serial.println("Valeur :");
      for(int i=0; i<10; i++){
        if(cpt[i]!=0){
          f[i]=val[i]/cpt[i];     
        }else{
          f[i]=0;
        } 
        //f[i]=val[i]*10;   
        Serial.println(val[i]/cpt[i]); 
        Serial.println(f[i]); 
      }
      
          
      tauxHumidite1 = dht1.readHumidity();
      Serial.println(tauxHumidite1);
      temperatureEnCelsius1 = dht1.readTemperature();
      Serial.println(temperatureEnCelsius1);
      tauxHumidite2 = dht2.readHumidity();
      Serial.println(tauxHumidite2);
      temperatureEnCelsius2 = dht2.readTemperature();      
      Serial.println(temperatureEnCelsius2);

       //hum et temp
      tmp1 = (temperatureEnCelsius1*1.02)*100;
      hum1 = tauxHumidite1*100;

      tmp2 = (temperatureEnCelsius2)*100;
      hum2 = tauxHumidite2*100;


  //code temp solo
      MaximWire::Discovery discovery = bus.Discover();
      short temp1_solo=(temperatureEnCelsius1+0.07)*100;
      short temp2_solo=(temperatureEnCelsius1-0.09)*100;
      
      int i=0;
      do {
        MaximWire::Address address;
        if (discovery.FindNextDevice(address)) {
            if (address.GetModelCode() == MaximWire::DS18B20::MODEL_CODE) {
                MaximWire::DS18B20 device(address);
                float tp = device.GetTemperature<float>(bus);
                device.Update(bus); 
                if(i==0){
                  temp1_solo=(tp*1.02)*100;  
                  i++;   
                }else{
                  temp2_solo=(tp)*100;
                  i--;
                }                     
           } 
        }
      }while (discovery.HaveMore());




      //partie mode sleep
      digitalWrite(SHDN,LOW);

      
      
      //envoie de mess
      //ligne en + non vérifiée pour assurer l'émission en SF12
      at_send_check_response("+DR: DR0", 1000, "AT+DR=DR0\r\n"); //ligne ajoutéé!

      
      //sprintf(cmd, "AT+MSGHEX=%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X\r\n", tmp1, hum1, temp1_solo,temp2_solo, pds, tmp2, hum2, tauxluminosite, batterie, fft);
      sprintf(cmd, "AT+MSGHEX=%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X\r\n", tmp1, hum1, temp1_solo,temp2_solo, pds, tmp2, hum2, tauxluminosite, batterie, fft, f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]); 
      //sprintf(cmd, "AT+MSGHEX=%04X%04X%04X%04X%04X%04X%04X%04X%04X%04X\r\n", f[0], f[1], f[2], f[3], f[4], f[5], f[6], f[7], f[8], f[9]);          
      //les valeurs sont multipliées par 100 pour être entière -> pouvoir envoyer en hexadécimale
      at_send_check_response("ACK Received", 5000, cmd);
      delay(20000);
    }
  }
  else{
    delay(1000);
  }
  //delay(3600000); //pour un délai d'1h car delay 1000=1sec
  //delay(580000);
  //delay(5000);
}

Credits

Vodhel

Vodhel

2 projects • 1 follower
VouauxHugo

VouauxHugo

2 projects • 1 follower
MathieuSemenzato

MathieuSemenzato

2 projects • 1 follower
CestClaireTaWu

CestClaireTaWu

2 projects • 1 follower

Comments