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

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...

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.