Go Down

Topic: Enregistrer sur mon disque les T° de 5 sondes DS18B20 (Read 6197 times) previous topic - next topic

zoroastre

#15
Mar 28, 2011, 01:06 pm Last Edit: Mar 28, 2011, 01:10 pm by zoroastre Reason: 1
Yep!

Chez moi ça marche impéccable avec le langage de programation Python, je peux enregistrer, lire, écrire des données provenant de l'Arduino. Et ensuite créer des graphs, les intégrer à mon site web, etc.

Il est vrai que le php semble poser des problèmes dans certaines situations. Mais d'autres y sont arrivés...

Pas besoin de matos supplémentaire, tu vois bien que la communication se fait bien entre le pc et l'arduino, il te manque juste l'interfaçe adequat.

En regardant en arrière, est tu sûr de "tty.usbmodem5d11" ???

@+

Zoroastre.
Gné! ;)

macbidule

#16
Mar 28, 2011, 04:53 pm Last Edit: Mar 28, 2011, 05:01 pm by macbidule Reason: 1
Yep! aussi !! et merci pour ton aide

Yep!

Chez moi ça marche impéccable avec le langage de programation Python, je peux enregistrer, lire, écrire des données provenant de l'Arduino. Et ensuite créer des graphs, les intégrer à mon site web, etc.

C'est précisément ce que souhaite faire, tu peux me décrire en quelques mots ta démarche (Au fait Mac ou PC ?).
[...]
Pas besoin de matos supplémentaire, tu vois bien que la communication se fait bien entre le pc et l'arduino, il te manque juste l'interfaçe adequat.[/quote]
Interface ?
Quote
En regardant en arrière, est tu sûr de "tty.usbmodem5d11" ???
@+
Zoroastre.

tty.usbmodem5d11 il s'agit du nom de l'interface visible dans le menu "TOOLS" d'Arduino pour choisir le port usb/serie. Ce nom appairerait automatiquement sur le mac lorsque l'on procède à l'installation du driver et quant on branche la carte. Comme les données transites correctement sur ce port, j'ai repris ce nom. (d'autant que celui indiqué dans le code php de base ne marche pas)

@+ macbidule

macbidule

#17
Mar 28, 2011, 05:00 pm Last Edit: Mar 28, 2011, 05:02 pm by macbidule Reason: 1
Merci pour ton aide aussi, vos messages m'encourage à poursuivre ...


Pourquoi n'utilise-tu pas Processing ? Tu peux communiquer avec Arduino dans les 2 sens, enregistrer sur ton disque, et même communiquer avec internet.
Alain.



Oui, cela fonctionne parfaitement.
A+

Tu peux m'indiquer en quelques mots, la démarche à suivre, peut être les bouts de code que tu utilises  :D

@+ macbidule


zoroastre

Yep!

Pour ma part, je travaille sous linux Debian ;)

Python + Python-serial, le code extremement simplifié pour lire des lignes provenant de l'arduino :

Code: [Select]
import serial

ser = serial.Serial('/dev/ttyUSB0',9600)

while 1:

    line = ser.readline()
    print line


Pour génerer les graphs, j'utilise GnuPlot. Je t'ai retrouvé le code de base qui pourrait te servir de referentiel.


Code: [Select]
# Access Arduino data from SheevaPlug
# Graph data and serve as web pages
#
# Copyright 2009 Ken Shirriff
# http://arcfn.com
import os
import serial
import threading
import time

from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler

GNUPLOT_CMD = """\
set xdata time
set format x "%m/%d"
set xtic 86400
set timefmt "%m/%d/%Y %H:%M"
set terminal png xeeeeee x000000 size 500, 500
set output 'graph.png'
set xlabel "Date"
set ylabel "Light"
set title "Illumination"
plot "/tmp/data" using 1:3 title "" with lines
"""

