Go Down

Topic: Brancher plusieurs ds1820 (Read 5287 times) previous topic - next topic

Jean-François

Apr 25, 2008, 08:43 am Last Edit: Apr 25, 2008, 08:43 am by jfs Reason: 1
Bonjour,

Est-il possible de brancher plusieurs capteurs de températures DS1820 sur le même pin ?

Si cela est possible, comment peut-on savoir duquel vient l'information ?

De quelle façon faut-il les brancher, j'ai vu plusieurs façon dont une dites "parasite" ?
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Skall

selon moi, tu peux brancher plusieurs DS1820 sur une meme fil, ils sont meme faits pour ca...

d'apres la datasheet http://www.ortodoxism.ro/datasheets/maxim/DS1820-DS1820S.pdf, c'est du 1-Wire donc il te faut implementer ce protocole par l'arduino.

Pour les differencier, chaque DS1820 possede un identifiant unique sur 64 bits.

Au demarrage, l'arduino doit decouvrir tous les codes des devices presents sur le bus 1-Wire

extrait de la datasheet :
Quote
SEARCH ROM [F0h]
When a system is initially powered up, the master must identify the ROM codes of all slave devices on
the bus, which allows the master to determine the number of slaves and their device types. The master
learns the ROM codes through a process of elimination that requires the master to perform a Search ROM
cycle (i.e., Search ROM command followed by data exchange) as many times as necessary to identify all
of the slave devices. If there is only one slave on the bus, the simpler Read ROM command (see below)
can be used in place of the Search ROM process. For a detailed explanation of the Search ROM
procedure, refer to the iButton Book of Standards at www.ibutton.com/ibuttons/standard.pdf. After every
Search ROM cycle, the bus master must return to Step 1 (Initialization) in the transaction sequence.


le protocole 1-Wire a surement deja été implementé pour l'arduino par qqun...

Jean-François

Ce que j'ai trouvé sur la datasheet pour les branchement :







Donc ça devrait permettre de faire ça ?  




La façon dont les flux d'informations passent :



MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

Traduit par Google, voici le protocole pour la recherche du "ROM", je supose que c'est le code d'identification de chaque capteur ?

[edit]Exemple d'une ROM de recherche
Le ROM processus de recherche est la répétition d'une simple
3-pas de routine: lire un peu, lire le complément du
bit, puis écrire la valeur désirée que de peu. Le bus maître
s'acquitte de cette simple, 3 étapes de routine sur chaque bit de
la ROM. Après une passe complète, le bus maître
connaît le contenu de la ROM en un seul dispositif. Le
restants nombre de dispositifs et de leurs codes mai ROM
être identifiés par des laissez-passer.
L'exemple suivant de la mémoire morte processus de recherche
suppose quatre différents périphériques sont connectés à la
même 1-Wire bus. Le ROM de données des quatre dispositifs
comme le montre:
Rom1 00110101 ...
ROM2 10101010 ...
ROM3 11110101 ...
ROM4 00010001 ...
Le processus de recherche est la suivante:

1. Le bus maître commence la séquence d'initialisation par
une émission d'impulsions de réinitialisation. L'esclave dispositifs de répondre par
la délivrance de présence simultanée des impulsions.

2. Le bus master va alors délivrer la recherche ROM
commande le 1-Wire bus.

3. Le bus maître lit un peu à partir du 1-Wire bus.
Chaque appareil répondre en mettant la valeur du
premier bit de leur ROM de données sur le 1-Wire
bus. Rom1 et ROM4 mettra un 0 sur la
1-Wire bus, c'est-à-dire, tirez-le vers le bas. ROM2 et sera ROM3
1 un lieu sur le 1-Wire bus en permettant à la ligne
restent élevés. Le résultat est la conséquence logique et de tous les dispositifs
sur la ligne, donc le bus maître voit un 0. Le
Bus Master peu un autre lit. Depuis la Recherche
ROM de données de commande est en cours d'exécution, tous les
dispositifs sur le 1-Wire bus répondre à cette deuxième
lire en plaçant le complément de la première peu de leur
ROM de données respectives sur le 1-Wire bus. Rom1
ROM4 et mettra un 1 sur le 1-Wire, ce qui permet
la ligne à rester élevés. ROM2 et ROM3 mettra un
0 sur le 1-Wire, ainsi il sera tiré faible. Le bus
capitaine observe à nouveau un 0 pour le complément de la
ROM premier bit de données. Le bus capitaine a déterminé
qu'il existe des dispositifs sur le 1-Wire bus qui
ont un 0 dans la première position et d'autres qui ont un 1.
DS1820
021497 11/27
Les données obtenues de ces deux lectures de l'étape 3 -
de routine sont les suivantes interprétations:
00 Il ya encore des dispositifs qui ont
conflit bits dans cette position.
01 Tous les dispositifs à couplage ont encore un 0-bit dans ce
bit.
10 Tous les dispositifs à couplage ont encore un 1-bit en ce
bit.
11 Il n'existe pas de dispositifs pour le 1-Wire
bus.

