Objets communiquants et gestion de l'énergie : Différence entre versions

De Wiki de Projets IMA
(Le code du Arduino)
(Le code du Arduino)
 
(6 révisions intermédiaires par 2 utilisateurs non affichées)
Ligne 102 : Ligne 102 :
 
*Un capteur de température
 
*Un capteur de température
 
*Un capteur de luminosité
 
*Un capteur de luminosité
*Un accéléromètre (dont les valeurs ne seront pas utilisées mais qui devait servir d'appareil supplémentaire pour la problématique de consommation)
 
  
 
====Le code du Arduino====
 
====Le code du Arduino====
Ligne 114 : Ligne 113 :
 
  int sensorLightPin = 1;
 
  int sensorLightPin = 1;
 
  int Light;
 
  int Light;
int XPin = 2;
 
int YPin = 3;
 
int ZPin = 4;
 
int XValue;
 
int YValue;
 
int ZValue;
 
 
   
 
   
 
  uint8_t values[] = { 0, 0, 0, 0 };
 
  uint8_t values[] = { 0, 0, 0, 0 };
Ligne 140 : 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);
  XValue = <span style="color: purple;">analogRead</span>(XPin);
 
  YValue = <span style="color: purple;">analogRead</span>(YPin);
 
  ZValue = <span style="color: purple;">analogRead</span>(ZPin);
 
 
   
 
   
 
   <span style="color: red;">// Listens on the Xbee protocol for any packet incoming.</span>
 
   <span style="color: red;">// Listens on the Xbee protocol for any packet incoming.</span>
Ligne 196 : Ligne 186 :
 
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.
 
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>():=====
 
=====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.
+
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===
+
===Le programme LINKER===
  
 
Code du programme de liaison
 
Code du programme de liaison
Ligne 263 : Ligne 253 :
 
   
 
   
 
</code>
 
</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.

http://www.metro.co.uk/tech/news/897731-technology-companies-charge-towards-next-generation-battery-future


  • 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.

Liste du matériel à acheter