J'hésitais à poster dns la rubrique mysensors, parce que je ne suis pas sûr que me problème vienne de là. Autant m'en ouvrir au plus grand nombre.
Ma config :
- un raspberry pi 3b qui héberge mon Domoticz (et seulement lui)
- 3 Arduino Mega (chacun avec le même script, uniquement des variables capteurs légèrement différentes dans leur nombre)
- sur chaque Mega, des relais 5V classiques (genre ça https://www.amazon.fr/Elegoo-Optocouple ... 431&sr=8-9 ; des détecteurs de mouvement HC-SR501 ; des DHT22 déjà montés sur pcb ; des photo-resistances genre ça https://www.amazon.fr/qualit%C3%A9-Lumi ... 217&sr=8-5 càd le composant brut avec resistance ad hoc, et dans un cas, une sonde de temperature DS18B20.
Mon code Arduino (quasi équivalent sur chaque mega) :
Code : Tout sélectionner
// Enable debug prints to serial monitor
#define MY_DEBUG
// Enable gateway ethernet module type
#define MY_GATEWAY_W5100
// Enable MY_IP_ADDRESS here if you want a static ip address (no DHCP)
#define MY_IP_ADDRESS xxx //<<<<<<<<<<<< indiquer ici l'adresse IP de l'Arduino
// The port to keep open on node server mode / or port to contact in client mode
#define MY_PORT xxx //<<<<<<<<<<<< indiquer ici le port de l'Arduino
// The MAC address can be anything you want but should be unique on your network.
// Newer boards have a MAC address printed on the underside of the PCB, which you can (optionally) use.
// Note that most of the Arduino examples use "DEAD BEEF FEED" for the MAC address.
#define MY_MAC_ADDRESS xxxx //<<<<<<<<<<<< indiquer ici l'adresse MAC de l'Arduino
// Enable inclusion mode
#define MY_INCLUSION_MODE_FEATURE
// Enable Inclusion mode button on gateway
//#define MY_INCLUSION_BUTTON_FEATURE
// Set inclusion mode duration (in seconds)
#define MY_INCLUSION_MODE_DURATION 60
// Digital pin used for inclusion mode button
//#define MY_INCLUSION_MODE_BUTTON_PIN 3
// Set blinking period
#define MY_DEFAULT_LED_BLINK_PERIOD 300
#if defined(MY_USE_UDP)
#include <EthernetUdp.h>
#endif
#include <Ethernet.h>
#include <MySensors.h>
//#include <SPI.h>
#include <Bounce2.h>
#include <DHT.h>
#include <DallasTemperature.h> // pour temperature avec DS18B20
#include <OneWire.h>
#include <avr/wdt.h>
#define MY_REPEATER_FEATURE
// !!!!!!! si les pins 0 et/ou 1 sont utilisés, le transfert du programme par USB est impossible !!!!!!
// !!!!!!! dans ce ca, débrancher préalablement le matériel connectés au pin 1 et 0 avant le téléversement !!!!!
// !!!!!!! sur UNO, ne pas utiliser les pins D10 - D11 - D12 - D13 utilisés pour la communication !!!!!
// Déclaration des variables
#define RELAY_PIN 22 // <<<<<<<<<< indiquer le pin du premier relais (second on pin+1 etc)
#define NUMBER_OF_RELAYS 8 // <<<<<<<<<<< Indiquer le nombre de relais ici
#define NUMBER_OF_SWITCHES 6 //<<<<<<<< indiquer le nombre d'interrupteurs ici
byte switchPin[NUMBER_OF_SWITCHES] = {8,9,11,12,13,14}; //<<<<<<<< indiquer les pins interrupteurs ici
#define NB_DP 2 //<<<<<<<< indiquer le nombre de motion sensor ici
byte DP_PIN[NB_DP] = {3,18}; //<<<<<<<< indiquer les pins de motion sensor ici (obligatoirement 2 et/ou 3 sur UNO)
#define NB_CP 3 //<<<<<<<< indiquer ici le nombre de capteurs photo-électriques
byte CP_PIN[NB_CP] = {0,1,2}; //<<<<<<<< indiquer ici les numéros de pin analogiques des capteurs photo-électriques
uint32_t SLEEP_TIME_CP = 30000; //<<<<<<<< indiquer ici le temps de repos entre 2 lectures capteurs photo-électriques
#define ANALOG_PIN 54 //<<<<<<<< indiquer ici 14 si Arduino Uno 54 si Arduino Mega
#define NUM_DHT 1 //<<<<<<<< indiquer le nombre de DHT ici
byte PIN_DHT[NUM_DHT] = {47}; //<<<<<<<< indiquer les pins de connexion DHT ici
byte tempID[NUM_DHT] = {47}; //<<<<<<<< modifier la série selon le nombre de DHT (mêmes valeurs que PIN_DHT)
byte humID[NUM_DHT] = {77}; //<<<<<<<< modifier la série selon le nombre de DHT (dans les 2X pour Uno, 7X pour Mega)
float lastTemp[NUM_DHT] = {0.0}; //<<<<<<<< augmenter la série selon le nombre de DHT
float lastHum[NUM_DHT] = {0.0}; //<<<<<<<< augmenter la série selon le nombre de DHT
// Sleep time between sensor updates (in milliseconds)
// Must be >1000ms for DHT22 and >2000ms for DHT11
static const uint64_t SLEEP_TIME_DHT = 7000; //<<<<< indiquer ici le temps de repos entre 2 lectures de température DHT
// !!!! SLEEP_TIME_DHT ne doit pas excéder SLEEP_TIME_CP sinon aucune mesure ne sera envoyée !!!! (mais pourquoi ???)
// Offset : un décalage de température entre le DHT22 et la réalité sera ajusté dans Domoticz
#define ONE_WIRE_BUS 46 //<<<<<<< indiquer ici le pin digital sur lequel est connecté le DS18B20
unsigned long SLEEP_TIME_TEMP = 30000; //<<<<<<< indiquer ici le temps de repos entre 2 lectures de température DS18B20
// Variables pour relais
#define RELAY_ON 1 // GPIO value to write to turn on attached relay
#define RELAY_OFF 0 // GPIO value to write to turn off attached relay
// Variables pour interrupteurs
Bounce debouncer[NUMBER_OF_SWITCHES];
int oldValue[NUMBER_OF_SWITCHES];
MyMessage msgInter(0,V_LIGHT);
// Change to V_LIGHT if you use S_LIGHT in presentation below, V_TRIPPED si S_DOOR ou S_MOTION
// Variables pour détecteurs de présence
Bounce debouncerDP[NB_DP];
int oldValueDP[NB_DP];
MyMessage msg_DP(0,V_TRIPPED);
// Variables pour cellules photo-électriques
MyMessage msg_CP(NB_CP, V_LEVEL);
int lastLightLevel[NB_CP];
int lightlevel[NB_CP];
// Variables pour DHT22
// Force sending an update of the temperature after n sensor reads, so a controller showing the
// timestamp of the last update doesn't show something like 3 hours in the unlikely case, that
// the value didn't change since;
// i.e. the sensor would force sending an update every UPDATE_INTERVAL*FORCE_UPDATE_N_READS [ms]
static const uint8_t FORCE_UPDATE_N_READS = 10;
uint8_t nNoUpdatesTemp;
uint8_t nNoUpdatesHum;
bool metric_DHT = true;
MyMessage msgHum(NUM_DHT, V_HUM);
MyMessage msgTemp(0, V_TEMP);
DHT* dht[NUM_DHT];
// pour temperature avec DS18B20
#define COMPARE_TEMP (0) // Send temperature only if changed? 1 = Yes 0 = No
#define MAX_ATTACHED_DS18B20 16
OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire); // Pass the oneWire reference to Dallas Temperature.
float lastTemperature[MAX_ATTACHED_DS18B20];
int numSensors=1;
bool receivedConfig = false;
bool metric_DS18B20 = true;
// Initialize temperature message
MyMessage msg_TEMP(0,V_TEMP);
void before()
{
for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
// Then set relay pins in output mode
pinMode(pin, OUTPUT);
int num_relais = RELAY_PIN + sensor - 1;
// Set relay to last known state (using eeprom storage)
digitalWrite(pin, loadState(num_relais)?RELAY_ON:RELAY_OFF);
}
// Température DS18B20
sensors.begin();
// Watchdog
wdt_disable(); // Might be redundant as the bootloader should have done this already
wdt_enable(WDTO_8S);
}
void setup()
{
// Setup locally attached sensors*
Serial.begin(9600);
// Interrupteurs
for (int j = 0; j < NUMBER_OF_SWITCHES; j++)
{
pinMode(switchPin[j],INPUT_PULLUP);
debouncer[j] = Bounce();
debouncer[j].attach(switchPin[j]);
debouncer[j].interval(5);
}
// Détecteurs de mouvement
for (int z = 0; z < NB_DP; z++)
{
pinMode(DP_PIN[z],INPUT_PULLUP);
debouncerDP[z] = Bounce();
debouncerDP[z].attach(DP_PIN[z]);
debouncerDP[z].interval(5);
}
// Température DHT
//Serial.begin(9600);
for (int i = 0; i < NUM_DHT; i++)
{
dht[i] = new DHT;
dht[i]->setup(PIN_DHT[i]);
}
// Température DS18B20
sensors.setWaitForConversion(false);
}
void presentation()
{
// present sensor to gateway
sendSketchInfo("Relay", "1.0");
for (int sensor=1, pin=RELAY_PIN; sensor<=NUMBER_OF_RELAYS; sensor++, pin++) {
// Register all sensors to gw (they will be created as child devices)
int num_relais = RELAY_PIN + sensor - 1;
present(num_relais, S_BINARY);
delay(300);
}
// Détecteurs de mouvement
// You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage.
// If S_LIGHT is used, remember to update variable type you send in. See "msg_DP" above.
for (int z = 0; z < NB_DP; z++)
{
present(DP_PIN[z], S_MOTION);
delay(300);
}
// Interrupteurs
// You can use S_DOOR, S_MOTION or S_LIGHT here depending on your usage.
// If S_LIGHT is used, remember to update variable type you send in. See "msgInter" above.
for (int j = 0; j < NUMBER_OF_SWITCHES; j++)
{
present(switchPin[j], S_LIGHT);
delay(300);
}
// Cellules photoélectriques
sendSketchInfo("Light Sensor", "1.0");
for (int k = 0; k < NB_CP; k++){
present(CP_PIN[k] + ANALOG_PIN, S_LIGHT_LEVEL);
delay(300);
}
// Température DHT
sendSketchInfo("TemperatureAndHumidity", "1.1");
for (int i = 0; i < NUM_DHT; i++)
{
present(humID[i], S_HUM);
present(tempID[i], S_TEMP);
delay(300);
}
metric_DHT = getControllerConfig().isMetric;
// pour temperature avec DS18B20
// Send the sketch version information to the gateway and Controller
sendSketchInfo("Temperature Sensor", "1.1");
// Fetch the number of attached temperature sensors
numSensors = sensors.getDeviceCount();
// Present all sensors to controller
for (int d=0; d<numSensors && d<MAX_ATTACHED_DS18B20; d++) {
present(d + ONE_WIRE_BUS + 100, S_TEMP);
delay(300);
}
}
void loop()
{
// Send locally attached sensors data here
// Détecteurs de mouvement
for (int z = 0; z < NB_DP; z++)
{
debouncerDP[z].update();
int valueDP = debouncerDP[z].read();
if (valueDP != oldValueDP[z])
{
send(msg_DP.setSensor(DP_PIN[z]).set(valueDP == HIGH? true : false), false);
}
oldValueDP[z] = valueDP;
}
// Interrupteurs
for (int j = 0; j < NUMBER_OF_SWITCHES; j++)
{
debouncer[j].update();
int value = debouncer[j].read();
if (value != oldValue[j])
{
send(msgInter.setSensor(switchPin[j]).set(value == HIGH? true : false), false);
}
oldValue[j] = value;
}
// Cellules photoélectriques
update_CP(SLEEP_TIME_CP);
// Température DHT
update_DHT(SLEEP_TIME_DHT);
// Température DS18B20
update_DS18B20(SLEEP_TIME_TEMP);
}
void update_CP(int frequence_CP)
{
static unsigned long lastupdateTime_CP;
if (millis() - lastupdateTime_CP >= frequence_CP)
{
for (int k = 0; k < NB_CP; k++)
{
int lightLevel = (analogRead(CP_PIN[k]));
if (lightLevel != lastLightLevel[k])
{
send(msg_CP.setSensor(CP_PIN[k] + ANALOG_PIN).set(lightLevel));
lastLightLevel[k] = lightLevel;
}
}
lastupdateTime_CP += frequence_CP;
}
}
void update_DHT(int frequence_DHT)
{
static unsigned long lastupdateTime_DHT;
if (millis() - lastupdateTime_DHT >= frequence_DHT)
{
// Send locally attached sensors data here
// Force reading sensor, so it works also after sleep()
for (int i = 0; i < NUM_DHT; i++)
{
wait(dht[i]->getMinimumSamplingPeriod());
// Get temperature from DHT library
float temperature = dht[i]->getTemperature();
if (isnan(temperature)) {
Serial.print(F("Failed reading temperature from DHT"));
Serial.println(i);
wdt_reset();
} else if (temperature != lastTemp[i] || nNoUpdatesTemp == FORCE_UPDATE_N_READS) {
// Only send temperature if it changed since the last measurement or if we didn't send an update for n times
lastTemp[i] = temperature;
if (!metric_DHT) {
temperature = dht[i]->toFahrenheit(temperature);
}
// Reset no updates counter
nNoUpdatesTemp = 0;
send(msgTemp.setSensor(i).set(temperature, 1));
#ifdef MY_DEBUG
//Serial.print(F("T"));
//Serial.print(i);
//Serial.print(F("= "));
//Serial.println(temperature);
#endif
} else {
// Increase no update counter if the temperature stayed the same
nNoUpdatesTemp++;
}
// Get humidity from DHT library
float humidity = dht[i]->getHumidity();
if (isnan(humidity)) {
//Serial.print("Failed reading humidity from DHT");
//Serial.println(i);
} else if (humidity != lastHum[i] || nNoUpdatesHum == FORCE_UPDATE_N_READS) {
// Only send humidity if it changed since the last measurement or if we didn't send an update for n times
lastHum[i] = humidity;
// Reset no updates counter
nNoUpdatesHum = 0;
send(msgHum.setSensor(i).set(humidity, 1));
#ifdef MY_DEBUG
//Serial.print(F("H"));
//Serial.print(i);
//Serial.print(F("= "));
//Serial.println(humidity);
#endif
} else {
// Increase no update counter if the humidity stayed the same
nNoUpdatesHum++;
}
}
lastupdateTime_DHT += frequence_DHT;
}
}
void update_DS18B20(int frequence_DS18B20)
{
// pour temperature avec DS18B20
static unsigned long lastupdateTime_DS18B20;
if (millis() - lastupdateTime_DS18B20 >= frequence_DS18B20)
{
// Fetch temperatures from Dallas sensors
sensors.requestTemperatures();
// query conversion time and sleep until conversion completed
int16_t conversionTime = sensors.millisToWaitForConversion(sensors.getResolution());
// sleep() call can be replaced by wait() call if node need to process incoming messages (or if node is repeater)
wait(conversionTime);
// Read temperatures and send them to controller
for (int d=0; d<numSensors && d<MAX_ATTACHED_DS18B20; d++)
{
// Fetch and round temperature to one decimal
float temperature = static_cast<float>(static_cast<int>((getControllerConfig().isMetric?sensors.getTempCByIndex(d):sensors.getTempFByIndex(d)) * 10.)) / 10.;
// Only send data if temperature has changed and no error
if (COMPARE_TEMP == 1)
{
if (lastTemperature[d] != temperature && temperature != -127.00 && temperature != 85.00)
{
// Send in the new temperature
send(msg_TEMP.setSensor(d + ONE_WIRE_BUS + 100).set(temperature,1));
// Save new temperatures for next compare
lastTemperature[d]=temperature;
Serial.print("Temperature for the device ");
Serial.print(d + ONE_WIRE_BUS);
Serial.print(" is: ");
Serial.println(temperature);
Serial.print("N° capteur : ");
Serial.println(d + ONE_WIRE_BUS + 100);
}
}
if (COMPARE_TEMP == 0)
{
if (temperature != -127.00 && temperature != 85.00)
{
// Send in the new temperature
send(msg_TEMP.setSensor(d + ONE_WIRE_BUS + 100).set(temperature,1));
// Save new temperatures for next compare
lastTemperature[d]=temperature;
Serial.print("Temperature for the device ");
Serial.print(numSensors);
Serial.print(" is: ");
Serial.println(temperature);
Serial.print("N° capteur : ");
Serial.println(d + ONE_WIRE_BUS + 100);
}
}
}
lastupdateTime_DS18B20 += frequence_DS18B20;
}
Serial.print("lastupdatetime : ");
Serial.println(lastupdateTime_DS18B20);
Serial.print("frequence : ");
Serial.println(frequence_DS18B20);
Serial.print("millis : ");
Serial.println(millis());
Serial.print("millis - lastupdate : ");
Serial.println(millis() - lastupdateTime_DS18B20);
}
void receive(const MyMessage &message)
{
// We only expect one type of message from controller. But we better check anyway.
// Relais
if (message.getType()==V_STATUS) {
// Change relay state
digitalWrite(message.getSensor(), message.getBool()?RELAY_ON:RELAY_OFF);
// Store state in eeprom
saveState(message.getSensor(), message.getBool());
}
}Je récupère toutes les valeurs (relais, mouvement, photorésistance, température DHT et température DS18B20) sur mon Domoticz.
Mon problème est le suivant : en gros toutes les 24h (vers 7h du matin) mon Domoticz ne reçoit plus les valeurs des DHT22. Les autres capteurs (mouvement, luminosité, tepérature DS18B20) fonctionnent sans problème.
Mon constat à l'heure actuelle :
- si AUCUNE CHARGE 230V n'est connectée aux relais => aucune perte de données (sur plus de 15 jours)
- dès q'une charge 230V est connectée aux relais => perte des données toutes les 24h (parfois toutes les 12h, mais toujours vers 7h ou 19h)
- si je coupe l'alimentation des Arduino pendant quelques secondes => je retrouve mes données DHT22, mais ça ne dure que 24h ou moins...
- l'activation manuelle du bouton reset sur les arduino ne change rien
- l'intégration dans le script d'un watchdog ne change rien (vous le verrez d'ailleurs inclus dans le code)
- si je connecte mon PC pur voir la sortie série => j'ai un retour "temperature is nan" des DHT22
- la réduction de la temporisation dans le code arduino pour les DHT ne change rien
- j'ai plusieurs scripts dzvents qui tournent sur le raspberry avec des fréquences de l'ordre de la minute => j'ai soupçonné un problème de charge sur le raspberry => j'ai désactivé la plupart des scripts réguliers => aucun changement
- Sur 1 des Mega, j'ai débranché le DHT22 pour le brancher sur un nouvel arduino uno avec seulement le DHT22 => toujours une perte de données, mais plus aléatoire
- je n'ai pas de crontab dans le raspberry qui tourne à cette heure là
-le seul événement que je puisse rapprocher vaguement est que la charge sur les relais sont des volets roulants qui s'ouvrent à peu près dans cette tranche horaire (script dzvents : 20 minutes avant le sunrise domoticz pour l'ouverture, 20 minutes après le sunset pour la fermeture) => mais pas de correspondance horaire exacte...
- et malgré cette vague similitude horaire avec l'action des relais sur les volets, bien souvent, la fermeture le soir ne perturbe pas les DHT22, mais c'est souvent vers 7h que je constate un souci...
J'y perds mon latin...
Vous prenez 2 arduino identiques, avec le même programme (à l'exception de l'ip et l'adresse mac) et les mêmes capteurs => sur l'un vous captez le DHT, sur l'autre vous les perdez toutes les 24h. La seule différence est que sur l'un les relais sont connectés aux volets roulants.
Du coup on soupconne les dits volets (enfin leurs moteurs pur être exact). Vous chargez un nouvel Arduino (même programme, nouvelle IP, nouvelle adresse MAC) branché uniquement avec le DHT22, et là bug...
Et pendant tout ça, le DS18B20 qui est aussi un capteur de température, fonctionne nickel...
Si un forumeur avait des idées de test ou mieux encore une solution.... Parce que là j'en suis à casser des enclumes
Merci d'avance !!!