GRAPH_HTML = """<html>
<head>
<link rel="stylesheet" type="text/css" href="/plug.css">
<title>Graph of light in my room</title>
</head>
<body>
<h1>Graph of light in my room</h1>
The following data is obtained by a SheevaPlug accessing an Arduino.
<img src="/graph.png">
<br>
Note: the light is in arbitrary units 0-1023
<p>
For more details see <a href="http://arcfn.com">http://arcfn.com</a>.
</body>
</html>"""

# The web server.  Supports /graph (page containing the graph)
# and static web pages
class MyHandler(SimpleHTTPRequestHandler):
  def do_GET(self):
    if self.path == '/graph':
      return self.graph()
    # Static file
    return SimpleHTTPRequestHandler.do_GET(self)

  # Generate and display the graph
  def graph(self):
    g = os.popen('gnuplot', 'w')
    print >>g, GNUPLOT_CMD
    self.send_response(200)
    self.send_header('Content-type', 'text/html')
    self.end_headers()
    self.wfile.write(GRAPH_HTML)

# Read data from Arduino serial port a line at a time
# and dump to file with timestamps
class Arduino(threading.Thread):
  def run(self):
    f = open('/tmp/data', 'a')
    # Port may vary from /dev/ttyUSB1
    self.ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=10)
    self.ser.flushInput()
    old_timestamp = None
    while 1:
      data = self.ser.readline().strip()
      if data:
        timestamp = time.strftime("%m/%d/%Y %H:%M", time.localtime())
        if timestamp != old_timestamp:
        # Only log once per minute
            print >>f, timestamp, data.strip()
            old_timestamp = timestamp
            f.flush()

def main():
  ard = Arduino()
  ard.start()
  server = HTTPServer(('', 80), MyHandler)
  print 'Starting server'
  server.serve_forever()

if __name__ == '__main__':
  main()


Python n'est pas un langage difficile à apprehender.

@+

Zoroastre.
Gné! ;)

macbidule

#19
Mar 29, 2011, 01:29 am Last Edit: Mar 29, 2011, 01:39 am by macbidule Reason: 1
:D
Il y a du nouveau, c'est pas encore çà, mais j'avance
apprendre Python çà prend du temps. Je décris ma démarche, çà peut servir à d'autre
j'ai installé Python (la version 2.7), la dernière version n'est semble t'il pas compatible avec le module pyserial-2.4 (apparemment l'équivalent de Python-serial, ce dernier ne marchant pas pour mac osx)
Donc dans la fenêtre shell, en tapant le code ligne par ligne, que tu m'as indiqué
Code: [Select]
import serial

ser = serial.Serial('/dev/tty.usbmodem5d11',9600)

while 1:

   line = ser.readline()
   print line

Quote
tty.usbmodem5d11 étant la bonne adresse; ttyUSB0 correspondant à linux

et en ayant fermé Arduino (sinon il y a interférence), j'obtiens mes T°.
...
Je poursuis demain, il est tard

macbidule

zoroastre

#20
Mar 29, 2011, 05:32 am Last Edit: Mar 29, 2011, 05:56 am by zoroastre Reason: 1
Yep!

De mieux en mieux ;)

Sous Debian, j'utilise la version 2.6 de Python.

Imaginons que tu veuilles enregistrer tes données dans un fichier texte.


Code: [Select]
import serial

ser = serial.Serial('/dev/ttyUSB0',9600)

file = open('logs.txt', 'w')
file.write('date : xx/xx/20xx, begin : xxhxx, end :')
file.write('\n')
file.close()

while 1:

   line = ser.readline()

   print line
   
   a = open('logs.txt', 'a')
   a.write(line[:-2] + '\n')
   a.close()


Pour créer le fichier texte, on utilise l'option 'w' pour write, l'option 'a' quant à elle, correspond à append.
Pour insérer des lignes dans notre fichier log, on appelle la variable contenant le fichier et on utilise a.write(quelquechose).

Il est possible également d'adjoindre la date à tout cela grace à la bibliothèque time de python, quelques exemples de manipulations ici :

Code: [Select]
#! /usr/bin/env python
# -*- coding:iso-8859-1 -*-

