Skocz do zawartości

Sterowanie podświetleniem schodów z wykorzystaniem Arduino - problem z odwróceniem logiki


dernis

Pomocna odpowiedź

#define P1 51

int brightness = 0;  // aktualny stan wypelnienia
int change = 5;      // zmiana PWM
int delayT = 20;


void setup() {

  Serial.begin(9600);

  //konfiguracja wysjc Arduino
  for (int i = 3; i < 13; i++) {
    pinMode(i, OUTPUT);
  }

  pinMode(P1, INPUT_PULLUP);
}

void loop() {

  if (isOn(P1, delayT)) {

    for (int i = 3; i < 15; i++) {
      // pomocnicza flaga do while() (lokalna!! trzeba cofnąć warunek wyjscia pętli po jednym obiegu)
      bool stat = true;

      switch (i) {
        case 3:
          stairsControl(i, stat);
          break;

        case 4:
          stairsControl(i, stat);
          break;

        case 5:
          stairsControl(i, stat);
          break;

        case 6:
          stairsControl(i, stat);
          break;

        case 7:
          stairsControl(i, stat);
          break;

        case 8:
          stairsControl(i, stat);
          break;

        case 9:
          stairsControl(i, stat);
          break;

        case 10:
          stairsControl(i, stat);
          break;

        case 11:
          stairsControl(i, stat);
          break;

        case 12:
          stairsControl(i, stat);
          break;

        case 13:
          stairsControl(i, stat);
          break;
      }
    }
  }
}

void stairsControl(int i, bool status) {

  while (status == true) {

    analogWrite(i, brightness);

    brightness = brightness + change;
    delay(10);

    //jeśli przejdziemy przez srodek wypelnienia to dekrementujemy "i", tym samym załączamy poprzedni i nastepny case.
    if (brightness == 125) {
      i = i - 1;
    }

    // zmiana statusu flagi dla while()
    if (brightness == 0) {
      status = !status;
    }

    // odwróć change w warosciach 0 i 255
    if (brightness <= 0 || brightness >= 255) {
      change = -change;
    }

    // test zmiennych i przyjmowanych wartosci
    Serial.print(i);
    Serial.print("-");
    Serial.println(brightness);
    delay(5);
  }
}

//Obsluga przycisku, drgania styków (symulacja czujnika ruchu)
bool isOn(int button, int T) {
  if (digitalRead(button) == LOW) {
    delay(T);
    if (digitalRead(button) == LOW) {
      return true;
    }
  }
  return false;
}

Witam,

Ogólny zarys schematu wygląda tak:

- 18 stopni z taśmami LED typu COB.

- Każdy "listek" ledowy jest sterowany przez Mosfety, poprzez PWM.

- Fotorezystor (funkcja dezaktywacji układu przez dzień), na analogówce.

- 2 czujniki w ścianach (jeden na pierwszym stopniu, drugi na ostatnim w montażu poziomym).

 

W tym okodowaniu, użyłem do symulacji 9 diod LED, i przycisku P1(czujnik) do zasymulowania działania układu. W instrukcji wyboru celowo przeciągam LEDy, żeby przy dekrementacji ( warunek if(brightness) w funkcji stairsControl())  wygaszać je do samego końca, jeśli tego nie zrobię , to program po przejściu przez wszystkie przypadki zostawia załączone dwie ostatnie diody LED.

 

Moje pytanie:

- Chciałbym, żeby przerwanie czujnika nr 2 (nie jest okodowany) , odwróciło logikę pętli for(). Bo bez sensu schodzić z góry i zapalać schody od dołu - na tą chwile utknąłem w martwym punkcie.

- Czy sensowne jest wprowadzanie naszego MCU w tryb sleep, STB? i wybudzanie go po odpowiednim dostosowaniu oświetlenia otoczenia? ( ograniczyć pobór).