4. Le bus maître écrit un 0. Cette désactive ROM2
ROM3 et pour le reste de cette recherche passe,
ne laissant que Rom1 et ROM4 liés à la
1-Wire bus.

5. Le bus maître effectue deux autres lectures et
reçoit un 0-bit suivi par un 1-bit. Cela indique
que tous les appareils encore couplé à l'autobus ont aussi 0
leur deuxième ROM bits de données.

6. Le bus capitaine a ensuite écrit un 0 à conserver les deux Rom1
ROM4 et couplés.

7. Le bus maître exécute deux lit et reçoit
0-deux bits. Cela indique que les deux 1-bits et 0-bits
exister en tant que troisième bit de la mémoire morte de données ci-joint
dispositifs.

8. Le bus maître écrit un 0-bit. Cette désactive Rom1
ROM4 laissant que le seul appareil toujours branché.

9. Le bus maître lit le reste de la ROM bits
pour ROM4 et continue à accéder à la partie si
désirée. Ceci termine la première passe et unique
identifie une partie de la 1-Wire bus.

10.Le bus maître débute une nouvelle séquence de recherche ROM
en répétant les étapes 1 à 7.

11. Le bus maître écrit un 1-bit. Cette dissocie
ROM4, ne laissant que Rom1 toujours de pair.

12.Le bus maître lit le reste de la ROM bits
pour Rom1 et communique à la logique sous-jacente
si vous le souhaitez. Ceci termine la deuxième ROM de recherche
passer, dans lequel un autre de la ROM a été trouvé.

13.The bus maître débute une nouvelle ROM de recherche en répétant
les étapes 1 à 3.

14.The Bus Master écrit un 1-bit. Cette désélectionne
Rom1 et ROM4 pour le reste de cette recherche
passer, ne laissant que ROM2 et ROM3 attelé à la
système.

15.Le Bus Master lire exécute deux créneaux horaires et
reçoit deux zéros.

16.The Bus Master écrit un 0-bit. Cette dissocie
ROM3, et ne laissant que ROM2.

17.The Bus Master lit le reste de la ROM bits
pour ROM2 et communique à la logique sous-jacente
si vous le souhaitez. Ceci termine la troisième ROM de recherche
passer, dans lequel un autre de la ROM a été trouvé.

18.The bus maître débute une nouvelle ROM de recherche en répétant
les étapes 13 à 15.

19.The Bus Master écrit un 1-bit. Cette dissocie
ROM2, ne laissant que ROM3.

20.The Bus Master lit le reste de la ROM bits
pour ROM3 et communique à la logique sous-jacente
si vous le souhaitez. Ceci termine la quatrième ROM de recherche
passer, dans lequel un autre de la ROM a été trouvé.
Notez les aspects suivants:
Le bus maître apprend le numéro d'identification unique (ROM de données
modèle) d'un 1-Wire sur chaque appareil ROM Recherche
. Le temps requis pour tirer partie de l'unique
Code de la ROM est:
960 ms + (8 + 3 x 64) 61 ms = 13,16 ms
Le bus master est donc en mesure d'identifier 75 différents
1-Wire dispositifs par seconde.[/edit]
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

Apparement en suivant l'adresse mentionnée, le fichier sample.c serait celui à mettre dans l'arduino :

