Un problème d'interférence entre un Sd shild et deux ds18B20

Bonjour à tous,

Nouveau sur le forum, je me lance dans un projet, automatiser une serre. Pour le moment j’essaye d’inscrire les données de mes deux capteurs 1-Wire Ds18b20 sur une carte SD.
Pour cela j’ai récupéré un programme qui écris sur un txt placé sur une SD : Arduino SD card data logger to Excel - Make it easy!
Egalement je suis partis d’un code que j’ai moi même composé d’autres code qui lui ne fait que lire deux capteurs DS18B20 sur le pin 10 et afficher cela sur un écran LCD :

/* DS18B20_sensor_to_LCD_screen
based on a sketch by Rik Kretzinger
Modified by Guillaume Leguen
this sketch reads temperature from 2 DS18B20 sensors
and reports to Serial Monitor
cc-by-sa Guillaume Leguen
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#define onewirepin 10 // Cette fonction defini le numéro de port où sont branchés les capteurs
#include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins – The numbers
//are the pin connected in sequence from RS to DB7, c'est pour l'écran
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

OneWire oneWire(onewirepin);
DallasTemperature sensors(&oneWire);

// Retrouver les adress OneWire gr^ce au code de recherche des adresses

uint8_t sensor1[8] = { 0x28, 0xFF, 0x41, 0xB2, 0x90, 0x16, 0x04, 0xF5 };
uint8_t sensor2[8] = { 0x28, 0xFF, 0x49, 0x9A, 0x87, 0x16, 0x03, 0x14 };

 

void setup(){
Serial.begin (115200);
Serial.print ("Initializing Temperature Control Library Version ");
Serial.println (DALLASTEMPLIBVERSION);

sensors.begin (); // Initialise le capteur et défini une resolution
sensors.setResolution(sensor1, 10);
sensors.setResolution(sensor2, 10);

delay(1000);
Serial.println();
Serial.print ("Number of Devices found on bus = ");
Serial.println (sensors.getDeviceCount());
Serial.print ("Getting temperatures… ");
Serial.println ();

// set up the LCD’s number of columns and rows:
lcd.begin(16, 2);
}

void loop()
{

sensors.requestTemperatures(); // Command all devices on bus to read temperature

Serial.print("In : ");
lcd.setCursor(0, 0);
lcd.print ("In : ");
printTemperature(sensor1);
Serial.print("Out : ");
lcd.setCursor(0, 1);
lcd.print ("Out : ");
printTemperature(sensor2);
Serial.println();
delay(500);

}

void printTemperature(DeviceAddress deviceAddress)
{

float tempC = sensors.getTempC(deviceAddress);

if (tempC == -127.00)
{
Serial.print ("Error getting temperature ");
lcd.print ("Reading Error");
}
else
{
Serial.print (tempC);
Serial.print ((char)176);
Serial.print ("C | ");
lcd.print(tempC);
lcd.print((char)223); // caractère degre
lcd.print("C  ");
}
}

Alors j’ai commencé à composer le code suivant en mixant les deux :

/* DS18B20_sensor_to_LCD_screen
based on a sketch by Rik Kretzinger
Modified by Guillaume Leguen
this sketch reads temperature from 2 DS18B20 sensors
and reports to Serial Monitor
cc-by-sa Guillaume Leguen
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#define onewirepin 10 // Cette fonction defini le numéro de port où sont branchés les capteurs
#include <LiquidCrystal.h> // initialize the library with the numbers of the interface pins – The numbers
#include <SPI.h> // for SD stock
#include <SD.h> // for SD stock
#include <Wire.h> // for SD stock
#include "DS3231.h" // for SD stock
//are the pin connected in sequence from RS to DB7, c'est pour l'écran
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

File myFile; //deffine var File

OneWire oneWire(onewirepin);
DallasTemperature sensors(&oneWire);

// Retrouver les adress OneWire grace au code de recherche des adresses

uint8_t sensor1[8] = { 0x28, 0xFF, 0x41, 0xB2, 0x90, 0x16, 0x04, 0xF5 };
uint8_t sensor2[8] = { 0x28, 0xFF, 0x49, 0x9A, 0x87, 0x16, 0x03, 0x14 };


void setup(){
  Serial.begin (115200);
  Wire.begin(); //for DS3231
  while (!Serial) {
   ; // wait for serial port to connect. Needed for native USB port only
   }
  delay(2000);  //afer reset Arduino, 2s to take out SD
  
  Serial.print("Initializing SD card...");
  
  Serial.print ("Initializing Temperature Control Library Version ");
  Serial.print("Initializing SD card...");
  Serial.println (DALLASTEMPLIBVERSION);

  sensors.begin (); // Initialise le capteur et défini une resolution
  sensors.setResolution(sensor1, 10);
  sensors.setResolution(sensor2, 10);

  delay(2000);
  Serial.println();
  Serial.print ("Number of Devices found on bus = ");
  Serial.println (sensors.getDeviceCount());
  Serial.print ("Getting temperatures… ");
  Serial.println ();

  // set up the LCD’s number of columns and rows:
  lcd.begin(16, 2);
  
  if (!SD.begin(9)) {
   Serial.println("initialization failed!");
  }
  else {
   Serial.println("initialization done.");
  }
  
}

void loop()
{
  
  sensors.requestTemperatures(); // Command all devices on bus to read temperature

  Serial.print("In : ");
  lcd.setCursor(0, 0);
  lcd.print ("In : ");
  printTemperature(sensor1);
  Serial.print("Out : ");
  lcd.setCursor(0, 1);
  lcd.print ("Out : ");
  printTemperature(sensor2);
  Serial.println();
  delay(500);

}

void printTemperature(DeviceAddress deviceAddress)
{

  float tempC = sensors.getTempC(deviceAddress);

  if (tempC == -127.00)
  {
  Serial.print ("Error getting temperature ");
  lcd.print ("Reading Error");
  }
  else
  {
  Serial.print (tempC);
  Serial.print ((char)176);
  Serial.print ("C | ");
  lcd.print(tempC);
  lcd.print((char)223); // caractère degre
  lcd.print("C  ");
  }
}

Hélas à l’execution, le script renvoi “error getting temperature” Ce qui correspond à une erreur de lecture des capteurs.
J’ai un peu exploré et il semblerait que ce soit ces quelques lignes qui gènent :

 if (!SD.begin(9)) {
   Serial.println("initialization failed!");
  }
  else {
   Serial.println("initialization done.");
  }

Si je les mets en commentaires tout fonctionne normalement. J’ai alors été voir le code SD.h et en cherchant la fonction begin, j’ai trouvé :

 boolean begin(uint8_t csPin = SD_CHIP_SELECT_PIN);

Il semblerait donc que cette fonction intéroge tous les ports uint8_t ce qui inclurait mes deux capteurs de température… ?
J’avoue être un peu perdu sur ce coup là ! Penssez-vous qu’il faille définir les adresses des capteurs autrement ?
Je précise que les capteurs sont sur le pin 10 et le CS du lecteur de carte est sur le 9. Je suis avec une arduino nano.
Trouvez-vous l’erreur ?
Merci à tous
GheLeguen

met le onewire sur 9 et le CS du lecteur sd sur 10
et changer les 10 par 9 et les 9 par 10 dans le croquis

"Note that even if you don't use the hardware SS pin, it must be left as an output or the SD library won't work. Different boards use different pins for this functionality, so be sure you’ve selected the correct pin in SD.begin(). "

"SS Must be an Output on the SPI master. If it is an Input and some other device drives it low, the Arduino will go into SPI slave mode.
SS does not have to be used as a chip select driver, but it has to be an output."

je pense que tu as tres mal choisi la pin10 pour onewire à cause de l'utilisation de la lib SD, sans celle-ci la lecture onewire doit fonctionner sur la pin10

avis qui n'engage que moi

Bonjour,

Effectivement la broche 10 a une fonction particulière. Elle est la broche SS par défaut du port SPI et si on utilise le SPI elle doit impérativement être en sortie. Si les périphériques SPI utilisent d’autre broches comme select il faut quand même que la broche 10 soit déclarée en sortie mais elle peut néanmoins être utilisée pour une autre fonction.

Concernant cette ligne, c’est une mauvaise pratique.

if (!SD.begin(9)) {

Il vaut mieux déclarer la broche en début de programme par un #define ou une constante, comme tu l’as fait pour onewirepin . Et utiliser le nom partout dans le programme ce qui rend beaucoup plus facile un changement d’affectation de broche.

La broche 10 fait partie du groupe de broches SPI.

En mode entrée si elle reçoit un niveau bas le bus SPI va commuter du mode maître au mode esclave et attendra les ordres d'un autre SPI maître comme celui d'une autre carte arduino par exemple..
C'est écrit sur le site arduino mais ce n'est vraiment pas clair. La datasheet du micro est bien plus claire.

En mode sortie la ligne CS sert à sélectionner un esclave. S'il n'y a qu'un seul esclave sur le SPI il est possible de mettre sa broche CS en pernanence à la masse sans utiliser la ligne CS.
S'il y a plusieurs esclaves il faudra une ligne CS par esclave.
Ce pourra être la pin 10 pour le premier esclave et n'importe quelles pins pour les esclaves suivants ( y compris les pins "dites" analogiques qui en fait sont des pins numériques avec une deuxième fonction analogique).

Bonjour à vous trois,

Merci pour vos éclairages. J'ai réussi à régler le problème en inverssant le pin 10 pour le CS du lecteur et le pin 9 pour la lecture des capteurs.
Mais cela ne suffisait pas. J'ai alors déclaré le numéro de pin par un int.

J'ai retravaillé mon code ce soir. Il intègre de nouvelles fonctionnalités grâce à un RTC.

Je débute alors il est peut être plein d'incertitudes. N'hésitez pas à me dire si vous y localisez des choses qui vous titillent.

/* Mesurer 2 temperatures et les archiver en carte SD
by Guillaume Leguen
this sketch reads temperature from 2 DS18B20 sensors
and reports to Serial Monitor
cc-by-sa Guillaume Leguen
*/

