Google+

Δευτέρα, 21 Φεβρουαρίου 2011

LM35 + LCD HD44780 = VisioTherm1.0

Συνδέσετε το Arduino με έναν αισθητήρα θερμοκρασίας LM35 και μια οθόνη LCD (parallel HD44780) για να φτιάξετε το δικό σας θερμόμετρο κι όχι μόνο!

Συνδεσμολογία Arduino-LCD εδώ.

Δείτε και το βίντεο.

Παρακάτω, ο κώδικας της εφαρμογής VisioTherm 1.0 - download :



/* VisioTherm - Temperature Sensor(LM35) reading and optical representation to LCD(HD47780) display
*
* Copyright (c) 2011 Stavros Kalapothas (stavros@itsystem.gr)
* Version 1.0 (27/01/2011)
* License: GPL v3 (http://www.gnu.org/licenses/gpl.html)
*
* This sketch is based on the "LCD Hola example" by DojoDave, Tomek for K3 and fh-potsdam. I have used LM35 temperature sensor and an LCD with HD44780 controller L1671 (16 chars x 1 line).
* According to LCD specs L1671 is initialized as a 2 line display so the second 8 chars (9-16) are addressed beginning on (C0).
*
* There are the following pins to be considered:
*
* DI, RW, DB0..DB3, Enable, tempPin (8 in total)
*
*/

//LM35 init vars
float tempC;
int tempD;
int tempPin = 0;

//LCD init vars
int led = 13;
int DI = 12;
int RW = 11;
int DB[] = { 7, 8, 9, 10};
int Enable = 6;
int count = 0;
int blink_count = 0;

void LcdCommandWrite(int value) {
int i = 0;
int value1 = 0;
value1 = value;

value1 >>= 4; //send the first 4 databits (from 8) + RW and DI
for (i=DB[0]; i <= DI; i++) {
digitalWrite(i,value1 & 01);
value1 >>= 1;
}
digitalWrite(Enable,LOW); // send a pulse to enable
delayMicroseconds(1);
digitalWrite(Enable,HIGH);
delayMicroseconds(1);
digitalWrite(Enable,LOW);
delayMicroseconds(1); // pause 1 ms according to datasheet
delay(1);

for (i=DB[0]; i <= DB[3]; i++) { // second part of the second 4 bits (from 8)
digitalWrite(i,value & 01);
value >>= 1;
}
value >>= 4; // send the RW and DI of the second 4 bits(from 8)
for (i=RW; i <= DI; i++) {
digitalWrite(i,value & 01);
value >>= 1;
}
digitalWrite(Enable,LOW); // send a pulse to enable
delayMicroseconds(1000);
digitalWrite(Enable,HIGH);
delayMicroseconds(1000);
digitalWrite(Enable,LOW);
delayMicroseconds(1000); // pause 1 ms according to datasheet
}

void LcdDataWrite(int value) {
int i = 0;
int value1 = 0;
digitalWrite(DI, HIGH);
digitalWrite(RW, LOW);
value1 =value;
value1 >>= 4; //send the first 4 databits (from 8)
for (i=DB[0]; i <= DB[3]; i++) {
digitalWrite(i,value1 & 01);
value1 >>= 1;
}
digitalWrite(Enable,LOW); // send a pulse to enable
delayMicroseconds(1000);
digitalWrite(Enable,HIGH);
delayMicroseconds(1000);
digitalWrite(Enable,LOW);
delayMicroseconds(1000); // pause 1 ms according to datasheet
delay(1);
digitalWrite(DI, HIGH);
digitalWrite(RW, LOW);
for (i=DB[0]; i <= DB[3]; i++) {
digitalWrite(i,value & 01);
value >>= 1;
}
digitalWrite(Enable,LOW); // send a pulse to enable
delayMicroseconds(1000);
digitalWrite(Enable,HIGH);
delayMicroseconds(1000);
digitalWrite(Enable,LOW);
delayMicroseconds(1000); // pause 1 ms according to datasheet
}

// this function help us to write number over 9, easily in the lcd display

