Skocz do zawartości

Zegarek binarny


Pomocna odpowiedź

Niedawno zacząłem zabawę z Arduino z kursem FORBOTa. Zabawa mnie wciągnęła i postanowiłem poskładać coś swojego. Tak powstał kolejny projekt na Arduino migający diodami LED 🙂 nic wielkiego.

Zawsze podobały mi się gadżety jakimi są zegarki binarne, więc postanowiłem zbudować swój własny. Wyświetla godzinę jako Binary Coded Decimal, bo uważam, że wygląda to ciekawiej niż tylko 3 rzędy LEDów.

Ponieważ nie chciałem używać diod adresowalnych, a wyjścia z Arduino są ograniczone wykorzystałem 3 rejestry przesuwne, każdy odpowiada za inną część czasu, w ten sposób wszystkie diody obsługiwane są z 3 pinów. Chciałem też, aby LEDy przygasały w nocy i świeciły jasno w dzień, dlatego wykorzystałem fotorezystor, a pomiędzy katodami diod a masą zainstalowałem tranzystor binarny sterowany przez PWM.

Obecnie zegarek prezentuje się tak: Gotowy prototyp - film na YT

Plany na dalszą przyszłość zakładają przeniesienie układu na PCB (ale to po nauce lutowania) i zmajstrowanie jakiejś ładnej obudowy. Prawdpodobnie dojdzie też kilka przycisków do ustawiania godziny, albo inny sposób synchronizacji czasu (obecnie czas przesyłam przy inicjalizacji układu przez Serial). Zamierzam też zrezygnować z pełnego Arduino i zapewne skorzystać z układu ATTiny.

Jestem otwarty na uwagi co jeszcze można poprawić lub dodać do układu.

Zastanawiam się też nad kwestią trazystora. Używam w tej chwili BC546B, bo taki miałem z zestawów do nauki Arduino, ale ponieważ jego maksymalny prąd to 100mA, to nie jest chyba tu optymalny, bo momentami zegarek może mieć włączone 14 LEDów, przy maksymalnej jasności 100mA to chyba trochę mało.

//Definicja używanych pinów Arduino i zmiennych
#define clockPin 8
#define dataPin 10
#define latchPin 9
#define pwmPin  6

byte hour = 0;
byte minute = 0;
byte second = 0;

void setup() {
  //Ustawienie pinów jako wyjścia
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  pinMode(latchPin, OUTPUT);
  pinMode(pwmPin, OUTPUT);

  Serial.begin(9600);
  while (!Serial) {
  }
  //Oczekiwanie na ustawienie czasu przez Serial
  while (Serial.available() < 1) {
  }
  //Czekamy na dane w formacie hhmmss
  long timeMsg = Serial.readString().toInt();
  second = timeMsg % 100;
  timeMsg = (timeMsg - second) / 100;
  minute = timeMsg % 100;
  hour = (timeMsg - minute) / 100;
  Serial.print(hour);
  Serial.print('\t');
  Serial.print(minute);
  Serial.print('\t');
  Serial.println(second);
}

//Inicjalizacja zmiennych czasu głównej pętli
unsigned long czasPoprzedni = 0;
unsigned long czasTeraz = 0;
unsigned long interval = 1000;

//Ustawienie zależności jasności LED od natężenia światła zewnętrznego
int minExtBrightness = 0;  //Zakres 0 - 1023
int maxExtBrightness = 600; //Zakres 0 - 1023
int minLedBrightness = 2; //Zakres 0 - 255
int maxLedBrightness = 255; //Zakres 0 - 255

void loop() {
  //Pętla główna, wykonywana co ustawiony interwał, domyślnie 1 sekunda
  czasTeraz = millis();
  if ( czasTeraz >= (czasPoprzedni + interval)) {
    czasPoprzedni = czasTeraz;

    //Funkcja wysyłająca czas do rejestrów przesuwnych
    shiftTime(hour, minute, second);

    //Odczyt jasności z fotorezystora i przeskalowanie do zakresu wyjścia PWM
    analogWrite(pwmPin, map(analogRead(A0), minExtBrightness, maxExtBrightness, minLedBrightness, maxLedBrightness));

    //Funkcja zmieniająca czas o sekundę do przodu
    timeTick();
  }
}

//Funkcja zmieniająca czas o sekundę do przodu
void timeTick() {
  if (second < 59) {
    second +=  1;
  } else {
    second = 0;
    if (minute < 59) {
      minute += 1;
    } else {
      minute = 0;
      if (hour < 23) {
        hour += 1;
      } else {
        hour = 0;
      }
    }
  }
}