#include 
#include 
//#define onewirepin 9 // Cette fonction defini le numéro de port où sont branchés les capteurs
#include  // initialize the library with the numbers of the interface pins – The numbers
#include  // for SD stock
#include  // for SD stock
#include  // for SD stock
#include "DS3231.h" // for SD stock
//are the pin connected in sequence from RS to DB7, c'est pour l'écran
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

RTClib RTC;
DS3231 Clock;

int pinSD = 10 ;
int pinSensorsDS = 9 ;
char NomFichier[20];
char NomFichierComp[20];
int Year;
int Month;
int Date;
int Hour;
int Minute;
int Second;
int tempC;
int interval = 1;
int Minute_last;
int Date_last;

File myFile; //deffine var File

OneWire oneWire(pinSensorsDS);
DallasTemperature sensors(&oneWire);

// Retrouver les adress OneWire grace au code de recherche des adresses

uint8_t sensor1[8] = { 0x28, 0xFF, 0x41, 0xB2, 0x90, 0x16, 0x04, 0xF5 };
uint8_t sensor2[8] = { 0x28, 0xFF, 0x49, 0x9A, 0x87, 0x16, 0x03, 0x14 };


void setup(){
  Serial.begin (115200);
  Wire.begin(); //for DS3231 for RTC
  while (!Serial) {
   ; // wait for serial port to connect. Needed for native USB port only
   }
  delay(2000);  //afer reset Arduino, 2s to take out SD
  
  Serial.print("Initializing SD card...");
  
  Serial.print ("Initializing Temperature Control Library Version ");
  Serial.print("Initializing SD card...");
  Serial.println (DALLASTEMPLIBVERSION);

  sensors.begin (); // Initialise le capteur et défini une resolution
  sensors.setResolution(sensor1, pinSensorsDS);
  sensors.setResolution(sensor2, pinSensorsDS);

  delay(2000);
  Serial.println();
  Serial.print ("Number of Devices found on bus = ");
  Serial.println (sensors.getDeviceCount());
  Serial.print ("Getting temperatures… ");
  Serial.println ();

  // set up the LCD’s number of columns and rows:
  lcd.begin(16, 2);
  
  if (!SD.begin(pinSD)) {
   Serial.println("initialization failed!");
  }
  else {
   Serial.println("initialization done.");
  }

  DateTime now = RTC.now();
  Year = now.year();
  Month = now.month();
  Date = now.day();
  Hour = now.hour();
  Minute = now.minute();
  Second = now.second();
  tempC = Clock.getTemperature();
  
  Date_last = Date ;
  sprintf(NomFichier,"%02d%02d%02d%",now.year(),now.month(),now.day()); 
  
write_header ();
Serial.println(NomFichier);
}

