Elements

Station météo exterieure

Role

Capter les données météo extérieures :

  • Pression atmospherique
  • Température (2x)
  • Humidité
  • Tension du condensateur
  • Status du panneau solaire

Transmettre les données captées à la station intérieure par radio à intervalle régulier.

Points chauds

Consommation électrique, la station doit tourner de façon autonome et être alimenté par panneaux solaires, elle doit rester active les nuits ainsi que lors de périodes de mauvais temps. La neige risque aussi d'être un problème.

Résistance aux intempéries. La station doit à la fois être au plus proche des éléments, pour capter les données les plus précises possible mais malgré tout être à l'abri de la pluie et de la rosée.

Horloge, les données doivent être transmises les plus régulièrement possible. A voir si la fonction delay suffit.

Composants

DevDuino Sensor Node V3.0 (ATmega 328)
Une carte compatible Arduino, spécialement conçue pour mettre sur pied un réseau sans fil reposant sur le tranceiver nRF24L01+. Il a l'avantage d'intégrer de base la gestion du panneau solaire. Il utilise un super condensateur pour stocker l'électricité produite par le panneau solaire. Des connecteurs grove sont intégrés, ce qui permet de s'affranchir d'un shield ou de la moindre soudure. Le module nRF24L01+ est aussi intégré sur la carte
nRF24L01+
Fourni en kit avec le DevDuino Sensor Node V3.0. Ce module semble être parfaitement adapté. Il propose une communication sans fil 2.4GHz, rapide et économique en énergie. Le module est de plus vraiment bon marché, comparé à un module Bluetooth ou wifi.
Grove - Temperature and Humidity Sensor Pro
Un capteur combinant la température et l'humidité. Il est le plus précis disponible au format Grove. Communique par Analogique.
Grove - Barometer Sensor
Un capteur de pression utilisant le Bosch BMP085. Il communique au moyen du bus I2C.

Station météo interieure

Role

Capter les données intérieures:

  • Température
  • Humidité
  • Qualité de l'air

Réceptionner les données transmises par la station extérieure

Communiquer l'intégralité des données au serveur Linux par liaison série

Afficher les valeurs actuelles sur le panneau LED de la station IROX

Points chauds

Interfaçage avec le panneau LED. Il est composé de 32x4 pistes à anode commune (à confirmer) ce qui nécessite l'utilisation de registre à décalage pour multiplier les sorties de l'arduino. Aucune documentation n'existe pour ce panneau.

Gestion des "threads" avec une architecture mono thread. La réception des données de la station extérieure, l'actualisation des données propres, la transmission des données au server et le control du panneau LED sont des taches distinctes à exécuter à un rythme différent ... ou pas.

Liaison bidirectionnelle avec le serveur Linux pour les prévisions, ou interpréter les variations de pression.

Afficher une heure fiable sur le panneau LED. Idéalement synchronisation avec l'antenne couramment utilisée en Europe. Ou grace à un module GPS. Au pire grace à un module RTC. Le réglage de l'heure est aussi à étudier

Composants

Arduino Uno R3
Celui fournit avec le starter kit. Une fois la station en place il faudra que j'en rachète un pour pouvoir continuer à bricoler des trucs.
Base shield v2
Histoire de brancher les différents capteurs grove
Grove - Temperature and Humidity Sensor Pro
Le même capteur que pour l'extérieur.
Grove - Air Quality Sensor
Un capteur de qualité de l'air, il peut pas dire ce qu'il y a dans l'air, ni la quantité, mais réagit néanmoins à tout un tas de gaz. On verra s'il permet de detecter quand aérer.
Tout le dispositif pour le control du lcd
Tout le dispositif pour receptionner l'heure radio diffusée

Server Linux

Role

Réceptionner et stocker les données transmises par les stations météo.

Rendre les données accessible par requêtes REST

Servir des pages web permettant de visualiser les donnes

Points chauds

Stockage des données, si possible en utilisant Munin. Le taux de rafraichissement des données risque de ne pas correspondre.

Design, une belle présentation pour les données fera la différence.

Android app

Role

Réside sur les téléphones, tablettes, télévision et montre.

Communique avec le serveur linux pour récupérer les données

Affiche les données météos de façon hergonomique quelque soit le support

Points chauds

Le design, l'hergonomie, reactivité

Gestion multidevice

Etapes

Découverte des capteurs

Comme premier job, je vais brancher chaque capteur sur le Arduino Uno, équipé du shield Grove. Et voir comment récupérer les données des capteurs. Le wiki de seeedStudio propose une page par capteur, cela ne devrait pas être trop difficile.

