sensore temperatura ds18b20 e 7 segment display sparkfun

Ciao a tutti ho acquistato da poco il nuovo 7segment display della Sparkfun.

Link:SparkFun 7-Segment Serial Display - Blue - COM-11442 - SparkFun Electronics

La mia intenzione era quella di visualizzare sul display la temperatura...piu precisamente nel formato ad esempio -23.5 (i numeri al massimo possono essere quattro, quindi solo con un decimale per avere la possibilità di aggiungere il - nel caso la temperatura sia sotto lo zero)

Ho guardato due sketch di esempio per inviare i dati tramite I2C oppure tramite Seriale ma non sono riuscito a farlo funzionare correttamente. il sensore viene letto correttamente infatti tramite seriale sul pc compare la temperatura corretto ad esempio 23.50 .Solo che il passaggio successivo e cioé formattare il float per poi inviarlo al display non so come fare. Qualcusa sa come si può fare? Vi posto i codici. Grazie

invio dati tramite I2C

/*
11-2-2012
Spark Fun Electronics
Nathan Seidle
This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

Serial7Segment is an open source seven segment display.

This is example code that shows how to send data over I2C to the display.
Note: This code expects the display to be listening at the default I2C address. If your display is not at 0x71, you can
do a software or hardware reset. See the Wiki for more info:
http://github.com/sparkfun/Serial7SegmentDisplay/wiki/Special-Commands
To get this code to work, attached an Serial7Segment to an Arduino Uno using the following pins:
A5 to SCL
A4 to SDA
VIN to PWR
GND to GND

*/

#include <Wire.h>

#define DISPLAY_ADDRESS1 0x71 //This is the default address of the OpenSegment with both solder jumpers open

int cycles = 0;

void setup()
{
  Wire.begin(); //Join the bus as master

  Serial.begin(9600); //Start serial communication at 9600 for debug statements
  Serial.println("OpenSegment Example Code");

  //Send the reset command to the display - this forces the cursor to return to the beginning of the display
  Wire.beginTransmission(DISPLAY_ADDRESS1);
  Wire.write('v');
  Wire.endTransmission();
}

void loop()
{
  cycles++; //Counting cycles! Yay!
  Serial.print("Cycle: ");
  Serial.println(cycles);
  
  i2cSendValue(cycles); //Send the four characters to the display
  
  delay(1); //If we remove the slow debug statements, we need a very small delay to prevent flickering
}

//Given a number, i2cSendValue chops up an integer into four values and sends them out over I2C
void i2cSendValue(int tempCycles)
{
  Wire.beginTransmission(DISPLAY_ADDRESS1); // transmit to device #1
  Wire.write(tempCycles / 1000); //Send the left most digit
  tempCycles %= 1000; //Now remove the left most digit from the number we want to display
  Wire.write(tempCycles / 100);
  tempCycles %= 100;
  Wire.write(tempCycles / 10);
  tempCycles %= 10;
  Wire.write(tempCycles); //Send the right most digit
  Wire.endTransmission(); //Stop I2C transmission
}

invio dati tramite Seriale

/*
9-23-2012
Spark Fun Electronics
Nathan Seidle
This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

Serial7Segment is an open source seven segment display.

This is example code that shows how to display basic numbers on the display.
Note: This code expects the display to be listening at 9600bps. If your display is not at 9600bps, you can
do a software or hardware reset. See the Wiki for more info:
http://github.com/sparkfun/Serial7SegmentDisplay/wiki/Special-Commands#wiki-baud
To get this code to work, attached an Serial7Segment to an Arduino Uno using the following pins:
Pin 8 on Uno (software serial TX) to RX on Serial7Segment
VIN to PWR
GND to GND
*/

#include <SoftwareSerial.h>

SoftwareSerial Serial7Segment(7, 8); //RX pin, TX pin

int cycles = 0;

void setup() {

  Serial.begin(9600);
  Serial.println("OpenSegment Example Code");

  Serial7Segment.begin(9600); //Talk to the Serial7Segment at 9600 bps
  Serial7Segment.write('v'); //Reset the display - this forces the cursor to return to the beginning of the display
}