import time

tic = time.time() + time.daylight*3600
tics = '\377' + str(tic)[0:10]

print time.time()
print time.daylight
print tic
print time.strftime("%d%b%Y", time.gmtime())
print time.strftime("%d %b %Y %H:%M |", time.gmtime())
print time.strftime("%d %b %Y %H:%M |", time.localtime())


Ainsi avant d'écrire ton enregistrement dans le fichier log (que tu peux renommer en fonction de la date, jour, semaine, mois,etc), tu peux y adjoindre la date comme ceci :

Code: [Select]
fichier = strftime("%d%b%Y", gmtime()) + '.txt'
logs = strftime("%d %b %Y %H:%M |", gmtime()) + line[:-2] + '\n'
enregistre(fichier, logs)


Avec une petite fonction 'enregistre' qui prend en arguments : (le_nom_du_fichier, le_log_formaté)

Code: [Select]
def enregistre(fichier, logs) :
   try :
file = open(fichier, 'a')
file.write(logs)
file.close()
   except :
       pass


Le code complet :

Code: [Select]
#! /usr/bin/env python
# -*- coding:iso-8859-1 -*-

import serial, time

is_serial = 0

def comm1() :
   if serial.Serial('com1', 9600) >= 1 :
  return serial.Serial('com1', 9600)
#er = serial.Serial('/dev/ttyUSB0',9600)
   else :
  is_serial = 1

def enregistre(fichier, logs) :
   try :
file = open(fichier, 'a')
file.write(logs)
file.close()
   except :
       pass

def update_time() :
   time.sleep(0.1)
   pic = time.time() + time.daylight*3600
   pics = '\377' + str(pic)[0:10]
   ser.write(pics)

def program() :
   while 1 :
       if is_serial == 1 :
           break;
       else :
           log = ser.readline()
           if log[0:6] == "MSG001" :
               update_time()
               time.sleep(0.1)
               log = log + '_GET ' + data1

           fichier = strftime("%d%b%Y", gmtime()) + '.txt'
           logs = strftime("%d %b %Y %H:%M |", gmtime()) + log + '\n'

           enregistre(fichier, logs)

ser = comm1()
update_time()
program()


Je ne m'en rappelle plus trop, mais ne tiens pas compte de la fonction update_time(), elle me servait si je ne me trompe à mettre à jour l'horloge (Biblio Time) de l'Arduino. Plus à jour d'ailleurs...

Je te laisse faire ta soupe ;)

Fais nous un petit retour pour la communauté !

@+

Zoroastre.
Gné! ;)

macbidule

Yep ! Aussi
bon je suis au travail, les pistes ouvertes fonctionnent, j'avance petit à petit, j'ai réussi à mettre en relation mon application domotique et la lecture des températures, il me reste encore des détails à résoudre.
Je me plonge dans l'apprentissage de python, (comment créer un application autonome, l'utilisation de python et sql) et je souhaite tester GnuPlot que tu mas présentés plus haut

Dès que j'aurais quelque chose de présentable, je reviens faire une synthèse... disons dans 3à4 jours

Merci pour ton aide zoroastre

macbidule

:)
Voilà j'ai fait une synthèse du résultat obtenu.

OBJECTIF RAPPEL :
Mise en place de 5 sondes de température DS18B20 sur MAC OSX10.6.7

Connecter la carte ARDUINO sur un port USB
Le mac construit automatique d'une nouvelle connexion.

Lancer ARDUINO
Sélectionner de type dev/tty.usbmodemfd1341 (le nom change en fonction de la prise usb utilisée) et la carte ARDUINO


Reprise du code de mise au point par PULSAR sur ce post http://arduino.cc/forum/index.php/topic,51062.0.html

SKETCH ARDUINO
Code: [Select]

#include <stdio.h>
#include <string.h>
#include <OneWire.h>

#define NBRE_CAPTEUR 5 // nombre de capteur sur l'arduino