Quote
All packaged in C++ form. Well, not the keywords.txt file. I'm not sure what that is, though I guess it has something to do with the color coding of the build in editor.

http://www.federated.com/~jim/onewire/ contains the library and a sample program. Feel free to vacuum it up into anything you like.

This library is general 1-wire. It might be nice to derive a DS18S20 class from this that knows about temperature to handle the conversions, or that might start making too much object code. Maybe I'm being too sensitive to code bloat, but it seems that higher level libraries will end up containing a lot of unused functions for any given application. e.g. I won't use the alarm threshold registers in my application but I'd end up with functions for them linked into my code. I had enough worry about that in just the generic functions that I ended up with a couple nasty preprocessor symbols to omit some of the larger functions that people might not need.


Pour suivre ce fil de discussion:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1161557194/30
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

#5
Apr 26, 2008, 07:56 am Last Edit: Apr 26, 2008, 08:46 am by jfs Reason: 1
J'ai branché deux ds18B20 sur mon arduino comme indiqué plus haut, et j'ai mis le sketch"sample.c".

la console série me sort ceci :



Le problème est que le capteur n'est pas reconnu comme un DS1820 :

Quote
does any one know if this works with the  DS18B20...

I have it hooked up per everything I have found here, in parasite mode, and all get is this
Code: [Select]
R=28 92 F1 7D 1 0 0 34 Device is not a DS18S20 family device

any ideas?



Solutions :

Quote
Yes I ran into that too, as I reported elsewhere - the family code for the 18B20 is different from that for the 18S20.   (There's a note one the Arduino OneWire page that mentions this.) Just replace the family code in the test (0x28) with the one for the 18B20 (0x10).  For the record, the DS1822 thermometer has yet another family code (0x22).


J'ai donc changé le 0x10 par 0x28 et maintenant j'ai ça :




Ce sketch semble servir à determiner les N° ROM des capteurs.

Je ne sais pas à quoi correspondent "P" et "CRC".

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

#6
Apr 26, 2008, 10:30 am Last Edit: Apr 26, 2008, 06:03 pm by jfs Reason: 1
"P" serait le Scratchpad du DS1820 et "CRC" un contrôle pour voir si la mesure renvoyée est correcte (?)...


Le Scratchpad pour le DS18B20 est composé comme cela :




Donc dans la console série ce serait ça :



Je peux retirer ces deux Bytes de la chaine en utilisant data[0] et data[1].
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

#7
Apr 26, 2008, 06:08 pm Last Edit: Apr 26, 2008, 07:06 pm by jfs Reason: 1
Actuellement je n'arrive pas à convertir ces deux Bytes en °C , il me semblait qu'en additionnant LSB à MSB et en les affichant en décimal j'aurais un affichage correct de la température, mais je me retrouve avec "120" pour 23,3 °Celcius.


J'ai trouvé un code qui semble afficher des °C et °F :

http://www.netfluvia.org/code/ds18B20_test.pde

Voici l'extrait qui m'intéresse :

Code: [Select]
/* compute the degrees in celcius / integer part */
 temp_c_int = 0;
 
 /* The measured temp is spread across two bytes of the returned data.
  *  The integer part of the temp value is spread across the least 3 significant
  *  bits of the most significant byte (MSB) and the most significant 4 of
  *  the LSB.  Here we shift those 7 bits into their proper place in our
  *  result byte.
  *
  * note: could do this with 2 bit-shift / mask operations, alternatively
  */
 set_bit = 6;
 for (test_bit = 2; test_bit >= 0; test_bit--) {
   temp_c_int |= ( ((data[TEMP_MSB] & (1 << test_bit)) >> test_bit) << set_bit );
   set_bit--;
 }
 for (test_bit = 7; test_bit >= 4; test_bit--) {
   temp_c_int |= ( ((data[TEMP_LSB] & (1 << test_bit)) >> test_bit) << set_bit );
   set_bit--;
 }

#ifdef DEBUG
 Serial.print(temp_c_int,DEC);
#endif

 /* compute the fractional part */

 /*  first figure out what resolution we're measuring in - varies between 1 and 4 bits
  *    after the decimal (based on the contents of the CONFIG_REG byte):
  *        bit 6 == 0 && bit 5 == 0 --> 9-bit resolution (ignore 3 least sig bits)
  *        bit 6 == 0 && bit 5 == 1 --> 10-bit resolution (ignore 2 least sig bits)
  *        bit 6 == 1 && bit 5 == 0 --> 11-bit resolution (ignore 1 least sig bits)
  *        bit 6 == 1 && bit 5 == 1 --> 12-bit resolution  
  */
 if ((data[CONFIG_REG] & (1 << 5)) > 0) {        
   if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 and 5 are set
     resolution_floor = 3;
   } else {                                      // bit 6 is set, 5 is clear
     resolution_floor = 2;
   }
 } else {
   if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 is clear, 5 is set
     resolution_floor = 1;
   } else {                                      // bit 6 and 5 are clear
     resolution_floor = 0;
   }
 }    

 temp_c_frac = 0;
 for (test_bit = 3; test_bit >= resolution_floor; test_bit--) {
   if ((data[TEMP_LSB] & (1 << test_bit)) > 0) {
     expon = test_bit - 4; // will be negative
     temp_c_frac += pow(2,expon);
   }
 }
