Witam! udało się! dodałem do programu debounce i blokady czasowe które defacto wyeliminowały wszystkie błędne impulsy! teraz działa poprawnie
oto zmodyfikowany kod, może komuś się przyda:)
// Definiowanie pinów dla wejść i wyjść
#define A0_PIN A0
#define A4_PIN A4 // Zmieniono z A1 na A4
#define A2_PIN A2
#define A3_PIN A3
#define OUTPUT_2 3
#define OUTPUT_4 4
#define OUTPUT_5 5
#define OUTPUT_6 6
#define OUTPUT_10 10
#define OUTPUT_11 11
#define OUTPUT_12 12
#define OUTPUT_13 13
// Zmienne do zarządzania stanem i czasem dla bram
int gate1_state = 0; // 0 = zatrzymana, 1 = otwieranie (OUTPUT_2), 2 = zamykanie (OUTPUT_4)
int gate2_state = 0; // 0 = zatrzymana, 1 = otwieranie (OUTPUT_5), 2 = zamykanie (OUTPUT_6)
unsigned long gate1_start_time = 0;
unsigned long gate2_start_time = 0;
const unsigned long interval = 27000; // 27 sekund w milisekundach
const unsigned long blockInterval = 1500; // 1,5 sekundy w milisekundach - blokada innych kanałów
const unsigned long channelCooldown = 380; // 0,38 sekundy w milisekundach - cooldown dla tego samego kanału
// Zmienne do zarządzania stanem oświetlenia
int lightingInternalState = 0; // 0 = wszystko wyłączone, 1 = OUTPUT_12 włączony, 2 = OUTPUT_13 włączony, 3 = oba włączone
int lightingExternalState = 0; // 0 = wszystko wyłączone, 1 = OUTPUT_10 włączony, 2 = OUTPUT_11 włączony, 3 = oba włączone
// Zmienne do debouncowania i czasów
unsigned long lastDebounceTimeA0 = 0;
unsigned long lastDebounceTimeA4 = 0;
unsigned long lastDebounceTimeA2 = 0;
unsigned long lastDebounceTimeA3 = 0;
unsigned long lastGlobalActivationTime = 0; // Czas globalny dla blokady wejść
unsigned long lastChannelActivationTime = 0; // Czas ostatniej aktywacji kanału
const unsigned long debounceDelay = 500; // 500 ms - czas debouncowania
const unsigned long stabilityDelay = 200; // 200 ms - czas na potwierdzenie stabilnego sygnału
// Funkcja sprawdzająca, czy wystarczająco dużo czasu upłynęło od ostatniej aktywacji dla wszystkich kanałów
bool isGlobalActivationAllowed() {
return (millis() - lastGlobalActivationTime) > blockInterval;
}
// Funkcja sprawdzająca, czy wystarczająco dużo czasu upłynęło od ostatniej aktywacji danego kanału
bool isChannelActivationAllowed() {
return (millis() - lastChannelActivationTime) > channelCooldown;
}
// Funkcja sprawdzająca, czy sygnał na pinie jest stabilny
bool isSignalStable(int pin, unsigned long stableTime) {
unsigned long startTime = millis();
while ((millis() - startTime) < stableTime) {
if (digitalRead(pin) != LOW) {
return false;
}
}
return true;
}
// Funkcja do debouncowania i filtrowania sygnałów wejściowych
bool debounceAndFilter(int pin, unsigned long &lastDebounceTime, unsigned long stableTime, unsigned long debounceDelay) {
if (digitalRead(pin) == LOW && (millis() - lastDebounceTime) > debounceDelay) {
if (isSignalStable(pin, stableTime)) {
lastDebounceTime = millis();
return true;
}
}
return false;
}
void setup() {
// Ustawienie pinów wejściowych na tryb INPUT_PULLUP
pinMode(A0_PIN, INPUT_PULLUP);
pinMode(A4_PIN, INPUT_PULLUP); // A4 zamiast A1
pinMode(A2_PIN, INPUT_PULLUP);
pinMode(A3_PIN, INPUT_PULLUP);
// Ustawienie pinów wyjściowych na tryb OUTPUT
pinMode(OUTPUT_2, OUTPUT);
pinMode(OUTPUT_4, OUTPUT);
pinMode(OUTPUT_5, OUTPUT);
pinMode(OUTPUT_6, OUTPUT);
pinMode(OUTPUT_10, OUTPUT);
pinMode(OUTPUT_11, OUTPUT);
pinMode(OUTPUT_12, OUTPUT);
pinMode(OUTPUT_13, OUTPUT);
// Inicjalizacja wszystkich wyjść na HIGH (wyłączone)
digitalWrite(OUTPUT_2, HIGH);
digitalWrite(OUTPUT_4, HIGH);
digitalWrite(OUTPUT_5, HIGH);
digitalWrite(OUTPUT_6, HIGH);
digitalWrite(OUTPUT_10, HIGH);
digitalWrite(OUTPUT_11, HIGH);
digitalWrite(OUTPUT_12, HIGH);
digitalWrite(OUTPUT_13, HIGH);
}
// Funkcja do sterowania Bramą 1
void controlGate1() {
if (gate1_state == 0) { // zatrzymana -> rozpocznij otwieranie
digitalWrite(OUTPUT_2, LOW); // Włącz otwieranie
digitalWrite(OUTPUT_4, HIGH); // Upewnij się, że zamykanie jest wyłączone
gate1_state = 1;
gate1_start_time = millis();
} else if (gate1_state == 1) { // otwieranie -> zatrzymanie
digitalWrite(OUTPUT_2, HIGH); // Zatrzymaj otwieranie
gate1_state = 2;
gate1_start_time = millis();
} else if (gate1_state == 2) { // zatrzymana -> rozpocznij zamykanie
digitalWrite(OUTPUT_4, LOW); // Włącz zamykanie
gate1_state = 3;
gate1_start_time = millis();
} else if (gate1_state == 3) { // zamykanie -> zatrzymanie
digitalWrite(OUTPUT_4, HIGH); // Zatrzymaj zamykanie
gate1_state = 0;
}
}
// Funkcja do sterowania Bramą 2
void controlGate2() {
if (gate2_state == 0) { // zatrzymana -> rozpocznij otwieranie
digitalWrite(OUTPUT_5, LOW); // Włącz otwieranie
digitalWrite(OUTPUT_6, HIGH); // Upewnij się, że zamykanie jest wyłączone
gate2_state = 1;
gate2_start_time = millis();
} else if (gate2_state == 1) { // otwieranie -> zatrzymanie
digitalWrite(OUTPUT_5, HIGH); // Zatrzymaj otwieranie
gate2_state = 2;
gate2_start_time = millis();
} else if (gate2_state == 2) { // zatrzymana -> rozpocznij zamykanie
digitalWrite(OUTPUT_6, LOW); // Włącz zamykanie
gate2_state = 3;
gate2_start_time = millis();
} else if (gate2_state == 3) { // zamykanie -> zatrzymanie
digitalWrite(OUTPUT_6, HIGH); // Zatrzymaj zamykanie
gate2_state = 0;
}
}
void loop() {
unsigned long currentTime = millis();
// Kontrola Bramy 1 z debouncowaniem, filtrowaniem i blokadą czasową
if (debounceAndFilter(A0_PIN, lastDebounceTimeA0, stabilityDelay, debounceDelay) && isChannelActivationAllowed()) {
lastChannelActivationTime = currentTime;
if (isGlobalActivationAllowed()) {
lastGlobalActivationTime = currentTime;
}
controlGate1();
}
// Kontrola Bramy 2 z debouncowaniem, filtrowaniem i blokadą czasową
if (debounceAndFilter(A4_PIN, lastDebounceTimeA4, stabilityDelay, debounceDelay) && isChannelActivationAllowed()) {
lastChannelActivationTime = currentTime;
if (isGlobalActivationAllowed()) {
lastGlobalActivationTime = currentTime;
}
controlGate2();
}
// Kontrola oświetlenia wewnętrznego z debouncowaniem, filtrowaniem i blokadą czasową
if (debounceAndFilter(A2_PIN, lastDebounceTimeA2, stabilityDelay, debounceDelay) && isChannelActivationAllowed()) {
lastChannelActivationTime = currentTime;
if (isGlobalActivationAllowed()) {
lastGlobalActivationTime = currentTime;
}
lightingInternalState = (lightingInternalState + 1) % 4;
switch (lightingInternalState) {
case 0:
digitalWrite(OUTPUT_12, HIGH); // Wyłącz oba światła
digitalWrite(OUTPUT_13, HIGH);
break;
case 1:
digitalWrite(OUTPUT_12, LOW); // Włącz pierwsze światło
digitalWrite(OUTPUT_13, HIGH);
break;
case 2:
digitalWrite(OUTPUT_12, HIGH); // Włącz drugie światło
digitalWrite(OUTPUT_13, LOW);
break;
case 3:
digitalWrite(OUTPUT_12, LOW); // Włącz oba światła
digitalWrite(OUTPUT_13, LOW);
break;
}
}
// Kontrola oświetlenia zewnętrznego z debouncowaniem, filtrowaniem i blokadą czasową
if (debounceAndFilter(A3_PIN, lastDebounceTimeA3, stabilityDelay, debounceDelay) && isChannelActivationAllowed()) {
lastChannelActivationTime = currentTime;
if (isGlobalActivationAllowed()) {
lastGlobalActivationTime = currentTime;
}
lightingExternalState = (lightingExternalState + 1) % 4;
switch (lightingExternalState) {
case 0:
digitalWrite(OUTPUT_10, HIGH); // Wyłącz oba światła
digitalWrite(OUTPUT_11, HIGH);
break;
case 1:
digitalWrite(OUTPUT_10, LOW); // Włącz pierwsze światło
digitalWrite(OUTPUT_11, HIGH);
break;
case 2:
digitalWrite(OUTPUT_10, HIGH); // Włącz drugie światło
digitalWrite(OUTPUT_11, LOW);
break;
case 3:
digitalWrite(OUTPUT_10, LOW); // Włącz oba światła
digitalWrite(OUTPUT_11, LOW);
break;
}
}
// Sprawdzanie, czy minęło 27 sekund dla Bramy 1
if (gate1_state != 0 && (millis() - gate1_start_time >= interval)) {
if (gate1_state == 1) {
digitalWrite(OUTPUT_2, HIGH); // Zatrzymaj otwieranie
} else if (gate1_state == 2) {
digitalWrite(OUTPUT_4, HIGH); // Zatrzymaj zamykanie
} else if (gate1_state == 3) {
digitalWrite(OUTPUT_4, HIGH); // Zatrzymaj zamykanie
}
gate1_state = 0; // Zatrzymaj bramę po 27 sekundach
}
// Sprawdzanie, czy minęło 27 sekund dla Bramy 2
if (gate2_state != 0 && (millis() - gate2_start_time >= interval)) {
if (gate2_state == 1) {
digitalWrite(OUTPUT_5, HIGH); // Zatrzymaj otwieranie
} else if (gate2_state == 2) {
digitalWrite(OUTPUT_6, HIGH); // Zatrzymaj zamykanie
} else if (gate2_state == 3) {
digitalWrite(OUTPUT_6, HIGH); // Zatrzymaj zamykanie
}
gate2_state = 0; // Zatrzymaj bramę po 27 sekundach
}
}
Oto szczegółowe omówienie działania kodu:
1. Inicjalizacja i ustawienia w funkcji setup():
Konfiguracja pinów:
Piny A0, A2, A3, A4 są ustawione jako wejścia z włączonym wewnętrznym rezystorem podciągającym (INPUT_PULLUP). To oznacza, że przyciski muszą być podłączone tak, aby po naciśnięciu zwierały pin do masy (LOW).
Piny 3, 4, 5, 6, 10, 11, 12, 13 są ustawione jako wyjścia, które będą sterować bramami oraz oświetleniem.
Wszystkie wyjścia są inicjalizowane stanem HIGH, co oznacza, że na starcie wszystkie urządzenia są wyłączone.
2. Sterowanie bramami (controlGate1() i controlGate2()):
Brama 1 (controlGate1()):
Stan 0: Brama jest zatrzymana. Po naciśnięciu przycisku (A0), brama zaczyna się otwierać (pin 3 ustawia się na LOW, co oznacza włączenie otwierania), a stan bramy zmienia się na 1.
Stan 1: Brama jest w trakcie otwierania. Kolejne naciśnięcie przycisku powoduje zatrzymanie otwierania (pin 3 ustawia się na HIGH) i zmienia stan bramy na 2.
Stan 2: Brama jest zatrzymana po otwieraniu. Kolejne naciśnięcie przycisku powoduje rozpoczęcie zamykania bramy (pin 4 ustawia się na LOW, co oznacza włączenie zamykania), a stan zmienia się na 3.
Stan 3: Brama jest w trakcie zamykania. Kolejne naciśnięcie przycisku powoduje zatrzymanie zamykania (pin 4 ustawia się na HIGH), a stan bramy wraca do 0.
Brama 2 (controlGate2()):
Działa dokładnie tak samo jak brama 1, ale sterowanie odbywa się przez piny 5 (otwieranie) i 6 (zamykanie), a przycisk sterujący to A4.
3. Sterowanie oświetleniem:
Oświetlenie wewnętrzne (lightingInternalState):
Stan oświetlenia zmienia się cyklicznie przy każdym naciśnięciu przycisku podłączonego do A2:
Wszystko wyłączone.
Włączone pierwsze światło (pin 12 LOW).
Włączone drugie światło (pin 13 LOW).
Oba światła włączone.
Oświetlenie zewnętrzne (lightingExternalState):
Działa analogicznie do oświetlenia wewnętrznego, ale sterowanie odbywa się przez piny 10 (pierwsze światło) i 11 (drugie światło), a przycisk sterujący to A3.
4. Logika blokad i debouncowania:
Debouncowanie: Kod wykorzystuje czas opóźnienia (debounceDelay), aby ignorować fałszywe sygnały spowodowane drganiami styków przycisków.
Blokada kanałów:
Po naciśnięciu dowolnego przycisku, blokowane są wszystkie inne kanały na 1,5 sekundy (blockInterval), aby uniknąć przypadkowych aktywacji innych urządzeń.
Każdy przycisk można ponownie aktywować po 0,38 sekundy (channelCooldown), ale inne kanały pozostają zablokowane przez pełne 1,5 sekundy.
5. Główna pętla (loop()):
Sprawdzanie i obsługa wejść:
Kod cyklicznie sprawdza stan każdego z czterech wejść (A0, A2, A3, A4), wykorzystując funkcję debounceAndFilter(), która realizuje zarówno debouncowanie, jak i filtrowanie sygnałów.
Jeżeli spełnione są wszystkie warunki (debouncowanie, sygnał stabilny, dozwolona aktywacja), kod aktywuje odpowiednią funkcję sterującą: controlGate1(), controlGate2(), lub przełącza stan oświetlenia wewnętrznego/zewnętrznego.
Automatyczne zatrzymanie bram:
Kod sprawdza, czy brama była otwarta lub zamykana przez 27 sekund. Jeżeli tak, brama zostaje automatycznie zatrzymana, aby zapobiec ciągłemu działaniu.
Podsumowanie:
Kanały A0 i A4 kontrolują odpowiednio Bramę 1 i Bramę 2, gdzie każda brama ma tryby otwierania, zatrzymywania i zamykania.
Kanały A2 i A3 sterują odpowiednio oświetleniem wewnętrznym i zewnętrznym, z cyklicznym przełączaniem stanów (wyłączone, jedno światło włączone, drugie światło włączone, oba światła włączone, wyłączone...).
Kod zawiera mechanizmy zabezpieczające przed drganiami styków oraz blokuje inne kanały po aktywacji dowolnego z nich, aby zapobiec przypadkowym aktywacjom i zapewnić przewidywalne działanie systemu.
Dodano po 2 [minuty]:
problem tkwił prawdopodobnie w impulsach wejściowych, gdzieś na wejsciu pojawialy sie błędne krótkotrwałe impulsy, które miały po kilka ms, dzieki za pomoc!
Dodano po 1 [minuty]:
>>21183202 właśnie nie do końca, jedynie zwieranie z GND uruchamia kanały