void loop()
{
  update_vartime();
  
  sensors.requestTemperatures(); // Command all devices on bus to read temperature
  
  Serial.print(Minute);
  Serial.print("In : ");
  lcd.setCursor(0, 0);
  lcd.print ("In : ");
  printTemperature(sensor1);
  Serial.print("Out : ");
  lcd.setCursor(0, 1);
  lcd.print ("Out : ");
  printTemperature(sensor2);
  Serial.println();
 // write_data1(sensor1);  //write data
 // write_data2(sensor2);
  delay(100);
  
  if ((Minute % interval == 0)&(Minute_last!=Minute))
  {
    write_data1(sensor1);  //write data
    write_data2(sensor2);
    Minute_last = Minute;
  }

}

void printTemperature(DeviceAddress deviceAddress)
{

  float tempC = sensors.getTempC(deviceAddress);

  if (tempC == -127.00)
  {
  Serial.print ("Error getting temperature ");
  lcd.print ("Reading Error");
  }
  else
  {
  Serial.print (tempC);
  Serial.print ((char)176);
  Serial.print ("C | ");
  lcd.print(tempC);
  lcd.print((char)223); // caractère degre
  lcd.print("C  ");
  }
}
void write_data1(DeviceAddress deviceAddress)
{
 float tempC = sensors.getTempC(deviceAddress);
  myFile = SD.open(NomFichier, FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    myFile.print(Year);
    myFile.print("/");
    myFile.print(Month);
    myFile.print("/");
    myFile.print(Date);
    myFile.print(";");
    myFile.print(Hour);
    myFile.print(":");
    myFile.print(Minute);
    myFile.print(";");
    myFile.print(tempC);
    myFile.print(";");
    myFile.close();
    Serial.println("Write file successful!"); //print out COM Port
  } else {
    Serial.println("error opening txt");
  }
}