void loop()
{
  cycles++; //Counting cycles! Yay!
  Serial.print("Cycle: ");
  Serial.println(cycles);
  
  char tempString[10]; //Used for sprintf
  sprintf(tempString, "%4d", cycles); //Convert deciSecond into a string that is right adjusted
  //sprintf(tempString, "%d", cycles); //Convert deciSecond into a string that is left adjusted (requires digit 1 command)
  //sprintf(tempString, "%04d", cycles); //Convert deciSecond into a string with leading zeros
  //sprintf(tempString, "%4X", cycles); //Count in HEX, right adjusted
  //int negativeCycles = cycles * -1;
  //sprintf(tempString, "%4d", negativeCycles); //Shows a negative sign infront of right adjusted number

  //Note: This method works well as long as your number is less than or equal to 4 digits.
  //14422 will cause the display to wrap (5 digits)
  //-5766 will cause the display to wrap (5 digits)
  //To fix this, send a 'v' character or look at how to control the digit placement
  //https://github.com/sparkfun/Serial7SegmentDisplay/wiki/Basic-Usage#wiki-cursor

  Serial7Segment.print(tempString); //Send serial string out the soft serial port to the S7S

  delay(10);
}

A mio modesto parere, se non hai una lib per gestire i segmenti dei vari display, ti devi realizzare tu un protocollo di comunicazione; quello è un display a catodo comune con i sette sementi (e il dp) tutti in parallelo tra loro, di conseguenza devi usare il multiplexing. Cerca il "Micrologio" di Leo72, lì c'è un ottimo sw di esempio fatto proprio per questo display.

Ciao Michele, non so se hai dato un'occhiata al link...questo è un nuovo display gia predisposto per la comunicazione I2C, Seriale, TTL,SPI

no, pardon, ho riconociuto l'immagine e pensavo fosse il solito mux, alla luce di quanto dici le cose cambiano e purtroppo non so come aiutarti

Devi inviare la cifra come int, moltiplicandola per 10 e poi aggiungere il comando per il punto decimale.
Con un if controlli se il numero è negativo e come primo carattere invii -

Dovresti modificare il codice di lettura della temperatura in modo che ti restituisca un intero moltiplicato per 10. Eviti cosi la conversione da float a int e risparmi memoria.

sinceramente non saprei come fare.... al momento sto usando la libreria DallasTemperature per leggere il sensore...

#include <OneWire.h>
#include <DallasTemperature.h>
 
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);
 
void setup(void)
{
// start serial port
Serial.begin(9600);
 
// Start up the library
sensors.begin(); // IC Default 9 bit. If you have troubles consider upping it 12. Ups the delay giving the IC more time to process the temperature measurement
}
 
void loop(void)
{
  sensors.requestTemperatures();
  Serial.print("Temperatura ");
  Serial.print(sensors.getTempCByIndex(0));
  Serial.println(" C");
}
void loop(void)
{
  sensors.requestTemperatures();
  Serial.print("Temperatura ");
  Serial.print(sensors.getTempCByIndex(0));
  Serial.println(" C");
 int temperature = (int) (sensors.getTempCByIndex(0)*10);
 i2cSendValue(temperature); //Send the four characters to the display
delay(1000);
}

void i2cSendValue(int temp)
{
  Wire.beginTransmission(DISPLAY_ADDRESS1); // transmit to device #1
  if (temp<0)
  {
   Wire.write(0x7B); // Seleziona la prima cifra   
   Wire.write(127); // invia il carattere -
   }
  Wire.write(temp / 1000); //Send the left most digit
  temp %= 1000; //Now remove the left most digit from the number we want to display
  Wire.write(temp / 100);
  temp %= 100;
  Wire.write(temp / 10);
  temp %= 10;
  Wire.write(temp); //Send the right most digit
  Wire.write(0x77); // invia il punto decimale
  Wire.write(4);
  Wire.endTransmission(); //Stop I2C transmission
}

Trovi i comandi per mandare il punto decimale qui --> Special Commands · sparkfun/Serial7SegmentDisplay Wiki · GitHub