// *********** declararation des variables gestion des capteurs de temperature  *******************
typedef struct Temperature Temperature;
struct Temperature
{
 float valeur; // temperature en Celsius, 1 chiffre apres la virgule
 byte addr[8]; // identifiant capteur
 int pin; // numero de pin a utiliser
 char mnemo[32]; // mnemonique de la variable
};

Temperature temperature[NBRE_CAPTEUR]; //creation des instances

// *********** fin declararation des variables gestion des capteurs de temperature  *******************


void setup(){

 Serial.begin(9600); // initialisation de la liaison serie


 // *********** initialisation des variables gestion des capteurs de temperature  *******************

 temperature[0].addr[0]=       0x28; //  capteur D1 Bureau
 temperature[0].addr[1]= 0x33;
 temperature[0].addr[2]= 0x75;
 temperature[0].addr[3]= 0xAB;
 temperature[0].addr[4]= 0x2;
 temperature[0].addr[5]= 0x0;
 temperature[0].addr[6]= 0x0;
 temperature[0].addr[7]= 0x67;
 temperature[0].pin=9;
 temperature[0].valeur=0; // temperature en C, 1 chiffre apres la virgule
 strcpy(temperature[0].mnemo,"D1 Bureau"); // ex: salon
 
 
temperature[1].addr[0]=       0x28; //  capteur D2 Exterieur
 temperature[1].addr[1]= 0x20;
 temperature[1].addr[2]= 0x4B;
 temperature[1].addr[3]= 0xAB;
 temperature[1].addr[4]= 0x2;
 temperature[1].addr[5]= 0x0;
 temperature[1].addr[6]= 0x0;
 temperature[1].addr[7]= 0x43;
 temperature[1].pin=9;
 temperature[1].valeur=1; // temperature en C, 1 chiffre apres la virgule
 strcpy(temperature[1].mnemo,"D2 Exterieur"); // ex: salon
 
 
temperature[2].addr[0]=       0x28; //  capteur D3 KL
 temperature[2].addr[1]= 0x3D;
 temperature[2].addr[2]= 0x63;
 temperature[2].addr[3]= 0xAB;
 temperature[2].addr[4]= 0x2;
 temperature[2].addr[5]= 0x0;
 temperature[2].addr[6]= 0x0;
 temperature[2].addr[7]= 0x94;
 temperature[2].pin=9;
 temperature[2].valeur=2; // temperature en C, 1 chiffre apres la virgule
 strcpy(temperature[2].mnemo,"D3 KL"); // ex: salon
 
 
temperature[3].addr[0]=       0x28; //  capteur D4 Matt
 temperature[3].addr[1]= 0x93;
 temperature[3].addr[2]= 0x51;
 temperature[3].addr[3]= 0xAB;
 temperature[3].addr[4]= 0x2;
 temperature[3].addr[5]= 0x0;
 temperature[3].addr[6]= 0x0;
 temperature[3].addr[7]= 0xDC;
 temperature[3].pin=9;
 temperature[3].valeur=3; // temperature en C, 1 chiffre apres la virgule
 strcpy(temperature[3].mnemo,"D4 Matt"); // ex: salon
 
 
 temperature[4].addr[0]=       0x28; //  capteur D5 Salon
 temperature[4].addr[1]= 0x34;
 temperature[4].addr[2]= 0x32;
 temperature[4].addr[3]= 0x85;
 temperature[4].addr[4]= 0x2;
 temperature[4].addr[5]= 0x0;
 temperature[4].addr[6]= 0x0;
 temperature[4].addr[7]= 0x3F;
 temperature[4].pin=9;
 temperature[4].valeur=4; // temperature en C, 1 chiffre apres la virgule
 strcpy(temperature[4].mnemo,"D5 Salon"); // ex: salon



}


void loop(){


 gestion_temperature();

 delay(5000);

}


