[141] Arduino i mierniki panelowe cz. 3

[141] Arduino i mierniki panelowe cz. 3

Nasza zabawka edukacyjna już działa, ale skoro jest edukacyjną, czas na ową edukację, czyli zamianę formy początkującej szkicu na taką bardziej zaawansowaną. Pierwszym etapem będzie zamiana całego bloku konwersji na taką skróconą formę, z którą już spotkaliśmy się.


analogWrite(miernik, (sekundy >= 25200 && sekundy <= 75600) ? map(sekundy, 25200, 75600, 17, 255) : 0);

Jest to dokładnie to samo, tylko bez słów if oraz else. Jedno zamienia się pytajnikiem, drugie dwukropkiem w takiej właśnie formie jak widać. Dla początkujących jest to może mniej czytelne, ale oszczędza sporo miejsca i warto do takich skrótów przywyknąć.

sekundy = (sekundy + 1) % 86400;

Drugą zmianą będzie już zmiana sposobu liczenia, a nie tylko zapisu. Zamiast tworzyć pętlę, można niejako automatem zerować sekundnik po zwiększeniu jego wartości o jeden, używając funkcji modulo i wartości maksymalnej. Da nam to taki sam wynik, ale szybciej i w jednej linii. Obie zmiany są czysto techniczne i nic nowego do programu nie wnoszą. Dla porządku, przytoczę cały szkic.

#include <TimerOne.h>  // Biblioteka obsługi przerwań.

const byte miernik = 11;        // Adres portu, do którego podłączony jest miernik.
volatile long sekundy = 25200;  // Licznik sekund.

void setup() {
  pinMode(miernik, OUTPUT);            // Deklaruj port miernika jako wyjście.
  Timer1.initialize(1000);             // Ustaw przerwania na jedną milisekundę.
  Timer1.attachInterrupt(przerwanie);  // Włącz przerwania z określeniem miejsca lądowania.
}
void loop() {
  analogWrite(miernik, (sekundy >= 25200 && sekundy <= 75600) ? map(sekundy, 25200, 75600, 17, 255) : 0);
  delay(100);  // Opóźnienie stabilizujące.
}
void przerwanie() {                 // Obsługa przerwania.
  sekundy = (sekundy + 1) % 86400;  // Zwiększaj licznik sekund i zeruj go po osiągnięciu maksimum
}

Zegar już działa, tylko nie da się go nastawić, więc czas na dokończenie dzieła. Jak wspominałem, używam płytki edukacyjnej TME dlatego, że mam tam różne przydasie. Dziś użyję dwóch pstryczków, które zostały osadzone pod adresem 4 i 7. Na płytce mam zapięte inwertery, więc obowiązuje tu logika dodatnia, czyli po ich wciśnięciu pojawia się stan wysoki. Kto użyje „gołego” arduino, musi dopasować stany aktywne.

#include <TimerOne.h>  // Biblioteka obsługi przerwań.

const byte miernik = 11;        // Adres portu, do którego podłączony jest miernik.
const byte minus = 4;           // Przycisk minus.
const byte plus = 7;            // Przycisk plus.
volatile long sekundy = 61200;  // Licznik sekund.

void setup() {
  pinMode(miernik, OUTPUT);  // Deklaruj porty.
  pinMode(minus, INPUT_PULLUP);
  pinMode(plus, INPUT_PULLUP);
  Timer1.initialize(1000000);          // Ustaw przerwania na jedną sekundę.
  Timer1.attachInterrupt(przerwanie);  // Włącz przerwania z określeniem miejsca lądowania.
}
void loop() {
  analogWrite(miernik, (sekundy >= 25200 && sekundy <= 75600) ? map(sekundy, 25200, 75600, 17, 255) : 0);

  if (digitalRead(minus) == HIGH) {              // Jeśli minus jest wciśnięty...
    sekundy -= 60;                               // Zmniejsz licznik sekund o minutę.
    sekundy = constrain(sekundy, 25200, 75599);  // Ustaw pułapkę na godziny nocne.
  }
  if (digitalRead(plus) == HIGH) {               // Jeśli plus jest wciśnięty...
    sekundy += 60;                               // Zwiększ licznik sekund o minutę.
    sekundy = constrain(sekundy, 25200, 75599);  // Ustaw pułapkę na godziny nocne.
  }
  delay(20);  // Opóźnienie autorepetycji.
}
void przerwanie() {                 // Obsługa przerwania.
  sekundy = (sekundy + 1) % 86400;  // Zwiększaj licznik sekund i zeruj go po osiągnięciu maksimum
}

Będziemy już operować na wartościach docelowych. Po resecie zegar wystartuje o siedemnastej (to moja ulubiona godzina), a przerwania będą już pędzić z szybkością jednego na sekundę. Jak widać, z nowości mamy tu tylko obsługę klawiatury. Gdy wciśniemy przycisk minus, licznik sekund zmniejszy się o 60, czyli o minutę. W naszym przypadku nie ma sensu zwiększanie rozdzielczości. Gdyby po takiej zmianie wartość wskazywała na godziny nocne, zostanie on dobity do przedziału wyznaczonego rzadko używaną funkcją constrain, która świetnie nam się tu przyda. Innymi słowy, regulacje zegara mają sens tylko wówczas, gdy widać ruch wskazówki. W godzinach nocnych spoczywa ona na zerze. Ta konstrukcja uniemożliwia więc jego regulację między 21, a 7, ale to nie wada, tylko że tak powiem, ten typ tak ma.

Zwiększanie czasu jest realizowane symetrycznie. Delay wyznacza w tym momencie także autorepetycję i w naszym wypadku, gdy niczego poza tym co widać nie robimy, możemy tak to zostawić. Nie jest też błędem praca na żywym organizmie, czyli na zmiennej sekundy, która w niewiadomym dla nas czasie może się zwiększyć za sprawą przerwań. Gdybyśmy jednak potrzebowali precyzji, podczas regulacji zegara należałoby przerwania zatrzymać. Pominąłem to, ale zmniejszyłem o jeden górną wartość progową (75599) właśnie z powodu pracy przerwań w tle, które cichaczem zwiększało nam wartość i wskazówka podczas trzymania przycisku zwiększającego sekundy na końcu zakresu skakałaby sobie pomiędzy skrajnymi stanami. W programie mamy też zbędne użycie mocy: mapowanie odbywa się co 20 mS, a wiadomo, że zmiana tej wartości ma miejsce co sekundę. Gdybyśmy potrzebowali tych mocy, jest okazja do optymalizacji. Ale nie potrzebujemy, więc zostawimy rzeczy jakimi są. Skoro zegar pracuje jak należy, czas zakończyć ten temat, a w kolejnym artykule przedstawić drugą, obiecaną zabawkę.

Powiązane tematy

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2Sprawdź tutaj

Przeczytaj również

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2025 arduino.pl