#ifdef DEBUG
 Serial.print(" ");
 Serial.print(temp_c_frac * 10000,DEC);
#endif

 /* put it all together */
 temp_c = (float)temp_c_int + temp_c_frac;  

 if ((data[TEMP_MSB] & (1 << 7)) > 0) {   // the temp is negative
   temp_c *= -1;
 }

 temp_f = c2f(temp_c);
 
 Serial.print(" Cx10k=");
 Serial.print(temp_c * 10000,DEC); // Serial.print truncates after the decimal pt
 Serial.print(" Fx10k=");
 Serial.print(temp_f * 10000,DEC);
 
 Serial.print("\n");  
}
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

#8
Apr 26, 2008, 07:38 pm Last Edit: Apr 27, 2008, 08:33 am by jfs Reason: 1
J'ai rajouté ça dans Sample.c en enlevant les parties qui ne m'intéressaient pas :

Code: [Select]
#include <OneWire.h>

/* DS18S20 Celcius degrees */


#define TEMP_LSB 0
#define TEMP_MSB 1
#define CONFIG_REG 4

OneWire  ds(10);  // on pin 10

void setup(void) {

 Serial.begin(9600);
}

void loop(void) {
 
 byte i;
 byte data[12];
 byte addr[8];
 byte present = 0;
 
 int set_bit;
 int resolution_floor;
 int msb,lsb,T;
 int temp_c_int;
 int test_bit;
 
 float expon;
 float temp_c_frac;
 float temp_c;
 float temp_f;
 
 if ( !ds.search(addr)) {
     Serial.print("No more addresses.\n");
     ds.reset_search();
     return;
 }
 
 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;
 }
 
 if ( addr[0] != 0x28) {
     Serial.print("Device is not a DS18B20 family device.\n");
     return;
 }

 ds.reset();
 ds.select(addr);
 ds.write(0x44,1);         // start conversion, with parasite power on at the end
 
 delay(1000);     // maybe 750ms is enough, maybe not
 // 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();
}

  /* compute the degrees in celcius / integer part */
 
 /* The measured temp is spread across two bytes of the returned data.
  *  The integer part of the temp value is spread across the least 3 significant
  *  bits of the most significant byte (MSB) and the most significant 4 of
  *  the LSB.  Here we shift those 7 bits into their proper place in our
  *  result byte.
  *
  * note: could do this with 2 bit-shift / mask operations, alternatively
  */
   temp_c_int = 0;
   set_bit = 6;
for (test_bit = 2; test_bit >= 0; test_bit--) {
   temp_c_int |= ( ((data[TEMP_MSB] & (1 << test_bit)) >> test_bit) << set_bit );
   set_bit--;
}
for (test_bit = 7; test_bit >= 4; test_bit--) {
   temp_c_int |= ( ((data[TEMP_LSB] & (1 << test_bit)) >> test_bit) << set_bit );
   set_bit--;
}

 /* compute the fractional part */

 /*  first figure out what resolution we're measuring in - varies between 1 and 4 bits
  *    after the decimal (based on the contents of the CONFIG_REG byte):
  *        bit 6 == 0 && bit 5 == 0 --> 9-bit resolution (ignore 3 least sig bits)
  *        bit 6 == 0 && bit 5 == 1 --> 10-bit resolution (ignore 2 least sig bits)
  *        bit 6 == 1 && bit 5 == 0 --> 11-bit resolution (ignore 1 least sig bits)
  *        bit 6 == 1 && bit 5 == 1 --> 12-bit resolution  
  */