void gestion_temperature()
{

 /********************************************************************************
  * Cette fonction permet d'interroger tous les capteurs de temperature OneWire
  * qui ont ete declare dans "temperature[i]"
  ********************************************************************************/

 byte i=0;
   Serial.println("#");
 for(i=0; i<NBRE_CAPTEUR; i++){


   temperature[i].valeur =getStuff(temperature[i].addr,temperature[i].pin);

   Serial.print(temperature[i].valeur);
   Serial.print(":");
   delay(100);

 }
 Serial.println("$");
}


float getStuff(byte addr[8], int pin) // indiquer le n° de pin à utiliser
{

 /********************************************************************************
  * Cette fonction permet d'interroger le capteur de temperature OneWire
  * qui a été déclaré dans "temperature[i]"
  ********************************************************************************/

 OneWire  ds(pin);  // creation d'un objet OneWire avec le bon numéro de pin

   byte i;
 byte present = 0;
 byte data[12];

 float real_temp;
 float temp_count;
 float read_temp;

 // Fonction recherche désactivée car non utilisée
 /*if ( !ds.search(addr)) {
  Serial.print("No more addresses.\n");
  ds.reset_search();
  }
 
 
  Serial.print("R=");
  for( i = 0; i < 8; i++) {
  Serial.print(addr[i], HEX);
  Serial.print(" ");
  }
 
  if ( OneWire::crc8( addr, 7) != addr[7]) {
  Serial.print("CRC is not valid!\n");
  return 998;
  }
 
  if ( addr[0] != 0x10) {
  Serial.print("Device is not a DS18S20 family device.\n");
  return 999;
  }
  */
 ds.reset();
 ds.select(addr);
 ds.write(0x44,1); // start conversion, with parasite power off at the end (1=parasite mode)

 delay(1000);     // delay de 1s si mode parasite. 100ms en mode normal
 // we might do a ds.depower() here, but the reset will take care of it.

 present = ds.reset();
 ds.select(addr);    
 ds.write(0xBE);         // Read Scratchpad


 for ( i = 0; i < 9; i++) {           // we need 9 bytes
   data[i] = ds.read();
 }

 read_temp=((data[1]<<8) | data[0]) >> 1 ;            // Divide the temperature by 2
 temp_count=float(data[7] - data[6])/(float)data[7];  // Convert to real temperature
 real_temp = ((float)read_temp-0.25)+temp_count;


 // arrondi 1 chiffre apres la virgule
 int temp = real_temp*1;
 real_temp = (float)temp/10;

 return real_temp;

}



macbidule

SUITE ...

RESULTAT:


Voilà le résultat  - Enjoy !!!

