INFORMACJA: Poniższy post nie wydostał się z Poczekalni :(
1. Wstęp
Dzisiaj pokażę jak zrobić prosty (dla niektórych może być trochę skomplikowany) zegarek z termometrem na Arduino. Szukałem w necie różnych zegarów, pobierałem a te nie miały “zero paddingu” (poprzedzania zerami liczb jednocyfrowych) albo pokazywały temperaturę zupełnie dziwną typu -140°C lub +89°C. Zrobiłem po swojemu. Ten zegar wykorzystuje czujnik temperatury LM335 i wyświetlacz LCD.
2. Co będzie potrzebne?
Potrzebne będą:
– Arduino (w moim przypadku UNO R3)
– głośnik 8-ohm ok. 0.5W (aby zegar wygrywał melodyjkę co godzinę)
– ok. 15-20 kabelków połączeniowych/drutów
– potencjometr 10kOhm
– 3 “buttony”
– 2x czujnik temp. LM335A
– płytka stykowa (tzw. breadboard)
– kabel USB A-B
– 3 rezystory 220Ohm i 1 2kOhm.
Oczywiście można kupić zestawy z większością tych części na przykład tutaj.
To tyle. Przejdźmy do realizacji!
3. Jak to zrobić?
Oczywiście trzeba mieć na komputerze program Arduino IDE do pobrania tutaj. Załączam obrazek tego programu:
Gdy już mamy program musimy połączyć wszystkie kable i części. Zrobiłem projekt w programie Fritzing:
Nie wygląda to zbyt imponująco, ponieważ mam tylko 11 lat, więc dodaję schemat i wyjaśniam:
Nie miałem LM35 więc zamiast LM35 użyjemy LM335 (schemat i breadboard jest do LM335!)
Lista połączeń wyświetlacza z Arduino:
Przed podłączeniem sprawdź swój typ wyświetlacza. Za uszkodzenie przez nieprawidłowe podłączenie ja nie odpowiadam.
LCD | Arduino |
pin 1 | GND |
pin 2 | +5V |
pin 3 | potencjometr 10kOhm (opis niżej) |
pin 4 | digital pin 5 |
pin 5 | GND |
pin 6 | digital pin 7 |
pin 7 | (nie podłączone) |
pin 8 | (nie podłączone) |
pin 9 | (nie podłączone) |
pin 10 | (nie podłączone) |
pin 11 | digital pin 9 |
pin 12 | digital pin 10 |
pin 13 | digital pin 11 |
pin 14 | digital pin12 |
pin 15 | +5V |
pin 16 | GND |
Potencjometr podłączyć tak: 1 nóżka do +5V, 2 nóżka do LCD pin 3, 3 nóżka do GND.
Inne połączenia:
głośnik | minus do GND, plus do digital pin 4 (Arduino) |
1. button | 1 nóżka do GND, druga nóżka do digital
pin 1 i przez rezystor 220Ohm do +5V |
2. button | 1 nóżka do GND, druga nóżka do digital pin 2 i przez rezystor 220Ohm do +5V |
3. button | 1 nóżka do GND, druga nóżka do digital
pin 2 i przez rezystor 220Ohm do +5V |
1. LM335 | od lewej: 2 nóżka do analog pin 0 i przez rezystor 2kOhm do +5V, 3 nóżka do GND |
2. LM335 | od lewej: 2 nóżka do analog pin 1 i przez
rezystor 2kOhm do +5V, 3 nóżka do GND |
4. Programowanie
Teraz, gdy mamy już wszystko podłączone trzeba zacząć programować. Otwieramy program Arduino IDE. Wpisujemy podany niżej kod programu:
/* Clock with thermometer - uses a 16x2 LCD display with Hitachi HD44780 driver The circuit: * LCD RS pin to digital pin 5 * LCD R/W pin to GND * LCD Enable pin to digital pin 7 * LCD D4 pin to digital pin 9 * LCD D5 pin to digital pin 10 * LCD D6 pin to digital pin 11 * LCD D7 pin to digital pin 12 * 10K resistor: - ends to +5V and ground - wiper to LCD VO pin (pin 3) * LM335A: - first to "nothing" - second pin to analog pin 0 and to +5V (with 2kohm resistor) - third pin to GND * 4 buttons: - first from GND to digital pin 1 - second from GND to digital pin 2 - third from GND to digital pin 3 - fourth from GND to RESET pin * 220 ohm resistor from +5V to digital pin 1 * 220 ohm resistor from +5V to digital pin 2 * 220 ohm resistor from +5V to digital pin 3 * 8 ohm speaker from digital pin 4 to GND */ // include the library codes: #include <LiquidCrystal.h> #include <EEPROM.h> #include "pitches.h" // initialize the library with the numbers of the interface pins: LiquidCrystal lcd(5,7,9,10,11,12); // makes first melody: int melody1dur[] = {4, 8, 8, 8}; int melody1[] = {NOTE_C4, NOTE_G3, NOTE_F3, NOTE_G3}; // sets....: double pomiar1, pomiar2, temp1, temp2; int second=0, minute=0, hour=0, day=1, month=1, year=2000, hourPin = 2, minutePin = 3, optionPin = 1, option=1; int addr=0, address=0; char* hellotext1="Zegar"; char* hellotext2="--text--"; char* version="2.4"; byte value; // define your char!: // 1=point, 0=nothing // 0b11111 = first line be black // 0b11111 = second line be black // 0b11111 = third line ..... byte znak[8] = { 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11111 }; // sets irregular chars: byte arms0[8] = { 0b00100, 0b01010, 0b00100, 0b00100, 0b11111, 0b00100, 0b00100, 0b01010 }; byte arms1[8] = { 0b00100, 0b01010, 0b00100, 0b00101, 0b01110, 0b10100, 0b00100, 0b01010 }; byte arms2[8] = { 0b00100, 0b01010, 0b00100, 0b10100, 0b01110, 0b00101, 0b00100, 0b01010 }; void setup() { // sets up irregular chars: lcd.createChar(1, znak); lcd.createChar(2, arms0); lcd.createChar(3, arms1); lcd.createChar(4, arms2); // set up the LCD's number of columns and rows: lcd.begin(16,2); // clears the LCD: lcd.clear(); // defines pins (INPUTs or OUTPUTs): pinMode(A0, INPUT); pinMode(A2, INPUT); pinMode(A3, INPUT); pinMode(hourPin, INPUT); pinMode(minutePin, INPUT); lcd.home(); // prints start page on the LCD: lcd.print(hellotext1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.setCursor(0, 1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.print(hellotext2); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); lcd.write(1); delay(2500); lcd.clear(); lcd.print("Version "); lcd.print(version); lcd.setCursor(0, 1); lcd.print("Loading..."); // prints a dancing man on the LCD lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(3); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(4); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(3); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(4); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(3); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(4); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(3); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(4); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(3); delay(100); lcd.setCursor(11, 1); lcd.write(2); delay(100); lcd.setCursor(11, 1); lcd.write(4); delay(100); lcd.setCursor(11, 1); lcd.write(5); lcd.clear(); for (int i = 0; i<16; i++) { lcd.print("."); delay(100); } lcd.setCursor(0,1); for (int i = 0; i<16; i++) { lcd.print("."); delay(100); } lcd.clear(); // reads date and time from the EEPROM memory (if available): hour=EEPROM.read(1); minute=EEPROM.read(2); second=EEPROM.read(3); day=EEPROM.read(4); month=EEPROM.read(5); year=EEPROM.read(6); } void loop(){ lcd.setCursor(0,0); // time counting: static unsigned long lastTick = 0; if (millis() - lastTick >= 1000) { lastTick = millis(); second++; } if (second >= 60) { minute++; second = 0;} if (minute >= 60) { hour++; minute = 0; melody1play();} if (hour >= 24) { day++; hour = 0;} if (day >= 30) { month++; day=0;} if (month>= 12) { year++; month= 0; melody2play();} if(digitalRead(minutePin)==0) { minute++; } if(digitalRead(hourPin)==0) { hour++; } // displays time: lcd.print(hour); lcd.print(":"); if (minute<10) { lcd.print(0); lcd.print(minute); } else { lcd.print(minute); } lcd.print(":"); if (second<10) { lcd.print(0); lcd.print(second); } else { lcd.print(second); } lcd.print(" "); lcd.setCursor(11,0); /*if (digitalRead(optionPin)==1) { lcd.print(""); } else { lcd.write(1); } if (digitalRead(hourPin)==1) { lcd.print(""); } else { lcd.write(1); } if (digitalRead(minutePin)==1) { lcd.print(""); } else { lcd.write(1); }*/ // save to EEPROM memory: EEPROM.write(1, hour); EEPROM.write(2, minute); EEPROM.write(3, second); EEPROM.write(4, day); EEPROM.write(5, month); EEPROM.write(6, year); // check for button push: delay(500); check(); delay(500); check(); } void check() { // if option button is pushed: if(digitalRead(optionPin)==LOW) {option=option+1; } lcd.setCursor(0,1); if(option ==1) { lcd.print(day); lcd.print("-"); lcd.print(month); lcd.print("-"); lcd.print(year); lcd.print(" "); } if(option ==2){ pomiar1 = analogRead(A0)*5/1024.0; temp1 = pomiar1 - 0.5; temp1 = temp1 / 0.01; pomiar2=analogRead(A1); temp2= (2.36 pomiar2 100 )/1024.0; lcd.setCursor(0,1); lcd.print("W:"); lcd.print(temp1,1); lcd.print("C "); lcd.setCursor(9,1); lcd.print("Z:"); lcd.print(temp2,1); lcd.print("C "); } if(option ==3){option=1;} // if EEPROM clear button (optionally) on digital pin 8 is pushed: if(digitalRead(8)==LOW) { /*for (int i = 0; i < 512; i++) EEPROM.write(i, 0); lcd.clear(); lcd.home(); lcd.print("EEPROM cleared."); hour=0; minute=00; second=00; day=25; month=10; year=2013; lcd.setCursor(0, 1); lcd.print(hour); lcd.print(":"); lcd.print(minute); lcd.print(":"); lcd.print(second); lcd.print(","); lcd.print(day); lcd.print("-"); lcd.print(month); lcd.print("-"); lcd.print(year); delay(2000); lcd.clear();*/ } } void melody1play() { // plays first melody (one per hour): for (int m1thisNote = 0; m1thisNote < 4; m1thisNote++) { int m1noteDuration = 1000/melody1dur[m1thisNote]; tone(4, melody1[m1thisNote],m1noteDuration); int m1pauseBetweenNotes = m1noteDuration * 1.30; delay(m1pauseBetweenNotes); noTone(4); } }
Pewnie zastanawiacie się co można zmienić na własne potrzeby. Otóż zmienne zadeklarowane na początku programu, czyli hellotext1 i hellotext2 można zmienić (zaawansowani pewnie umieją zmienić wszystko). Wtedy zegar będzie wyświetlał te teksty po podłączeniu zasilania. Zegar też pokazuje wersję “sprzętu” zapisaną w zmiennej version. Ale uwaga! Ona musi mieć wartość integer, czyli liczbę (ostatecznie z kropką). Gdy zmienna version będzie równa 1.5, wtedy zegar wyświetli ‘Version 1.5‘. Po wersji zegar wyświetla ‘Loading‘ i – mały skromny dodatek – tańczącego ludka. Gdy tańczenie mu się znudzi na ekranie będzie przybywać kropek i w końcu pokaże się godzina. Zmienić godzinę można przez naciśnięcie którychś z buttonów (ten na pinie 2 to minuty, a ten na 3 to godziny). A po co ten trzeci? Służy on do zmieniania opcji. Opcja to tekst, który wyświetla się w drugiej linijce ekranu. Jest to albo data albo temperatura. Co do melodii można je zmienić w zmiennych melody1, ale napiszę to w następnej aktualizacji. Przypominam, że melodia 1. gra co godzinę.
Więcej o termometrze w następnej aktualizacji.
To był mój pierwszy post, więc jak macie zastrzeżenia to piszcie.
kuba2k2
INFORMACJA: Poniższy post nie wydostał się z Poczekalni :(
Na serio masz 11 lat?
Też o tym pomyślałem. :]
Właśnie miałem o to zapytać.
skoro masz 11 lat to świetny projekt jednak kilka rad na przyszłość – nie nadaje sie to na zegarek – nie jesteś w stanie wygenerować idealnej sekundy w przerwaniach na atmedze więc niedługo spodziewaj się duuuuzych błędów w godzinie, do tego stosuje się zewnętrzne układy zegarowe, polecam pcf8583
Dzięki wszystkim za rady, poprawiłem kilka błędów i na serio mam 11lat. Niedługo dodam ten zewnętrzny zegar.
Jak Donau napisał to rzeczywiście przyznaję, że miałem wizytę Spidermana :-) :-) :-)
przeleciałem to sobie na szybko i jedyne co kuje oczy to schemat, że masz 11 lat to nie zwalnia cię to z rysowania dobrych schematów, musisz to zmienić ponieważ przyzwyczaisz się do tego i dalej będziesz takie rysował, jestem niewiele starszy od ciebie a rysuje poprawne schematy
trzeba przyznać że jak na te !! lat to poradziłeś sobie nieźle . Z pewnościa z czasem nabierzesz wprawy i zredukujesz program po przez stosowanie własnych procedur. a co do schematów to podstawa elektronika i tu ma racje “Tomek” .
czy ma ktoś pomysł co zrobić aby zamiast przekreślonego zera na wyświetlaczu lcd , pojawiało zero takie jak duża litera “O” ?