1 Circuit d’alimentation
J’utilise une batterie type auto de 40Ah, ça dure un bon moment. Pour alimenter mon circuit qui fonctionne en 5V, un convertisseur à haut rendement de type LM2596 délivre une tension ajustable avec un débit de 2A. C’est plus qu’il n’en faut.

Pour la surveillance de la tension batterie, il est nécessaire d’ajouter un pont diviseur destiné à abaisser la tension batterie variable de 12 à 14v à une valeur compatible avec l’entrée analogique de l’Atmega qui est de 5V maxi. Ceci est réalisé par un pont diviseur composé de 2 résistances de 24000 ohms et 10000 ohms.
Ceci donne un rapport de 14 / (24+10) * 10 = 4.12V , tension maximale compatible avec l’entrée de mesure analogique de l’Atmega.

2 Croquis ou sketch Arduino
Il gère les fonctions suivante :
- gestion du module interface HX711 avec la cellule de charge
- mémorisation de la valeur de la tare en mémoire EEPROM avec possibilité de réinitialiser par appuis sur un bouton
- interface avec un capteur de température Dallas DS18B20
- dialogue avec le module émetteur récepteur radio NRF24L01
- enclenchement périodique d’une séquence de mesure de poids
- surveillance du poids de la ruche
- transmission de la valeur de poids périodique ou sur variation rapide de poids.
Scketch Arduino en cours d’évolution à copier coller dans un nouveau projet sur l’IDE Arduino.
Attention, il est nécessaire d’installer les librairies MySensors.h, HX711.h, One Wire.h, DallasTemperature.h et Vcc.h qui ne sont pas installées par défaut dans l’IDE Arduino.
/* Sketch pour la création d'une balance connectée à usage apiculture
Une cellule de charge à jauge de contrainte de gamme de mesure 75kg
est insérée sous la ruche dont on veut surveiller le poids.
Un module HX711 spécialisé pour les ponts de mesure converti le signal
analogique en information digitales.
Une sonde Dallas DS18B20 sert de capteur de température ambiante.
Un module radio 2.4 Ghz NRF24L01 transmet les informations suivant le
protocole MySensors.
Un module Arduino Pro Mini constitue le coeur du système
La valeur de la tare est enregistrée dans la mémoire EEPROM de l'Arduino
Un bouton permet de réinitialiser la tare.
*/
// Enable debug prints : debug trames MySensors
//#define MY_DEBUG
// Enable and select radio type attached
#define MY_RADIO_NRF24
#define MY_NODE_ID 182 // Sets a static id for a node
// Definitions des paramètres application
#define DebugProg
#define SN "Balance api v2" // nom du scketch MySensors
#define SV "26/08/2016" // version du sckletch
#include <SPI.h>
#include <MySensors.h>
#include "HX711.h"
#include <EEPROM.h>
#include <DallasTemperature.h>
#include <OneWire.h>
#include <Vcc.h>
// Definition des connexions E/S
const int analogInPin = A5; // Analog pin the voltage divider is attached to
const int BOUTON = 2; // bouton de reset tare actif niveau bas
const int ONE_WIRE_BUS = 3; // Pin where dallase sensor is connected
const int DOUT2 = 5; // Pin data HX711 num 2
const int CLK2 = 6; // Pin clock HX711 num 2
const int DOUT1 = 7; // Pin data HX711 num 1
const int CLK1 = 8; // Pin clock HX711 num 1
// Identifiants MySensors
const int ID_TEMP = 0;
const int ID_POIDS = 1;
const int ID_BatPcnt = 2;
const int ID_BATT = 3;
const int ID_TARE = 4;
const int GAIN = 128; // gain amplificateur HX711
const float calibration_factor = 461; // coefficient de calibration : 10g / unité
const uint16_t SLEEP_TIME = 60 / 15; // tempo envoi en secondes
// Tension mini en-dessous de laquelle la batterie doit être rechargée :
const float VccMin = 12; // Vcc mini 11V batterie déchargée
const float VccMax = 13.6; // Vcc Maximum 14V batterie complètement chargée
const float R1 = 24000; // Voltage divider R1 (Ohm)
const float R2 = 10000; // Voltage divider R2 (Ohm)
const float VccCorrection = 4.98 / 5.16; // Vcc multimetre / Vcc mesuré par l'Arduino
// Déclaration des variables
boolean receivedConfig = false;
boolean metric = true;
boolean envoiTare = true; // pour envoyer la valeur de la tare au reset
uint8_t battLoop = 10; // pour envoi tension batterie dès le reset
uint16_t seconde = 0; // compteur seconde pendule
int oldBatteryPcnt = 0;
long lastPoids = 0;
long tare;
// Déclaration des objets
OneWire oneWire(ONE_WIRE_BUS); // pour capteur de temperature DS18B20
DallasTemperature sensors(&oneWire); // pour librairie Dallas
Vcc vcc(VccCorrection); // pour mesure tension d'alimentation
HX711 scale1(DOUT1, CLK1, GAIN); // pour module HX711 n°1
//HX711 scale2(DOUT2, CLK2, GAIN); // pour module HX711 n°2
// Déclaration des messages MySensors
MyMessage msgTemp(ID_TEMP, V_TEMP); // type V_TEMP pour temperature
MyMessage msgPoids(ID_POIDS, V_WEIGHT); // type V_WEIGHT au lieu de V_VAR1
MyMessage msgBAT(ID_BATT, V_VOLTAGE); // type V_VOLTAGE au lieu de V_VAR2
MyMessage msgTare(ID_TARE, V_VAR3); // type V_VAR3 pour la tare HX711
//***********************************************************************************
//***** Code d'initialisation à faire avant demarrage de MySensors *****
//***********************************************************************************
void before() {
// This will execute before MySensors starts up
}
//************************************************************************************
//***** Fonction de presentation du noeud *****
//************************************************************************************
void presentation() {
// Send the sketch version information to the gateway and Controller
sendSketchInfo(SN, SV);
// présentation identifiants MySensors et type de données
present(ID_TEMP, V_TEMP);
present(ID_POIDS, V_WEIGHT);
present(ID_BATT, V_VOLTAGE);
present(ID_TARE, V_VAR3);
metric = getConfig().isMetric;
}
//**********************************************************************************
//***** FONCTION SETUP = Code d'initialisation générale du programme *****
//**********************************************************************************
void setup() {
Serial.begin(115200); //standard serial
delay(200);
digitalWrite(BOUTON, HIGH); // active résistance de pullup interne
Serial.println();
Serial.print(SN);
Serial.print(" - ");
Serial.println(SV);
sensors.begin(); // init capteur de température DS18B20
// Fetch the number of attached temperature sensors
int numSensors = sensors.getDeviceCount();
#ifdef DebugProg
Serial.print(numSensors);
Serial.println(F(" DS18B20 trouvé"));
#endif
#ifdef DebugProg
long zero_factor = scale1.read_average(); //Get a baseline reading
Serial.print(F("Zero factor: "));
Serial.println(zero_factor);
#endif
// forçage valeur de la tare
//tare = 664120; // ancienne tare
//EEPROMWritelong(EEPROM_LOCAL_CONFIG_ADDRESS, tare);
scale1.power_up(); // pour alimenter la cellule de charge
scale1.set_scale(calibration_factor); // Adjust to this calibration factor
tare = EEPROMReadlong(EEPROM_LOCAL_CONFIG_ADDRESS); // recupere valeur tare en EEPROM
scale1.set_offset(tare); // initialise la tare
scale1.power_down();
#ifdef DebugProg
Serial.print(F("Init tare depuis EEPROM = "));
Serial.println(tare);
#endif
check_batt();
seconde = 0;
}
//************************************************************************************
//***** FONCTION mesure tension batterie ******
//************************************************************************************
float tension_batt() {
// mesure de Vcc
float Vcc = vcc.Read_Volts();
// read the analog in value:
int sensorValue = analogRead(analogInPin);
// Serial.println(sensorValue); // for debug / calibration
float v_pin = Vcc * sensorValue / 1023.;
float v_bat = v_pin / (R2 / (R1 + R2));
#ifdef DebugProg
Serial.print(F("Tension batterie: Vcc:"));
Serial.print(Vcc); // affiche Vcc
Serial.print(F(" v_pin:"));
Serial.print(v_pin); // affiche tension sortie diviseur tension
Serial.print(F(" Vbatt= "));
Serial.println(v_bat); // affiche tension batterie calculée
#endif
return (v_bat);
}
//************************************************************************************
//***** FONCTION controle tension batterie ******
//************************************************************************************
void check_batt()
{
// mesure de Vcc
//float batteryVolt = vcc.Read_Volts();
float batteryVolt = tension_batt();
/*
#ifdef DebugProg
Serial.print(F("Tension batterie = "));
Serial.println(batteryVolt);
#endif
*/
// calcul du % de charge batterie
float batteryPcnt = 100 * ((batteryVolt - VccMin) / (VccMax - VccMin));
sendBatteryLevel(batteryPcnt); // envoi % batterie
oldBatteryPcnt = batteryPcnt;
send(msgBAT.set(batteryVolt, 2)); // et tension avec 2 décimales
}
//************************************************************************************
//***** FONCTION reception messages NRF24L01 ******
//************************************************************************************
void incomingMessage(const MyMessage &message) {
Serial.print(F("reception Message: "));
Serial.print(message.sensor);
Serial.print(F(" msg-type: "));
Serial.println(message.type);
int value = 0;
if (message.type == V_VAR3) {
tare = atol( message.data);
scale1.set_offset(tare); // parametre la valeur de la tare
saveState(ID_TARE, tare); // memorise la tare en eprom
send(msgTare.set(value) ); // retourne la valeur de la tare à Jeedom
#ifdef DebugProg
Serial.print(F("Reception tare Jeedom ="));
Serial.println(tare);
#endif
}
}
//************************************************************************************
// This function will write a 4 byte (32bit) long to the eeprom at
// the specified address to address + 3.
//************************************************************************************
void EEPROMWritelong(int address, long value)
{
//Decomposition from a long to 4 bytes by using bitshift.
//One = Most significant -> Four = Least significant byte
byte four = (value & 0xFF);
byte three = ((value >> 8) & 0xFF);
byte two = ((value >> 16) & 0xFF);
byte one = ((value >> 24) & 0xFF);
//Write the 4 bytes into the eeprom memory.
EEPROM.write(address, four);
EEPROM.write(address + 1, three);
EEPROM.write(address + 2, two);
EEPROM.write(address + 3, one);
}
//************************************************************************************
// This function will return a 4 byte (32bit) long from the eeprom
// at the specified address to address + 3.
//************************************************************************************
long EEPROMReadlong(long address)
{
//Read the 4 bytes from the eeprom memory.
long four = EEPROM.read(address);
long three = EEPROM.read(address + 1);
long two = EEPROM.read(address + 2);
long one = EEPROM.read(address + 3);
//Return the recomposed long by using bitshift.
return ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
}
//**********************************************************************************
//***** Fonction Msure de poids *****
//**********************************************************************************
long Mesure() {
scale1.power_up();
long mesureP = -scale1.get_units(20);
scale1.power_down();
#ifdef DebugProg
Serial.print("Poids = ");
Serial.println(mesureP);
#endif
return (mesureP);
}
//**********************************************************************************
//*************** FONCTION LOOP = Boucle sans fin = coeur du programme *************
//**********************************************************************************
void loop() {
long Poids = Mesure();
if (abs(lastPoids - Poids) > 10) {
send(msgPoids.set(Poids));
lastPoids = Poids;
}
// Surveillance du bouton de reset tare
// tempo 1 seconde
for (uint8_t i = 0; i < 118; i++) {
if (digitalRead(BOUTON) == LOW) {
scale1.power_up();
scale1.tare(10); //Reset the scale to 0
tare = scale1.get_offset(); // lit la valeur de la tare
scale1.power_down();
EEPROMWritelong(EEPROM_LOCAL_CONFIG_ADDRESS, tare);
#ifdef DebugProg
Serial.print(F("Reset tare = "));
Serial.println(tare);
#endif
envoiTare = true; // pour envoi tare à Jeedom
}
sleep(100); // pour tempo en ms
}
seconde += 3;
/*
#ifdef DebugProg
Serial.print("Tempo ");
Serial.print(seconde);
Serial.print(' ');
#endif
*/
// envoi tare à Jeedom si reset Arduino ou réinitialisation tare
if (envoiTare) {
send( msgTare.set(tare) );
envoiTare = false;
sleep(1000); // tempo 1 seconde
}
if (seconde >= SLEEP_TIME) {
// Fetch temperatures from Dallas sensors
sensors.requestTemperatures();
float temperature =
static_cast<float>
(static_cast<int>
((getConfig().isMetric ?
sensors.getTempCByIndex(0) :
sensors.getTempFByIndex(0)) * 10.)) / 10.;
#ifdef DebugProg
Serial.print(F("Temperature = "));
Serial.println(temperature, 1);
#endif
if ( temperature > -30.0) // elimine valeur erronnées
send(msgTemp.set(temperature, 1));
send(msgPoids.set(Poids));
lastPoids = Poids;
seconde = 0;
// test batterie toutes les 10 minutes
battLoop++;
if (battLoop >= 10) {
check_batt();
battLoop = 0;
envoiTare = true;
}
}
}
Vous pouvez ajouter ou supprimer les // en début de paramètre pour activer ou désactiver les fonctions de debug sur la console.
//#define MY_DEBUG // Enable and select radio type attached //#define DebugProg
Les valeurs de résistance sont à modifier en fonction du pont diviseur que vous avez mesuré.
const float R1 = 24000; // Voltage divider R1 (Ohm) const float R2 = 10000; // Voltage divider R2 (Ohm)
Au sujet de la librairie Vcc, cette fonction sert à apporter les compensations dues aux écarts de tension d’alimentation de l’Atmega. Elle n’est pas indispensable si vous ne recherchez pas une grande précision