void write_data2(DeviceAddress deviceAddress)
{
 float tempC = sensors.getTempC(deviceAddress);
  myFile = SD.open(NomFichier, FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    myFile.print(tempC);
    myFile.println();
    myFile.close();
    Serial.println("Write file successful!"); //print out COM Port
  } else {
    Serial.println("error opening txt");
  }
}

void write_header()
{
  myFile = SD.open(NomFichier, FILE_WRITE);

  // if the file opened okay, write to it:
  if (myFile) {
    myFile.println("Donnees de temperatures");
    myFile.println("Serre de FSP");
    myFile.print(Year);
    myFile.print("/");
    myFile.print(Month);
    myFile.print("/");
    myFile.println(Date);
    myFile.println();
    myFile.println("Date;Time;In;Out");
    myFile.close();
    Serial.println("Write header successful!"); //print out COM Port
  } else {
    Serial.println("error opening txt");
  }
}

void update_vartime()
{
  DateTime now = RTC.now();
  Year = now.year();
  Month = now.month();
  Date = now.day();
  Hour = now.hour();
  Minute = now.minute();
  Second = now.second();
  tempC = Clock.getTemperature();
 
  if((Date % interval == 0)&(Date_last!=Date)) { //permets de créer un nouveau fichier à chaque changement de date.
    sprintf(NomFichier,"%02d%02d%02d%",now.year(),now.month(),now.day()); 
    Serial.print("Changement de date, nouveau fichier : ");
    Serial.println(NomFichier);
    Date_last = Date ;
    write_header ();
  }
}

Encore merci à vous.

Je continue mon projet maintenant.

Bonne suite
gheleguen

if ((Minute % interval == 0)&(Minute_last!=Minute))devrait être écrit

if ((Minute % interval == 0)&&(Minute_last!=Minute))

voir & et &&