Je branche donc le capteur de température et pression sur le connecteur A0 du shield Grove, le capteur de qualité de l'air sur le connecteur A1 et le capteur de pression sur un connecteur I2C. Le capteur de température et celui de qualité d'air n'utilise qu'un seul entrée analogique, ce qui permet de les connecter sur 2 connecteurs adjacent. J'aurai donc la température sur A0 et la qualité de l'air sur A1. Et la pression en I2C, il faut que je découvre comment fonctionne ce protocole.

Vu shematique du branchement, les capteurs sont branchés sur le shield, mais finissent relié de la sorte.
Le montage lors du test.

Température et humidité

En utilisant la librarie et le script d'exemple fournient par SeeedStudio, le capteur fonctionne imédiatement :

// Example testing sketch for various DHT humidity/temperature sensors
// Written by ladyada, public domain

#include "DHT.h"

#define DHTPIN A0     // what pin we're connected to

// Uncomment whatever type you're using!
//#define DHTTYPE DHT11   // DHT 11 
#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);

void setup() 
{
		Serial.begin(9600); 
		Serial.println("DHTxx test!");

		dht.begin();
}

void loop() 
{
		// Reading temperature or humidity takes about 250 milliseconds!
		// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
		float h = dht.readHumidity();
		float t = dht.readTemperature();

		// check if returns are valid, if they are NaN (not a number) then something went wrong!
		if (isnan(t) || isnan(h)) 
		{
				Serial.println("Failed to read from DHT");
		} 
		else 
		{
				Serial.print("Humidity: "); 
				Serial.print(h);
				Serial.print(" %\t");
				Serial.print("Temperature: "); 
				Serial.print(t);
				Serial.println(" *C");
		}
}
				
Humidity: 41.50 %	Temperature: 23.80 *C
Humidity: 41.50 %	Temperature: 23.80 *C
Humidity: 41.50 %	Temperature: 23.80 *C
Humidity: 41.50 %	Temperature: 23.80 *C
Humidity: 41.50 %	Temperature: 23.80 *C
Humidity: 41.50 %	Temperature: 23.80 *C
				

Tout semble fonctionner, on pourra utiliser le code tel quel. Lire les données du capteur prend par contre un peu plus de 250ms et les données sont mises à jour toute les 2 secondes. Prévoyant de logger chaque 30 sencondes voir 5 minutes pour se conformé à Munin, le délai ne semble pas génant.

Une autre librarie existe, à tester, semble peut-être plus sérieuse.

Qualité de l'air

2ème capteur en analogique, de nouveau, une librarie et un exemple sont fournit. Il faut juste adapter le pin

/*
	AirQuality Demo V1.0.
	connect to A1 to start testing. it will needs about 20s to start 
* By: http://www.seeedstudio.com
*/
#include"AirQuality.h"
#include"Arduino.h"
AirQuality airqualitysensor;
int current_quality =-1;
void setup()
{
		Serial.begin(9600);
		airqualitysensor.init(14);
}
void loop()
{
	current_quality=airqualitysensor.slope();
		if (current_quality >= 0)// if a valid data returned.
		{
				if (current_quality==0)
						Serial.println("High pollution! Force signal active");
				else if (current_quality==1)
						Serial.println("High pollution!");
				else if (current_quality==2)
						Serial.println("Low pollution!");
				else if (current_quality ==3)
						Serial.println("Fresh air");
		}
}
ISR(TIMER2_OVF_vect)
{
	if(airqualitysensor.counter==122)//set 2 seconds as a detected duty
	{

			airqualitysensor.last_vol=airqualitysensor.first_vol;
			airqualitysensor.first_vol=analogRead(A0);
			airqualitysensor.counter=0;
			airqualitysensor.timer_index=1;
			PORTB=PORTB^0x20;
	}
	else
	{
		airqualitysensor.counter++;
	}
}
				
sys_starting...
The init voltage is ...
49
Sensor ready.
Test begin...
High pollution! Force signal active.
High pollution! Force signal active
High pollution! Force signal active.
High pollution! Force signal active
High pollution! Force signal active.
High pollution! Force signal active
High pollution! Force signal active.
High pollution! Force signal active
High pollution! Force signal active.
				

Marche pas bien apparemment, le démarrage et très lent, 20 secondes d'après les commentaires et la librairie ne retourne qu'un indice de qualité, entre 0 et 3. J'espère optenir des valeurs un peu plus détaillé. Temps de jeter un oeil à la librairie fournie.

