Skocz do zawartości

Bezprzewodowy sterownik funkcji na kierownicę samochodu.


Pomocna odpowiedź

@etet100dzięki za pomoc nadal próbuję to ogarnąć ale faktycznie ja nie programuję i się raczej nie nauczę zatem zgodnie z radą @ethanakzłożyłem ofertę w dziale ogłoszeń.
Wiem, że czas jest cenny a za wiedzę trzeba zapłacić i chętnie za udzieloną pomoc zapłacę.
Wracając do sedna.
Tylko część klawiszy ma mieć podwójne funkcje czyli krótkie/długie naciśnięcie (kierunkowskazy oraz światła drogowe/mijania. Zatem skleiłem na razie obie wersje tak by dwa ostatnie załączały tylko przy naciśnięciu.
 

int out1Pin = 2;
int out2Pin = 3;
int out3Pin = 4;
int out4Pin = 5;
int out5Pin = 6;
int out6Pin = 7;
int out7Pin = 8;
int out8Pin = 9;
int buttonPin = 0;
int buttonValue;

#define BTN_NONE 0
#define BTN1 1
#define BTN2 2
#define BTN3 3
#define BTN4 4
#define BTN5 5
#define BTN6 6
#define BTN7 7
#define BTN8 8


void setup() { Serial.begin(9600);}

int getBtn() {
  buttonValue = analogRead(buttonPin);
//  Serial.println(buttonValue);

  if (buttonValue == 0) {return BTN1;}
  if (buttonValue > 4 && buttonValue < 8) {return BTN2;}
  if (buttonValue > 22 && buttonValue < 28) {return BTN3;}
  if (buttonValue > 8 && buttonValue < 13) {return BTN4;}
  if (buttonValue > 52 && buttonValue < 57) {return BTN5;}
  if (buttonValue > 129 && buttonValue < 134) {return BTN6;}
//  if (buttonValue > 80 && buttonValue < 85) {return BTN7;}
//  if (buttonValue > 15 && buttonValue < 20) {return BTN8;} 
  return BTN_NONE;
}

void loop() {
  int btn = BTN_NONE;
  unsigned long start = millis();
  while (true) {
    // tu w pętli sprawdzamy stan przycisków i czekamy na zmianę
    int newBtn = getBtn();
    // wykrywajmy zmianę stanu przycisków
    if (newBtn != btn) {
      // jeśli do tej pory jakiś przycisk był wciśnięty
      if (btn != BTN_NONE) {
        // wciśnięty powyżej sekundy???
        if (millis() - start > 1000) {
          Serial.print("LONG ");
          Serial.println(btn);
          // tutaj można dodać kod obsługi długiego wciśnięcia
        } else
         if (millis() - start > 100) {
            Serial.print("SHORT ");
            Serial.println(btn);
            // tutaj można dodać kod obsługi krótkiego wciśnięcia
//            if (BTN1 == SHORT 1) {digitalWrite(out1Pin,HIGH);}
        }    
        else {
          Serial.print("TOO SHORT ");
          Serial.println(btn);
        }
      }
      // zapamiętujemy aktualny czas, jeśli przycisk się zmieni to
      // będziemy mogli policzyć czas jego wciśnięcia
      start = millis();
      // zapamiętujemy nowy stan jako bieżący stan
      btn = newBtn;
    }
    if (buttonValue > 81 && buttonValue < 84) {digitalWrite(out7Pin,HIGH);}
    else {digitalWrite(out7Pin,LOW);}
    if (buttonValue > 16 && buttonValue < 18) {digitalWrite(out8Pin,HIGH);}
    else {digitalWrite(out8Pin,LOW);
    } 
  }
}  


 

(edytowany)

Trzeba napisać bardzo dokładnie o co chodzi. Tu nawet nie było żadnego pytania. Jeśli potrzebujesz/oczekujesz pomocy to nie każ szukać o co mogło chodzić.  W kodzie też brakuje komentarzy. Gdyby było napisane co te zmiany mają robić, to łatwiej by było ocenić czy to robią.

Poza tym... zawsze w takich sytuacjach polecam zapoznanie się z podstawami git/github. To są stosunkowo proste (jeśli chodzi o podstawy) narzędzia, dzięki którym nie trzeba tego kodu w kółko przeklejać z edytora do przeglądarki i spowrotem. Robisz u siebie poprawki, tworzysz "commit" (czyli zapis aktualnego stanu), klikasz żeby wysłało się do github. Dodatkowo, jeśli chcesz ten kod i tak kiedyś udostępnić publicznie to github w zasadzie jest tu standardem. Naprawdę warto.

Wrzuciłem roboczą wersję tu

https://github.com/etet100/sterownik-samochodu/blob/main/main.cpp

Edytowano przez etet100
(edytowany)

Nie wiem czy prawidłowo ale dopisałem komentarze na githubie.
Teraz przyciski 7 i 8  działają w interakcji ale na zasadzie załącz lewy załącz prawy i nie wyłączają się.


Dlatego próbowałem zrobić krótkie i długie naciśnięcie a dokładnie:
BTN1 kierunkowskaz prawy
- krótkie naciśnięcie - sprawdź stan OUT1 jeśli OFF to załącz OUT1 na określony czas np. 20 sekund
                                                                       jeśli ON to wyłącz OUT1
-długie naciśnięcie - załącz OUT1 i czekaj na wyłączenie z BTN1 lub BTN2 lub INPUT3 - czujnik obrotu kierownicy

BTN2 analogicznie kierunkowskaz lewy
- krótkie naciśnięcie - sprawdź stan OUT2 jeśli OFF to załącz OUT2 na określony czas np. 20 sekund
                                                                       jeśli ON to wyłącz OUT2
-długie naciśnięcie - załącz OUT2 i czekaj na wyłączenie z BTN1 lub BTN2 lub INPUT3 - czujnik obrotu kierownicy

BTN3 - światła drogowe
- krótkie naciśnięcie - sprawdź stan OUT3 jeśli OFF to załącz OUT3 na np. 3 sekundy
                                                                        jeśli ON to wyłącz OUT3
- długie naciśnięcie - załącz OUT3
BTN4 - wycieraczki 1
- krótkie naciśnięcie - załącz OUT4 na czas naciśnięcia- jednokrotne zadziałanie wycieraczek
- długie naciśnięcie - załącz OUT5 na czas naciśnięcia -  spryskiwacz + 3 krotne zadziałanie wycieraczek
BTN5 - wycieraczki 2
- krótkie naciśnięcie - ONN/OFF - załącz/wyłącz przednie wycieraczki na zasadzie kolejne krótkie naciśnięcie zmienia stan OUT6 na przeciwny
- długie naciśnięcie - ONN/OFF - załącz/wyłącz tylne wycieraczki i na zasadzie kolejne długie naciśnięcie zmienia stan OUT7 na przeciwny
BTN6 - wycieraczki 3
- aby to rozpracować muszę rozebrać samochód ale najprawdopodobniej będzie jako przycisk w pętli który załącza kolejno 3 wyjścia prędkości wycieraczek 
  wyłączając poprzednie ale to muszę już sprawdzić na manipulatorze, który kupiłem i jak dojdzie to rozbiorę i pomierzę dokładnie.

Miałem nadzieję, że ktoś poda mi fragmenty kodu dla różnych rozwiązań takich klawiszy a ja posklejam to sobie już dalej wg. własnych potrzeb i testów.
Zapewne gdyby to był nadajnik - odbiornik a nie ta gotowa klawiatura, która jednak ułatwia zadanie od strony mechanicznej i estetycznej to byłoby prościej skorzystać z gotowej biblioteki EasyButton ale i tak pewnie nie dałbym rady sam.

 

 

Edytowano przez GaaD

Polecam:

Bounce2 - tam można łatwo zrobić long, double i takie tam, ale biblioteka udostępnia tylko możliwości.

Dla dociekliwych - kod obsługi klawiatury Lektona. Olać i2c, są kody obsługi click/long, kombinacji klawiszy i co tam potrzebne. Pisałem sobie, ale kod powinien być czytelny.

4 godziny temu, GaaD napisał:

Nie wiem czy prawidłowo ale dopisałem komentarze na githubie.
Teraz przyciski 7 i 8  działają w interakcji ale na zasadzie załącz lewy załącz prawy i nie wyłączają się.

Bo ja myślałem że 7,8 to kierunkowskazy.

Wrzuciłem trochę zmian, już się to powoli domaga jakiegoś rozbicia na funkcje/moduły.

Ja tego kodu nie kompiluje i nie testuje. Mogę być literówki większe i mniejsze.

(edytowany)

Nie udało mi się tego skompilować.
Ale znalazłem gotową bibliotekę pod taką klawiaturę:
https://github.com/rlogiacco/AnalogButtons/tree/master?tab=readme-ov-file#1-buttons-definition

tylko mam jeden problem jak zmienić parametr, który domyślnie w bibliotece ma wartość 10
"the analog value margin which takes into account slight resistance fluctuations and ADC errors transforming the button value into a range (defaults to 10)"
na inną wartość? Mogę to zrobić w kodzie czy muszę edytować plik tej biblioteki? (Ok. ogarnąłem znalazłem i zmieniłem w bibliotece.)

Ta biblioteka rozwiązuje raczej wszelkie problemy z klawiaturą i pozostaje wyłącznie logika wyjść.
Mam nadzieję, że do wtorku dotrze do mnie oryginalny przełącznik z manetkami wtedy postaram się rozpracować i już precyzyjnie określić wszystkie potrzebne funkcje i jak je załączać.

Edytowano przez GaaD

Nie przeglądałem szczegółowo, ale np. zmiana na drogowe i miganie pod jednym przyciskiem, to chcąc przełączyć na drogowe, powinno to się odbywać niezwłocznie po naciśnięciu przycisku. Nie, że np. program sprawdza, czy było pojedyncze naciśnięcia, czy przytrzymanie przycisku przez np. 1 s i wtedy robi, co mu każą. Taka tylko uwaga co do logiki - może jest git już teraz, nie wiem.

Dnia 13.10.2025 o 16:01, GaaD napisał:

(Ok. ogarnąłem znalazłem i zmieniłem w bibliotece.)

To się robi tworząc ten obiekt. Nie trzeba edytować biblioteki.

AnalogButtons analogButtons(ANALOG_PIN, INPUT, 5, 10);

Dnia 13.10.2025 o 16:01, GaaD napisał:

Nie udało mi się tego skompilować

Abstrahując od problemów z kompilacją.

Gdybym robił to dla kogoś (i to jednoręcznego), to klawiatura z 9 przyciskami by mi "przez gardło nie przeszła" 😉

Ergonomia obsługi tego będzie problematyczna.

Są dostępne tanie czujniki gestów. Albo nawet do rozpoznawania mowy. Część funkcjonalności można obsłużyć bezkontaktowo.

(edytowany)

Zapewniam, że funkcjonalność tych przycisków polepszy komfort jazdy. Córka już jeździ i radzi sobie doskonale.
Ma obie ręce ale prawą stroną nie włada w pełni. Sam pomysł nie jest mój to kopia dedykowanego urządzenia z linka w pierwszym poście. 8 przycisków to i tak o jeden mniej niż w oryginale, który zapewne kupimy do nowego auta. Nie jest to krytyczne dla bezpieczeństwa jazdy ale kierunkowskazy mają ułatwić np. opuszczanie ronda gdy ręka na kierownicy jest często daleko od wyłącznika. Ważne są też wycieraczki a światła drogowe/mijania to już wykorzystanie wolnych przycisków i chyba najmniej skomplikowany kawałek kodu w tym wszystkim. Mam już drugi wyłącznik zespolony i trochę teraz muszę pokombinować bo w Mondeo i to starym jest to zupełnie inaczej zrobione niż w dużo nowszej Toyocie. W wyłączniku jest jednostka sterująca z magistralą LIN i zastanawiam się, czy nie udałoby się sterować tym wszystkim po CAN. Jeśli nie to muszę wpinać się delikatnie pod styki wyłączników, które właśnie rozrysowuję aby wiedzieć ile wyjść i przekaźników będę potrzebował.

Edytowano przez GaaD
  • 4 tygodnie później...
(edytowany)

Witam.
Zacząłem kurs ale tak czy inaczej ten projekt okazał się dla mnie zbyt trudny ale nie dla ChatGPT i to w wersji darmowej.
Po paru godzinach stworzył mi działający skrypt, który się kompiluje i załącza przekaźniki tak jak tego chcę. Mam już 6 przycisków dwa ostatnie to już raczej nie będzie problem.
Wklejam może uznacie, że coś można poprawić.
 

#include <AnalogButtons.h>

#define ANALOG_PIN A0
#define DEBUG 0  // ustaw 1 aby włączyć debug przez Serial

// ====== Deklaracje callbacków ======
void b1Click(); void b1Hold();
void b2Click(); void b2Hold();
void b3Click(); void b3Hold();
void b4Click(); void b4Hold();
void b5Click(); void b5Hold();
void b6Click(); void b6Hold();

// ====== Definicje pinów ======
#define REL1 2
#define REL2 3
#define REL3 4
#define REL4 5
#define REL5 6
#define REL6 7
#define REL7 8
#define REL8 9
#define REL9 10
#define REL10 11
#define REL11 12
#define CZUJNIK 13

// ====== Czas działania ======
const unsigned long relayInterval = 2000;
const unsigned long sensorWindow = 60000;

// ====== Stany przekaźników ======
bool relay1Active=false, relay2Active=false, relay3Active=false;
bool relay4Active=false, relay5Active=false, relay6Active=false;
bool relay7Active=false, relay8Active=false;

bool relay1Permanent=false, relay2Permanent=false, relay3Permanent=false;
bool relay4Permanent=false, relay5Permanent=false, relay6Permanent=false;
bool relay7Permanent=false, relay8Permanent=false;

unsigned long relay1StartTime=0, relay2StartTime=0, relay3StartTime=0;
unsigned long relay4StartTime=0, relay5StartTime=0, relay6StartTime=0;
unsigned long relay7StartTime=0, relay8StartTime=0;

// ====== Czujnik ======
int lastSensorState = HIGH;
unsigned long lastSensorChangeTime = 0;
int sensorChangeCount = 0;

// ====== Analog Buttons ======
AnalogButtons analogButtons(ANALOG_PIN, INPUT, 5, 10);

Button b1 = Button(0,   &b1Click, &b1Hold, 500, 1500);
Button b2 = Button(110, &b2Click, &b2Hold, 500, 1500);
Button b3 = Button(495, &b3Click, &b3Hold, 500, 1500);
Button b4 = Button(315, &b4Click, &b4Hold, 500, 1500);
Button b5 = Button(170, &b5Click, &b5Hold, 500, 1500);
Button b6 = Button(720, &b6Click, &b6Hold, 500, 1500);

void setup() {
#if DEBUG
  Serial.begin(9600);
  Serial.println("System gotowy");
#endif

  analogButtons.add(b1);
  analogButtons.add(b2);
  analogButtons.add(b3);
  analogButtons.add(b4);
  analogButtons.add(b5);
  analogButtons.add(b6);

  for (int i = REL1; i <= REL11; i++) {
    pinMode(i, OUTPUT);
    digitalWrite(i, LOW);
  }
  pinMode(CZUJNIK, INPUT_PULLUP);
}

void loop() {
  analogButtons.check();

  unsigned long now = millis();

  // automatyczne wyłączanie czasowe
  if (relay1Active && !relay1Permanent && now - relay1StartTime >= relayInterval) { digitalWrite(REL1, LOW); relay1Active=false; }
  if (relay2Active && !relay2Permanent && now - relay2StartTime >= relayInterval) { digitalWrite(REL2, LOW); relay2Active=false; }
  if (relay3Active && !relay3Permanent && now - relay3StartTime >= relayInterval) { digitalWrite(REL3, LOW); relay3Active=false; }
  if (relay4Active && !relay4Permanent && now - relay4StartTime >= relayInterval) { digitalWrite(REL4, LOW); relay4Active=false; }
  if (relay5Active && !relay5Permanent && now - relay5StartTime >= relayInterval) { digitalWrite(REL5, LOW); relay5Active=false; }
  if (relay6Active && !relay6Permanent && now - relay6StartTime >= relayInterval) { digitalWrite(REL6, LOW); relay6Active=false; }
  if (relay7Active && !relay7Permanent && now - relay7StartTime >= relayInterval) { digitalWrite(REL7, LOW); relay7Active=false; }
  if (relay8Active && !relay8Permanent && now - relay8StartTime >= relayInterval) { digitalWrite(REL8, LOW); digitalWrite(REL9, LOW); relay8Active=false; }

  // czujnik — wyłącza REL1 i REL2 przy dwukrotnej zmianie
  int sensorState = digitalRead(CZUJNIK);
  if (sensorState != lastSensorState) {
    lastSensorState = sensorState;
    if (now - lastSensorChangeTime < sensorWindow) sensorChangeCount++;
    else sensorChangeCount = 1;
    lastSensorChangeTime = now;
    if (sensorChangeCount >= 2) {
      digitalWrite(REL1, LOW); digitalWrite(REL2, LOW);
      relay1Active = relay2Active = false;
      relay1Permanent = relay2Permanent = false;
      sensorChangeCount = 0;
    }
  }
}

/* ====== CALLBACKI ====== */

// --- b1 ---
void b1Click() {
  if (relay1Permanent) { digitalWrite(REL1, LOW); relay1Active=relay1Permanent=false; }
  else if (!relay1Active) { digitalWrite(REL2, LOW); digitalWrite(REL1, HIGH); relay1Active=true; relay1Permanent=false; relay1StartTime=millis(); }
}
void b1Hold() { digitalWrite(REL2, LOW); digitalWrite(REL1, HIGH); relay1Active=relay1Permanent=true; }

// --- b2 ---
void b2Click() {
  if (relay2Permanent) { digitalWrite(REL2, LOW); relay2Active=relay2Permanent=false; }
  else if (!relay2Active) { digitalWrite(REL1, LOW); digitalWrite(REL2, HIGH); relay2Active=true; relay2Permanent=false; relay2StartTime=millis(); }
}
void b2Hold() { digitalWrite(REL1, LOW); digitalWrite(REL2, HIGH); relay2Active=relay2Permanent=true; }

// --- b3 ---
void b3Click() {
  if (relay3Permanent) { digitalWrite(REL3, LOW); relay3Active=relay3Permanent=false; }
  else if (!relay3Active) { digitalWrite(REL3, HIGH); relay3Active=true; relay3Permanent=false; relay3StartTime=millis(); }
}
void b3Hold() { digitalWrite(REL3, HIGH); relay3Active=relay3Permanent=true; }

// --- b4 ---
void b4Click() {
  if (relay7Permanent) { digitalWrite(REL7, LOW); relay7Active=relay7Permanent=false; }
  else if (!relay7Active) { digitalWrite(REL7, HIGH); relay7Active=true; relay7Permanent=false; relay7StartTime=millis(); }
}
void b4Hold() {
  digitalWrite(REL4, HIGH); relay4Active=relay4Permanent=true;
  digitalWrite(REL5, HIGH); relay5Active=relay5Permanent=true;
}

// --- b5 ---
int b5Cycle = 0;
void b5Click() {
  if (relay4Permanent && relay5Permanent) {
    b5Cycle = (b5Cycle + 1) % 3;
    if (b5Cycle == 0) { digitalWrite(REL4, HIGH); digitalWrite(REL5, HIGH); digitalWrite(REL6, LOW); }
    else if (b5Cycle == 1) { digitalWrite(REL4, HIGH); digitalWrite(REL5, HIGH); digitalWrite(REL6, HIGH); }
    else if (b5Cycle == 2) { digitalWrite(REL4, HIGH); digitalWrite(REL5, LOW); digitalWrite(REL6, HIGH); }
  }
}
void b5Hold() { digitalWrite(REL4, LOW); digitalWrite(REL5, LOW); digitalWrite(REL6, LOW); relay4Active=relay5Active=relay6Active=false; relay4Permanent=relay5Permanent=relay6Permanent=false; b5Cycle=0; }

// --- b6 ---
void b6Click() {
  if (relay8Permanent) {
    digitalWrite(REL8, LOW);
    relay8Active = relay8Permanent = false;
  } else if (!relay8Active) {
    digitalWrite(REL8, HIGH);
    digitalWrite(REL9, HIGH);
    relay8Active = true;
    relay8Permanent = false;
    relay8StartTime = millis();
  }
}
void b6Hold() {
  digitalWrite(REL8, HIGH);
  relay8Active = relay8Permanent = true;
}

Ponieważ w moim starym Nano coś stało się z pamięcią w Atmega328 wymieniłem ją na Atmega8 i mam Nano z Atmega8.
Trochę brakło RAMu więc wyrzuciłem Serial.Print.
Na dzisiaj darmowy limit chata wyczerpany ale chyba i bez niego dam radę to dokończyć.

Klawisze 1 i 2: kierunkowskazy click włącza na chwilę tzw. mrugnięcie hold na stałe. Kolejny click wyłącza lub zadziałanie czujnika skrętu.
Kklawisz3: światła drogowe/mijania: click mrugnięcie, hold włączenie drogowych kolejny click gdy są włączone wyłącza.
Klawisz 4: click wycieraczka przednia i spryskiwacz, hold włącza wycieraczkę przednią na tryb automatyczny (czujnik deszczu)
Klawisz 5 : jeśli wycieraczki są włączone po klawiszu4hold to w pętli przełączają z automatu na 1szą prędkość---drugą prędkość----i ponownie automat długie naciśnięcie klawisza 5 wyłącza wycieraczki.
Klawisz 6: wycierczka tylna - click spryskiwacz i 1 raz wycieraczka, hold włącz samą wycieraczkę, kolejny click po hold wyłącz.

Kompiluje się i działa na razie z ledami zamiast przekaźników.

Edytowano przez GaaD
(edytowany)

Nie mogę zrobić edycji poprzedniego posta więc napiszę kolejny:

Wersja finalna z opcją resetu po b8hold.
Wszystkie funkcje działają tak jak założyłem.
Dodany przycisk 7 i 8 z opcją j.w.
Optymalizacja kodu przez chatGPT trochę rozwala pętlę przycisku b5click więc jej tu nie wklejam bo nie sądzę aby ktokolwiek miał ochotę to analizować i poprawiać. Klawiatura działa teraz będę składał prototyp i podłączał pod elektronikę wyłącznika zespolonego. W okolicach świąt gdy auto nie będzie używane i będzie je można na dłużej unieruchomić może uda nam się zdemontować kierownicę i założyć układ testowy. To pozwoli mi być może przetestować czy wszystko działa tak jak powinno. Z pewnością testów wymaga czujnik skrętu. Postaram się opisać dalszy postęp prac ale trochę to potrwa.
Działający program:

#include <AnalogButtons.h>
#include <avr/wdt.h>

#define ANALOG_PIN A0
#define DEBUG 0  // 1 = włącz debug przez Serial

// ====== Definicje pinów ======
const int relayPins[11] = {2,3,4,5,6,7,8,9,10,11,12}; // REL1..REL11
#define CZUJNIK 13

// ====== Czasy w ms ======
const unsigned long relayTimes[11] = {
  1000, // REL1
  1000, // REL2
  1000, // REL3
  3000,    // REL4
  0,    // REL5
  3000, // REL6
  3000, // REL7
  3000, // REL8
  3000, // REL9
  1000, // REL10
  1000  // REL11
};

const unsigned long sensorWindow = 60000;

// ====== Stany przekaźników ======
bool relayActive[11] = {false};
bool relayPermanent[11] = {false};
unsigned long relayStart[11] = {0};

// ====== Czujnik ======
int lastSensorState = HIGH;
unsigned long lastSensorChangeTime = 0;
int sensorChangeCount = 0;

// ====== Analog Buttons ======
AnalogButtons analogButtons(ANALOG_PIN, INPUT, 5, 15);

// ====== Deklaracje callbacków ======
void b1Click(); void b1Hold();
void b2Click(); void b2Hold();
void b3Click(); void b3Hold();
void b4Click(); void b4Hold();
void b5Click(); void b5Hold();
void b6Click(); void b6Hold();
void b7Click(); void b7Hold();
void b8Click(); void b8Hold();

Button b1 = Button(0,   &b1Click, &b1Hold, 700, 1500);
Button b2 = Button(110, &b2Click, &b2Hold, 700, 1500);
Button b3 = Button(495, &b3Click, &b3Hold, 700, 1500);
Button b4 = Button(315, &b4Click, &b4Hold, 800, 1500);
Button b5 = Button(170, &b5Click, &b5Hold, 500, 1500);
Button b6 = Button(720, &b6Click, &b6Hold, 500, 1500);
Button b7 = Button(605, &b7Click, &b7Hold, 500, 1500);
Button b8 = Button(240, &b8Click, &b8Hold, 500, 1500);

// ====== Dodatkowe zmienne ======
int b5Cycle = 0;

void setup() {
#if DEBUG
  Serial.begin(9600);
#endif

  analogButtons.add(b1); analogButtons.add(b2); analogButtons.add(b3); analogButtons.add(b4);
  analogButtons.add(b5); analogButtons.add(b6); analogButtons.add(b7); analogButtons.add(b8);

  for (int i = 0; i < 11; i++) {
    pinMode(relayPins[i], OUTPUT);
    digitalWrite(relayPins[i], LOW);
  }

  pinMode(CZUJNIK, INPUT_PULLUP);
}

void loop() {
  analogButtons.check();
  unsigned long now = millis();

  // automatyczne wyłączanie przekaźników czasowych
  for (int i = 0; i < 11; i++) {
    if (relayActive[i] && !relayPermanent[i] && relayTimes[i] > 0 && now - relayStart[i] >= relayTimes[i]) {
      digitalWrite(relayPins[i], LOW);
      relayActive[i] = false;
    }
  }

  // czujnik — wyłącza REL1 i REL2 przy dwukrotnej zmianie
  int sensorState = digitalRead(CZUJNIK);
  if (sensorState != lastSensorState) {
    lastSensorState = sensorState;
    if (now - lastSensorChangeTime < sensorWindow) sensorChangeCount++;
    else sensorChangeCount = 1;
    lastSensorChangeTime = now;
    if (sensorChangeCount >= 2) {
      digitalWrite(relayPins[0], LOW); // REL1
      digitalWrite(relayPins[1], LOW); // REL2
      relayActive[0] = relayActive[1] = false;
      relayPermanent[0] = relayPermanent[1] = false;
      sensorChangeCount = 0;
    }
  }
}

/* ====== CALLBACKI ====== */

// --- b1 ---
void b1Click() {
  if (relayPermanent[0]) { digitalWrite(relayPins[0], LOW); relayActive[0]=relayPermanent[0]=false; }
  else { digitalWrite(relayPins[1], LOW); digitalWrite(relayPins[0], HIGH); relayActive[0]=true; relayPermanent[0]=false; relayStart[0]=millis(); }
}
void b1Hold() { digitalWrite(relayPins[1], LOW); digitalWrite(relayPins[0], HIGH); relayActive[0]=relayPermanent[0]=true; }

// --- b2 ---
void b2Click() {
  if (relayPermanent[1]) { digitalWrite(relayPins[1], LOW); relayActive[1]=relayPermanent[1]=false; }
  else { digitalWrite(relayPins[0], LOW); digitalWrite(relayPins[1], HIGH); relayActive[1]=true; relayPermanent[1]=false; relayStart[1]=millis(); }
}
void b2Hold() { digitalWrite(relayPins[0], LOW); digitalWrite(relayPins[1], HIGH); relayActive[1]=relayPermanent[1]=true; }

// --- b3 ---
void b3Click() { if (relayPermanent[2]) { digitalWrite(relayPins[2], LOW); relayActive[2]=relayPermanent[2]=false; }
  else { digitalWrite(relayPins[2], HIGH); relayActive[2]=true; relayPermanent[2]=false; relayStart[2]=millis(); } }
void b3Hold() { digitalWrite(relayPins[2], HIGH); relayActive[2]=relayPermanent[2]=true; }

// --- b4 ---
void b4Click() {
  // --- REL7 zawsze na 3 sekundy ---
  digitalWrite(relayPins[6], HIGH);      // REL7
  relayActive[6] = true;
  relayPermanent[6] = false;
  relayStart[6] = millis();

  // --- REL4: tylko jeśli NIE jest permanentny ---
  if (!relayPermanent[3]) {
    digitalWrite(relayPins[3], HIGH);    // REL4
    relayActive[3] = true;
    relayPermanent[3] = false;
    relayStart[3] = millis();            // licz czas REL4
  }

  // Jeśli REL4 permanentny → zostaje tak jak był, nic nie zmieniamy
}

void b4Hold() {
  // REL4 i REL5 na stałe
  digitalWrite(relayPins[3], HIGH); relayActive[3] = relayPermanent[3] = true;
  digitalWrite(relayPins[4], HIGH); relayActive[4] = relayPermanent[4] = true;
}
// --- b5 ---
void b5Click() {
  if (relayPermanent[3] && relayPermanent[4]) {
    b5Cycle = (b5Cycle + 1) % 3;
    if (b5Cycle==0) { digitalWrite(relayPins[3], HIGH); digitalWrite(relayPins[4], HIGH); digitalWrite(relayPins[5], LOW); }
    else if (b5Cycle==1) { digitalWrite(relayPins[3], HIGH); digitalWrite(relayPins[4], HIGH); digitalWrite(relayPins[5], HIGH); }
    else if (b5Cycle==2) { digitalWrite(relayPins[3], HIGH); digitalWrite(relayPins[4], LOW); digitalWrite(relayPins[5], HIGH); }
  }
}
void b5Hold() { digitalWrite(relayPins[3], LOW); digitalWrite(relayPins[4], LOW); digitalWrite(relayPins[5], LOW);
                relayActive[3]=relayActive[4]=relayActive[5]=false;
                relayPermanent[3]=relayPermanent[4]=relayPermanent[5]=false;
                b5Cycle=0; }

// --- b6 ---
void b6Click() {
  // Jeśli REL8 jest permanentny → klik wyłącza REL8 i nic więcej
  if (relayPermanent[7]) {  // REL8 index 7
    digitalWrite(relayPins[7], LOW);
    relayPermanent[7] = false;
    relayActive[7] = false;
    relayActive[8] = false; // REL9 bezpieczeństwo
    return;
  }

  // Normalny tryb czasowy 3 sekundy dla REL8 i REL9
  digitalWrite(relayPins[7], HIGH);  // REL8
  relayActive[7] = true;
  relayPermanent[7] = false;
  relayStart[7] = millis();

  digitalWrite(relayPins[8], HIGH);  // REL9
  relayActive[8] = true;
  relayPermanent[8] = false;
  relayStart[8] = millis();
}

void b6Hold() {
  // Włącza REL8 na stałe
  digitalWrite(relayPins[7], HIGH);
  relayPermanent[7] = true;
  relayActive[7] = false;  // wyłączamy czasomierz

  // REL9 zawsze wyłączony w trybie permanentnym REL8
  digitalWrite(relayPins[8], LOW);
  relayPermanent[8] = false;
  relayActive[8] = false;
}

// --- b7 ---
void b7Click() { if (relayPermanent[9]) { digitalWrite(relayPins[9], LOW); relayActive[9]=relayPermanent[9]=false; }
  else { digitalWrite(relayPins[9], HIGH); relayActive[9]=true; relayPermanent[9]=false; relayStart[9]=millis(); } }
void b7Hold() { digitalWrite(relayPins[9], HIGH); relayActive[9]=relayPermanent[9]=true; }

// --- b8 ---
void b8Click() { if (relayPermanent[10]) { digitalWrite(relayPins[10], LOW); relayActive[10]=relayPermanent[10]=false; }
  else { digitalWrite(relayPins[10], HIGH); relayActive[10]=true; relayPermanent[10]=false; relayStart[10]=millis(); } }
//void b8Hold() { digitalWrite(relayPins[10], HIGH); relayActive[10]=relayPermanent[10]=true; }
void b8Hold() {
  // Wyłącz wszystkie przekaźniki
  for(int i=0; i<11; i++) {
    digitalWrite(relayPins[i], LOW);
    relayActive[i] = false;
    relayPermanent[i] = false;
  }
  b5Cycle = 0;
  sensorChangeCount = 0;

  // Wymuszenie resetu przez Watchdog
  wdt_enable(WDTO_15MS); // ustaw watchdog na 15 ms
  while(1) {}             // czekaj aż watchdog zresetuje MCU
}

 

Edytowano przez GaaD

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...