if ((data[CONFIG_REG] & (1 << 5)) > 0) {        
 if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 and 5 are set
     resolution_floor = 3;
   } else {                                      // bit 6 is set, 5 is clear
     resolution_floor = 2;
   }
   } else {
   if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 is clear, 5 is set
     resolution_floor = 1;
   } else {                                      // bit 6 and 5 are clear
     resolution_floor = 0;
   }
}    

 temp_c_frac = 0;
for (test_bit = 3; test_bit >= resolution_floor; test_bit--) {
   if ((data[TEMP_LSB] & (1 << test_bit)) > 0) {
     expon = test_bit - 4; // will be negative
     temp_c_frac += pow(2,expon);
   }
}

 /* put it all together */
 temp_c = (float)temp_c_int + temp_c_frac;  

if ((data[TEMP_MSB] & (1 << 7)) > 0) {   // the temp is negative
   temp_c *= -1;
}
 
 
 Serial.print("   Temp en C= ");
 Serial.print(temp_c_int,DEC);
 Serial.print(".");
 Serial.print(temp_c_frac * 100,DEC);
 Serial.println();  
}


A la console série :




La mesure est au demi degrés près.
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Jean-François

#9
Apr 27, 2008, 09:00 am Last Edit: Apr 27, 2008, 09:02 am by jfs Reason: 1
Cette partie de code sert à déterminer la résolution des capteurs, je l'ai supprimée :

Code: [Select]
 /* compute the fractional part */

 /*  first figure out what resolution we're measuring in - varies between 1 and 4 bits
  *    after the decimal (based on the contents of the CONFIG_REG byte):
  *        bit 6 == 0 && bit 5 == 0 --> 9-bit resolution (ignore 3 least sig bits)
  *        bit 6 == 0 && bit 5 == 1 --> 10-bit resolution (ignore 2 least sig bits)
  *        bit 6 == 1 && bit 5 == 0 --> 11-bit resolution (ignore 1 least sig bits)
  *        bit 6 == 1 && bit 5 == 1 --> 12-bit resolution  
 
if ((data[CONFIG_REG] & (1 << 5)) > 0) {        
 if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 and 5 are set
     resolution_floor = 3;
   } else {                                      // bit 6 is set, 5 is clear
     resolution_floor = 2;
   }
   } else {
   if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 is clear, 5 is set
     resolution_floor = 1;
   } else {                                      // bit 6 and 5 are clear
     resolution_floor = 0;
   }
}  




J'ai modifié ça :

Code: [Select]
 int resolution_floor = 1;   //for setting resolution 0 = High-resolution , 3 = Low resolution

Si "resolution_floor" est mis à 3, la résolution est basse, si il est mis à 0 elle devient élevée (permet l'utilisation des chiffres après la virgule, ici 3 chiffres) .


Et j'ai enlevé également ça qui ne sert plus :

Code: [Select]
#define CONFIG_REG 4


Il faut encore multiplier la fraction pour le nombre de chiffres à afficher après la virgule :

Code: [Select]
Serial.print(temp_c_frac * 1000,DEC);

A la console série :

MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Bonjour,

peux-tu nous fournir le contenu du fichier Sample.c que tu as après modification/amelioration ?

je vais démarrer des tests avec mes capteurs très bientot.

merci...

Gromain
"pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires..."

projet domotique xPLDuino
IRC: freenode #xplduino

Jean-François

#11
Feb 13, 2009, 12:43 pm Last Edit: Feb 13, 2009, 12:52 pm by jfs Reason: 1
Voici le code Sample.c :

Code: [Select]
#include <OneWire.h>

/* DS18S20 Temperature chip i/o

*/

OneWire  ds(10);  // on pin 10

void setup(void) {
 // initialize inputs/outputs
 // start serial port
 Serial.begin(9600);
}