Première conclusion, le délai de 20 secondes ne sert pas à grand chose. En fait la function init() attends jusque à ce que la valeur lue sur le port analogique se trouve entre 10 et 798 tent que ce n'est pas le cas, elle attend 60 sencondes et lit l'entrée à nouveau. Ensuite elle configure sauvagement les registres pour obtenir un timer interrupt. L'interrupt est quant à lui géré dans le script, en gros, toutes les 2 secondes il modifie une variable de la librairie qui pourra être lu dans loop().

La function loop() appelle la function slope() de la librairie, qui fait des trucs, mais ça merde.

Pas terrible au final. La seule chose importante dans tout ça, c'est que la valeur sera farfelu au début, le capteur devant chauffer et qu'en suite plus la valeur est base, meilleur est la qualité. Je vais donc juste loguer cette valeur est voir ce qu'elle peut bien indiquer.

Deuxième script de test donc, sans utiliser la librairie

#define AIR_PIN A1

void setup() {
	Serial.begin(9600);
	Serial.println("Starting...");
	// utilisation du pin en entrée
	pinMode(AIR_PIN, INPUT);
}

void loop() {
	// on lit la valeur et l'écrit sur la liaison série
	int value = analogRead(AIR_PIN);
	Serial.print("polution indice: ");
	Serial.println(value);
	
	// on attend quelques instant
	delay(500);
}
				
Starting...
polution indice: 51
polution indice: 56
polution indice: 47
polution indice: 51
polution indice: 51
				

En envoyant du gaz d'un briquet sur le capteur, on voit directement la variation:

polution indice: 46
polution indice: 45
polution indice: 43
polution indice: 171
polution indice: 585
polution indice: 646
polution indice: 658
polution indice: 632
polution indice: 546
polution indice: 468
polution indice: 437
polution indice: 390
polution indice: 348
polution indice: 310
polution indice: 275
polution indice: 239
polution indice: 190
polution indice: 168
polution indice: 145
polution indice: 137
polution indice: 118
polution indice: 92
polution indice: 91
polution indice: 81
polution indice: 68
polution indice: 70
polution indice: 72
polution indice: 67
polution indice: 70
				
Variation de la valeur du capteur de qualité d'air, lors de l'exposition à du gaz de briquet

Resultats convaincant, pas besoin de plus.

Capteur barométrique

Ce capteur repose sur le protocole I2C. De nouveau, une librairie et un exemple sont fournit. Let's go

/* Barometer demo V1.0
* Based largely on code by  Jim Lindblom
* Get pressure, altitude, and temperature from the BMP085.
* Serial.print it out at 9600 baud to serial monitor.
*
* By:http://www.seeedstudio.com
*/
#include "Barometer.h"
#include <Wire.h>
float temperature;
float pressure;
float atm;
float altitude;
Barometer myBarometer;
void setup(){
	Serial.begin(9600);
	myBarometer.init();
	
}

void loop()
{
	 temperature = myBarometer.bmp085GetTemperature(myBarometer.bmp085ReadUT()); //Get the temperature, bmp085ReadUT MUST be called first
	 pressure = myBarometer.bmp085GetPressure(myBarometer.bmp085ReadUP());//Get the temperature
	 altitude = myBarometer.calcAltitude(pressure); //Uncompensated caculation - in Meters 
	 atm = pressure / 101325; 
	
	Serial.print("Temperature: ");
	Serial.print(temperature, 2); //display 2 decimal places
	Serial.println("deg C");

	Serial.print("Pressure: ");
	Serial.print(pressure, 0); //whole number only.
	Serial.println(" Pa");

	Serial.print("Ralated Atmosphere: ");
	Serial.println(atm, 4); //display 4 decimal places

	Serial.print("Altitude: ");
	Serial.print(altitude, 2); //display 2 decimal places
	Serial.println(" m");

	Serial.println();

	delay(1000); //wait a second and get values again.
}
				
Temperaturet: Temperaturet2: Temperature: 23.60deg C
Pressure: 97175 Pa
Ralated Atmosphere: 0.9590
Altitude: 351.33 m

Temperature: 23.70deg C
Pressure: 97178 Pa
Ralated Atmosphere: 0.9591
Altitude: 351.07 m

Temperature: 23.70deg C
Pressure: 97178 Pa
Ralated Atmosphere: 0.9591
Altitude: 351.07 m
				

Voilà un résultat très prométeur, j'ai même la température en bonus, à comparer à celle fournie par le capteur de température. Très peu de délai pour lire les valeurs.

Les 3 capteurs ensemble

On utilisera donc la librarie pour le capteur de température et humidité ainsi que celui de pression et on lira directement la valeur analogique du capteur de qualité de l'air.