- Czy ten kod jest ogólnie znośnie napisany?? (dwa lata temu ostatni raz siedziałem w IDE).

Cały program był pisany samodzielnie, nie był kopiowany z żadnych źródeł.

 

Zostawiam aktywny UART, do możliwości podglądu jak symulacja wygląda (na liczbach). Dzięki za pomoc.

Gif przestawia symulacje.

 

test.gif

Edytowano przez dernis
  • Lubię! 1
Link do komentarza
Share on other sites

zmienna x = 0; 

  if(czujnik1 || czujnik2 && x== 0) { 
  x = 1;
  for (int i = 3; i < 13; i++) { 
  for (int jasnosc =0; jasnosc < 255; jasnosc+5) { 
    analogWrite(i, jasnosc);
    delay(10); 
    } 
 } 
  if(czujnik1 || czujnik2 && x== 1) { 
  x = 0;
  for (int i = 3; i < 13; i++) { 
  for (int jasnosc =255; jasnosc > 0; jasnosc-5) { 
    analogWrite(i, jasnosc);
    delay(10); 
    } 
    

Ten switch case tam nie potrzebny, bez niego w pętli for wykona się tak samo...musisz zrobić tak że jeśli któryś czujnik uruchomiony to ustawisz odpowiednią flagę i wykonujesz odpowiedni kawałek kodu...

 

To powyżej powinno działać tak jak chcesz

  • Lubię! 1
Link do komentarza
Share on other sites

#define P1 51
#define P2 52

void setup() {
  for (int i = 3; i < 12; i++) {
    pinMode(i, OUTPUT);
  }

  pinMode(P1, INPUT_PULLUP);
  pinMode(P2, INPUT_PULLUP);
}

void loop() {

  if (isOn(P1)) {
    stairsControlUp(3, 12);
  }
  if (isOn(P2)) {
    stairsControlDown(12, 2);
  }
}

void stairsControlUp(int a, int b) {

  for (int i = a; i < b; i++) {
    for (int j = 0; j <= 255; j++) {
      analogWrite(i, j);
      delay(20);

      if (j == 255) {
        for (int k = 255; k > 1; k--) {
          analogWrite(i, k);
          delay(5);
        }
      }
    }
  }
}

void stairsControlDown(int a, int b) {

  for (int i = a; i > b; i--) {
    for (int j = 0; j <= 255; j++) {
      analogWrite(i, j);
      delay(1);

      if (j == 255) {
        for (int k = 255; k > 1; k--) {
          analogWrite(i, k);
          delay(5);
        }
      }
    }
  }
}

bool isOn(int button) {
  if (digitalRead(button) == LOW) {
    delay(20);
    if (digitalRead(button) == LOW) {
      return true;
    }
  }
  return false;
}

Ok, nowy kodzik wygląda tak (wg Twojej propozycji). W teorii prawie już gra.. ale.. Chciałbym, żeby Ledy zapalały się w sekwencji jak na gifie:

1 stopień - start do wypełnienia 50% następnie:

2 stopien - start od 0% do wypełnienia 50% kiedy poprzednia już takie osiągnie(50%) (poprzedni(stopień 1) zaczyna wracać z wypełnienia 100% w tym momencie).

3 stopień - start od 0% do wypełnienia 50% jeśli poprzedni osiągnął 50%  (1 stopień zaczyna zbliżać się do 0% i się wyłącza).

i tak do ostanie diody.

rozumiem, że jak mam wypełnienie, w tym przypadku 255 na PWM, to najlepiej byłoby uwzględnić połowe wartości np if(wypełnienie == 125) zrób coś żeby załączyć kolejny port. Przez wartość 125 nasz if wykona się dwa razy z uwagi na to, że nasza wartość w pętli(związana z niewypełnieniami) rośnie przechodząc przez 125 i przy powrocie po raz kolejny przechodzi przez tą wartość.

i w pętli for() nie mogę tego aktualnie opanować.

 

stairsControlUp i Down - przyjmują dwa argumenty(do ustalenia od jakiego portu zaczynamy i na jakim kończymy).

Dziękuje za sugestie i pomoc.

  • Lubię! 1
Link do komentarza
Share on other sites

(edytowany)

https://files.fm/f/pd56jzjwm

Film z działania.. nie miałem switcha więc zwarłem igłami pomiarowymi:)

 

Wykorzystałem Twój i mój pomysł zawierając while w pętli for 🙂  Program działa dokładnie tak jak chciałem. Jeszcze tylko parę detali zostało do dopieszczenia. Jeśli są jakieś uwagi lub jeśli można zastosować ciekawsze rozwiązania to proszę o komentarz.

#define P1 51
#define P2 52

int brightness = 0;
int change = 5;

void setup() {
  for (int i = 3; i < 12; i++) {
    pinMode(i, OUTPUT);
  }

  pinMode(P1, INPUT_PULLUP);
  pinMode(P2, INPUT_PULLUP);
}

void loop() {

 //------------Czujnik dolny------------//
  if (isOn(P1)) {
    for (int i = 3; i < 14; i++) {
      bool stat = true;
      stairsControlUp(i, stat);
    }
  }

  //------------Czujnik górny----------//

  if (isOn(P2)) {
    for (int i = 14; i >= 1; i--) {
      bool stat = true;
      stairsControlDown(i, stat); 
    }
  }
}


// ----------------FUNKCJE-------------------------
void stairsControlUp(int i, bool status) {

  while (status) {

    analogWrite(i, brightness);
    brightness = brightness + change;
    delay(10);

    //jeśli przejdziemy przez srodek wypelnienia to dekrementujemy "i", tym samym załączamy poprzedni i nastepny case.
    if (brightness == 125) {
      i = i - 1;
    }

    if (brightness <= 0 || brightness >= 255) {
      change = -change;
    }

    // zmiana statusu flagi dla while()
    if (brightness == 0) {
      status = !status;
    }
  }
}

//Odwrócona logika aby z każdego pkt (niezależnie) był wykryty ruch(czy schodzi kilka osob, czy wychodzi kilka osob)

void stairsControlDown(int i, bool status) {

  while (status) {

    analogWrite(i, brightness);
    brightness = brightness + change;
    delay(10);

    //jeśli przejdziemy przez srodek wypelnienia to dekrementujemy "i", tym samym załączamy poprzedni i nastepny case.
    if (brightness == 125) {
      i = i + 1;
    }

    if (brightness <= 0 || brightness >= 255) {
      change = -change;
    }

    // zmiana statusu flagi dla while()
    if (brightness == 0) {
      status = !status;
    }
  }
}

//----------obsluga przycisków-------------//

bool isOn(int button) {
  if (digitalRead(button) == LOW) {
    delay(20);
    if (digitalRead(button) == LOW) {
      return true;
    }
  }
  return false;
}

 

Edytowano przez dernis
  • Lubię! 1
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Dnia 1.06.2023 o 17:56, Santiago napisał:

Witam .  Co się stanie jeżeli ktoś idzie na dół , a ktoś po chwili zaczyna wspinaczkę : ). Domyślam się , że program nie zareaguje odpowiednio...

Program zawsze dziala odpowiednio jak się go dobrze "okoduje":) W moim przypadku działa to na zasadzie... który czujnik aktywuje się najpierw, uruchamia sekwencję świecenia  (góra, czy dół).  Drugi efekt jest  taki(tutaj ho nie ma) , że zapala równocześnie pierwszy i ostatni stopień i w parach wędrują, na środku się mijają i tak leci do końca..  nie ma wtedy znaczenia kto wchodzi, a kto wychodzi. Jeśli chciałbyś wykrywać każde wejście, można byłoby wykorzystać przerwanie i zresetowac wątek i zaczynać funkcje od nowa.

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.