void loop(void) {
 byte i;
 byte present = 0;
 byte data[12];
 byte addr[8];
 
 if ( !ds.search(addr)) {
     Serial.print("No more addresses.\n");
     ds.reset_search();
     return;
 }
 
 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;
 }
 
 if ( addr[0] != 0x10) {
     Serial.print("Device is not a DS18S20 family device.\n");
     return;
 }

 ds.reset();
 ds.select(addr);
 ds.write(0x44,1);         // start conversion, with parasite power on at the end
 
 delay(1000);     // maybe 750ms is enough, maybe not
 // 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

 Serial.print("P=");
 Serial.print(present,HEX);
 Serial.print(" ");
 for ( i = 0; i < 9; i++) {           // we need 9 bytes
   data[i] = ds.read();
   Serial.print(data[i], HEX);
   Serial.print(" ");
 }
 Serial.print(" CRC=");
 Serial.print( OneWire::crc8( data, 8), HEX);
 Serial.println();
}


et le code Celsius_18b20.pde :

Code: [Select]
#include <OneWire.h>

/* DS18S20 Celcius degrees */


#define TEMP_LSB 0
#define TEMP_MSB 1
//#define CONFIG_REG 4

OneWire  ds(10);  // on pin 10

void setup(void) {

 Serial.begin(9600);
}

void loop(void) {
 
 byte i;
 byte data[12];
 byte addr[8];
 byte present = 0;
 
 int set_bit;
 int resolution_floor = 1;   //for setting resolution 0 = High-resolution , 3 = Low resolution
 int msb,lsb,T;
 int temp_c_int;
 int test_bit;
 
 float expon;
 float temp_c_frac;
 float temp_c;
 float temp_f;
 
 if ( !ds.search(addr)) {
     Serial.print("No more addresses.\n");
     ds.reset_search();
     return;
 }
 
 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;
 }
 
 if ( addr[0] != 0x28) {
     Serial.print("Device is not a DS18B20 family device.\n");
     return;
 }

 ds.reset();
 ds.select(addr);
 ds.write(0x44,1);         // start conversion, with parasite power on at the end
 
 delay(1000);     // maybe 750ms is enough, maybe not
 // 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 < 12; i++) {           // we need 9 bytes
   data[i] = ds.read();
}

  /* compute the degrees in celcius / integer part */
 
 /* The measured temp is spread across two bytes of the returned data.
  *  The integer part of the temp value is spread across the least 3 significant
  *  bits of the most significant byte (MSB) and the most significant 4 of
  *  the LSB.  Here we shift those 7 bits into their proper place in our
  *  result byte.
  *
  * note: could do this with 2 bit-shift / mask operations, alternatively
  */
   temp_c_int = 0;
   set_bit = 6;
for (test_bit = 2; test_bit >= 0; test_bit--) {
   temp_c_int |= ( ((data[TEMP_MSB] & (1 << test_bit)) >> test_bit) << set_bit );
   set_bit--;
}
for (test_bit = 7; test_bit >= 4; test_bit--) {
   temp_c_int |= ( ((data[TEMP_LSB] & (1 << test_bit)) >> test_bit) << set_bit );
   set_bit--;
}

 /* compute the fractional part */

 /*  first figure out what resolution we're measuring in - varies between 1 and 4 bits
  *    after the decimal (based on the contents of the CONFIG_REG byte):
  *        bit 6 == 0 && bit 5 == 0 --> 9-bit resolution (ignore 3 least sig bits)
  *        bit 6 == 0 && bit 5 == 1 --> 10-bit resolution (ignore 2 least sig bits)
  *        bit 6 == 1 && bit 5 == 0 --> 11-bit resolution (ignore 1 least sig bits)
  *        bit 6 == 1 && bit 5 == 1 --> 12-bit resolution  
 
if ((data[CONFIG_REG] & (1 << 5)) > 0) {        
 if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 and 5 are set
     resolution_floor = 3;
   } else {                                      // bit 6 is set, 5 is clear
     resolution_floor = 2;
   }
   } else {
   if ((data[CONFIG_REG] & (1 << 4)) > 0) {      // bits 6 is clear, 5 is set
     resolution_floor = 1;
   } else {                                      // bit 6 and 5 are clear
     resolution_floor = 0;
   }
}    */

 temp_c_frac = 0;
