Informatyka 
 
Arduino - nie tylko programowanie (8)
Narcyz
Arduino może być także sercem urządzeń budowanych w stylu vintage i steam punk. Musimy jednak samodzielnie napisać programy obsługujące manipulatory i interfejsy z epoki w której elektronika bazowała na lampach transformatorach i przekaźnikach. W tym odcinku – tarcza telefonu.

W czasach elektromechanicznych central telefonicznych, wybieranie numeru było dokonywane metodą impulsową. Telefon wysyłał ciągi zwarć linii a centrala po każdym impulsie przesuwała wybierak na kolejną pozycję, wykorzystując chwile przerwy na zmianę wybieraka. Pozwalało to na „wykręcanie numerów” przy pomocy impulsatora mechanicznego w którym ilość impulsów wybierano odpowiednio przekręcając a następnie puszczając obrotową tarczę1. Taką tarczę telefoniczną możemy wymontować ze starego telefonu który możemy znaleźć na strychu, w piwnicy lub na targu staroci na niewielkie pieniądze. Nam udało się zdobyć taki telefon w bardzo dobrym stanie za 10zł.

Typowa tarcza telefoniczna posiada dwie pary styków. Jedna służy do przekazywania odpowiedniej liczby impulsów, druga informuje o tym, że tarcza nie jest w położeniu spoczynkowym. Sprawdzając stan styków możemy programowo odebrać informacje wprowadzone przy pomocy tarczy. Jest jednak pewien problem – styki mechaniczne nie łączą się natychmiast – tylko drgają, generując ciąg impulsów w momencie łączenia lub rozłączania. Dlatego zliczanie impulsów przy pomocy liczników wbudowanych w Arduino nie będzie dobrym pomysłem. Wybieraki mechaniczne nie reagowały na tak krótkie impulsy, jednak liczniki elektroniczne są bardziej czułe. Można próbować odfiltrowywać, jednak wymaga to dodatkowych układów formujących impulsy umieszczonych za filtrami RC.

Aktywne oczekiwanie na impuls z głównej pętli programu nie jest dobrym pomysłem. Po pierwsze, impulsy moglibyśmy przeoczyć. Po drugie – cały czas procesor byłby zajęty oczekiwaniem na to, że cokolwiek się zdarzy. I po trzecie – nie dowiedzielibyśmy się niczego nowego. Dlatego znacznie lepiej dołączyć styki do wejść które mogą wyzwalać przerwania – czyli wołać funkcje gdy stan na danych wejściu się zmieni. W przypadku Arduino UNO, są to wejścia cyfrowe 2 i 3

 

Czym są przerwania? Na początku mówiliśmy, że program w Arduino składa się w dwóch funkcji. Jedna wykonywana jest dokładnie raz, na początku działania programu (czyli po włączeniu lub po naciśnięciu przycisku reset). Druga powtarzana jest cały czas doku nie wyłączymy naszego Arduino. Jednak to nie wszystko – możemy w dowolnym momencie przerwać wykonywanie programu, by zawołać specjalną funkcję wymuszając określony stan na wejściu przerywającym. Funkcja ta nie musi mieć żadnej specjalnej nazwy, jednak musimy ją zarejestrować jako funkcję obsługującą określone przerwanie.

Funkcja ta może być zawołana w dowolnym momencie, nie powinna więc wykonywać się zbyt długo, ponieważ na czas obsługi przerwania zawieszane są wszystkie inne działania – w tym także zliczanie czasu i odbieranie danych z wejść szeregowych. Ponadto funkcja ta nie powinna zwracać wartość ani przyjmować żadnych argumentów, bo co też miałby zrobić nasz mikrokomputer ze zwracaną wartością i skąd miałby wziąć wartości jej argumentów.

 

Rejestracji funkcji obsługującej przerwanie dokonujemy wołając funkcję attachInterupt która przyjmuje trzy argumenty:

  • numer przerwania, który możemy uzyskać wołając funkcję digitalPinToInterrupt i podając jej numer wejścia cyfrowego.
  • nazwę funkcji – musi to być funkcja o sygnaturze void f(), nie może to być więc niestateczna metoda żadnej klasy – bo obiekt na rzecz którego wołana jest funkcja – także jest argumentem.
  • warunek kiedy funkcja jest wołana. Do wybory mamy stan wysoki, dowolną zmianę wartości, zmianę 0->1 lub 1->0.

class DialerClass  {
    // Dialer uses hardcoded inputs of Atmega: Int0
    // for finishing dialing and Int1 for pulse counter
    public:
        void setup() {
            attachInterrupt(digitalPinToInterrupt(2), DialerClass::finished, RISING); 
            attachInterrupt(digitalPinToInterrupt(3), DialerClass::impulse, RISING); 
            lasttick = millis();
            counter = 0;
            value = -1;
        }
        int get()  {
            int val = value;
            value = -1;
            if (val == 10)  {
               val = 0;
            }
            if (val < 0 || val > 9) {
                val = -2; 
            }
            return val;
        }
    private:
        static short int value;
        static short int counter;
        static unsigned long lasttick;

    private:
        static void finished()  {
            if (counter != 0)  {
                value = counter;
                counter = 0;
            }
        }
        static void impulse()  {
            unsigned long currenttick = millis();
            if (currenttick - lasttick > 10) {
                ++counter;
            }
            lasttick = currenttick;
        }
} Dialer;

short int DialerClass::value = -1;
short int DialerClass::counter = 0;
unsigned long DialerClass::lasttick = 0;

void setup() {
    // put your setup code here, to run once:
    Dialer.setup();
    Serial.begin(9600);
}

void loop() {
    // put your main code here, to run repeatedly:
    int i = Dialer.get();
    if (i>=0) {
        Serial.print("Dialer selects ");
        Serial.println(i);
    }
} 

Odbierając informacje ze styków tarczy telefonicznej, musimy pamiętać, by ignorować impulsy które przychodzą zaraz po sobie. Są to najprawdopodobniej drgania styków i jeśli występują częściej niż co 10ms – ignorujemy je.


1
 Można było nawet dzwonić z telefonów z uszkodzoną tarczą – wystukując numer na widełkach na których odwieszaliśmy słuchawkę
 
Opinie
 
Facebook
 
  
29865 wyświetleń

numer 10/2016
2016-10-01

Od redakcji
Aktualności
Ekonomia
Felieton
Literatura
Matematyka
Psychologia
Rozmaitości

nowyOlimp.net na Twitterze

nowy Olimp - internetowe czasopismo naukowe dla młodzieży.
Kolegium redakcyjne: gaja@nowyolimp.net; hefajstos@nowyolimp.net