void LcdNumberWrite(int nr) {

int n1 = 0;
int n2 = 0;

n1 = n2 = nr;

n1 = n1 / 100;
LcdCommandWrite(560 + n1); //512 used to write data (see commands for character module)
n2 = (n2 - n1 * 100) / 10;
LcdCommandWrite(560 + n2); //512 used to write data (see commands for character module)
nr = nr - n1 *100 - n2 * 10;
LcdCommandWrite(560 + nr); //512 used to write data (see commands for character module)
}

void setup (void) {

//LM35 init
Serial.begin(9600); //open serial port, sets data rate to 9600 bps
analogReference(INTERNAL);

//LCD init
int i = 0;
for (i=Enable; i <= DI; i++) {
pinMode(i,OUTPUT);
}
delay(100);
// initiatize lcd after a short pause
// needed by the LCD controller

///////////////////////////////////////////////////// 4 pin initialization
LcdCommandWrite(0x03); // function set:
// 4 pin initialization
delay(64);
LcdCommandWrite(0x03); // function set:
// 4 pin initialization
delay(50);
LcdCommandWrite(0x03); // function set:
// 4 pin initialization
delay(50);
LcdCommandWrite(0x02); // function set:
// 4 pin initialization
delay(50);
LcdCommandWrite(0x28); // function set:
// 4-bit interface, 2 display lines, 5x7 font
///////////////////////////////////////////////////// end of 4 pin initialization
delay(20);
LcdCommandWrite(0x06); // entry mode set:
// increment automatically, no display shift
delay(20);
LcdCommandWrite(0x0E); // display control:
// turn display on, cursor on, no blinking
delay(20);
LcdCommandWrite(0x01); // clear display, set cursor position to zero
delay(100);

LcdCommandWrite(0x80); // display control:
delay(20);

//////// under this line are the special stuff you don't need for a initialization

LcdCommandWrite(0x0F); // cursor blink
delay(10);
}

void loop (void) {

tempC = analogRead(tempPin); //read the analog value from the sensor
tempC = (1.1 * tempC * 100.0)/1024; //convert the analog data to temperature
tempD=tempC*100;
Serial.println(tempC); //send the data to the computer for debug

//>>>>>>>>>>>>>>>>>>>>>>>>>>>possible commands for the Lcd Display>>>>>>><< able to use for LcdDisplays with 4 or with 8 DataPins

//LcdCommandWrite(0x01); // clear display, set the cursor to home position
//LcdCommandWrite(0x02); // set cursor position to zero
//LcdCommandWrite(0x0A); // set the display off
//LcdCommandWrite(0x0E); // set the display on and with out cursor blink
//LcdCommandWrite(0x0F); // set the display on and with cursor blink
//LcdCommandWrite(0x0F); // cursor blink
//LcdCommandWrite(0x0E); // cursor not blink
//LcdCommandWrite(0x18); // shift display and cursor to the left
//LcdCommandWrite(0x1c); // shift display and cursor to the right
//LcdCommandWrite(0x14); // shift cursor to the right
//LcdCommandWrite(0x10); // shift cursor to the left

//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> example <<<<<<<<<

LcdCommandWrite(0x02); // set cursor position to zero
delay(10);

// Write the message
//like this
//LcdDataWrite('I');
//and Number over 9 easely like this
//LcdNumberWrite(4);

//first msg
for ( count = 0; count<=7; count++) {
int wrote [] = { 'I', 'T', 's', 'y', 's', 't', 'e', 'm'};
LcdDataWrite(wrote[count]);
}
LcdCommandWrite(0xC0); //enable second line (2nd 8 chars for an 1X16 LCD)
delay(20);
for ( count = 0; count<=7; count++) {
int wrote [] = { ' ', 'G', 'a', 'd', 'g', 'e', 't', 's'};
LcdDataWrite(wrote[count]);
}
delay(3000);

//scroll right
for ( count = 0; count<=7; count++) {
delay(500);
LcdCommandWrite(0x1c); //shift display & cursor to the right
}

LcdCommandWrite(0x01); //clear display
delay(1000);

//blink message 3 times
for ( blink_count = 0; blink_count<=2; blink_count++) {
//first 8 chars of message
for ( count = 0; count<=7; count++) {
int wrote [] = { 'V', 'i', 's', 'i', 'o', 'T', 'h', 'e'};
LcdDataWrite(wrote[count]);
}
//second 8 chars of message
LcdCommandWrite(0xC0); //enable second line
delay(20);
for ( count = 0; count<=7; count++) {
int wrote [] = { 'r', 'm', ' ', '2', '0', '1', '1', ' '};
LcdDataWrite(wrote[count]);
}
delay(1000);
LcdCommandWrite(0x01);
delay(1000);
}

//tempDisplay
LcdCommandWrite(0x01);
delay(1000);
tempDisplay(tempD);
delay(5000);
}