Non ho idea se compila o meno. Non l'ho testato.

Grandissimo Paolo! :slight_smile:

Funziona alla grande... l'unica cosa è che rimane fisso lo zero/gli zeri prima dei numeri della temperatura..come si vede in foto... si riesce a non farli accendere?
sotto lo zero non riesco a provare , ne con il ghiaccio, ne mettendo il sensore all'esterno anche se abito in Valle d'Aosta! :slight_smile:

non sono riuscito ad inserire l'immagine e non so perché comunque viene visualizzato ad esempio 023.4 o 009.6

si, bisogna rivedere l'algoritmo. :roll_eyes:

void i2cSendValue(int temp)
{
  Wire.beginTransmission(DISPLAY_ADDRESS1); // transmit to device #1
  if (temp<0)
  {
   Wire.write(0x7B); // Seleziona la prima cifra   
   Wire.write(127); // invia il carattere -
   temp = temp * -1;
   }
 if (temp/1000>0) 
    { 
     Wire.write(temp / 1000); //Send the left most digit
    }
  else
    { 
     Wire.write(0x79);
     Wire.write(0x01);
    }
  temp %= 1000; //Now remove the left most digit from the number we want to display
 if (temp/100>0) 
    { 
     Wire.write(temp / 100);
    }
  else
    { 
     Wire.write(0x79);
     Wire.write(0x02);
    }  
  temp %= 100;
  Wire.write(temp / 10);
  temp %= 10;
  Wire.write(temp); //Send the right most digit
  Wire.write(0x77); // invia il punto decimale
  Wire.write(4);
  Wire.endTransmission(); //Stop I2C transmission
}

Prova...
Devo ancora ragionare per i numeri negativi. Ancora non mi convince.
Purtroppo non ho un display a 7 segmenti per fare le prove e sto scrivendo il codice a sentimento.

Puoi postare lo sketch completo? :wink:

Ciao Paolo, scusa ma non ho avuto piu avuto il tempo di fare le prove... :wink:

posto lo sketch completo... per provare con il segno meno ho impostare im modo che superando i 25 gradi viene aggiunto il segno -
Funziona...solo che quando la temperatura ritorna al di sotto dei 25 gradi mantiene il segno meno... come si potrebbe fare? bisognerebbe resettare il display al cambio di segno?

ho provato...dato che per fare il segno meno ho usato Wire.write(0x7B); Wire.write(0b01000000);

ho pensato che magari inviando Wire.write(0x7B); Wire.write(0b00000000); non accendesse nessun led ma invece non funziona

/*
11-2-2012
Spark Fun Electronics
Nathan Seidle
This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).

Serial7Segment is an open source seven segment display.

This is example code that shows how to send data over I2C to the display.
Note: This code expects the display to be listening at the default I2C address. If your display is not at 0x71, you can
do a software or hardware reset. See the Wiki for more info:
http://github.com/sparkfun/Serial7SegmentDisplay/wiki/Special-Commands
To get this code to work, attached an Serial7Segment to an Arduino Uno using the following pins:
A5 to SCL
A4 to SDA
VIN to PWR
GND to GND

*/

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define DISPLAY_ADDRESS1 0x71 //This is the default address of the OpenSegment with both solder jumpers open
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);


void setup()
{
  Wire.begin(); //Join the bus as master
  sensors.begin();
  Serial.begin(9600); //Start serial communication at 9600 for debug statements

  //Send the reset command to the display - this forces the cursor to return to the beginning of the display
  Wire.beginTransmission(DISPLAY_ADDRESS1);
  Wire.write('v');
  Wire.endTransmission();
}

void loop(void)
{
  sensors.requestTemperatures();
  Serial.print("Temperatura ");
  Serial.print(sensors.getTempCByIndex(0));
  Serial.println(" C");
 int temperature = (int) (sensors.getTempCByIndex(0)*10);
 i2cSendValue(temperature); //Send the four characters to the display
delay(1000);
}