Encore faut il les exploiter
Avec l'aide de INDISPENSABLE de ZOROASTRE (merci à toi)
je me suis lancer dans Python (pas sans mal !!!)
Mon objectif :
création de deux fichiers :
Temps.txt (fichier inscrivant le dernier relevé de température générer toutes les minutes par la carte)
et
TempsData.txt (fichier inscrivant le fil complet des données pour établir des courbes dans le temps et rajoutant l'heure - Fréquence 10mn )

J'ai choisi de border mes données par # en entrée et $ en sortie pour permettre leurs traitements dans mes applications suivantes.

le code Python
Code: [Select]

#! /usr/bin/env python
# -*- coding:iso-8859-1 -*-
import serial
import time
tic = time.time() + time.daylight*3600
tics = '\377' + str(tic)[0:10]
#print time.time()
#print tic

ser = serial.Serial('/dev/tty.usbmodemfd1341',9600)
nb=1
j=1
file = open('TempsData.txt', 'w') #Deuxieme fichier en continu

while 1:
   i=1
   while i <6 :
       line = ser.readline()
       if (line[0:1] ==  "#") or (line[0:1] ==  "$"):
           continue
       else :
           #premier fichier en ecriture par ligne
           file = open('Temps.txt', 'w')
           #print line
           a = open('Temps.txt', 'a')
           a.write(line[:-2] + '\n')
           a.close()
           #Deuxieme fichier en ecriture en continu avec dates et heures
           if (j<60):
               #print j
               j+=1
               continue
           else :
               b = open('TempsData.txt', 'a')
               b.write(repr(time.time()) +":"+ repr(nb) +":"+ line[:-2] + '\n')
               #print (repr(time.time()) +":"+ repr(nb) +":"+ line[:-2] + '\n')
               j=1                
       i+=1
       nb+=1
b.close() #Deuxieme fichier en continu


Les données étant sur le mac, deux usages
- Application domestique INDIGO de …..
Dans cette application on peut utiliser  applescript pour aller un peut plus loin dans les scénarios

Code applescript pour lire les données dans mon fichier "Temps.txt " toutes les minutes
Code: [Select]

set releve to "Temps.txt"
open for access releve
set Tvaleur to (read releve as list using delimiter ":")
close access releve

set T1 to item 1 of Tvaleur
set T2 to item 2 of Tvaleur
set T3 to item 3 of Tvaleur
set T4 to item 4 of Tvaleur
set T5 to item 5 of Tvaleur

tell application "IndigoServer"
    set the value of variable "TempBureau" to T1
    set the value of variable "TempExt" to T2
    set the value of variable "TempKL" to T3
    set the value of variable "TempMatt" to T4
    set the value of variable "TempSalon" to T5
end tell


Résultat en image
Page de contrôle principale


Dans le détail d'une sonde (ici 21,1°)


Le deuxième fichier TempsData.txt  me permet d'afficher une courbe des températures (il reste des trucs à mettre au point) dans une page html
(j'utilise pour ce faire jpgraph)



Voilà
XD


Il me reste à développer pour avoir plusieurs courbes
1 sur 24h, une sur une semaine et unes sur la saison de chauffe






zoroastre

Yep!

Beau résultat !
Je trouve ta page de contrôle trés bien pensé, bravo ;)

Je me demande de plus en plus si on ne devrait pas créer un site dédié domotique, tant cette technicité me semble avoir de l'avenir...

@+

Zoroastre.
Gné! ;)

zoroastre

Yep!

Si tu es embêté avec tes ports usb qui changent tout le temps, tu peux ajouter à ton script quelque-chose comme çà :

Code: [Select]
locations=['/dev/ttyUSB0','/dev/ttyUSB1','/dev/ttyUSB2','/dev/ttyUSB3',
'/dev/ttyS0','/dev/ttyS1','/dev/ttyS2','/dev/ttyS3']

for device in locations:
    try:
  print "Trying...",device
  arduino = serial.Serial(device, 9600)
  break
    except:
  print "Failed to connect on",device


;)

@+

Zoroastre.
Gné! ;)

chicotore

Belle interface  ;) En regroupant tout nos travaux on pourrais vraiment arriver a faire une belle interface et un programme bien pensé spécial domotique ....  :)
Mon Blog sur l'environnement Arduino ... Tutos fait par un débutant pour les débutants ^^

http://chicowebsite.free.fr/

bobbyscip



Donc dans la fenêtre shell, en tapant le code ligne par ligne, que tu m'as indiqué
Code: [Select]
import serial

ser = serial.Serial('/dev/tty.usbmodem5d11',9600)

while 1:

   line = ser.readline()
   print line

Quote
tty.usbmodem5d11 étant la bonne adresse; ttyUSB0 correspondant à linux

et en ayant fermé Arduino (sinon il y a interférence), j'obtiens mes T°.
...
Je poursuis demain, il est tard

macbidule


Quesion, comment tu fais pour afficher ta fenêtre de valeur??

fdufnews

Quote
comment tu fais pour afficher ta fenêtre de valeur??

Il est dans une fenêtre shell donc le texte s'affiche dans la fenêtre en question.
C'est du python, par défaut il s'exécute en mode texte dans un terminal (sous Linux/Mac OS X) et une fenêtre commande (si tu es sous Windows "menu demarrer/executer cmd")
Si tu veux avoir une fenêtre graphique il faut utiliser  par exemple Tkinter.


Go Up