void shiftTime(byte hours, byte minutes, byte seconds) {
  int i = 0;
  int pinState;

  //Zerowanie wyjść, na wszelki wypadek
  digitalWrite(dataPin, 0);
  digitalWrite(clockPin, 0);

  //Rozpoczynamy zapisywanie rejestrów
  digitalWrite(latchPin, 0);

  //Godziny

  //Rozdzielenie godziny na dziesiątki i jedności
  byte hoursTens = trunc(hours / 10);
  byte hoursOnes = hours - hoursTens * 10;

  //Przesłanie dziesiętnej części godziny
  for (i = 1; i >= 0; i--) {
    if (hoursTens & (1 << i)) {
      pinState = 1;
    } else {
      pinState = 0;
    }
    digitalWrite(clockPin, 0);
    digitalWrite(dataPin, pinState);  //Wysłanie wartości do rejestru
    digitalWrite(clockPin, 1);
  }
  //Przesłanie jedynkowej części godziny
  for (i = 4; i >= 0; i--) {
    if (i == 0) { //Nie używam wyjścia Q0 z rejestru, jego stan ustawiam na 0
      pinState = 0;
    } else if (hoursOnes & (1 << i - 1)) { //Przesunięcie bitowe w lewo o (i - 1), ponownie z racji nieużywanego wyjścia Q0
      pinState = 1;
    } else {
      pinState = 0;
    }
    digitalWrite(clockPin, 0);
    digitalWrite(dataPin, pinState);  //Wysłanie wartości do rejestru
    digitalWrite(clockPin, 1);
  }

  //Minuty

  //Wszystko dzieje się analogicznie do przesyłania godziny
  //Jedyna różnica, to i = 2, zamiast i = 1 przy przesyłaniu dziesiętnej części minut, z racji większego zakresu
  byte minutesTens = trunc(minutes / 10);
  byte minutesOnes = minutes - minutesTens * 10;
  for (i = 2; i >= 0; i--) {
    if (minutesTens & (1 << i)) {
      pinState = 1;
    } else {
      pinState = 0;
    }
    digitalWrite(clockPin, 0);
    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, 1);
  }
  for (i = 4; i >= 0; i--) {
    if (i == 0) {
      pinState = 0;
    } else if (minutesOnes & (1 << i - 1)) {
      pinState = 1;
    } else {
      pinState = 0;
    }
    digitalWrite(clockPin, 0);
    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, 1);
  }

  //Sekundy
  //Analogicznie jak w przypadku minut
  byte secondsTens = trunc(seconds / 10);
  byte secondsOnes = seconds - secondsTens * 10;
  for (i = 2; i >= 0; i--) {
    if (secondsTens & (1 << i)) {
      pinState = 1;
    } else {
      pinState = 0;
    }
    digitalWrite(clockPin, 0);
    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, 1);
  }
  for (i = 4; i >= 0; i--) {
    if (i == 0) {
      pinState = 0;
    } else if (secondsOnes & (1 << i - 1)) {
      pinState = 1;
    } else {
      pinState = 0;
    }
    digitalWrite(clockPin, 0);
    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, 1);
  }
  //Koniec wysyłania danych do rejestru, ustawienie wartości wyjść zgodnie ze stanem w pamięci rejestru
  digitalWrite(latchPin, 1);

}

 

Schematic_Binary-Clock_Sheet-1_20180902133910.png

  • Lubię! 2
Link do komentarza
Share on other sites

Ho, ho, fajny projekt. Miło gdy ktoś pokazuje swój dorobek a nie ściągniętego z sieci gotowca.

W sprawie modulacji jasności: użyj wejść /OE rejestrów. Te piny sterują załączaniem driverów wyjściowych więc jeśli tam podepniesz swój PWM, to w stanie 0 będzie jak teraz a w stanie 1 wszystkie diody zgasną. Ponieważ jest to całkowicie niezależne od pozostałych funkcji rejestru, z niczym nie koliduje i za darmo masz "bezmocowe" sterowanie całym polem LEDów. Tranzystor możesz wtedy oczywiście wyrzucić.

Jako "klawiatury" do programowania np. czasu możesz użyć odbionika IR. Przyciski zajmują dużo miejsca a to jest mały element, no i tylko jeden. Wygodny pilot IR może być wzięty od jakiegoś sprzętu AV lub kupiony jakiś najtańszy. Co prawda widziałem zegarki itp urządzenia programowane jednym(!) przyciskiem, ale to katorga - nikomu nie życzę. Na dwóch już latwiej.