for (test_bit = 3; test_bit >= resolution_floor; test_bit--) {
   if ((data[TEMP_LSB] & (1 << test_bit)) > 0) {
     expon = test_bit - 4; // will be negative
     temp_c_frac += pow(2,expon);
   }
}

 /* put it all together */
 temp_c = (float)temp_c_int + temp_c_frac;  

if ((data[TEMP_MSB] & (1 << 7)) > 0) {   // the temp is negative
   temp_c *= -1;
}
 
 
 Serial.print("   Temp en C= ");
 Serial.print(temp_c_int,DEC);
 Serial.print(".");
 Serial.print(temp_c_frac * 10000,DEC);
 Serial.println();  
}
MacBook intel core 2 duo  os X snow Leopard 10.6<br/> eMac PPc G4  os X Leopard 10.5<br/>powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

Geof

Bonjour, je rencontre quelques problèmes pour faire fonctionner ce bus 1-Wire.

Je le programme par un pic 16F84A qui lui-même est programmé en assembleur, voici la séquence de programmation que j'utilise, puis le programme. Le but est de lui donner deux seuils de température, puis de le mettre en mode thermostat.

Séquence de programmation :

1 RESET puis attente de réponse (800µs)
2 SKIP ROM (on passe la rom car un seul bus)
3 ENVOIE de la commande 4Eh pour écrire dans le scratchpad
4 ENVOIE du premier byte TH, puis envoie du deuxième byte TL
5 RESET puis attente de réponse (800µs)
6 SKIP ROM
7 ENVOIE de la commande 48h pour copier le scratchpad dans l'EEPROM
8 RESET puis attente de réponse (800µs)
9 SKIP ROM
10 ENVOIE de la commande ECh pour le mettre en mode thermostat
FIN

Voilà, cela ne fonctionne pas et je ne comprends pas pourquoi, j'ai utiliser un temps de 1µs entre chaque bit lorsque j'envoie un byte.

Pour info, voici le programme complet, si quelqu'un peut m'aider, cela serait génial car je suis pris avec le temps pour un TFE.


Bonjour,

je déterre un peu ce post.
J'ai chez moi 3 DS18B20:
- 2 sont connectés à l'extrémité d'une branche d'une vingtaine de mètre
- le 3eme est connecté sur une autre branche de 10 mètres env.
- ces 2 branches sont connectées entre-elles juste avant d'attaquer l'interface (=> réseau en "étoile")
- Chaque capteur est connecté à Vdd, Gnd et Data (=> pas en mode parasite)

Le tout fonctionne bien avec le convertisseur PC USB-1Wire, je vois les 3 capteurs.
Par contre, connectés à l'arduino je ne sais détecter que les branches séparément. Si je connecte les 2 branches ensembles, j'ai plein d'erreur de CRC (CRC is not valid!) et je suis incapable de récupérer les données: les données reçues changent sans arrêt. J'utilise le code de Jean-François ci-dessus pour mes tests.

c'est idem lorsque je les branche en mode parasite (Vdd et Gnd reliées)

Je ne comprend pas trop pourquoi ca fonctionne avec le convertisseur USB et pas avec l'arduino...

Est-ce que quelqu'un a un réseau 1-Wire fonctionnel avec Arduino ?
Le fait que le réseau soit en étoile pose-t-il problème ?

merci d'avance si vous avez des pistes...
"pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires..."

projet domotique xPLDuino
IRC: freenode #xplduino

Bon, j'ai trouvé une parade en affectant chaque branche à une pin différente.
Au lieu de créer une fois l'objet "ds" OneWire en début de sketch comme dans le code exemple,  je crée l'objet ds à chaque appel de la fonction de lecture en changeant le n° de pin.
J'en ai profité pour créer une table contenant les noms des capteurs à interroger, ça m'évite d'utiliser la fonction search.
"pour résoudre un gros problème, il est souvent plus facile de le diviser en petits problèmes élémentaires..."

projet domotique xPLDuino
IRC: freenode #xplduino

Go Up