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

Sterownik na Arduino - przerwania itp.

PGrzesiek 22 Maj 2016 08:58 963 4
  • #1 22 Maj 2016 08:58
    PGrzesiek
    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ść?

    0 4
  • Relpol
  • #2 22 Maj 2016 09:53
    krzysssztof
    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"

    0
  • Relpol
  • #3 22 Maj 2016 09:53
    kudlaty1125
    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?

    0
  • #4 22 Maj 2016 10:52
    PGrzesiek
    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ą?

    0
  Szukaj w 5mln produktów