Możesz użyć malutkich LEDów SMD, w obudowach np. 0603 lub trochę większych 0805. Takie cosie już przy prądach <1mA a świecą niewiarygodnie jasno, a przecież zegarek to zwykle bateryjny jest. W ogóle pomyśl teraz o zmniejszeniu prądożerności. Procesor nie musi pracować wciąż z pełną prędkością. Zainteresuj się trybami obniżonych poborów mocy, np. IDLE. To bez problemu możesz tu zaimplementować i z kilkunastu mA od razu robi się kilka, bo większość czasu spędzasz przecież na oczekiwaniu na upłynięcie sekundy.

W sumie: gratulacje. Pokaz jeszcze jak to cudo wygląda i jak masz zamiar zrobić to docelowo.

Z pomysłów na przyszłość to kilka trywialnych: programowany budzik/alarm, załączanie czegoś (jeżeli zegarek nie jest planowany jako naręczny oczywiście), wyświetlanie daty i dnia tygodnia, melodyjki, specjalna sekwencja klawiszy (jeżeli będą) wyłączająca alarm (żeby było trudniej go zignorować rano), skorzystanie z pinów dodatkowego kwarcu 32kHz dla timera 2 - wtedy możesz zejść z prądem procesora do pojedynczych uA itd..

EDIT: Rejestrom HC595 o wiele bardziej potrzebne są malutkie, ceramiczne 100nF niż te mikrofarady. 

Edytowano przez marek1707
  • Lubię! 1
Link do komentarza
Share on other sites

Dziękuję za porady. Faktycznie, sterowanie jasnością przez OE działa bez zarzutu, kondensatory wymienię.

W pierwszym poście jest link do filmiku na YT, który pokazuje jak to obecnie wygląda w działaniu. Załączam jeszcze zdjęcia:

20180902_161149.thumb.jpg.3ab0639be0a9a6b6d80e505cafb3be9a.jpg20180902_161211.thumb.jpg.e5c22c595a631484c99181ebd46e6a3a.jpg

Faktycznie, pobór prądu przydałoby się zmniejszyc, w tej chwili bez zasilacza nie ma opcji, zasilanie bateryjne dla zegarka byłoby dużo lepsze. Pytanie czy jeśli nigdy nie miałem lutownicy w ręku to czy dam radę z LEDami SMD? Obniżenie zużycia energii przez kontroler też w takim razie sprawdzę.

 

Jeśli chodzi o docelowy wygląd to jeszcze tego do końca nie przemyślałem, ale raczej nie chciałbym tego wrzucać do zwykłej plastikowej obudowy.

Podoba mi się na przykład taki projekt:

maxresdefault.jpg

Alternatywnie zastanawiałem się czy jestem temu w stanie nadać steampunkowy wygląd.

  • Lubię! 2
Link do komentarza
Share on other sites

Moim zdaniem wartości binarne łatwiej się odczytuje gdy paski diod leżą poziomo. Tak więc trzeba zrobić albo bardzo szeroką i płaską obudowę, tak by godziny były po lewej a sekundy (czy rzeczywiście są potrzebne?) po prawej, albo w pionie - czyli godziny na górze i w dół kolejne wartości. Poeksperymentuj z tym na sobie lub znajomych. Nie wiem, czy różne kolory diod to zaleta. Spada czytelność, w końcu to nie dyskoteka tylko jednak zegar - bedzie stał w pokoju i świecił miesiącami. Nie może męczyć ani drażnić. W wersji docelowej dałbym wszystkie diody takie same i bardziej naturalne, może coś spokojniejszego typu zielone lub są takie fajne pomarańczowe lub nawet żółte, ale na pewno ani czerwone ani niebieskie.

W wykonaniu steampunk obowiązkowa metalowo-drewniana obudowa (blacha mosiężna na okucia, nity, lakier na drewnie itp) plus koniecznie żarówki i to świecące tak na połowie mocy, np. 12-woltowe (samochodowe 1W?) napędzane z 6-8V. Żadne tam LEDy. Jakaś wystająca i wracająca do wnętrza rurka miedziana lub dwie i +10 do wyglądu. Możesz dodać sygnalizator dźwiękowy (jakiś mały głośniczek, są takie o średnicy nawet 10mm) udający ciche cykanie mechanizmu.

Przy diodach LED potrzebujących 10-20mA to walka o procesor trochę nie ma sensu, ale gdybyś zszedł z poborem każdego punktu do 1mA, to już warto. Zakładając, że średnio świeci 6 diodek (tylko godziny i minuty) to masz 6mA. Do tego procesor powiedzmy 2 i masz w sumie 8mA. Z jednego taniego akumulatora 18650/2Ah masz wtedy 250h czyli ponad 10 dni autonomicznej pracy po naładowaniu. A jeśli zdecydujesz się na zasilanie sieciowe (np. z 5V z typowego zasilacza lub z kompa przez gniazdko USB), to daj chociaż jakiąś małą baterię do podtrzymania pracy w czasie awarii sieci AC.

 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.