#include <Wire.h>

#include <DHT.h>
#include <Barometer.h>

#define DHT_PIN A0
#define AIR_PIN A1
#define DHT_TYPE DHT22 // (AM2302)

#define SAMPLING_INTERVAL 60000

DHT dht(DHT_PIN, DHT_TYPE);
Barometer barometer;

void setup() {
	Serial.begin(9600);
	Serial.println("Starting...");
	
	// Température et humidité
	dht.begin();  
	
	// Qualité de l'air
	pinMode(AIR_PIN, INPUT);
	
	// baromètre
	barometer.init();
}

void loop() {
	long startTime = millis();
	
	// on récupère toutes les valeurs
	float humidity = dht.readHumidity();
	float temperature1 = dht.readTemperature();
	int   airPollution = analogRead(AIR_PIN);
	float pressure = barometer.bmp085GetPressure(barometer.bmp085ReadUP());
	float temperature2 = barometer.bmp085GetTemperature(barometer.bmp085ReadUT());

	// on écrit le tout
	Serial.print("timestamp: ");
	Serial.print(startTime);
	Serial.print("   humidity: ");
	Serial.print(humidity);
	Serial.print("   temperature 1: ");
	Serial.print(temperature1);
	Serial.print("   temperature 2: ");
	Serial.print(temperature2);
	Serial.print("   air pollution: ");
	Serial.print(airPollution);
	Serial.print("   pressure: ");
	Serial.print(pressure);
	Serial.println();
	
	// on attend x secondes pour la suite
	delay(SAMPLING_INTERVAL - (millis() - startTime));
}
				
				Starting...
				timestamp: 6   humidity: 50.20   temperature 1: 23.60   temperature 2: 23.40   air pollution: 30   pressure: 89730.00
				timestamp: 60005   humidity: 50.80   temperature 1: 23.60   temperature 2: 23.40   air pollution: 35   pressure: 96006.00
				timestamp: 120005   humidity: 50.80   temperature 1: 23.70   temperature 2: 23.40   air pollution: 29   pressure: 96012.00
				timestamp: 180005   humidity: 50.80   temperature 1: 23.70   temperature 2: 23.40   air pollution: 40   pressure: 96012.00
				timestamp: 240006   humidity: 51.00   temperature 1: 23.70   temperature 2: 23.40   air pollution: 41   pressure: 96015.00
				timestamp: 300006   humidity: 51.10   temperature 1: 23.70   temperature 2: 23.50   air pollution: 38   pressure: 96015.00
				

Pour garder une fréquence de mesure à peu prêt constante, je calcule le temps pris pour le relevé des capteurs. J'attends en suite la durée souhaitée - temps de relevé. Le but étant de limiter la dérive des mesures. Il faut de toute façon s'attendre à un timing de mesure peu précis. Et notamment pour la station extérieure dont j'ignore quel source de timer elle utiliser. Au final le temps du server fera fois. Un décalage des quelques millisecondes voir secondes ne sera pas génant. La station intérieure, étant déstiné à afficher l'heure, je pense lui ajoindre une antenne pour capter le signal DCF77.

Programation de la carte DevDuino

La carte DevDuino Sensor Node ne possède pas de port usb contrairement à l'Arduino Uno, on ne peut donc pas le brancher directement sur le pc. Il existe des programmeur, qui se branche sur le port ISP de la carte ou on peut utiliser un Arduino comme programmateur. C'est cette 2ème solution que j'ai choisi pour l'instant, n'ayant pas de programmeur. De la documentation existe directement sur le site d'Arduino. Il ne reste plus qu'a trouver où se trouvent les ports nécessaire.

Il faut donc que je me branche sur les port 11, 12 et 13, le port reset ainsi que GND et VCC. Selon la documentation du DevDuino, je retrouverai les port 11, 12, 13, VCC et GND au niveau du connecteur du transiver nRF24L01+ et le port reset sur le connecteur ISP.

Dans le code source du script servant à transformer un Arduino en programmer, on peut aussi lire que les pins 7, 8 et 9 sont utilisé pour des led indiquant l'état du programmer. J'obtiens donc ce shema de branchement:

Branchement pour la programmation du DevDuino SensorNode v3.0.
L'installation en pleine programmation.

La première étape est donc de programmer l'arduino Uno pour qu'il se comporte comme un programmer. Le sketch a utilisé se trouve dans les menu exemples, il s'appelle ArduinoISP. Aucun problème de ce coté, la led verte se met à pulser, signe du bon fonctionnement de l'Arduino.

