LED - LCD - Temperature
In our previous project, we will add, in addition to the character display, the LED that blinks intermittently, a temperature sensor DS18B20 that uses 1-Wire communication.
This sensor is usually found in a TO-92 package or in a protective sheath.
We will increase the difficulty level by transmitting the temperature information read from the DS18B20 sensor via serial communication.
I connected the sensor to digital pin 2 of the Sanguino board, as shown in the image below.
The 4.7k pull-up resistor is mandatory.
The temperature will be displayed on the serial communication in a terminal.
Thus, I introduced the serial communication mode.
The code used is as follows:
/*
Conectarea LCD la Sanguino
* LCD RS la pinul digital pin 22
* LCD Enable la pinul digital pin 23
* LCD D4 la pinul digital pin 24
* LCD D5 la pinul digital pin 25
* LCD D6 la pinul digital pin 26
* LCD D7 la pinul digital pin 28
* LCD R/W la masa
Conectare LED
* LED K la pinul digital 13
* LED A la +5V printr-o rezistenta de 1k
Conectare DS18B20 - senzor de temperatura capsula TO92
* DS18B20 DQ la pinul digital 2
* DS18B20 Vdd la +5V
* DS18B20 GND la masa
* DS18B20 o rezistenta pull-up de 4k7 intre Vdd si pinul DQ
*/
#include <Arduino.h>
#include <LiquidCrystal.h> // load the library for the LCD display
#include "OneWireNg_CurrentPlatform.h"
// constantele sunt variabile cu valoare fixa
const int ledPin = 13; // pinul unde este conectat LED-ul
const long intervalBlink = 500; // intervalul de timp in care se va aprinde ledul (in milisecunde)
boolean started = false;
// variabile a caror valoare se va modifica
int ledState = HIGH; // ledState utilzat pentru a seta LED-ul ON sau OFF (HiGH => LED=OFF)
unsigned long previousMillisBlink = 0; // variabila care va stoca timpul când starea LED-ului a fost actualizata
// intializez libraria si asociez pinii Sanguino la LCD
const int rs = 22, en = 23, d4 = 24, d5 = 25, d6 = 26, d7 = 27;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
// Declaratiile necesare pentru senzorul DS18
#define OW_PIN 2 // the pin where the DS18 sensor is connected
// #define PARASITE_POWER // uncomment for parasite power support
#ifdef PARASITE_POWER
/* sterge comentarea pentru alimentarea tranzistorului
si controlul acestuia prin pinul 9 sau altul */
// # define PWR_CTRL_PIN 9
#endif
/* Comenzile pentru circuitele DS */
#define CMD_CONVERT_T 0x44
#define CMD_COPY_SCRATCHPAD 0x48
#define CMD_WRITE_SCRATCHPAD 0x4e
#define CMD_RECALL_EEPROM 0xb8
#define CMD_READ_POW_SUPPLY 0xb4
#define CMD_READ_SCRATCHPAD 0xbe
/* Tipurile de circuite DS suportate */
#define DS18S20 0x10
#define DS1822 0x22
#define DS18B20 0x28
#define DS1825 0x3b
#define DS28EA00 0x42
#define ARRSZ(t) (sizeof(t)/sizeof((t)[0]))
static struct {
uint8_t code;
const char *name;
}
DSTH_CODES[] = {
{ DS18S20, "DS18S20" },
{ DS1822, "DS1822" },
{ DS18B20, "DS18B20" },
{ DS1825, "DS1825" },
{ DS28EA00,"DS28EA00" }
};
static OneWireNg *ow = NULL;
/* returneaza NULL daca nu este suportat */
static const char *dsthName(const OneWireNg::Id& id) {
for (size_t i=0; i < ARRSZ(DSTH_CODES); i++) {
if (id[0] == DSTH_CODES[i].code)
return DSTH_CODES[i].name;
}
return NULL;
}
// sfarsitul declaratiilor necesare pentru circuitele DS
// declar functiile utilizate
void blinkLed(); // fuctia care aprinde un LED
void printSerialTemp(); // functia care va afisa temperatura la portul serial
// aceasta functie va fi rulata o data
void setup() {
#ifdef PWR_CTRL_PIN
ow = new OneWireNg_CurrentPlatform(OW_PIN, PWR_CTRL_PIN, false);
#else
ow = new OneWireNg_CurrentPlatform(OW_PIN, false);
#endif
delay(500);
#if (CONFIG_MAX_SRCH_FILTERS > 0)
/* if filtering is enabled - filter to supported devices only;
CONFIG_MAX_SRCH_FILTERS must be large enough to embrace all code ids */
for (size_t i=0; i < ARRSZ(DSTH_CODES); i++)
ow->searchFilterAdd(DSTH_CODES[i].code);
#endif
Serial.begin(9600); // intializez comunicatia seriala
lcd.begin(16, 2); // setez nr. de coloane si de linii ale LCD-ului
lcd.print("salut, lume!"); // Afisez un mesaj la LCD
pinMode(ledPin, OUTPUT); // setez pinul digital aferent ledPin ca iesire
}
//acesta functie va fi rulata la infinit
void loop() {
lcd.setCursor(0, 1); // setez cursorul la coloana 0, linia 1 (pe randul 2)
lcd.print(millis()/1000); // afisez nr. de secunde de la ultimul reset
blinkLed(); // apelez functia ce aprinde LED-ul
printSerialTemp(); // apelez functia care afiseaza la portul serial temperatura
}
// acesta functie va aprinde un led
void blinkLed() {
// verifica daca e trecut timpul pentru a schimba satrea LED-ului (ON sau OFF)
// daca diferenta dintre timpul curent (currentMillis) si ultimul timp (previosMillis) salvat
// este mai mare decat timpul impus prin variabila (intervalBlink)
unsigned long currentMillisBlink = millis(); // stochez in curentMillis timpul curent
if (currentMillisBlink - previousMillisBlink >= intervalBlink) {
// verific daca s-a scurs intervalul de timp dorit
// daca da, atunci,
previousMillisBlink = currentMillisBlink; //salvez timpul current
if (ledState == HIGH) {
// daca LED-ul este OFF atunci schimb starea lui in ON si invers
ledState = LOW;
}
else {
ledState = HIGH;
}
digitalWrite(ledPin, ledState); // setez starea pinului cu variabila ledState stabilita anterior
}
}
//afisare la portul serial a temperaturii
void printSerialTemp() {
OneWireNg::Id id;
OneWireNg::ErrorCode ec;
ow->searchReset();
do {
ec = ow->search(id);
if (!(ec == OneWireNg::EC_MORE || ec == OneWireNg::EC_DONE))
break;
/* porneste conversia temperaturii */
ow->addressSingle(id);
ow->writeByte(CMD_CONVERT_T);
#ifdef PARASITE_POWER
/* alimenteaza magistrala */
ow->powerBus(true);
#endif
delay(500); // asteptam pentru realizarea conversiei
uint8_t touchScrpd[] = {
CMD_READ_SCRATCHPAD,
/* datele citite scratchpad sunt plasate aici (9 bytes) */
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
};
ow->addressSingle(id);
ow->touchBytes(touchScrpd, sizeof(touchScrpd));
uint8_t *scrpd = &touchScrpd[1]; /* datele scratchpad */
if (OneWireNg::crc8(scrpd, 8) != scrpd[8]) {
Serial.println(" Invalid CRC!");
continue;
}
long temp = ((long)(int8_t)scrpd[1] << 8) | scrpd[0];
if (id[0] != DS18S20) {
unsigned res = (scrpd[4] >> 5) & 3;
temp = (temp >> (3-res)) << (3-res); /* bitii nedefiniti devin zero */
temp = (temp*1000)/16;
}
else if (scrpd[7]) {
temp = 1000*(temp >> 1) - 250;
temp += 1000*(scrpd[7] - scrpd[6]) / scrpd[7];
}
else {
/* ar trebui sa nu se intample */
temp = (temp*1000)/2;
Serial.println(" Zeroed COUNT_PER_C detected!");
}
Serial.print(" Temperatura: ");
if (temp < 0) {
temp = -temp;
Serial.print('-');
}
Serial.print(temp / 1000);
Serial.print('.');
Serial.print(temp % 1000);
Serial.println(" C");
} while (ec == OneWireNg::EC_MORE);
}
The libraries used are:
I also tried the DallasTemperature library, but it often had conversion/temperature measurement errors.
The operation of the assembly in Proteus can be seen in the video below:
The entire project (source code and the file for Proteus) can be downloaded from here LCD_Blink_LED_DS18B20.zip