Google+

Πέμπτη 24 Φεβρουαρίου 2011

Use 2 or 3 wires for Arduino <-> LCD interface

Το "κακό" με τις LCD που χρησιμοποιούν τον ελεγκτή της σειράς HD447xx είναι, ότι δεσμεύεις τουλάχιστον 7 pin στο Arduino για τον "οδηγήσεις" (4 -αν όχι 8- για data και 3 για enable, r/w, reset) οπότε, σου περισσεύουν λιγότερα pin για άλλα, πιο χρήσιμα για την κατασκευή σου όπως αιθητήρες, διακόπτες, led, κουμπιά κτλ.

Για το παραπάνω πρόβλημα υπάρχουν 2 λύσεις :

1. βρίσκεις/αγοράζεις μια έτοιμη serial LCD που δεσμεύει λιγότερα pin
2. κατασκευάζεις μια serial LCD χρησιμοποιώντας καταχωρητή ολίσθησης-shift register για να οδηγήσεις thν υπάρχουσα "παράλληλη" LCD με τον HD447xx

Ειδικότερα για το 2. έχει δημιουργηθεί library(ShiftRegLCD) και schematic για την χρήση του 74LS164 ως καταχωρητή ολίσθησης που θα βρείτε εδώ.

Μερικές φώτο από μια δοκιμή με 74LS164 :


3 καλώδια πράσινο(clk), πορτοκαλί(data), κίτρινο(enable).


full working set : lcd(κάτω), arduino(πάνω), 74ls164(δεξιά)


μερικοί custom characters από τα example codes της library

Τέλος, ένα pdf με λίγη θεωρία για τους καταχωρητές ολίσθησης.

PS. Many thanx @efxa για το tip με τη library!

Δευτέρα 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);

}