Pour uploader un sketch vers le DevDuino, il faut choisir le bon programmer, dans Outils -> Programmateurs et choisir Arduino as ISP. Il faut aussi choisir un type de carte. Mais laquelle, j'en ai aucune idée. Il y a bien une carte à ajouter un fichier boards.txt pour faire tourner le DevDuino à 1Mhz, mais rien n'indique comment le faire tourner normalement. La config ne fonctionne pas. Il manque une ligne s328o1.upload.tool et il y a des doublons. Voilà une config fonctionnelle:

s328o1.name=Sensor328p (int 1MHz, 2.66V)

s328o1.upload.tool=avrdude
s328o1.upload.protocol=arduino
s328o1.upload.maximum_size=30720
s328o1.upload.speed=19200

s328o1.bootloader.tool=avrdude
s328o1.bootloader.low_fuses=0x62
s328o1.bootloader.high_fuses=0xda
s328o1.bootloader.extended_fuses=0x06
s328o1.bootloader.path=atmega

s328o1.bootloader.file=ATmegaBOOT_168_atmega328_pro_8MHz.hex

#s328o8.bootloader.file=ATmegaBOOT_168_atmega328.hex

s328o1.bootloader.unlock_bits=0x3F
s328o1.bootloader.lock_bits=0x0F

s328o1.build.mcu=atmega328p
s328o1.build.f_cpu=1000000L
s328o1.build.core=arduino
s328o1.build.variant=standard
				

Partant avec ça, j'upload le sketch d'exemple Blink, en modifiant juste le port de la led, celui du DevDuino étant le port 9. La led jaune clignote quelques fois et ...

La led verte du DevDuino se met à clignoter, mais bien trop vite. 8x trop vite à vu d'oeil :). Ce qui semble explicable. La configuration dans boards.txt indique que le processeur tourne à 1MHz, alors que le bootloader semble avoir été écrit avec les fuses pour 8MHz. Lors de la compilation, les délais semblent donc faussé. En modifiant la ligne s328o1.build.f_cpu pour qu'elle indique 8'000'000, la led clignote au bon rythme.

Principal problème maintenant, je n'ai pas d'autre moyen de récupérer les données du devDuino pour l'instant. Il va faloir s'attaquer à l'antenne et transmettre les données par onde. Le débugguage s'annonce palpitant.

Un autre tutoriel
Pour configurer et comprendre le fichier boards.txt Calcul des fuse de ATmega328p

Les modules nRF24L01+

Le branchement sur le DevDuino est immédiat, un connecteur est prévu pour. Pour l'Arduino Uno, voilà le schema que j'ai utilisé, bien faire attention à utiliser le 3.3v pour alimenté le module radio, la communication peut être en 5v quant à elle. J'ai aussi ajouter un condensateur de 1nF, ayant lu ici que cela pouvait aider. J'ai aussi laissé les leds branchées comme ça j'ai moins de branchement à changer quand je dois reprogramer le DevDuino. La led rouge est allumée quand le nRF24L01+ est en mode reception, la verte est libre, je vais l'utiliser comme indicateur dans mes sketchs.

Branchement du module radio sur l'Arduino Uno.

Pour tester ces modules, je vais utilisé la library RF24, celle mentionnée par la doc du DevDuino et apparemment bien complète. Il en existe d'autre, disponible sur le site d'Arduino.cc. La library vient avec un certain nombre d'exemple. J'ai donc commencé avec le GettingStarted. Il faut juste modifier les pins utilisés : RF24 radio(8,7); ligne 16 et pensé à choisir un radioNumber différent pour chaque radio. On peut aussi modifier le role pour que la carte boot directement avec le bon role. Pour ce premier test, le DevDuino sera la radio 0 avec le role 0 et l'Arduino Uno la radio avec le role 1. J'upload les 2 scripts et ... ça marche:

RF24/examples/GettingStarted
*** PRESS 'T' to begin transmitting to the other node
Now sending
failed
Failed, response timed out.
Now sending
failed
Failed, response timed out.
Now sending
failed
Failed, response timed out.
Now sending
failed
Failed, response timed out.
Now sending
Sent 29792168, Got response 29393804, Round-trip delay 398364 microseconds
Now sending
Failed, response timed out.
Now sending
Sent 33207132, Got response 31004036, Round-trip delay 2203096 microseconds
Now sending
Sent 34621300, Got response 33005868, Round-trip delay 1615432 microseconds
Now sending
Sent 36035476, Got response 34420040, Round-trip delay 1615436 microseconds
Now sending
Sent 37451592, Got response 35834212, Round-trip delay 1617380 microseconds
Now sending
Sent 38865756, Got response 37248380, Round-trip delay 1617376 microseconds
Now sending
Sent 40279916, Got response 38664492, Round-trip delay 1615424 microseconds
Now sending
Sent 41696040, Got response 40078656, Round-trip delay 1617384 microseconds
				