//temp reading calculation function
void tempDisplay(int value)
{
int first, second, third, fourth;

first = value / 1000;
second = (value - 1000 * first)/ 100;
third = (value - 1000 * first - 100 * second)/ 10;
fourth = (value - 1000 * first - 100 * second - 10 * third);

LcdDataWrite(' ');
LcdDataWrite(' ');
LcdDataWrite(' ');
LcdDataWrite(' ');
LcdDataWrite(' ');
LcdDataWrite(value > 999 ? first + 48 : ' '); // begin onscreen
LcdDataWrite(value > 99 ? second + 48 : ' ');
LcdDataWrite('.');
LcdCommandWrite(0xC0);
LcdDataWrite(third + 48);
LcdDataWrite(fourth + 48);
LcdDataWrite(0xDF);

}

2 σχόλια:

  1. Πολύ πολύ ενδιαφέρον και χρήσιμο. Σκέφτομαι το πρώτο μου arduino project να είναι θερμοστάστης δωματίου για θέρμανση (αν και ο πρώτος κώδικας που hardware που βλέπω για οθόνη είναι ο δικός σου).
    Επίσης οι κοινοί θερμοστάτες μόλις φτάσουν την θερμοκρασία που έχεις ορίσει ενώ ανοίγει η επαφή του ρελε, δεν λαμβάνουν υπόψη τους το γεγονός ότι για κάποια λεπτά ακόμη συνεχίζει να κυκλοφορεί ζεστό νερό στα σώματα και η πραγματική θερμοκρασία ξεπερνά αυτή που έχει οριστεί στον κοινό αυτό θερμοστάτη. Επίσης δεν υπάρχει ένας απλός χρονοδιακόπτης π.χ. των 15 λεπτών για ζεστένει νερό για μπάνιο το καλοκαίρι.
    Κάποιοι που κυκλοφορούν έτοιμοι στο εμπόριο τέτοιοι θερμοστάτες και με τις 2 παραπάνω λειτουργίες έχουν 120 ευρώ και ισχυρίζονται 25% οικονομία στην κατανάλωση. Πολλά δεν είναι τα 120 ευρώ;

    Τί κώδικα θα μπορούσα να βάλω για τον υπολογισμό αυτόυ του χρόνου;
    Εισόδους; π.χ. για καθορισμό θερμοκρασίας (ή αργότερα αφού πετύχει για καθορισμό εβδομαδιαίας λειτουργιας); Μπορεί να γίνει fully computer operated π.χ. από browser αντί χρήσης οθόνης;

    ΑπάντησηΔιαγραφή
  2. Χαίρομαι που βρήκες το project χρήσιμο!

    Για τη δική σου ιδέα νομίζω ότι θα μπορούσες να οδηγήσεις με ρελέ κάποιον κυκλοφορητή για τον έλεγχο της ροής του νερού ανάλογα με τη θερμοκρασία δωματίου. Θα πρότεινα τη συμβουλή κάποιου θερμοϋδραυλικού για να σου αναλύσει την αρχή λειτουργίας του όλου συστήματος ώστε να μη πηγαίνεις στα τυφλά.

    Όσο για το τελυταίο που ρωτάς, αυτό γίνεται κάλλιστα με κάποιο ethernet shield+library για να χτίσεις έναν απλό webserver που υπακούει σε http.

    ΑπάντησηΔιαγραφή