Objets communiquants et gestion de l'énergie : Différence entre versions
(→Réalisation) |
(→Le code du Arduino) |
||
(17 révisions intermédiaires par 2 utilisateurs non affichées) | |||
Ligne 95 : | Ligne 95 : | ||
== Réalisation == | == Réalisation == | ||
− | = | + | ===Le Arduino=== |
+ | ====Architecture de l'objet communiquant==== | ||
+ | |||
+ | *Un Arduino Mega 2560 | ||
+ | *Un XBee | ||
+ | *Un capteur de température | ||
+ | *Un capteur de luminosité | ||
+ | |||
+ | ====Le code du Arduino==== | ||
<code> | <code> | ||
Ligne 105 : | Ligne 113 : | ||
int sensorLightPin = 1; | int sensorLightPin = 1; | ||
int Light; | int Light; | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
uint8_t values[] = { 0, 0, 0, 0 }; | uint8_t values[] = { 0, 0, 0, 0 }; | ||
Ligne 131 : | Ligne 133 : | ||
Light = <span style="color: purple;">analogRead</span>(sensorLightPin); | Light = <span style="color: purple;">analogRead</span>(sensorLightPin); | ||
Temp = <span style="color: purple;">analogRead</span>(sensorTempPin); | Temp = <span style="color: purple;">analogRead</span>(sensorTempPin); | ||
− | |||
− | |||
− | |||
+ | <span style="color: red;">// Listens on the Xbee protocol for any packet incoming.</span> | ||
xbee.<span style="color: purple;">readPacket</span>(); | xbee.<span style="color: purple;">readPacket</span>(); | ||
Ligne 182 : | Ligne 182 : | ||
} | } | ||
</code> | </code> | ||
+ | Ce code fonctionne de la manière suivante: | ||
+ | =====Fonction <span style="color: purple;">setup</span>():===== | ||
+ | Une fois implémenté sur le Arduino, la fonction setup va faire démarrer le protocole XBee et le protocole Série afin de pouvoir envoyer et recevoir des messages par XBee, et d'imprimer les messages d'erreur sur le port Série s'il y a lieu. | ||
+ | =====Fonction <span style="color: purple;">loop</span>():===== | ||
+ | Cette fonction va réaliser une boucle toutes les 0.5s pour mettre a jour les données des différents capteurs et les envoyer au serveur au travers du protocole XBee. Pour plus de détails voir les commentaires expliquant chaque étape du déroulement de la boucle. | ||
+ | |||
+ | ===Le programme LINKER=== | ||
+ | |||
+ | Code du programme de liaison | ||
+ | |||
+ | ce programme en java est constitué de 5 classes | ||
+ | |||
+ | ====Le Main==== | ||
+ | <code> | ||
+ | public class main { | ||
+ | |||
+ | public static SQLinker linker; | ||
+ | public static Xbee xbee; | ||
+ | |||
+ | public static void main(String[] args){ | ||
+ | String address = new String("jdbc:mysql://sitedb.polytech-lille.net/cdelberg?"); | ||
+ | String user = new String("user=cdelberg&password=myLo9ufonese"); | ||
+ | String COM; | ||
+ | |||
+ | |||
+ | <span style="color: red;">// We ask the user on the Communication Port to connect the XBee</span> | ||
+ | System.out.println("Please enter the Communication port of the Xbee"); | ||
+ | Scanner sc = new Scanner(System.in); | ||
+ | COM = sc.next(); | ||
+ | System.out.println("COM port changed to: "+COM); | ||
+ | |||
+ | <span style="color: red;">//Creation of the Variables that will be used to connect to the Database and the Xbee</span> | ||
+ | linker = new SQLinker(address, user); | ||
+ | linker.FillArdList(); | ||
+ | xbee = new Xbee(COM); | ||
+ | |||
+ | <span style="color: red;">//Creating the Updates Threads</span> | ||
+ | W8Thread thread1 = new W8Thread(); | ||
+ | thread1.start(); | ||
+ | UpTestThread thread2 = new UpTestThread(); | ||
+ | thread2.start(); | ||
+ | |||
+ | <span style="color: red;">//We now allow the user to enter a command</span> | ||
+ | String command; | ||
+ | System.out.println("vous pouvez maintenant lancer une commande si vous le souhaitez"); | ||
+ | System.out.println("tapez help pour plus d'informations"); | ||
+ | boolean exit=false; | ||
+ | |||
+ | while(exit==false){ | ||
+ | command=sc.next(); | ||
+ | |||
+ | if(command.equals("help")){ | ||
+ | System.out.println("print => affiche la liste des arduinos"); | ||
+ | System.out.println("exit => ferme le programme"); | ||
+ | } | ||
+ | if(command.equals("print")){linker.PrintArdList();} | ||
+ | if(command.equals("exit")){exit=true;} | ||
+ | |||
+ | } | ||
+ | <span style="color: red;">//if the user ask to stop the program, it will do those final commands</span> | ||
+ | sc.close(); | ||
+ | thread1.stop(); | ||
+ | thread2.stop(); | ||
+ | xbee.XbeeClosing(); | ||
+ | //System.out.println("Program finished successfully"); | ||
+ | |||
+ | } | ||
+ | |||
+ | } | ||
+ | |||
+ | </code> | ||
+ | |||
+ | Le main est la racine du programme. Il va créer les ressources nécessaires pour la connexion à la base de donnée et au XBee lui même connecté au PC. | ||
+ | Il crée ensuite 2 threads, l'un faisant une MAJ des valeurs des Arduinos dans la base de donnée à intervalles réguliers. | ||
+ | L'autre regarde sur la base de donnée si un utilisateur a fait une demande de MAJ, et ce toute les secondes, puis y répond. | ||
+ | |||
+ | ====La classe SQLinker==== | ||
+ | <code> | ||
+ | public class SQLinker { | ||
+ | |||
+ | Connection connect; | ||
+ | Statement stmt; | ||
+ | PreparedStatement pst; | ||
+ | ResultSet rs; | ||
+ | int[] ArdList = new int[10]; | ||
+ | int[][] ArdListMatrix = new int[10][2]; | ||
+ | String[] table = {"Battery", "Light", "Temperature", "Updating"}; | ||
+ | <span style="color: red;">//List of variables used to connect to the database and store some informations</span> | ||
+ | |||
+ | <span style="color: red;">//Constructor, create a connection when called</span> | ||
+ | public SQLinker(String address, String user){ | ||
+ | |||
+ | try{ | ||
+ | Class.forName("com.mysql.jdbc.Driver").newInstance(); | ||
+ | } catch(Exception ex){ | ||
+ | System.out.println("can't register the Driver"); | ||
+ | } | ||
+ | |||
+ | try{ | ||
+ | connect = DriverManager.getConnection(address+user); | ||
+ | stmt = connect.createStatement(); | ||
+ | } catch(Exception ex){ | ||
+ | System.out.println("connection issue"); | ||
+ | System.out.println("SQLException: " + ex.getMessage()); | ||
+ | } | ||
+ | if (connect!= null){ | ||
+ | System.out.println("connected to the database " + address); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | <span style="color: red;">//Fill a matrix with the list of Arduinos stored in the database</span> | ||
+ | public void FillArdList(){ | ||
+ | try{ | ||
+ | rs = stmt.executeQuery("SELECT Arduino FROM Arduinos"); | ||
+ | int i=0; | ||
+ | int m,c,d,u; | ||
+ | while(rs.next()){ | ||
+ | ArdList[i] = Integer.parseInt(rs.getString(1)); | ||
+ | m=ArdList[i]/1000; | ||
+ | c=(ArdList[i]-m*1000)/100; | ||
+ | d=(ArdList[i]-m*1000-c*100)/10; | ||
+ | u=(ArdList[i]-m*1000-c*100-d*10); | ||
+ | ArdListMatrix[i][0]=(m*10+c); | ||
+ | ArdListMatrix[i][1]=(d*10+u); | ||
+ | i++; | ||
+ | } | ||
+ | ArdList[i]=-1; | ||
+ | } catch (SQLException e){ | ||
+ | System.out.println("SQLException: " + e.getMessage()); | ||
+ | System.out.println("SQLState: " + e.getSQLState()); | ||
+ | System.out.println("VendorError: " + e.getErrorCode()); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | <span style="color: red;">//print the list of arduinos stored in the program</span> | ||
+ | public void PrintArdList(){ | ||
+ | int i=0; | ||
+ | while(ArdList[i]!=-1){ | ||
+ | i++; | ||
+ | System.out.println("Code Arduino n°"+i+": "+ArdList[i]); | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | <span style="color: red;">//Print the values of a specific arduino</span> | ||
+ | public void PrintArdValues(int ard){ | ||
+ | for(int i=0; i<=2;i++){ | ||
+ | |||
+ | try { | ||
+ | rs = stmt.executeQuery("SELECT " +table[i]+" FROM Arduinos WHERE Arduino ="+ard); | ||
+ | } catch (SQLException e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | try { | ||
+ | while(rs.next()){ | ||
+ | System.out.println(table[i] +"=" + rs.getString(1)); | ||
+ | } | ||
+ | } catch (SQLException e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | <span style="color: red;">//print the values of every arduino stored in the program</span> | ||
+ | public void PrintAllArdValues(){ | ||
+ | int i=0; | ||
+ | while(ArdList[i]!=-1){ | ||
+ | this.PrintArdValues(i); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | <span style="color: red;">//set the values obtained from an arduino to the database</span> | ||
+ | public void SetArdValues(int Ard, int[] values){ | ||
+ | int i=0; | ||
+ | while(values[i]!=-1){ | ||
+ | |||
+ | try { | ||
+ | pst = connect.prepareStatement("UPDATE Arduinos SET "+table[values[i]]+" = "+values[i+1] +" WHERE Arduino ="+Ard); | ||
+ | pst.executeUpdate(); | ||
+ | } catch (SQLException e){ | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | |||
+ | |||
+ | i+=2; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | <span style="color: red;">//verify if an update as been demanded by a user on the website</span> | ||
+ | public int CheckUpdate(){ | ||
+ | int i=0; | ||
+ | int ret=0; | ||
+ | while(ArdList[i]!=-1 && ret!=1){ | ||
+ | try { | ||
+ | rs = stmt.executeQuery("SELECT Updating FROM Arduinos WHERE Arduino ="+ArdList[i]); | ||
+ | while(rs.next()){ | ||
+ | ret = Integer.parseInt(rs.getString(1)); | ||
+ | } | ||
+ | } catch (SQLException e) { | ||
+ | e.printStackTrace(); | ||
+ | } | ||
+ | i++; | ||
+ | } | ||
+ | return ret; <span style="color: red;">//return 1 if update demanded</span> | ||
+ | |||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | </code> | ||
+ | Cette classe regroupe toutes les fonctions permettant de se connecter à une base de donnée et d'en traiter les données. | ||
+ | |||
=== Liste du matériel à acheter === | === Liste du matériel à acheter === |
Version actuelle datée du 25 février 2013 à 07:14
Présentation du projet
Planning prévisionnel provisoire (jusqu'à la pré-soutenance)
Ce planning pourrait être amené à être modifié.
I) Etat de l'art ( ~2-3 semaines)
-Energy harvesting (Calvin)
-Batteries (Justin)
II) Mesure de puissance des différents appareil Arduino ( ~2 semaines)
III) Confronter théorie/réalité ( ~1 semaine) -estimer consommation de puissance
-vérifier en pratique
Amené à être ajouté:
Mesure du Arduino de sa propre consommation.
Mesure de la consommation du code (?)
Applications:
-Envoi des valeurs de l'Arduino au serveur.
-Interface web pour interagir avec l'objet.
Etat de l'art
Energy Harvesting
- Mosquino:
Mosquino est un matériel compatible avec le développement logiciel et dérivé de Arduino, il permet de récupérer de l'énergie des sources ambiantes (chaleur, luminosité, vibrations)
Il n'est destiné qu'aux faibles consommations électriques et n'est encore qu'en phase de développement, il n'a pas encore été véritablement testé.
http://tim.cexx.org/?page_id=760
- Breakout board BOB-o9946 :
Cette carte utilise le collecteur d'énergie piezoelectrique LTC3588 de Linear Technologies et permet non seulement de récupérer l'énergie piezoélectrique mais aussi l'énergie solaire. Initialement prévu pour fonctionner à faible voltage, la capacité de sortie peut-être dimensionnée pour recevoir une salve de courant de sortie plus élevée.
https://www.sparkfun.com/products/9946
Batteries
- nouvelles technologies:
ces dernières années, de nouvelles technologies sont apparues, sans être encore réellement utilisées. je pense notamment aux batteries contenues dans des câbles: http://phys.org/news/2012-09-lg-chem-cable-batteries-reshape.html
ainsi qu'aux batteries ultra fines dévellopées par thinergy: http://www.infinitepowersolutions.com/products.html
Néanmoins, les tensions pouvant etre délivrées par ces technologies naissantes sont loin de pouvoir alimenter le materiel qui nous interresse, à savoir des Arduino (necessitant une alimentation comprise entre 7V-12V)
D'autres techno sont encore en phase de développement, comme les batteries lithium-Air d'IBM, les piles au graphène utilisant la chaleur pour produire de l’énergie (plutôt de l'energy harvesting pour le coup). Comme ces technologies sont encore en phase de développement, elles n’apparaîtrons pas sur le marché avant au moins 10 ans.
- technologies adaptée à notre usage:
comme je l'ai rappelé plus haut, ce PFE tourne principalement autour d'Arduino. ces plates-formes nécessitant une tension d'alimentation supérieure à 7V, le choix le plus intéressant reste les piles rechargeable.
Seulement, il existe plusieurs types de piles rechargeables. dans l'usage qu'il en sera fait, et si ces batteries sont couplées à des technologies de récupération d'énergie, il est important de choisir des piles Lithium-Ion.
En effet, ces piles sont les plus intéressantes pour plusieurs raisons:
tout d'abord, elles sont insensibles à l'effet mémoire. du coup elles ne perdent pas de leur capacité de stockage d’énergie au cours du temps.
le circuit intégré à ces piles empêche toute surtension lors de la charge.
elles peuvent être rechargée en même temps qu'elles sont utilisées.
dans une époque ou la pollution est un sujet préoccupation, ces piles sont moins dangereuse pour l’environnement que leurs homologues au nickel-Cadmium
le seul problème pourrais venir du fait qu'elles ne supporte pas bien la chaleur, mais à moins de les coller à un radiateur, il ne devrais pas y avoir de soucis.
Mesure de la consommation énergétique
WSIM permet la simulation de capteurs sans fil. Il permet notamment d'estimer la consommation électrique http://wsim.gforge.inria.fr/index.html Pour l'instant il ne fonctionne qu'avec des microcontrolleurs TI. Le support des AVR est en cours. L'estimation de la consommation énergétique utilise esimu http://esimu.gforge.inria.fr/index.html
Réalisation
Le Arduino
Architecture de l'objet communiquant
- Un Arduino Mega 2560
- Un XBee
- Un capteur de température
- Un capteur de luminosité
Le code du Arduino
#include <XBee.h> // Define variables, pins.. int sensorTempPin = 0; int Temp; int sensorLightPin = 1; int Light; uint8_t values[] = { 0, 0, 0, 0 }; XBee xbee = XBee(); XBeeResponse response = XBeeResponse(); Rx16Response rx = Rx16Response(); Tx16Request tx = Tx16Request(0x1111, values, sizeof(values)); TxStatusResponse txStatus = TxStatusResponse(); void setup() { // Initialise xbee / serial xbee.begin(9600); Serial.begin(9600); } void loop() { // Read the values on analog pins Light = analogRead(sensorLightPin); Temp = analogRead(sensorTempPin); // Listens on the Xbee protocol for any packet incoming. xbee.readPacket(); if(xbee.getResponse().isAvailable()){ // Got something Serial.print("Got something\n"); // Break the 10-bits of information retrieved from light // and temperature into 2 bytes for each. values[0] = Temp >> 8 & 0xff; values[1] = Temp & 0xff; values[2] = Light >> 8 & 0xff; values[3] = Light & 0xff; Serial.print(values[0]); // Sending values to server xbee.send(tx); // After sending a tx request, we expect a status response // from the server // Wait up to 5 seconds for the status response if (xbee.readPacket(5000)) { // We got a response! Serial.print("We got a response\n"); // It should be a znet tx status if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) { xbee.getResponse().getZBTxStatusResponse(txStatus); // get the delivery status, the fifth byte if (txStatus.getStatus() == SUCCESS){ // Success! Time to celebrate Serial.print("SUCCESS! Time to celebrate\n"); } else { // The remote XBee did not receive our packet. Is it powered on? Serial.print("The remote Xbee did not receive our packet\n"); } } } else { // local XBee did not provide a timely TX Status Response -- should not happen Serial.print("Local Xbee did not provide a timely TX Status Response\n"); } } delay(500); }
Ce code fonctionne de la manière suivante:
Fonction setup():
Une fois implémenté sur le Arduino, la fonction setup va faire démarrer le protocole XBee et le protocole Série afin de pouvoir envoyer et recevoir des messages par XBee, et d'imprimer les messages d'erreur sur le port Série s'il y a lieu.
Fonction loop():
Cette fonction va réaliser une boucle toutes les 0.5s pour mettre a jour les données des différents capteurs et les envoyer au serveur au travers du protocole XBee. Pour plus de détails voir les commentaires expliquant chaque étape du déroulement de la boucle.
Le programme LINKER
Code du programme de liaison
ce programme en java est constitué de 5 classes
Le Main
public class main { public static SQLinker linker; public static Xbee xbee; public static void main(String[] args){ String address = new String("jdbc:mysql://sitedb.polytech-lille.net/cdelberg?"); String user = new String("user=cdelberg&password=myLo9ufonese"); String COM; // We ask the user on the Communication Port to connect the XBee System.out.println("Please enter the Communication port of the Xbee"); Scanner sc = new Scanner(System.in); COM = sc.next(); System.out.println("COM port changed to: "+COM); //Creation of the Variables that will be used to connect to the Database and the Xbee linker = new SQLinker(address, user); linker.FillArdList(); xbee = new Xbee(COM); //Creating the Updates Threads W8Thread thread1 = new W8Thread(); thread1.start(); UpTestThread thread2 = new UpTestThread(); thread2.start(); //We now allow the user to enter a command String command; System.out.println("vous pouvez maintenant lancer une commande si vous le souhaitez"); System.out.println("tapez help pour plus d'informations"); boolean exit=false; while(exit==false){ command=sc.next(); if(command.equals("help")){ System.out.println("print => affiche la liste des arduinos"); System.out.println("exit => ferme le programme"); } if(command.equals("print")){linker.PrintArdList();} if(command.equals("exit")){exit=true;} } //if the user ask to stop the program, it will do those final commands sc.close(); thread1.stop(); thread2.stop(); xbee.XbeeClosing(); //System.out.println("Program finished successfully"); } }
Le main est la racine du programme. Il va créer les ressources nécessaires pour la connexion à la base de donnée et au XBee lui même connecté au PC. Il crée ensuite 2 threads, l'un faisant une MAJ des valeurs des Arduinos dans la base de donnée à intervalles réguliers. L'autre regarde sur la base de donnée si un utilisateur a fait une demande de MAJ, et ce toute les secondes, puis y répond.
La classe SQLinker
public class SQLinker { Connection connect; Statement stmt; PreparedStatement pst; ResultSet rs; int[] ArdList = new int[10]; int[][] ArdListMatrix = new int[10][2]; String[] table = {"Battery", "Light", "Temperature", "Updating"}; //List of variables used to connect to the database and store some informations //Constructor, create a connection when called public SQLinker(String address, String user){ try{ Class.forName("com.mysql.jdbc.Driver").newInstance(); } catch(Exception ex){ System.out.println("can't register the Driver"); } try{ connect = DriverManager.getConnection(address+user); stmt = connect.createStatement(); } catch(Exception ex){ System.out.println("connection issue"); System.out.println("SQLException: " + ex.getMessage()); } if (connect!= null){ System.out.println("connected to the database " + address); } } //Fill a matrix with the list of Arduinos stored in the database public void FillArdList(){ try{ rs = stmt.executeQuery("SELECT Arduino FROM Arduinos"); int i=0; int m,c,d,u; while(rs.next()){ ArdList[i] = Integer.parseInt(rs.getString(1)); m=ArdList[i]/1000; c=(ArdList[i]-m*1000)/100; d=(ArdList[i]-m*1000-c*100)/10; u=(ArdList[i]-m*1000-c*100-d*10); ArdListMatrix[i][0]=(m*10+c); ArdListMatrix[i][1]=(d*10+u); i++; } ArdList[i]=-1; } catch (SQLException e){ System.out.println("SQLException: " + e.getMessage()); System.out.println("SQLState: " + e.getSQLState()); System.out.println("VendorError: " + e.getErrorCode()); } } //print the list of arduinos stored in the program public void PrintArdList(){ int i=0; while(ArdList[i]!=-1){ i++; System.out.println("Code Arduino n°"+i+": "+ArdList[i]); } } //Print the values of a specific arduino public void PrintArdValues(int ard){ for(int i=0; i<=2;i++){ try { rs = stmt.executeQuery("SELECT " +table[i]+" FROM Arduinos WHERE Arduino ="+ard); } catch (SQLException e) { e.printStackTrace(); } try { while(rs.next()){ System.out.println(table[i] +"=" + rs.getString(1)); } } catch (SQLException e) { e.printStackTrace(); } } } //print the values of every arduino stored in the program public void PrintAllArdValues(){ int i=0; while(ArdList[i]!=-1){ this.PrintArdValues(i); } } //set the values obtained from an arduino to the database public void SetArdValues(int Ard, int[] values){ int i=0; while(values[i]!=-1){ try { pst = connect.prepareStatement("UPDATE Arduinos SET "+table[values[i]]+" = "+values[i+1] +" WHERE Arduino ="+Ard); pst.executeUpdate(); } catch (SQLException e){ e.printStackTrace(); } i+=2; } } //verify if an update as been demanded by a user on the website public int CheckUpdate(){ int i=0; int ret=0; while(ArdList[i]!=-1 && ret!=1){ try { rs = stmt.executeQuery("SELECT Updating FROM Arduinos WHERE Arduino ="+ArdList[i]); while(rs.next()){ ret = Integer.parseInt(rs.getString(1)); } } catch (SQLException e) { e.printStackTrace(); } i++; } return ret; //return 1 if update demanded } }
Cette classe regroupe toutes les fonctions permettant de se connecter à une base de donnée et d'en traiter les données.