[137] Budujemy licznik (nie tylko) do magnetofonu cz. 3
![[137] Budujemy licznik (nie tylko) do magnetofonu cz. 3](/_next/image?url=https%3A%2F%2Farduino.pl%2Fimgproxy%2F594wt9wDrX_Te5cnkH9HDGHHwSgvFII4W5KqdQfwFug%2Ff%3Awebp%2Fw%3A1200%2FbG9jYWw6Ly8vaW1hZ2VzLzAtNjkyLzg3ODVkLzdmZDM1LzAtNjkyODc4NWQ3ZmQzNTAzMzA3MzgyMS5wbmc%3D.webp&w=3840&q=75)
Ponieważ część szkicu związaną z wyświetlaniem stanu licznika dokładnie omówiłem w pierwszym artykule serii, skupię się teraz na elementach realizujących zamianę sygnałów z enkodera – przedstawionego w drugiej części – na zmianę wartości licznika.
#include <TimerOne.h> // Biblioteka obsługi przerwań.
const byte segmenty[7] = { 6, 5, 4, 3, 2, 1, 0 }; // Adresy portów kolejnych segmentów: od A do G
const byte katody[4] = { A0, A1, A2, A3 }; // Adresy portów wspólnych wyprowadzeń (katod) kolejnych wyświetlaczy.
const byte reset = 8; // Adres przycisku resetującego licznik.
const byte fotoLewy = A4; // Adresy portów fototranzystorów.
const byte fotoPrawy = A5;
volatile byte cyfry[4] = { 0, 0, 0, 0 }; // Tablica z cyframi, którą wyświetla przerwanie.
volatile byte aktywnaCyfra = 0; // Aktualnie świecąca się cyfra w multipleksie.
int licznik = 0; // Zmienna przechowująca stan licznika obrotów.
bool poprzedniFotoLewy; // Zmienne poprzedniego stanu fototranzystorów.
bool poprzedniFotoPrawy;
const byte ksztalty[10] = {
B1111110, // 0, Tablica zawierająca wzorce znaków wyświetlacza siedmiosegmentowego.
B0110000, // 1, Schemat: A-B-C-D-E-F-G
B1101101, // 2
B1111001, // 3
B0110011, // 4
B1011011, // 5
B1011111, // 6
B1110000, // 7
B1111111, // 8
B1111011 // 9
};
void setup() {
for (byte x = 0; x < 7; x++) // Deklaruj porty kolejnych segmentów wyświetlaczy.
pinMode(segmenty[x], OUTPUT);
for (byte x = 0; x < 4; x++) { // Dla każdej katody wyświetlacza...
pinMode(katody[x], OUTPUT); // Deklaruj porty.
digitalWrite(katody[x], HIGH); // Odłącz napięcie.
}
pinMode(reset, INPUT_PULLUP); // Deklaruj port przycisku resetującego licznik.
pinMode(fotoLewy, INPUT); // Deklaruj porty fototranzystorów.
pinMode(fotoPrawy, INPUT);
poprzedniFotoLewy = digitalRead(fotoLewy); // Załaduj stany fototranzystorów.
poprzedniFotoPrawy = digitalRead(fotoPrawy);
Timer1.initialize(1000); // Ustaw przerwania na milisekundę.
Timer1.attachInterrupt(przerwanie); // Włącz przerwania z określeniem miejsca lądowania.
}
void loop() {
if (digitalRead(reset) == HIGH) { // Jeśli wciśnięto przycisk resetu...
licznik = 0; // Resetuj licznik.
przeladuj(); // Odśwież stan wyświetlacza.
}
bool aktualnyFotoLewy = digitalRead(fotoLewy); // Załaduj stany fototranzystorów.
bool aktualnyFotoPrawy = digitalRead(fotoPrawy);
if (aktualnyFotoLewy != poprzedniFotoLewy || aktualnyFotoPrawy != poprzedniFotoPrawy) { // Jeśli nastąpiła jakakolwiek zmiana stanu fotorezystorów...
if (poprzedniFotoLewy != aktualnyFotoLewy && aktualnyFotoPrawy == LOW) { // Zidentyfikuj interesującą nas sekwencję.
licznik += (aktualnyFotoLewy == HIGH) ? 1 : -1; // W zależności od stanu lewego fototranzystora zwiększ lub zmniejsz stan licznika.
}
poprzedniFotoLewy = aktualnyFotoLewy; // Zapamiętaj stany fototranzystorów do kolejnej analizy.
poprzedniFotoPrawy = aktualnyFotoPrawy;
licznik = (licznik + 10000) % 10000; // Ogranicz zliczanie do przedziału 0...9999
przeladuj();
}
}
void przeladuj() {
cyfry[0] = (licznik / 1000) % 10; // Załaduj do tablicy cyfry reprezentujące wartość licznika.
cyfry[1] = (licznik / 100) % 10;
cyfry[2] = (licznik / 10) % 10;
cyfry[3] = licznik % 10;
}
void przerwanie() { // Obsługa przerwania.
for (byte x = 0; x < 4; x++) // Odłącz napięcie od wszystkich katod wyświetlaczy.
digitalWrite(katody[x], HIGH);
byte y = ksztalty[cyfry[aktywnaCyfra]]; // Wyprowadź kształt do wyświetlenia.
for (byte x = 0; x < 7; x++) // Zaświeć odpowiednie segmenty aktywnej pozycji wyświetlacza.
digitalWrite(segmenty[x], (y & (1 << (6 - x))));
digitalWrite(katody[aktywnaCyfra], LOW); // Zaświeć aktywny wyświetlacz.
aktywnaCyfra = (aktywnaCyfra + 1) % 4; // Zwiększ wartość aktywnego wyświetlacza modulo 4
}W deklaracjach oczywiście będziemy potrzebowali portów enkodera oraz resetu – bo cóż to za licznik bez możliwości resetowania go w dowolnej chwili? Będą potrzebne jeszcze binarne zmienne przechowujące stany odczytanych sensorów: poprzedniFotoLewy i poprzedniFotoPrawy. Wszystkie zmiany nastąpią w pętli głównej. Na początek – obsłużymy sobie reset.
if (digitalRead(reset) == HIGH) { // Jeśli wciśnięto przycisk resetu...
licznik = 0; // Resetuj licznik.
przeladuj(); // Odśwież stan wyświetlacza.
}Sprawa jest prosta, jeśli zostanie wciśnięty, licznik zostanie wyzerowany. Podprogram przeładuj natychmiast zamieni wartość licznika na reprezentanta składającego się z czterech cyfr; to już było w poprzednim szkicu.
if (aktualnyFotoLewy != poprzedniFotoLewy || aktualnyFotoPrawy != poprzedniFotoPrawy) { // Jeśli nastąpiła jakakolwiek zmiana stanu fotorezystorów...Następnie ładujemy stany sensorów do zmiennych, jako „aktualne”. Kolejna linia porównuje stany aktualne z poprzednimi. Warunek będzie spełniony tylko wówczas, jeśli nastąpiła jakaś zmiana.
if (poprzedniFotoLewy != aktualnyFotoLewy && aktualnyFotoPrawy == LOW) { // Zidentyfikuj interesującą nas sekwencję.
licznik += (aktualnyFotoLewy == HIGH) ? 1 : -1; // W zależności od stanu lewego fototranzystora zwiększ lub zmniejsz stan licznika.
}
poprzedniFotoLewy = aktualnyFotoLewy; // Zapamiętaj stany fototranzystorów do kolejnej analizy.
poprzedniFotoPrawy = aktualnyFotoPrawy;Wtedy należy sprawdzić kolejny warunek, ponieważ mogą wystąpić dwa: zmiana z oświetlonego na zaciemniony lub odwrotnie. Odrzucamy jeden z nich i analizujemy kolejne dwie sytuacje, które już jednoznacznie określą, że właśnie nastąpił obrót o 360 stopni i w konkretną stronę. W zależności od niej albo zwiększymy stan licznika, albo zmniejszymy. Na końcu trzeba jeszcze koniecznie zapamiętać aktualny stan sensorów dla porównań w kolejnym przejściu pętli.
licznik = (licznik + 10000) % 10000; // Ogranicz zliczanie do przedziału 0...9999
przeladuj();Ponieważ licznik wyświetla maksymalnie cztery dziewiątki, w ten elegancji sposób ograniczymy zakres do tegoż właśnie. Teraz można już uczynić konwersję stanu licznika na cyfry do wyświetlenia przez procedury w przerwaniu, ale o tym już było, więc zapraszam do poprzednich artykułów. Po kompilacji możemy sobie przetestować układ i zbudować go już w formie finalnej. Ale to nie wszystko – ale o tym w czwartej, ostatniej części serii.













































