The most important requirement for the system is the autonomy using a battery and a small solar cell.
It will first be necessary to make a prototype on a board. The sensor data will have to be reported on a data visualization platform, in our case Ubidots and Beep Monitor, with a dashboard that allows to evaluate the quantities over time and possibly generate alarms (email or SMS).
We have to design an electronic circuit (PCB) with the engraver and a box to have a robust product that can be used outdoors.
- OneWire sensors
Arduino code
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire ds18x20[] = { 6, 7 };
const int oneWireCount = sizeof(ds18x20)/sizeof(OneWire);
DallasTemperature sensor[oneWireCount];
void setup(void) {
// start serial port
Serial.begin(9600);
// Start up the library on all defined bus-wires
DeviceAddress deviceAddress;
for (int i = 0; i < oneWireCount; i++) {
sensor[i].setOneWire(&ds18x20[i]);
sensor[i].begin();
if (sensor[i].getAddress(deviceAddress, 0))
//sensor[i].setResolution(deviceAddress, 8);
sensor[i].setResolution(deviceAddress, 8);
}
}
void loop(void) {
// call sensors.requestTemperatures() to issue a global temperature
// request to all devices on the bus
Serial.print("Requesting temperatures...");
for (int i = 0; i < oneWireCount; i++) {
sensor[i].requestTemperatures();
}
Serial.println("DONE");
delay(1000);
for (int i = 0; i < oneWireCount; i++) {
float temperature = sensor[i].getTempCByIndex(0);
Serial.print("Temperature for the sensor ");
Serial.print(i+1);
Serial.print(" is ");
Serial.println(temperature,1);
}
Serial.println();
}
- DHT22
Arduino code
#include <dht.h>
#define dht_apin A0 // Analog Pin sensor is connected to
dht DHT;
void setup(){
Serial.begin(9600);
Serial.println("DHT11 Humidity & temperature Sensor\n\n");
}
void loop(){
DHT.read11(dht_apin);
Serial.print("Current humidity = ");
Serial.print(DHT.humidity);
Serial.print("% ");
Serial.print("Current temperature = ");
Serial.print(DHT.temperature);
Serial.println("C ");
delay(10000);
}
- Weight sensor HX711
Arduino code
#include <HX711.h>
#define LOADCELL_DOUT_PIN 5
#define LOADCELL_SCK_PIN 4
HX711 scale;
float calibration_factor = 21067; // for 16,6 -> 21067 and for ~93,5 -> 21387
float meas, p, real_meas;
void setup() {
Serial.begin(9600);
Serial.println("HX711 calibration sketch");
Serial.println("Remove all weight from scale");
Serial.println("After readings begin, place known weight on scale");
Serial.println("Press + or a to increase calibration factor");
Serial.println("Press - or z to decrease calibration factor");
scale.begin(LOADCELL_DOUT_PIN, LOADCELL_SCK_PIN);
scale.set_scale();
scale.tare(); //Reset the scale to 0
long zero_factor = scale.read_average(); //Get a baseline reading
Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects.
Serial.println(zero_factor);
}
void loop() {
scale.set_scale(calibration_factor); //Adjust to this calibration factor
Serial.print("Reading: ");
//Serial.print(scale.get_units(), 1);
meas = scale.get_units(10);
Serial.print(meas);
p = meas/3.7;
Serial.print(p);
Serial.print(" kg "); //Change this to kg and re-adjust the calibration factor if you follow SI units like a sane person
real_meas = meas - p;
Serial.print(real_meas);
Serial.print(" calibration_factor: ");
Serial.print(calibration_factor);
Serial.println();
if(Serial.available())
{
char temp = Serial.read();
if(temp == '+' || temp == 'a')
calibration_factor += 10;
else if(temp == '-' || temp == 'z')
calibration_factor -= 10;
}
}
- INA
Code Arduino
#include <Wire.h>
#include "DFRobot_INA219.h"
/**
* @fn DFRobot_INA219_IIC
* @brief pWire I2C controller pointer
* @param i2caddr I2C address
* @n INA219_I2C_ADDRESS1 0x40 A0 = 0 A1 = 0
* @n INA219_I2C_ADDRESS2 0x41 A0 = 1 A1 = 0
* @n INA219_I2C_ADDRESS3 0x44 A0 = 0 A1 = 1
* @n INA219_I2C_ADDRESS4 0x45 A0 = 1 A1 = 1
/
DFRobot_INA219_IIC ina219(&Wire, INA219_I2C_ADDRESS4);
short var_pow;
float meas_pow;
// Revise the following two paramters according to actual reading of the INA219 and the multimeter
// for linearly calibration
float ina219Reading_mA = 1;
float extMeterReading_mA = 5000;
void setup(void)
{
Serial.begin(115200);
//Open the serial port
while(!Serial);
Serial.println();
//Initialize the sensor
while(ina219.begin() != true) {
Serial.println("INA219 begin failed");
delay(2000);
}
//Linear calibration
ina219.linearCalibrate(/The measured current before calibration/ina219Reading_mA, /The current measured by other current testers/extMeterReading_mA);
Serial.println();
}
void loop(void)
{
Serial.print("BusVoltage: ");
Serial.print(ina219.getBusVoltage_V(), 2);
Serial.println("V");
Serial.print("ShuntVoltage: ");
Serial.print(ina219.getShuntVoltage_mV(), 3);
Serial.println("mV");
Serial.print("Current: ");
Serial.print(ina219.getCurrent_mA(), 1);
Serial.println("mA");
Serial.print("Power: ");
Serial.print(ina219.getPower_mW(), 1);
Serial.println("mW");
Serial.println("");
meas_pow = ina219.getPower_mW();
meas_pow = (meas_pow10)/14.4;
var_pow = (short)(meas_pow * 100);
Serial.print("meas pow2: ");
Serial.print(meas_pow);
Serial.print(" lux");
Serial.println("");
delay(1000);
}
- Power system
Arduino code
#define analogPin A3
float val = 0; // variable to store the value read
float resultat= 0; // le resultat en volt
float pourcentage=0; //la charge de la batterie en pourcentage
void setup() {
Serial.begin(9600); // setup serial
}
void loop() {
val = analogRead(analogPin); // read the input pin
Serial.print("Val : ");
Serial.println(val);
resultat = (val*3.3/1023); //(val*3.3/1024) 10 bits avec analogRead
pourcentage =(resultat*100/3.3);
Serial.print("Pourcentage batterie : "); // debug value
Serial.println(pourcentage);
delay(1000);
}
- System's consumption
With a tool called OTII ARC, we have estimated the consumption of the system while we have configure the arduino in Deep Sleep Mode to maximaze the autonomy of the battery system. We can see that our battery has an autonomy of 241 hours which means 9.5 days.
In order to display the values sent through TTN, we have to decode it by implementing a decoding function. We are dividing each value by 100 because they were multiplied by 100 in the arduino code (the purpose here is to have a range precision of 2 digits).
We have to customize the decoding function by using the same order of sending data in the Arduino code.
function decodeUplink(bytes) {
var decoded = {};
//if (bytes[0] == 1) {
// If received data is of Environment Monitoring type
decoded.humidity = (bytes[1] << 8 | (bytes[0])) /100;
decoded.temperature = (bytes[3] << 8 | (bytes[2])) /100;
decoded.humidity_exterieur = (bytes[5] << 8 | (bytes[4])) /100;
decoded.temperature_exterieur = (bytes[7] << 8 | (bytes[6])) /100;
decoded.battery = (bytes[9] << 8 | (bytes[8])) /100;
decoded.sonde_temperature_1 = (bytes[11] << 8 | (bytes[10])) /100;
decoded.sonde_temperature_2 = (bytes[13] << 8 | (bytes[12])) /100;
decoded.power = (bytes[15] << 8 | (bytes[14])) /100;
decoded.poids = (bytes[17] << 8 | (bytes[16])) /100;
//}
return {"data": decoded};
}
Once that is done, we have to create variables in Ubidots to stock that data and also create and customize a dashboard to display them.
To connect all the sensors to the microcontroller, we have to connected them through grove connectors on the PCB.
Thus we designed this schematic with Kicad:
Once that is done, it's time to move to the routing part of the PCB
Then we have printed our PCB, we have welded the differents components and placed them in a waterproof box:
On Beep Monitor, we have declared the main variables for the differents sensors.
Then, we used those names to write the decoding function in the payload formatter of TTN.
function decodeUplink(input) {
var data = {};
data.key ="your_data_key";
data.h_i = (input.bytes[1] << 8 | (input.bytes[0])) / 100;
data.t_i = (input.bytes[3] << 8 | (input.bytes[2])) / 100;
data.h = (input.bytes[5] << 8 | (input.bytes[4])) /100;
data.t = (input.bytes[7] << 8 | (input.bytes[6])) /100;
data.bv = (input.bytes[9] << 8 | (input.bytes[8])) /100;
data.t_0 = (input.bytes[11] << 8 | (input.bytes[10])) /100;
data.t_1 = (input.bytes[13] << 8 | (input.bytes[12])) /100;
data.l = (input.bytes[15] << 8 | (input.bytes[14])) /100;
data.weight_kg = (input.bytes[17] << 8 | (input.bytes[16])) /100;
return {
data: data,
warnings: [],
errors: []
};
}
After that, we went through an intensive testing phase and send the data with TTN. The data were then display on Beep Monitor where we can obtain these results:
Once the results are approved, we went to the farm where the hives are and we install our system!
Comments
Please log in or sign up to comment.