void i2cSendValue(int temp)
{
  Wire.beginTransmission(DISPLAY_ADDRESS1); // transmit to device #1
  if (temp>250)
  {
   Wire.write(0x7B); // Seleziona la prima cifra   
   Wire.write(0b01000000); // invia il carattere -
  
   }
 if (temp/1000>0) 
    { 
     Wire.write(temp / 1000); //Send the left most digit
    }
  else
    { 
     Wire.write(0x79);
     Wire.write(0x01);
    }
  temp %= 1000; //Now remove the left most digit from the number we want to display
 if (temp/100>0) 
    { 
     Wire.write(temp / 100);
    }
  else
    { 
     Wire.write(0x79);
     Wire.write(0x02);
    }  
  temp %= 100;
  Wire.write(temp / 10);
  temp %= 10;
  Wire.write(temp); //Send the right most digit
  Wire.write(0x77); // invia il punto decimale
  Wire.write(4);
  Wire.endTransmission(); //Stop I2C transmission
}

ho provato così e il cambio di segno funziona... così non invia nulla sulla prima cifra Wire.write(0x7B); Wire.write(0b10000000);
però ho cambiato un po lo sketch...ed è da sistemare..in caso di 2 cifre o una cifra.

void i2cSendValue(int temperature)
{
  Wire.beginTransmission(DISPLAY_ADDRESS1); // transmit to device #1
  
  if (temperature>250)
  {
  Wire.write(0x7B);
  Wire.write(0b01000000);
  Wire.write(0x79);
  Wire.write(0x01);
  Wire.write(temperature  / 100);
  temperature  %= 100;
  Wire.write(0x79);
  Wire.write(0x02);
  Wire.write(temperature  / 10);
  temperature  %= 10;
  Wire.write(0x79);   
  Wire.write(0x03);
  Wire.write(temperature );
  Wire.write(0x77);
  Wire.write(4);
  Wire.endTransmission(); 
  }
 else
 {
  Wire.write(0x7B);  
  Wire.write(0b10000000);
  Wire.write(0x79);
  Wire.write(0x01);
  Wire.write(temperature  / 100);
  temperature  %= 100;
  Wire.write(0x79); 
  Wire.write(0x02);
  Wire.write(temperature  / 10);
  temperature  %= 10;
  Wire.write(0x79); 
  Wire.write(0x03);
  Wire.write(temperature );
  Wire.write(0x77);
  Wire.write(4);
  Wire.endTransmission(); 
}
}

Nickb84:
posto lo sketch completo... per provare con il segno meno ho impostare im modo che superando i 25 gradi viene aggiunto il segno -
Funziona...solo che quando la temperatura ritorna al di sotto dei 25 gradi mantiene il segno meno... come si potrebbe fare? bisognerebbe resettare il display al cambio di segno?

Si, bisogna prevedere un sistema per includere o meno il segno in base al valore della temperatura.

Nickb84:
ho provato...dato che per fare il segno meno ho usato Wire.write(0x7B); Wire.write(0b01000000);
ho pensato che magari inviando Wire.write(0x7B); Wire.write(0b00000000); non accendesse nessun led ma invece non funziona

Certo che non funziona. :grin:
Wire.write(0x7B); è un comando che dice al display di accendere i segmenti della prima cifra in base a quello che si trasmette subito dopo. La trasmissione immediatamente successiva è Wire.write(0b01000000); e il display accende il segmento numero 7.
Trovi le info qui --> Special Commands · sparkfun/Serial7SegmentDisplay Wiki · GitHub

Adesso provo a dare uno sguardo al codice. :wink:

Prova così.

#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define DISPLAY_ADDRESS1 0x71 //This is the default address of the OpenSegment with both solder jumpers open
// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);


void setup()
{
  Wire.begin();
  sensors.begin();
  Serial.begin(9600);

  //Send the reset command to the display - this forces the cursor to return to the beginning of the display
  Wire.beginTransmission(DISPLAY_ADDRESS1);
  Wire.write('v');
  Wire.endTransmission();
}

