Annexes | ||
---|---|---|
Précédent | Utiliser une carte Arduino dans une station météo |
#include < SPI.h>//ouvre le port qui gère la carte SD
/* SD card attached to SPI bus as follows:
** MOSI - pin 11
** MISO - pin 12
** CLK - pin 13
** CS - pin 4*/
#include < SD.h>//carte SD
#include "HTU21D.h"//bibliothèques des capteurs sparkfun humidité
#include SFE_BMP180.h// bibliothèques des capteurs sparkfun pression
#include Wire.h//Pour le port I2C
File Myfile;
char fichier_[12];
SFE_BMP180 pressure;//Capteur de pression et de température
HTU21D myHumidity;// capteur d'hygrométrie
long minute_debut;
char commande_mesure;
char message;
int mois_;
int jour_;
int an_;
int heure_=0;
int minute_=0;
int seconde_ = 0;
int anemometre = 2; //Anemometre connecte sur le port 2
long date_ini_veille;
boolean debut=true;//A la mise sous tension de l'Arduino, debut = true afin que la boucle loop effectue l'initialisation des données enregistrée et que le Xbeene soit pas mis en mode veille
long date_ini,date_depart,date_depart_;
//long date_courante;
boolean Xbee_reveille=true;
//String reponse="";
char status;
long temps;
void setup()
{
pinMode(anemometre, INPUT);
Serial.begin(9600); //Port Xbee
pressure.begin();
delay(10);
myHumidity.begin();
delay(100);
//Réglage en mode veille du Xbee;
// La borne 9 de l'Arduino est reliée à la borne9 du Xbee
date_depart=millis();
debut=true;
pinMode(9, OUTPUT);//borne de sortie pour commander la mise ne veille du Xbee nécéssite le réglage de avec XCTU
digitalWrite(9, LOW);//mode réveillé du XBee
pinMode(10, OUTPUT);
digitalWrite(10, HIGH);//obligatoire pour que la carte sd soit reconnue
//SD.begin(4);//Sur leonardo ou mega voir https://learn.adafruit.com/adafruit-data-logger-shield/for-the-mega-and-leonardo
if (SD.begin(4)){//vérification de la présence de la carte SD
Serial.println("La carte SD est reconnue");
delay(1000);
return;
}
else{
Serial.println("La carte SD n'est pas reconnue");
}
}
void loop(){
//double T,P,p0;
if (debut==true){
initialisation_jour_heure();
changt_fichier();
delay(1000);
if (!SD.exists(fichier_)){
Myfile = SD.open(fichier_, FILE_WRITE);
Myfile.println("date ; heure; température; pression; hygrométrie;vent :");
Myfile.close();
}
else{
}
delay(1000);
date_ini=millis();
debut =false;
Serial.write("down");
delay(100);
digitalWrite(9,HIGH);
date_ini_veille=millis();
Xbee_reveille = false;
}
if (Serial.available()){//Si le port Xbee recoit une donnée de la part de l'ordinateur par les ondes wifi
commande_mesure=Serial.read();//Lecture de la valeur sur le port Xbee
delay(100);
if (commande_mesure==49){//Si la valeur est de 49; valeur 1 en code ASCII envoyé par processing : mesures instantanées
delay(1000);
//envoie des quatres valeurs les unes après les autres, cela se traduit par un chaîne de caractère recue par le programme python
Serial.print(mesure_temperature());//envoie sur le Xbee
delay(400);//delais technique
Serial.print(';');//séparation des données
delay(10);
Serial.print(mesure_pression(mesure_temperature()));
delay(400);
Serial.print(';');
delay(10);
Serial.print(mesure_hygrometrie());
delay(400);
Serial.print(';');
delay(10);
Serial.print(vitesse_vent());
delay(400);
Serial.print(';');
delay(10);
Serial.print(analogRead(0));//Envoyer surle port Xbee la valeur du niveau de la batterie
delay(10);
delay(3000);//délais technique
initialisation_jour_heure();
delay(2000);
date_ini=millis();
Serial.flush();
}
if (commande_mesure==50){//Si la valeur est de 50; valeur 2 en code ASCII envoyé par processinglectures des données du jour en cours
if (SD.exists(fichier_)){
//Serial.print(fichier_);
Myfile = SD.open(fichier_);
while(Myfile.available()){
Serial.print( char(Myfile.read()));
}
delay(10);
Myfile.close();
}}
if (commande_mesure==51){ // Si la valeur est 3 : valeur 51 en code ASCII: Lecture des données des fichiers non encore lus (_U) de la carte SD ces fichiers sont alors nommés _L
delay(100);
File racine = SD.open("/");
racine.rewindDirectory();
while(true) {
File fichier_donnees = racine.openNextFile();
char fichier_tmp[12];
if (! fichier_donnees) {
// no more files
//Serial.println("**nofiles**");
//racine.rewindDirectory();
break;
}
Serial.println(fichier_donnees.name());
if (fichier_donnees.name()[6]=='U'){
//boolean transfere = false;
for(int n = 0;n <12;n++){
fichier_tmp[n]=fichier_donnees.name()[n];
}
fichier_donnees.close();
//Serial.println(fichier_tmp);
Myfile = SD.open(fichier_tmp);
while(Myfile.available()){
Serial.print( char(Myfile.read()));
}
/*transfere=true;
delay(10);
if (transfere==true){
char fichier_tmp_[12];
for(int n = 0;n 12;n++){
fichier_tmp_[n]=fichier_tmp[n];
}
fichier_tmp_[6]='L';
File Myfile_tmp = SD.open(fichier_tmp_,FILE_WRITE);
Myfile.seek(0);
while(Myfile.available()){
Myfile_tmp.write(Myfile.read());
}
Myfile_tmp.close();
}*/
Myfile.close();
}
else{fichier_donnees.close();}
}
//racine.close();
}
}
/**********************************************************************************************************************
* MESURES toutes les 60 s- mise en veille *
***********************************************************************************************************************/
double tempe_;
double pression_;
float hygro_;
float vent_;
if (millis()>=date_ini + 60000){//mesure effectuée environ toutes les minutes
digitalWrite(9,LOW);//réveil du Xbee
delay(1000);//délais technique dû au temps de réveil du Xbee
tempe_ =mesure_temperature();
delay(400);
pression_= mesure_pression(tempe_);
delay(400);
hygro_=mesure_hygrometrie();
delay(400);
vent_=vitesse_vent();
delay(1100);
determination_date();//Calcul de la date de la mesure
sauv_donnees(tempe_,pression_,hygro_,vent_);//sauvegarde dans le fichier du jour des dates et valeurs
date_ini=millis();//initialisation de la date de la mesure en milliseconde
digitalWrite(9,HIGH);
}
if ((millis()=date_ini_veille + 600000)(Xbee_reveille == false)){//réveil du Xbbe toutes les 10 min pendant 1 min pour permettre la communication avec l'ordi
digitalWrite(9,LOW);
delay(100);
Serial.write("up");
Xbee_reveille = true;
}
if ((millis()>=date_ini_veille + 690000)(Xbee_reveille == true)){//réveil du Xbbe toutes les 10 min pour permettre la communication avec l'ordi
Serial.write("down");
delay(100);
digitalWrite(9,HIGH);
date_ini_veille=millis();
Xbee_reveille = false;
}
//Serial.flush();
}
/**********************************************************************************************************************
* Diverses fonctions *
***********************************************************************************************************************/
double mesure_temperature(){// fontion de mesure de la température codée sur un entier
double T;
status = pressure.startTemperature();//la mesure de la température s'effectue sur le module sparkfun BMP201 et utilisation de la bibliothèque de ce module pour lancer la mesure
if (status != 0)//si le module répond
{
delay(status);//délais imposé par le module
// Retrieve the completed temperature measurement:
// Note that the measurement is stored in the variable T.
// Function returns 1 if successful, 0 if failure.
status = pressure.getTemperature(T);
}//lecture de la température
return T;//renvoie la valeur de T
}
double mesure_pression(double T){//fonction de mesure de la pression codée sur un entier
double P;//défintion de la variable pression
status = pressure.startPressure(3);//demarrage de la mesure de la pression
if (status != 0)//si le module répond
{
delay(status);//délais imposé par le module
status = pressure.getPressure(P,T);//lecture de la pression sur le module
delay(50);
}//imposé par le calcul qui suit
float p0 = pressure.sealevel(P,200);//Pression corrigée de l'altitude de 200 m, changer la veleur selon le lieu
delay(50);//imposé par le calcul précédent
return p0;//renvoie la pression corrigée de l'altitude
}
float mesure_hygrometrie(){//fonction de mesure de le l'hygrométrie codée sur un réel
float humd = myHumidity.readHumidity(); //lecture de la valeur de l'humidité sur le module sparkfun
return humd; //renvoie la valeur de l'humidité
}
float vitesse_vent(){//Mesure et Calcul la vitesse du vent : http://www.lextronic.fr/P28025-capteur-anenometre.html
unsigned long vent= 0;
vent=pulseIn(anemometre,HIGH,800000);
//Serial.println(vent);
//Serial.println(vent2);
float valeur=0;
if (vent>0){
valeur=(70000.0*6.2/vent)*3.6;
//Serial.print("valeur=");
//Serial.println(valeur);
}
//formule donnée par le constructeur du moulinet
//Serial.print(valeur);
return valeur;
}
String reponse_Xbee(){//fonction de lecture des donnees recues par le Xbee lors
int n=0;
while(!Serial.available()){
n++;
if(n>50000){break;}};
char byte_recu = Serial.read();//le xbee envoie un succession de charactère
String reponse_="";
while (byte_recu!=-1){ //si on lit -1 sur le port série cela signifie que la communication n'a pas lieu et on répète tant qu'on reçoit des charactère
if (byte_recu!=-1){//on vérifie de nouveau car la boucle while comporte deux lectures et la deuxième peut être mauvaise
reponse_=reponse_+byte_recu;
}//on crée une chaîne de caractère en concaténant les charactères reçus
byte_recu = Serial.read();//lecture du charactère
delay(20);
} //délais technique
//Xbee.println(reponse_);
return reponse_ ; //renvoie de la chaîne réponse
//Xbee.flush();
}
void sauv_donnees(float tempe_,float pression_, float hygro_,float vent_){//Sauvegarde des données dans le fichier de la date courante
if (SD.exists(fichier_)) {
Myfile = SD.open(fichier_, FILE_WRITE);
Myfile.print(an_);
Myfile.print(";");
Myfile.print(mois_);
Myfile.print(";");
Myfile.print(jour_);
Myfile.print(";");
Myfile.print(heure_);
Myfile.print(";");
Myfile.print(minute_);
Myfile.print(";");
Myfile.print(seconde_);
Myfile.print(";");
Myfile.print(tempe_);
Myfile.print(";");
Myfile.print(pression_);
Myfile.print(";");
Myfile.print(hygro_);
Myfile.print(";");
Myfile.println(vent_);
//Myfile.println(":");
//Myfile.print("\r\n");
delay(10);
Myfile.close();}
else {changt_fichier();}
}
void initialisation_jour_heure(){//fonction nécessaire si on ne dispose pas d'un module timing extérieur
String reponse="";
boolean reponse_=false;
//int n=0;
//Serial.println("initialisation de la date");
Serial.flush();//effacement des données sur tampon de réception du port Xbee
delay(1000);
Serial.print('T');
delay(2000);
reponse=reponse_Xbee();
delay(1000);
if (reponse!=""){
//Serial.println(reponse);
//Serial.println("date recue");
int repere_1= reponse.indexOf(';');
int repere_2= reponse.indexOf(';',repere_1+1);
//Serial.println(repere_1);
int repere_3 = reponse.indexOf(';',repere_2+1);
//Serial.println(repere_2);
int repere_4 = reponse.indexOf(';',repere_3+1);
//Serial.println(repere_3);
int repere_5 = reponse.indexOf(';',repere_4+1);
//Serial.println(repere_4);
if((repere_1!=0)(repere_2!=0)(repere_3!=0)(repere_4!=0)(repere_5!=0)){
an_=reponse.substring(0,repere_1).toInt();
mois_=reponse.substring(repere_1+1,repere_2).toInt();
// Serial.println(mois_ini);
jour_=reponse.substring(repere_2+1,repere_3).toInt();
// Serial.println(jour_);
heure_=reponse.substring(repere_3+1,repere_4).toInt();
//Serial.println(heure_);
minute_=reponse.substring(repere_4+1,repere_5).toInt();
//Serial.println(minute_);
seconde_=reponse.substring(repere_5+1).toInt();
//Xbee.println(minute_);
//changt_fichier();
//delay(1000);
date_ini=seconde_*1000;}}
Serial.flush();
}
void determination_date(){//fonction nécessaire si on ne dispose pas d'un module timing extérieur
boolean changt_date = false;
long date_presente = millis();
long temps_ecoule=date_presente-date_ini+1250;
temps_ecoule=temps_ecoule/1000;
if ((seconde_+temps_ecoule)59){seconde_ = seconde_+temps_ecoule;}
else{seconde_=(temps_ecoule-59);
if (minute_<59){minute_=minute_+1;}
else{minute_=0;
if(heure_<23){heure_=heure_+1;}
else{heure_=0;
switch (mois_) {
case 1 :if (jour_<31){jour_=jour_+1;}
else{jour_ = 1;
mois_= 2;}
break;
case 2 :if (jour_<28){jour_=jour_+1;}
else{jour_ = 1;
mois_= 3;}
break;
case 3 :if (jour_<31){jour_=jour_+1;}
else{jour_ = 1;
mois_= 4;}
break;
case 4 :if (jour_<30){jour_=jour_+1;}
else{jour_ = 1;
mois_= 5;}
break;
case 5 :if (jour_<31){jour_=jour_+1;}
else{jour_ = 1;
mois_= 6;}
break;
case 6 :if (jour_<30){jour_=jour_+1;}
else{jour_ = 1;
mois_= 7;}
break;
case 7 :if (jour_<31){jour_=jour_+1;}
else{jour_ = 1;
mois_= 8;}
break;
case 8 :if (jour_<31){jour_=jour_+1;}
else{jour_ = 1;
mois_= 9;}
break;
case 9 :if (jour_<30){jour_=jour_+1;}
else{jour_ = 1;
mois_= 10;}
break;
case 10 :if (jour_<31){jour_=jour_+1;}
else{jour_ = 1;
mois_= 11;}
break;
case 11 :if (jour_<30){jour_=jour_+1;}
else{jour_ = 1;
mois_= 12;}
break;
case 12 :if (jour_<31){jour_=jour_+1;}
else{jour_ = 1;
mois_= 1;
an_= an_+1;}
break;
}
changt_fichier();
delay(1000);}}
}
}
void changt_fichier(){
int n=0;
String string_mois;
String string_jour;
if (mois_<10){string_mois = "0"+ String(mois_);}
if (mois_>=10){string_mois = String(mois_);}
if (jour_<10){string_jour = "0"+ String(jour_);}
if (jour_>=10){string_jour = String(jour_);}
String nom_fichier=string_mois+"-"+string_jour+"-"+"U"+"."+"TXT";
while(n<11){
fichier_[n]=nom_fichier[n];
n++;
}
//Serial.println("nom du fichier ="+nom_fichier);
if (!SD.exists(fichier_)){
Myfile = SD.open(fichier_, FILE_WRITE);//Creation du fichier de sauvegarde
Myfile.println("date ; heure; temperature; pression; hygrometrie;vent :");//Premiere ligne de la sauvegarde
Myfile.close();//Fermeture du fichier
}
}
]]
# -*- coding: utf-8 -*-
#
# Module de lecture/ecriture du port Xbee station météo
from Tkinter import *
from serial import *
import time
import threading
from datetime import datetime,date,timedelta
from time import gmtime, strftime
import platform
from serial.tools import list_ports
import os, io,itertools
import signal
import sys
import pylab
from PIL import Image, ImageTk
import tkMessageBox
if platform.system() == 'Windows':#Détection du système , utilisation du registre windows
import _winreg as winreg
else:
import glob
port_Xbee=''
path = 'HARDWARE\\DEVICEMAP\\SERIALCOMM'
marche=True
debut=True
forcage=False
mise_en_veille_active=True
def enumerate_serial_ports(): # fonction listant l'ensemble des ports série(USB) utilisés sur la machine
#définition du chemin de la clef du registre donnant la lsite des ports séries en activité
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path) #défintion de la clef du registre des ports séries
except WindowsError:
raise Exception
for i in itertools.count(): #pour l'ensemble des ports série détectés,les lister dans l'ordre croissant
try:
val = winreg.EnumValue(key, i) # valeur des différents ports
yield (str(val[1])) # , str(val[0])) #La fonction yield permet de garder la liste des ports classés
#print(str(val[i]))
except EnvironmentError:
print("erreur")
break
def detection_port_Xbee():
global Xbee
liste_des_ports=enumerate_serial_ports()
for i in liste_des_ports :#Détetection du port série(USB) sur lequel est branché le module xbee
print(i)
try :
with Serial(port=i, baudrate=9600, timeout=1, writeTimeout=1) as Xbee:
if Xbee.isOpen():
time.sleep(1)
Xbee.write('+++')
time.sleep(1.2)
ligne = Xbee.readline()
if (ligne=='OK'+chr(13)) :
port_Xbee=i
#return port_Xbee
break
Xbee.close()
except :
continue
Xbee = Serial(port=port_Xbee, baudrate=9600, timeout=1, writeTimeout=1)
chaine = "Xbee branché sur le port :" +port_Xbee
B1.config(state=DISABLED)#change l état des boutons
B3.config(state=NORMAL)
B5.config(state=NORMAL)
text1.set(chaine ) #indication du port utilisé
detection_creation_fichier_sauvegarde() #Détecte si le fichier de sauvegarde est présent
#
def Configuration_Xbee() :#Entrée dans le mode configuration du Xbee relié à l'orinateur (pas utilisé)
while Xbee.isOpen():
time.sleep(1)
Xbee.write('+++') #activation du mode config du Xbee
time.sleep(1.2)
ligne = Xbee.readline()
if (ligne=='OK'+chr(13)) : #Vérification de la réponse du Xbee
print(ligne)
print( 'mode config')
Xbee.write('ATID'+chr(13)) #lecture de n° identification du Xbee
time.sleep(1)
ligne = Xbee.readline()
time.sleep(0.2)
print(ligne)
Xbee.write('ATCN'+chr(13)) # on quitte le mode config
time.sleep(1)
ligne = Xbee.readline()
time.sleep(0.2)
print(ligne)
reponse =raw_input("Taper q pour quitter le mode config :")# Demande à l'opérateur si on doit quitter
#le mode config la fonction input n'est pas adaptée en python 2 :
#interprétation du code
print reponse
if (reponse == 'q'):
break
print('terminé')
#Envoie de données de la carte Arduino vers l'ordinateur:
def lecture_des_donnees(moment_d_acquisition) :#Commande à l'arduino de lire les données
if (Xbee.isOpen()) :
Xbee.write('1') #code 1 : indique à l'arduino qu'il faut lire les données
b.stop()#arrêt du timer de 10 s pour eviter les conflits de lecture du port série
time.sleep(2)#pause de 2s
mesure_ = Xbee.readline()#lecture du port série de la ligne envoyé par l'Arduino
time.sleep(2)#mise en veille technique
mesure=mesure_.split(";")#Sépare les données et les transforme en tableau : le';' est envoyépar l'arduino entre chaque valeur
print mesure#écrit la ligne dans la console pour vérification
if (len(mesure)==5):#si il y a 5 éléments dans le tableau la lecture est sans doute bonne
temperature=mesure[0] #l'élément 1 du tableau est la tempé
#print('Temperature = '+temperature)
text_tempe.set( "Tempé =" +temperature[:4] + "°C")
pression=mesure[1] #l'élément 2 du tableau est la pression
#print('Pression = '+ pression)
text_pression.set("Pression = "+pression[:4] + " hPa")
hygro = mesure[2]#l'élément 3 du tableau est l'hygrométrie
#print('Hygrométrie =' +hygro)
text_hygro.set("Hygrométrie = " + hygro[:4]+" % hum")
vent=mesure[3]#l'élément 4 du tableau est la vitesse du vent
text_vent.set("vent ="+vent[:4]+"km/h")
batterie = mesure[4]#l'élément 5 du tableau est la tension aux bornes de la batterie
#print('Batterie =' +batterie)
y=int(float(batterie)/860*700)#donne un nombre de pixel proportionnel à la tension de charge de la batterie
tension=round(float(batterie)/1024.0*16.0,1)#Permet d'obtenir la tension à partir du nombre binaire
texte=str(tension)+ " V"
#print(y)
text2.set("Mesures : Temperature = " + temperature +"°C ;" +" Pression = " +pression+"hPa ;"+" Hygrométrie = " + hygro + "%"+vent+" km/h")
text3.set("Heures des données affichées : "+ str(moment_d_acquisition.hour) +":"+ str(moment_d_acquisition.minute))
can1.delete(ALL)#effacemement du canvas de charge de batterie
if (tension>=9.0) :
poly2=can1.create_polygon(0, 0, y, 0,y,50,0,50, fill='green')#Si la charge de la batterie est bonne on trace un rectangle vert
else :
poly2=can1.create_polygon(0, 0, y, 0,y,50,0,50, fill='red')#Si la charge de la batterie est insuffisant on trace un rectangle rouge
#tracé d'un rectangle de couleur et de longueur proprotionnelle à la tesnion aux bornes de la batterie
texte1=can1.create_text(y, 12, text=texte, font="Arial 12 italic", fill="black")
texte2=can1.create_text(350, 30, text="charge batterie", font="Arial 16", fill="blue")
return [temperature,pression,hygro,vent,batterie]#La fonction de lecture des données renvoie les valeurs
Xbee.flushInput()#efface les données du tampon de réception du port série
b.start();#redémarrage du timer de 2 s : lecture du port série
else :
can3.delete(ALL)
text2.set("La station météo n'est pas prête")#Si la lecture est mauvaise
can2.create_oval(5,5,45,45,fill='red')#le voyant rouge s'allume
can3.create_text(200,24, text =' Rouge : station en mode veille')#indique que la station ne répond pas
return [0,0,0,0]
Xbee.flushInput()#efface les données du tampon de réception du port série
b.start() #redémarrage du timer de 2 s : lecture du port série
else :
print('Le module Xbee ne répond pas')
return [0,0,0,0]
b.start();#redémarrage du timer de 2 s : lecture du port série
def sauvegarde_donnees(donnees) :#Sauvegarde des données dans un fichier csv
if os.path.isfile('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv') :
fichier = open('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv',"a")
#fichier.write( strftime("%a, %d %b %Y %H:%M", gmtime())+';')
for i in range(6) :
fichier.write(str(donnees[i]))
fichier.write(';')
fichier.write('\n')
fichier.close()
else :
print('Le fichier n''existe pas')
donnees=[0,0,0,0] #pour éviter une erreur d'écriture
def test_date_recuperation():
if os.path.isfile('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv') :
fichier = open('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv',"r")
chaine = fichier.read()
print chaine
fichier.close()
def detection_creation_fichier_sauvegarde(): #Vérification de l'existence d'un fichier de sauvegarde, sinon le créer
if (os.path.isfile('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv')!=True) :
fichier = open('C:\IFE\Météo\documents_contribution\programme python\donnees_meteo.csv',"w")
fichier.close()
def fermer_programme():
"""Fonction appelée quand vient l'heure de fermer notre programme"""
print("C'est l'heure de la fermeture !")
if (Xbee.isOpen()) :
Xbee.close()
if (a) :
a.stop()
if(b) :
b.stop()
fenetre_meteo.destroy()
def mise_enveille_Xbee(moment_d_acquisition):
if (Xbee.isOpen()) :
time.sleep(1)
Xbee.write('5') # 5 est le code de mise en veille du Xbee station
time.sleep(1)
Xbee.write(str(moment_d_acquisition.hour))#Donne l'heure à la station
time.sleep(1)
Xbee.write(str(moment_d_acquisition.minute))#Donne les minutes à la station
time.sleep(1)
def mesures() :
#fonction appelée par le timer toutes les 60s, la mesure n'est ici effectuée que chaque heure
global debut
global forcage
B2.config(state=DISABLED)#le bouton arret des mesures est désactivé
#if( ((moment_d_acquisition.minute%2)==0)and (moment_d_acquisition.second==0)):#toutes les heures (((moment_d_acquisition.minute)==0)and (moment_d_acquisition.second==0)):#chaque heure en réalité
moment_d_acquisition = datetime.now()
if (moment_d_acquisition.minute>0):#pour que l'acquisition n'ai lieu qu'a l'heure pile
global acquisition_effectuee#variable globale indiquant que l'acquisition est effectuée
acquisition_effectuee =False
if (((moment_d_acquisition.minute==0)and (acquisition_effectuee==False))or(debut==True)or(forcage==True)):#démarrage du timer à une heure pleine(((moment_d_acquisition.minute)==0)and (moment_d_acquisition.second==0)):#chaque heure en réalité
b.stop()#L'acquisition a lieu lorsque le timer de 2 s est à l'arrêt
time.sleep(1.5)#Mise en veille technique.
Xbee.flushInput() #effacement des données entrantes du port série
debut=False #indique que ce n'est plus la première mesure
forcage=False #indique que l'on de force pas la lecture de la meusre à un moment quelconque
acquisition_effectuee=True;
donnees=lecture_des_donnees(moment_d_acquisition) #appel de la lecture des données sur l'Arduino distant
jour = datetime.now()
date_= str(jour.day)+"/"+str(jour.month)+"/"+str(jour.year)#lecture de la date et de l'heure
heure_=str(jour.hour)+"h"+str(jour.minute)
donnees.insert(0,heure_)
donnees.insert(0,date_)
print(donnees)
sauvegarde_donnees(donnees)#appel de la fonction de sauvgarde des données
#mise_enveille_Xbee(moment_d_acquisition)#met en veille le Xbee pour préserver les batteries de la staion météo autonome
Xbee.flushInput()
b.start()
B2.config(state=NORMAL)#le bouton arret des mesures est activé
def scrutation_mise_en_veille() :#fonction applée par le timer de 2 s pour srcuter la mise en veille de la station
examen_veille=Xbee.readline()#lecture du port série
time.sleep(0.1);
print ("Le port Xbee indique : "+examen_veille)
if(examen_veille=="up"):#si la station envoie up, elle se réveille
can3.delete(ALL)
can2.create_oval(5,5,45,45,fill='green')
can3.create_text(200,24, text ='Vert : station accessible.')
B7.config(text="Desactiver la mise en veille")
forcage_mesures()
Xbee.flushInput()
if(examen_veille=="down"):#si la station envoir down, elle se met en veille
can3.delete(ALL)
can2.create_oval(5,5,45,45,fill='red')
heure_courante = datetime.now()
phrase=' Rouge : station en mode veille à '+str(heure_courante.hour)+' h' +str(heure_courante.minute)+'.'
can3.create_text(200,24, text =phrase)
Xbee.flushInput()
if (examen_veille=="T"):
b.stop()
time.sleep(1.0);
heure_courante = datetime.now()
date_heure = str(heure_courante.year) + ";"+str(heure_courante.month) + ";" + str(heure_courante.day) + ";"+str(heure_courante.hour)+";"+str(heure_courante.minute)+";"+str(heure_courante.second)
Xbee.write(date_heure)
print(date_heure)
time.sleep(1.0)
b.start()
Xbee.flushInput()
class MyTimer: #classe définissant un timer
def __init__(self, tempo, target, args= [], kwargs={}):
self._target = target
self._args = args
self._kwargs = kwargs
self._tempo = tempo
def _run(self):
self._timer = threading.Timer(self._tempo, self._run)
self._timer.start()
self._target()
def start(self):
self._timer = threading.Timer(self._tempo, self._run)
self._timer.start()
def stop(self):
self._timer.cancel()
def lance_mesures() :#lance les mesures
B3.config(state=DISABLED)#le bouton de lancement des mesures est déactivé
B4.config(state=NORMAL)#
print('debut des mesures')
debut=True
#mesures() #une première serie de mesure est prise au début
moment_d_acquisition = datetime.now()
while (moment_d_acquisition.second!=0) :#afin que le démarrage du timer ne prenne effet que lorsque l'heure est de la forme x h y h 00s
moment_d_acquisition = datetime.now()
B6.config(state=NORMAL)
a.start()
b.start()
mesures()
def arret_mesures() :
B3.config(state=NORMAL)
B4.config(state=DISABLED)
debut=True
b.stop()
a.stop()
def forcage_mesures():
global forcage
forcage= True
mesures()
def recup_mesures_total():
code_lecture = '3'
lecture_mesures(code_lecture)
def recup_mesures() :
code_lecture = '2'
lecture_mesures(code_lecture)
def lecture_mesures(code_lecture):#permet la récupération des mesures des 48 h précédentes
b.stop()
time.sleep(1)
Xbee.write(code_lecture)
#Lecture des mesures
time.sleep(2)
M = Xbee.readlines()
#décompose M en autant de lignes qu'il y a d'heures M=M_.split(':')
print M
for n in range(0,len(M)-1):
A = M[n].split(';')
date_=A[2]+"/"+A[1]+"/"+A[0]
A[9]=A[9][0:4]
heure_ = A[3]+"h"+A[4]
mesures_=[date_,heure_,A[6],A[7],A[8],A[9]]
print mesures_
try :
sauvegarde_donnees(mesures_)
except :
tkMessageBox.showwarning('Warning','Accés au fichier impossible ! Veuillez le fermer !')
b.start()
b.start()
def desactive_veille() :#désactive la mise en veille de l'Arduinostation pour la maintenance
global mise_en_veille_active
if (Xbee.isOpen()) :
time.sleep(1)
Xbee.write('7') #code indiquant qu'il faut sortir ou entrer du mode éco
time.sleep(1)
if (mise_en_veille_active==True) :#informe que le mode éco est actif
mise_en_veille_active=False
B7.config(text='Activer la mise en veille')
elif (mise_en_veille_active==False) :#informe que le mode éco est déactivé
mise_en_veille_active=True
B7.config(text='Désactiver la mise en veille')
#######################################################################
# Programme principal #
#######################################################################
fenetre_meteo=Tk()#créaction d'une fenêtre graphique
fenetre_meteo.title("Mesures de la station météo")
fenetre_meteo.geometry("800x800")
text1 = StringVar()
text1.set("Activer la recherche du Xbee") #initialise le message : il faut lancer la détection du Xbee
text2 = StringVar()
text2.set("Mesures : ") #
text3 = StringVar()
text3.set("Temps : ")
text_tempe = StringVar()
text_tempe.set("°C")
text_pression=StringVar()
text_hygro=StringVar()
text_vent=StringVar()
label_tempe =Label(fenetre_meteo,textvariable=text_tempe,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="red")
label_tempe.place(x=20,y=400) #affichage de la température
label_pression =Label(fenetre_meteo,textvariable=text_pression,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="blue")
label_pression .place(x=20,y=450) #affichage de la pression
label_hygro =Label(fenetre_meteo,textvariable=text_hygro,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="orange")
label_hygro.place(x=20,y=500) #affichage de l'hygrométrie
label_vent = Label(fenetre_meteo,textvariable=text_vent,relief=RAISED,font=("Sans Serif", "24", "bold"),fg ="green")
label_vent.place(x=20,y=550)#affichage de la vitesse du vent
B1=Button(fenetre_meteo,text="Détection du Xbee",command=detection_port_Xbee,state=NORMAL,width=100)#Bouton d'arrêt du programme
B1.place(x=20,y=10)#bouton de détection du Xbee
croix=PhotoImage(file='C:/IFE/Météo/documents_contribution/programme python/croix.gif')#image de la croix du bouton de fermeture
B2=Button(fenetre_meteo,image=croix,text='Fermer',command=fermer_programme,state=NORMAL)#Bouton de fermeture du programme
B2.place(x=600,y=700)
L1=Label(fenetre_meteo,textvariable=text1)#Label Texte affichant l'état d erecherche du Xbee
L1.place(x = 160, y=50)
B3=Button(fenetre_meteo,text="Lancer les mesures ",command=lance_mesures,state=DISABLED,width=100)#bouton de lancement des mesures
B3.place(x=20,y=200)#
B4=Button(fenetre_meteo,text="Arrêter les mesures ",command=arret_mesures,state=DISABLED,width=100)#bouton d'arrêt du timer de 1 h
B4.place(x=20,y=250)
B5=Button(fenetre_meteo,text="SD : récuperer les mesures enregistrées",command=recup_mesures,state=NORMAL,width=50)
B5.place(x=100,y=700)#commande la lecture du fichier du jour en cours
B7=Button(fenetre_meteo,text="SD : récuperer les mesures enregistrées les jours précédents",command=recup_mesures_total,state=NORMAL,width=50)
B7.place(x=100,y=650)#commande la lecture de tous les fichiers
B6=Button(fenetre_meteo,text="Forçage des mesures",command=forcage_mesures,state=DISABLED,width=50)
B6.place(x=100,y=100)#commande manuelle la lecture des mesures
B7=Button(fenetre_meteo,text="Désactiver la mise en veille",command=desactive_veille,state=NORMAL,width=50)
B7.place(x=400,y=100)# Bouton permettant de désactivier la mise en veille du Xbee Distant
L2=Label(fenetre_meteo,textvariable=text2)
L2.place(x = 20, y=300)#Label d'affichage
L3=Label(fenetre_meteo,textvariable=text3)
L3.place(x = 20, y=350)
can1 = Canvas(fenetre_meteo,bg='yellow',height=50,width=700)#canvas d'affichage de l'état de la batterie fond
can1.place(x= 20, y = 600)
can2 = Canvas(fenetre_meteo,height=50,width=50)#canvas d'affichage de l'état de la batterie
can2.place(x=650,y=450)
can3 = Canvas(fenetre_meteo,height=50,width=400)
can3.place(x=400,y=400)
poly2=can1.create_polygon(0, 0, 0, 0,0,50,0,50, fill='red')#canvas d'affichage de l'état de la batterie en rouge si pas assez chargée
txt0=can1.create_text(350, 30, text="charge batterie", font=("Arial"," 16"), fill="blue")#Texte indiquant l'état de la batterie
texte1=can1.create_text(0, 12, text="0 V" , font=("Arial"," 12"," italic"), fill="black")
a = MyTimer(60, mesures, ["MyTimer"]) #un timer de 1 h demande la lecture des données et leur enregistrement
b = MyTimer(2, scrutation_mise_en_veille, ["MyTimer"])#un timer de 2 s scrute le port Xbee
fenetre_meteo.mainloop()