Mais pas longtemps, j'ai fait grillé les modules radio. Principalement par ce que j'ai eu la bonne idée de les alimenter en 5V alors qu'ils veulent du 3.3V. Pour voir qu'ils ont grillé, il y a 2 choses à faire. radio.isPVariant() ne retourne pas 1. La fonction devrait retourner 1 pour indiquer que c'est un module radio nRF24L01+. radio.getPALevel() ne retourne pas le niveau fixé juste en dessus.

Certains modules répondaient encore correctement à ces 2 fonctions. Par contre en utilisant le sketch Scanner, fourni avec la librairie, plus aucun résultat n'est visible. Tout les canneaux ont l'air vide.

Je vais en recommander 1 ou 2 en suisse, à prix d'or mais j'espère livraison rapide. Et un lot en chine sur AliExpress.com, on trouve ces modules à moins de 1$, free shipping, par contre il faut prévoir 1 mois pour être livré.

2ème round

2ème livraison de module radio. Avec du 3.3v, ça marche tout de suite mieux. J'avais préparé 2 scripts comme test, le DevDuino agit comme émetteur uniquement. Il lit la tension de Vcc en utilisant le sketch de la page wiki de la carte. Il incrémente un compteur et envoie ces 2 valeurs par liaison sans fil à l'Arduino Uno. Ce dernier recopie les valeurs reçues sur le port serie pour être lu sur le pc. Voilà le genre de donnée reçu sur le pc :

Time: 87468 Seq#: 70 Tension: 3349
Time: 92869 Seq#: 71 Tension: 3349
Time: 98269 Seq#: 72 Tension: 3160
Time: 103681 Seq#: 73 Tension: 3016
Time: 109100 Seq#: 74 Tension: 2961
Time: 114520 Seq#: 75 Tension: 2915
Time: 119941 Seq#: 76 Tension: 2878
Time: 125366 Seq#: 77 Tension: 2848
Time: 130792 Seq#: 78 Tension: 2827
Time: 136218 Seq#: 79 Tension: 2806
Time: 141645 Seq#: 80 Tension: 2785
Time: 147075 Seq#: 81 Tension: 2764
Time: 152504 Seq#: 82 Tension: 2744
Time: 157934 Seq#: 83 Tension: 2718
				

En reportant ces valeurs dans un tableur, voilà le graph obtenu, on retrouve bien la courbe caractéristique d'une décharge de condensateur. On remarque aussi en fin de graph que le numéro de séquence retombe à 0, le microcontroller n'ayant plus assez de tension pour fonctionner sans risque, il se met en reset. L'éclairage ambiant fournissant assez d'énergie pour redémarrer le microcontroller et envoyer un échantillon de donnée.

La courbe de décharge de DevDuino, sans stratégie d'économie d'énergie ... et sans capteur. de 3.3v à 1.88v en 8 minutes 30 secondes. La cible étant au moins 12 heures pour se décharger.

Et ça grille encore. Enfin je ne sais pas trop ce qu'il c'est passé. J'ai branché le DevDuino sur l'Arduino Uno, comme je l'ai fait des dizaines de fois mais quelque chose c'est mal passé. J'ai eu une erreur lors de la programmation, la vérification n'a pas passé et depuis impossible de programmer le microcontroller. AVRDude me dit que la signature du microcontroller n'est pas bonne et refuse d'aller plus loin. Même en forçant j'obtiens rien. Comme piste, j'ai lu qu'il y avait des problèmes de reset qui pouvait survenir, de manque de courant ou de clock externe qui n'existe pas sur cette carte. 20 balles de plus en direction du cimetière electronique.

3ème round

J'ai donc un 2ème DevDuino entre mes mains. Je vais tacher de ne pas le griller, de ne pas griller les radios non plus. En plus du DevDuino, j'ai acheter un programmer, histoire de faciliter les branchements. Finalement tout fonctionne à merveille. La transmission se passe bien, bien que la portée soit encore trop courte.

2585;2;3.29;24.22;0.00;0.00;96927;24.20
11004;3;3.29;24.22;0.00;0.00;96947;24.20
19425;4;3.30;24.44;0.00;0.00;96947;24.10
27844;5;3.30;24.44;0.00;0.00;96944;24.10
36264;6;3.30;24.65;0.00;0.00;96950;24.10
44686;7;3.30;24.65;0.00;0.00;96944;24.10
53107;8;3.30;24.32;0.00;0.00;96947;24.10
61529;9;3.31;24.55;0.00;0.00;96945;24.10
69950;10;3.31;24.55;0.00;0.00;96947;24.10
78371;11;3.31;24.55;0.00;0.00;96933;24.10
86794;12;3.31;24.55;0.00;0.00;96938;24.10
95216;13;3.31;24.55;0.00;0.00;96936;24.20
103639;14;3.32;24.45;0.00;0.00;96935;24.20
112061;15;3.32;24.45;0.00;0.00;96935;24.20
120483;16;3.32;24.45;0.00;0.00;96941;24.20
128907;17;3.32;24.45;0.00;0.00;96929;24.30
137329;18;3.32;24.45;0.00;0.00;96920;24.30
				
Une journée de mesure. Les 3 courbes de températures, en bleu la température provenant du capteur intégré à la carte, en rouge, la température provenant du DHT22 et en jaune celle du capteur de pression, un Bosch BMP085
La même journée, mais la courbe représente l'humdité dans l'air.
Finallement la pression.

J'ai ensuite laissé tourner le tout pendant une journée, pour le fun et voir comment les capteurs réagissent. En début de journée, le DevDuino était juste sur ma terrasse, en plein soleil, ce qui explique la forte montée en température. En fin de journée, j'ai repris la carte à l'intérieur, ce qui explique la brusque montée de température.

Pour la température, je remarque que le capteur Bosch BMP085 à l'air très réactif et l'écart entre 2 valeurs est faible. Ca sera surement ce capteur que j'utiliserai principalement pour afficher la température extérieure. Le capteur intégré, un MCP9700, est moyen, l'écart entre 2 valeurs étant assez élevé. Le capteur provenant du DHT22 est pas terrible, il réagit moins rapidement que les 2 autres, mais surtout un grand nombre de valeurs sont abérantes. L'écart de mesure entre les 3 capteurs est relativement faible, -0.5°C au maximum, ce qui me laisse pensé que les valeurs sont juste.

Pour l'humidité, le même problème que pour le capteur de température existe. Le nombre de valeurs abérentes est très élevé. Il me faudra déterminé si ces valeurs sont effectivement celle que le capteur croit mesurer ou si le problème survient lors du transfer des mesures entre le capteur et la carte. Le protocole de communication n'étant pas standard et d'après ce que j'ai lu, pas facile a mettre en place. Un autre problème existe avec ce capteur, il consomme pas mal de courant et ne fonctionne plus lorsque la tension baisse. A partir de 3.04V, les valeurs ne sont plus exact, l'humidité prenant l'ascenseur et l ne fonctionne plus à 2.65V. En plus, je le soupsonne de consommer plus de courant lorsque il n'a pas assez de tension. On le voit assez clairement avec la courbe de tension. C'est très problématique

Pour la pression rien à dire je pense. Pendant la journée, bien ensoleillé, il y avait des coups de vent local, expliquant la variation cyclique de la pression. Quand les conditions se sont calmées, les variations de pression ont aussi diminuée. Je pourrai confirmer avec le temps que ces mesures sont cohérentes.

Branchement du module radio
La page du fabriquant du module
Les branchements des pin de l'arduino

Recherche de la moindre consomation

Autre job, il faut que je diminue la consommation du devDuino. Actuellement, il peine à recharger le condensateur. Il tient au grand maximum quelques minutes en autonomie.

2 pistes sont à explorer. La première c'est de plonger le microcontroller en veille la majeur partie du temps. J'ai pas besoin qu'il soit toujours actif. Un échantillon de mesure toutes les 30 secondes ou 1 minutes serait amplement suffisant pour avoir un historique détaillé de la météo. Il existe cette library qui s'annonce très prometteuse. Elle permet de desactiver certaine partie du microcontroller, comme les convertisseur analogique -> digital et de le faire dormire pour une durée déterminée.

La seconde piste, c'est de faire tourner le DevDuino à moindre fréquence, avec une tension de fonctionnement la plus base possible. De la documentation existe à ce sujet sur la page wiki du DevDuino, je peux apparamment reduire la frequence de 8MHz à 1 MHz, pour autant que les libraries des différents capteurs le supporte. low power arduino library

"Protocole" de test

