Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Relpol przekaźniki
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Casowe sterowanie przekaźnikami (programowo)

carrozzeria 21 Oct 2019 19:57 384 5
  • #1
    carrozzeria
    Level 8  
    Witam,
    Dostałem ostatnio ogrzewanie przyczepy kempingowej z uszkodzonym sterownikiem. Chciałbym je zastosować do mojego garażu. Muszę zrobić prosty sterownik do tego ogrzewania i znalazłem program, który trochę przerobiłem.
    Quote:
    #include <OneWire.h>
    #include <DS18B20.h>
    #include <LCD.h>
    #include <LiquidCrystal_I2C.h>
    #define ONEWIRE_PIN 8 // Numer pinu do którego podłaczasz czujnik
    #define SENSORS_NUM 3 // Liczba 3 to liczba czujników, które chcemy obsługiwać
    #define BACKLIGHT_PIN 3
    LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Adres wyświetlacza
    const byte address[SENSORS_NUM][8] PROGMEM = {
    0x28, 0xC4, 0xB9, 0xF4, 0x5A, 0x14, 0x1, 0x6,
    0x28, 0x94, 0x61, 0xFB, 0x5A, 0x14, 0x1, 0xD2,
    0x28, 0xE6, 0x4F, 0xE3, 0x5A, 0x14, 0x1, 0x5A
    }; // Adres czujników (Dyrektywa PROGMEM powoduje, że tablica jest przechowywana w pamięci Flash. Dzięki temu przy większej ilości czujników oszczędzisz pamięć RAM (której jest mało) na inne zmienne.)
    OneWire onewire(ONEWIRE_PIN);
    DS18B20 sensors(&onewire);

    float set;
    float temperature;

    int buttonState = 0;

    void setup()
    {
    pinMode(13, INPUT_PULLUP); //przycisk
    pinMode(12, INPUT_PULLUP); //przycisk temp +
    pinMode(11, INPUT_PULLUP); //przycisk temp -
    pinMode(10, INPUT_PULLUP); //przycisk
    pinMode(9, OUTPUT); //buzzer
    pinMode(7, OUTPUT); //wentylator
    pinMode(6, OUTPUT); //iskrownik
    pinMode(5, OUTPUT); //gaz
    pinMode(4, OUTPUT); //przekażnik
    digitalWrite(7, HIGH);
    digitalWrite(6, HIGH);
    digitalWrite(5, HIGH);
    digitalWrite(4, HIGH);
    set=30;


    sensors.begin(); //Metoda begin wyszukuje czujniki i ustawia we wszystkich rozdzielczość. Domyślnie jest to 12 bitów.
    lcd.begin(16,2);
    lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
    lcd.setBacklight(HIGH); //włączanie podświetlenia
    }

    void loop()
    {

    if (sensors.available())
    {
    sensors.request(); //Metoda request wysyła rozkaz do czujnika o adresie podanym w argumencie, by zaczął obliczać temperaturę.
    temperature = sensors.readTemperature(FA(address));
    }
    //Wyświetlenie tekstu na wyświetlaczu
    lcd.setCursor(0,0);
    lcd.print(temperature);
    lcd.print(F("C"));
    lcd.setCursor(6,0);
    lcd.print("U:");
    lcd.setCursor(8,0);
    lcd.print(set);
    lcd.print(F("*C"));
    lcd.setCursor(0,1);
    lcd.print("W:");
    lcd.setCursor(5,1);
    lcd.print("I:");
    lcd.setCursor(10,1);
    lcd.print("G:");


    //przycisk a temperatura

    if(digitalRead(12) == LOW)
    {
    delay(50);
    set++;
    }
    buttonState = digitalRead(12);

    if (buttonState == HIGH) {
    // turn buzzer on:
    digitalWrite(9, LOW);
    } else {
    // turn buzzer off:
    digitalWrite(9, HIGH);
    }

    if(digitalRead(11) == LOW)
    {
    delay(50);
    set--;
    }
    buttonState = digitalRead(11);

    if (buttonState == HIGH) {
    // turn buzzer on:
    digitalWrite(9, LOW);
    } else {
    // turn buzzer off:
    digitalWrite(9, HIGH);
    }

    //porównanie temp zadanej z ustawioną
    if(temperature >= set+0.2)
    {
    digitalWrite(7, LOW);
    lcd.setCursor(2,1);
    lcd.print(" ");
    lcd.setCursor(2,1);
    lcd.print("ON");
    digitalWrite(6, LOW);
    lcd.setCursor(7,1);
    lcd.print(" ");
    lcd.setCursor(7,1);
    lcd.print("ON");
    digitalWrite(5, LOW);
    lcd.setCursor(12,1);
    lcd.print(" ");
    lcd.setCursor(12,1);
    lcd.print("ON");
    }

    if(temperature <= set-0.2)
    {
    digitalWrite(7, HIGH);
    lcd.setCursor(2,1);
    lcd.print(" ");
    lcd.setCursor(2,1);
    lcd.print("OFF");
    digitalWrite(6, HIGH);
    lcd.setCursor(7,1);
    lcd.print(" ");
    lcd.setCursor(7,1);
    lcd.print("OFF");
    digitalWrite(5, HIGH);
    lcd.setCursor(12,1);
    lcd.print(" ");
    lcd.setCursor(12,1);
    lcd.print("OFF");
    }
    }

    Ogólnie jest ok tylko chciałbym żeby najpierw załączał się wentylator po 5 sekundach iskrownik (iskrownik musiał by działać przez 3 sekundy i przez ten czas działać jak coś w stylu "blink") i po sekundzie od iskrownika załączał by się gaz.
    Próbowałem to zrobić jakoś funkcją millis(), ale nie wychodzi mi to. Byłbym wdzięczny za pomoc lub jakąś podpowiedź.
    Ethernet jednoparowy (SPE) - rozwiązania w przemyśle. Szkolenie 29.09.2021r. g. 11.00 Zarejestruj się za darmo
  • Relpol przekaźniki
  • #2
    carrozzeria
    Level 8  
    Z iskrownikiem poradziłem sobie mechanicznie tj. zrobiłem sobie przerywacz. Nadal niestety mam problem z załączaniem się przekaźników. Nie wiem jak zrobić żeby załączać jeden po drugim, a nie wszystkie naraz. Aaa i jeden z nich chciałbym żeby załączał się na określony czas. Czy jest to w ogóle możliwe? Jeśli tak to będę wdzięczny za jakieś podpowiedzi.
  • Relpol przekaźniki
  • #3
    emarcus
    Level 38  
    carrozzeria wrote:
    Nie wiem jak zrobić żeby załączać jeden po drugim, a nie wszystkie naraz. Aaa i jeden z nich chciałbym żeby załączał się na określony czas. Czy jest to w ogóle możliwe?

    Tak, jest to nawet dośc proste!
    Kontynuuj tak jak zacząłeś w poprzednim poście z funkcją millis().
    Wzoruj się na przykładzie w Arduino; 'BlinkWithoutDelay' , w którym zamiast błyskania diodą incrementuj jakąś zmienną; powiedzmy 'Z.'
    Interwały czasowe dobierz aby względnie pasowały do rozdzielczości załączania/wyłączania przekaźników, bądz jej wielokrotnośc.
    W dalszej części programu zastosuj konstrukcję 'switch ...case' gdzie sensorem dla 'switch' będzie twoja zmienna 'Z'
    W kolejnych lub tylko wybranych 'case' z numerem 'Z' wpiszesz odpowiednie instrukcje dla przekaźnika/grupy przekaźników.
    Aby zmienna Z nie była incrementowana do przepełnienia i liczona 'od nowa' , załóż dla niej ograniczenie (constrain) wynikające z potrzeb programu/systemu.
    Jeżeli tych 'case' jest nie wiele, możesz je zastąpic instrukcjami warunkowymi if() {}

    e marcus
  • #4
    carrozzeria
    Level 8  
    emarcus wrote:
    carrozzeria wrote:
    Nie wiem jak zrobić żeby załączać jeden po drugim, a nie wszystkie naraz. Aaa i jeden z nich chciałbym żeby załączał się na określony czas. Czy jest to w ogóle możliwe?

    Tak, jest to nawet dośc proste!
    Kontynuuj tak jak zacząłeś w poprzednim poście z funkcją millis().
    Wzoruj się na przykładzie w Arduino; 'BlinkWithoutDelay' , w którym zamiast błyskania diodą incrementuj jakąś zmienną; powiedzmy 'Z.'
    Interwały czasowe dobierz aby względnie pasowały do rozdzielczości załączania/wyłączania przekaźników, bądz jej wielokrotnośc.
    W dalszej części programu zastosuj konstrukcję 'switch ...case' gdzie sensorem dla 'switch' będzie twoja zmienna 'Z'
    W kolejnych lub tylko wybranych 'case' z numerem 'Z' wpiszesz odpowiednie instrukcje dla przekaźnika/grupy przekaźników.
    Aby zmienna Z nie była incrementowana do przepełnienia i liczona 'od nowa' , załóż dla niej ograniczenie (constrain) wynikające z potrzeb programu/systemu.
    Jeżeli tych 'case' jest nie wiele, możesz je zastąpic instrukcjami warunkowymi if() {}

    e marcus

    Dzięki za odp. W weekend będę się bawił, trochę rzeczy jest do ogarnięcia z tego co widzę. Dam znać jakie są rezultaty.
  • #5
    carrozzeria
    Level 8  
    Witam ogólnie to mam już prawie ogarnięte, ale mam jeszcze pytanie w ramach testów trochę zmieniłem program i w tym momencie steruje przekaźnikiem za pomocą temperatury i histerezy.
    I o tą histerezę mi chodzi, czy może to tak wyglądać? Ogólnie mało jest info na temat regulacji histerezy.
    Quote:
    #include <OneWire.h>
    #include <DS18B20.h>
    #include <LCD.h>
    #include <LiquidCrystal_I2C.h>
    #define ONEWIRE_PIN 8 // Numer pinu do którego podłaczasz czujnik
    #define BACKLIGHT_PIN 3
    LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Adres wyświetlacza
    byte address[8] = {0x28, 0xC4, 0xB9, 0xF4, 0x5A, 0x14, 0x1, 0x6}; // Adres czujnika


    OneWire onewire(ONEWIRE_PIN);
    DS18B20 sensors(&onewire);

    float set;
    float temperature;
    float histereza;

    void setup()
    {
    pinMode(13, INPUT_PULLUP); //histereza +
    pinMode(12, INPUT_PULLUP); //przycisk temp +
    pinMode(11, INPUT_PULLUP); //przycisk temp -
    pinMode(10, INPUT_PULLUP); //histereza -
    pinMode(7, OUTPUT); //przekaźnik 1
    digitalWrite(7, HIGH);
    set=4;


    sensors.begin();
    lcd.begin(16,2);
    lcd.setBacklightPin(BACKLIGHT_PIN, POSITIVE);
    lcd.setBacklight(HIGH); //włączanie podświetlenia
    }

    void loop()
    {

    if (sensors.available())
    {
    sensors.request(address);
    temperature = sensors.readTemperature(address);
    }
    //Wyświetlenie tekstu na wyświetlaczu
    lcd.setCursor(0,0);
    lcd.print(temperature);
    lcd.print(F("C"));
    lcd.setCursor(6,0);
    lcd.print("U:");
    lcd.setCursor(8,0);
    lcd.print(set);
    lcd.print(F("*C"));
    lcd.setCursor(0,1);
    lcd.print("W:");
    lcd.setCursor(6,1);
    lcd.print("H:");
    lcd.setCursor(8,1);
    lcd.print(histereza);
    lcd.print(F("*C"));

    //przycisk a temperatura

    if(digitalRead(12) == LOW)
    {
    delay(50);
    set++;
    }

    if(digitalRead(11) == LOW)
    {
    delay(50);
    set--;
    }


    if(digitalRead(13) == LOW)
    {
    delay(50);
    histereza++;
    }

    if(digitalRead(10) == LOW)
    {
    delay(50);
    histereza--;
    }

    //porównanie temp zadanej z ustawioną
    if(temperature >= set+histereza+0)
    {
    digitalWrite(7, LOW);
    lcd.setCursor(2,1);
    lcd.print(" ");
    lcd.setCursor(2,1);
    lcd.print("ON");

    }

    if(temperature <= set-histereza-0)
    {
    digitalWrite(7, HIGH);
    lcd.setCursor(2,1);
    lcd.print(" ");
    lcd.setCursor(2,1);
    lcd.print("OFF");

    }
    }

    Niby da się nią sterować, ale w momęcię gdy robię histerezę na -1 to przekaźnik zaczyna włączać się i wyłączać.
    Pewnie coś źle zrobiłem.
  • #6
    emarcus
    Level 38  
    carrozzeria wrote:
    mam jeszcze pytanie w ramach testów trochę zmieniłem program i w tym momencie steruje przekaźnikiem za pomocą temperatury i histerezy.
    I o tą histerezę mi chodzi, czy może to tak wyglądać? Ogólnie mało jest info na temat regulacji histerezy.

    .......................
    Niby da się nią sterować, ale w momęcię gdy robię histerezę na -1 to przekaźnik zaczyna włączać się i wyłączać.
    Pewnie coś źle zrobiłem.


    Oczywiście, mało jest informacji na temat regulacji histerezy w systemach ogrzewania z cyrkulacją powietrza pomieszczeń mieszkalnych, bo praktycznie regulacji tego parametru nie stosuje się w powszechnie dostępnych/stosowanych termostatach, nawet tych z najwyższej półki. Mam w domu system chłodzenia (AC) /ogrzewanie gazowe z powietrzną cyrkulacją od lat 40. Na przestrzeni tych lat termostaty wymieniałem relatywnie często. Z reguły nie z powodu uszkodzeń, ale dlatego że pokazywały się na rynku nowocześniejsze wielofunkcyjne z możliwościami ustawień kilku różnych temperatur w ciągu dnia/nocy, od analogowych z wyłącznikiem kapsułki rtęciowej do cyfrowych SSR z komunikacją B/T do smart phone. Żadne z nich nie miały regulacji histerezy.
    Z uwagi na komfort mieszkalny, histereza w tych termostatach jest stała i nie sądzę aby przekraczała 2 st C. Jest to dostatecznie dużo jak na zmiany temp. ogrzewanego pomieszczenia mieszkalnego. Nie musisz zamarznąć w oczekiwaniu na załączenie się pieca/systemu.
    Do ogrzewania garażu nie jest ci potrzebny aż taki komfort i tę histerezę możesz powiększyć do 4 a nawet 5 stopni i w programie traktować to jako 'const', a nie zmienna (do tego jeszcze typu float).
    Możesz pokusić się na dołożenie zegara DS3231 /DS1307 i manipulować temperaturami w zależności od pory dnia/nocy.
    Druga sprawa: Nie wygląda abyś rozumiał dokładnie koncept histerezy. W praktyce, jedną graniczną temperaturę powiedzmy górna (wyłączającą grzanie ) przyjmuje się tę 'Temp_set', natomiast ten drugi, dolny poziom dla załączenia rachuje się jako 'Temp_set - histereza'
    Wtedy masz:
    [syntax=c]
    if(temperature >= Temp_set)
    {
    digitalWrite(7, LOW); //wyłączenie grzania i ew, nawiewu
    }
    ----------------------------------------------
    I drugi warunek
    if(temperature <= Temp_set - histereza)
    {
    .....
    }
    e marcus