void loop(void)
{
  sensors.requestTemperatures();
  Serial.print("Temperatura ");
  Serial.print(sensors.getTempCByIndex(0));
  Serial.println(" C");
  int temperature = (int) (sensors.getTempCByIndex(0)*10);
  i2cSendValue(temperature); //Send the four characters to the display
  delay(1000);
}

void i2cSendValue(int number)
{
  Serial.print("Debug number: ");
  Serial.println(number);

  Wire.beginTransmission(DISPLAY_ADDRESS1); // transmit to device #1
  Wire.write(0x76); // Clear display
  Wire.write(0x79); // Set cursor
  Wire.write(0x00); // at position 0

    if (number<0) // Negative temperature
  {
    Wire.write(0x7B); // Digit 1 control  
    Wire.write(0b01000000); // Set segment X
    number = number * -1;
  }

  Serial.print("1000 number: ");
  Serial.println(number);

  if (number>999) 
  { 
    Wire.write(number / 1000);
  }
  else
  { 
    Wire.write(0x79);
    Wire.write(0x01);
  }
  number %= 1000; //Now remove the left most digit from the number we want to display

  Serial.print("100 number: ");
  Serial.println(number);

  if (number>99) 
  { 
    Wire.write(number / 100);
  }
  else
  { 
    Wire.write(0x79);
    Wire.write(0x02);
  }  
  number %= 100;

  Serial.print("10 number: ");
  Serial.println(number);

  if (number>9) 
  { 
    Wire.write(number / 10);
  }
  else
  { 
    Wire.write(0x79);
    Wire.write(0x03);
  }  
  number %= 10;

  Serial.print("1 number: ");
  Serial.println(number);

  Wire.write(number); //Send the right most digit
  Wire.write(0x77); // Set Decimal
  Wire.write(0b00000100); 
  Wire.endTransmission(); //Stop I2C transmission
}

Apri il serial monitor e dimmi che cosa ti esce. Ho messo dei serial print per fare il debug.

Si, appunto da quel link che ho capito come accendere il led 7... ;)...comunque con Wire.write(0x7B); Wire.write(0b10000000); ...Funziona! il passaggio dal segno - meno al +....spegne completamente la prima cifra... l'ultimo sketch che ho postato...è un po elementare però se imposto i vari intervalli dovrebbe funzionare credo... temp>0 ; temp>99 ; temp<0 ;temp>-99

secondo te non va bene?

Ho appena provato il tuo ultimo sketch... non gli piace il:

Wire.write(0x79);
Wire.write(0x00);

Prova a modificare il

Wire.write(0x79);
Wire.write(0x00);

con

Wire.write(0x79);
Wire.write((byte) 0);

il comando serve a posizionare il cursore sul primo carattere.

Nickb84:
Si, appunto da quel link che ho capito come accendere il led 7... ;)...comunque con Wire.write(0x7B); Wire.write(0b10000000); ...Funziona! il passaggio dal segno - meno al +....spegne completamente la prima cifra...

dal sito sembra che per accendere il meno debba accendere il 7° segmento quindi 0b01000000, ma se ti funziona con 0b10000000 allora va bene lo stesso.

Nickb84:
l'ultimo sketch che ho postato...è un po elementare però se imposto i vari intervalli dovrebbe funzionare credo... temp>0 ; temp>99 ; temp<0 ;temp>-99
secondo te non va bene?

No, gli intervalli da considerare sono

999
il numero ha 4 cifre quindi devi scriverle tutte nel display

99
numero a tre cifre. salti la prima casella e scrivi le altre tre.

9
numero a 2 cifre. salti la prima e la seconda e scrivi il numero nelle ultime due celle

infine c'è il numero ad una cifra.
lo scrivi nella quarta cella saltando le prime tre.

Se la temperatura è minore di 0, scrivi il meno e trasformi il numero in positivo controllando i casi precedenti.
Se misuri in °C non puoi misurare meno di -276 quindi non hai problemi con negativi a 4 cifre.

Per il problema col write(0) ho scritto nel post precedente.

taac! bellissimo! :smiley:

devo ancora vedere se i range funzionano.

Grazie

Prego. :wink: