Elektroda.pl
Elektroda.pl
X
Relpol przekaźniki nadzorczeRelpol przekaźniki nadzorcze
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Sterownik na Arduino - przerwania itp.

22 Maj 2016 08:58 1164 4
  • Poziom 9  
    Witam,
    potrzebuję zrobić jak najszybciej sterownik oparty na Arduino.
    Komponenty:
    DS1307, DS18b20, LCD 16x2 po I2C, enkoder i bramka SMS oparta na G510, 6 przekaźników sterowanych po i2c (PCF8574).

    Obsługa każdego z elementów to łatwizna. Wszystko działa.

    Potrzebuję kontrolować cały czas temperaturę i w momencie spadku poniżej XX włączenie przekaźnika od grzałki. Jeżeli po włączeniu grzałki temperatura spada dalej (uszkodzona grzałka) to wysyłka SMS'a z informacją.

    Dwa przekaźniki mają kontrolować czas włączenie/wyłączenia gniazd 230V o zadanych godzinach.

    W czym problem?
    Nie mogę odczytywać temperatury, sterować LCD w przerwaniach timera. Czas na odczyt temperatury jest zbyt długi i program "umiera".

    Jak rozwiązać sterowanie tym wszystkim przy pomocy przerwań, lub inne pomysły mile widziane. Enkoder ma służyć do poruszania się po menu ustawień (osobny podprogram w pętli while(1), ale wtedy nie ma sprawdzania temperatury itp. (wiem, że mogę dodać).

    Jak byście to poskładali w całość?
  • Relpol przekaźniki nadzorczeRelpol przekaźniki nadzorcze
  • Poziom 20  
    Fajną metodą jest zagospodarowanie sobie jednego timera do generowania "timera programowego".

    Opis:
    Któryś timer ustawiasz sobie tak, aby generował przerwanie co 10ms.
    W timerze tym tworzysz kilka zmiennych inkrementowanych za każdym przerwaniem i sprawdzasz, czy osiągnęły pożądaną wielkość. Jeśli tak, to ustawiasz sobie flagę/znacznik, że należy wykonać jakąś czynność.
    W pętli głównej sprawdzasz tą flagę i w razie potrzeby wykonujesz pożądane działania.
    W ten sposób drastycznie skracasz obsługę przerwań oraz zwiększasz dostępną ilość timerów.

    Przykład:
    Chcesz, żeby co 100ms procesor wysyłał dane do LCD:
    - w przerwaniu od timera inkrementujesz sobie zmienną "tim_lcd". W momencie, gdy osiągnie wartość 10 (10x10ms=100ms) ustawiasz flagę "wyslij_lcd" oraz zmienną "tim_lcd" zmieniasz na 0, żeby zacząć liczyć od nowa.
    - za każdym obiegiem pętli głównej sprawdzasz, czy "wyslij_lcd" jest ustawione. Jeśli tak, to wykonujesz operacje wysyłania danych do lcd i kasujesz flagę "wyślij_lcd"
  • Relpol przekaźniki nadzorczeRelpol przekaźniki nadzorcze
  • Poziom 15  
    na wyświetlacz timera nie potrzeba, jeśli to zwyklły 16x2 to on nie wymaga zbyt wiele. Timery wtedy możesz na inne rzeczy wykorzystać.

    Jak odczytujesz temperaturę? Wykorzystujesz watchdoga, resetujesz go właściwie?
  • Poziom 9  
    kudlaty1125 napisał:
    na wyświetlacz timera nie potrzeba, jeśli to zwyklły 16x2 to on nie wymaga zbyt wiele. Timery wtedy możesz na inne rzeczy wykorzystać.

    Jak odczytujesz temperaturę? Wykorzystujesz watchdoga, resetujesz go właściwie?


    Pytasz o watchdoga - nie konfigurowałem go, czy on jest z automatu włączony?

    Code:

    sensors.requestTemperatures();
    temperatura = sensors.getTempCByIndex(0);


    I bez względu na to, które z powyższych dam do timera to program "wisi".

    "Proste" rzeczy, typu zmiana stanu pinu, jak poniżej działają pięknie, bo nie wymagają czasu (tak mi się wydaje).
    Code:

    ISR(TIMER1_OVF_vect)        // interrupt service routine that wraps a user defined function supplied by attachInterrupt
    {

      TCNT1 = 34286;
      digitalWrite(13, digitalRead(13) ^ 1);

    }

    void inicjalizacjaTimera() {
      TCCR1A = 0;
      TCCR1B = 0;

      TCNT1 = 34286;            // preload timer 65536-16MHz/256/2Hz
      TCCR1B |= (1 << CS12);    // 256 prescaler
      TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
    }


    Dodano po 2 [minuty]:

    krzysssztof napisał:
    Fajną metodą jest zagospodarowanie sobie jednego timera do generowania "timera programowego".

    Opis:
    Któryś timer ustawiasz sobie tak, aby generował przerwanie co 10ms.
    W timerze tym tworzysz kilka zmiennych inkrementowanych za każdym przerwaniem i sprawdzasz, czy osiągnęły pożądaną wielkość. Jeśli tak, to ustawiasz sobie flagę/znacznik, że należy wykonać jakąś czynność.
    W pętli głównej sprawdzasz tą flagę i w razie potrzeby wykonujesz pożądane działania.
    W ten sposób drastycznie skracasz obsługę przerwań oraz zwiększasz dostępną ilość timerów.

    Przykład:
    Chcesz, żeby co 100ms procesor wysyłał dane do LCD:
    - w przerwaniu od timera inkrementujesz sobie zmienną "tim_lcd". W momencie, gdy osiągnie wartość 10 (10x10ms=100ms) ustawiasz flagę "wyslij_lcd" oraz zmienną "tim_lcd" zmieniasz na 0, żeby zacząć liczyć od nowa.
    - za każdym obiegiem pętli głównej sprawdzasz, czy "wyslij_lcd" jest ustawione. Jeśli tak, to wykonujesz operacje wysyłania danych do lcd i kasujesz flagę "wyślij_lcd"


    Jest to dobra opcja, ale.
    W tym przypadku w kilku miejscach muszę sprawdzać flagi, prawda?

    Np. Jeżeli jestem w menu ustawień, które działa w pętli while(1) to muszę sprawdzać flagi, tak samo, jak w głównej pętli programu, prawda?

    Czyli będzie tak, że w przypadku poruszania się po menu będę miał brak reakcji na kręcenie enkoderem aż do czasu zakończenia czynności związanej z daną flagą?