Je ne sais pas vraiment comment mesurer le courant instantané consommé par la carte et les capteurs, d'autant plus que la consommation doit enormément varier entre les periodes de veille et celle de mesure et de transmission. Je vais donc mesurer le temps de décharge du condensateur et donc la baisse de tension de service, que je peux mesurer sur le pin A2. Je vais prendre le temps nécessaire pour passer de 3.3V à 2.3V. Je peux recharger rapidement le condensateur avec une pile 9V à la place du capteur solaire. Je vais donc pouvoir reproduire l'expérience quelques fois.

Mesure de référence

Pour cette première série de mesure, le capteur de pression et celui d'humidité sont connectés, ainsi que le module radio. Je réveille la radio, je relève toute les valeurs, pour ensuite les transmettre à puissance maximum. J'éteinds ensuite la radio et plonge le microcontroller en veille profonde pendant 8 secondes. Je recommence une série de mesure et ainsi de suite. J'en ai profité pour afficher sur le graphique le relevé d'humidité, curieux de voir comment il se corrèle avec la baisse de tension.

Les courbes des 3 séries de mesure. Avec l'humidité en axe secondaire.
  1. On remarque nettement l'augmentation de la consommation lorsque le DHT22 arrête de fonctionner et la dérive lorsque la tension passe la barre des 3V. Une optimisation évidente sera donc de ne plus l'utiliser quand la tension est trop faible. Je pourrai aussi essayer de corriger les valeurs quand elles commence à prendre l'ascenseur, à condition que ce soit linéaire, quelque soit la température et l'humidité. D'autant plus que la librairie du capteur d'humidité met beaucoup de temps à s'executer, principalement dû à un delay de 250 ms avant une mesure. Mais c'est la seule librairie que j'ai trouvé qui fonctionne. J'ai rien lu dans la datasheet concernant ce delai. Le DevDuino tournant à pleine puissance durant cette attente, je peux notablement réduire la consomation en diminuant ce delai.

  2. Il faut aussi que je teste un reveil plus tardif du module radio. Je le fait actuellement au début de la boucle, il passe donc 250 ms au moins sans utilitée. En reveillant la radio après la mesure, je gagnerai quelques mW.

  3. Je vais aussi prendre une mesure sans la mise en veille de 8 seconde, mais avec un delay à la place. J'aurai comme ça véritablement le pire cas. La chute devrait être brutale.

  4. Je peux aussi essayer de désactiver certaines parties du microcontroller que je n'utilise pas pendant la periode de mesure.

  5. A tester aussi, en mettant le microcontroller en veille pendant 30 secondes, comment réagit le temps de fonctionnement.

Les premiers résultats de l'optimisation.

Au vu des résultats, j'ai définitivement abandonné le capteur d'humidité. Il n'est pas fait pour fonctionner en base tension et consomme bien trop. Le simple fait de ne plus l'appeler ne fonctionne pas, il consomme malgré tout beaucoup, notamment à <2.7V. Je peux essayer de le remplacer par le TPH Board utilisant les connecteurs Grove, ou passer sur un capteur sur breakboard.

Sans les délais de la librairie du DHT22, réveiller la radio tardivement n'est plus aussi pertinent. Il y a du reste un delai de 5ms dans la function powerUp de la librairie RF24, je devrais pouvoir combiner tous les delais, celui de readVcc, celui de la radio, etc ...

Sans surprise, le pire cas, sans powerDown est catastrophique, 6 minutes d'autonomie.

En faisant des veilles de 30 secondes au lieu de 8. Le temps est prolongé de 2.5 fois.

Comme deuxième phase d'optimisation, j'ai un peu réduit la plage de mesure à 3.1V. Le début n'étant pas très precis à 3.3V, ainsi que 2.4V au lieu de 2.2V. Je suis aussi passé à des temps de veille de 2 secondes, juste pour rendre les runs un plus rapide, 1h30 par test commençait à faire long. J'ai premièrement tester les les différentes vitesse de transmission de la radio. La porté devrait être maximum à 250kbps, par contre le temps de transmission augmente, et donc la consommation.

better Vcc reading

Interfaçage de l'affichage LED

Plusieures sous-étapes à réaliser. Il faut que je reverse-engineer l'affichage, 36 pins pour une centaine de segments. Il faut aussi que je découvre comment fonctionne les shift registry (registre à décalage en français sauf erreur). Il va aussi falloir que je bricole un système pour brancher l'affichage à l'Arduino, enfin aux sorties des registres. Et ne pas oublier d'écrire une librairie pour controller le tout.

Reverse engineering

Première étape, tout démonter pour voir ce qu'il y a à l'interieur. Quelques vis, des clips et de la colle ferme le tout

Découverte des registres

Le cablage

Horloge radio commandée