Stránka 1 z 1

Arduino - traťový souhlas

Napsal: 04 říj 2023, 21:23
od matyasm
Zdravím, učím se programovat Arduino a chtěl jsem vyzkoušet udělat něco jako traťový souhlas pro modelovou železnici. Měl by fungovat následovně:
Pokud zmáčknu zelené tlačítko 1, rozbliká se led dioda, pokud následně zmáčknu červené tlačítko, led dioda bude svítit. Pokud následně podruhé zmáčknu červené tlačítko, led dioda zhasne. Pokud bych ale po zmáčknutí zeleného tlačítka 1 zmáčkl zelené tlačítko 2 místo toho červeného, led dioda okamžitě zhasne.
Zkoušel jsem to různě naprogramovat, ale vždy docílím jen toho, že po zmáčknutí zeleného tlačítka 1 se dioda rozbliká, ale po zmáčknutí červeného se již nic neděje. Nedokázal by mi někdo poradit? Zatím kód vypadá takto a zkouším to v tinkercadu:

// digitální piny
const int zeleneTlac1 = 2;
const int cerveneTlac = 3;
const int zeleneTlac2 = 4;
const int led = 13;

// Proměnná
bool stavLed = false;

// INPUT/OUTPUT
void setup() {
pinMode(zeleneTlac1, INPUT);
pinMode(cerveneTlac, INPUT);
pinMode(zeleneTlac2, INPUT);
pinMode(led, OUTPUT);
}


void loop() {
// stav zeleného tlačítka 1
if (digitalRead(zeleneTlac1) == HIGH) {
// blikání
stavLed = true;
while (stavLed) {
digitalWrite(led, HIGH);
delay(250);
digitalWrite(led, LOW);
delay(250);
}
}

// stav červeného tlačítka
if (digitalRead(cerveneTlac) == HIGH) {
// LED svítí
digitalWrite(led, HIGH);
stavLed = true;
}

// stav zeleného tlačítka 2
if (digitalRead(zeleneTlac2) == HIGH) {
// LED zhasne
digitalWrite(led, LOW);
stavLed = false;
}
}

Napsal: 04 říj 2023, 21:53
od pocitujlasku
Ako prve, daj si tlacidla na gnd. teda po stlaceni bude stav LOW, to iste led, rozsvecuj ju tak, ze pin das do log. 0
tlacidla nadefinuj ako INPUT_PULLUP. Tym docielis toho, ze nezapojene tlacidlo nebude vo vzduchu (nedefinovany stav), ale bude vzdy log. 1
Dalsia dost casta vec zaciatocnikov je delay. Zabudni nan. Program sa vykonava po instrukciach, a ty si zastavil program na:

Kód: Vybrat vše

while (stavLed) {
  digitalWrite(led, HIGH);
  delay(250);
  digitalWrite(led, LOW);
  delay(250);
}

nikdy sa odtialto nedostane dalej. tu tvoj program konci.
Je viac moznosti, ako to riesit. dat tlacidla na prerusenia a v preruseni nastavit nejaku premennu, ze tlacidlo bolo stlacene a v loop len cez if kontrolovat, ci ta premenna je nastavena, alebo to robit v loope, ako to mas teraz, ale ten while nahradit if-om.
Blikanie sa robi napr. cez kontrolu na millis, na internete je na to kopec navodou, nechce sa mi to teraz hladat.

Kód: Vybrat vše

unsigned long actualMillis;
unsigned long refreshMillis = 0;
bool ledstate = false;
LOOP

  actualMillis = millis();
  if (refreshMillis<=actualMillis) {
    refreshMillis=actualMillis+250;
    ledstate = !ledstate;   
    digitalWrite(led, !ledtate);
  }

pisem to z hlavy, tak mozno tam budu nejake chyby, ale pre predstavu by to mohlo stacit. To je samotne blikanie. K tomu if mozes este pridat podmienku na to, ci ma blikat, alebo nie.

Napsal: 04 říj 2023, 21:58
od gilhad
Já bych to vzal podle té tvojí definice jako jednoduchý stavový automat

Kód: Vybrat vše


// tvoje definice a setup() zustavaji, pridavam

int Stav=0;
unsigned long prevMillis;
unsigned int interval=250UL; // doba sviceni/zhasnuti
bool cerveneTlacPodruhe = false; // = cekame na DRUHE stisknuti tlacitka

void loop() {
  ////////////////////
  // LED
  ////////////////////
  if (Stav == 0) { // tma
    digitalWrite(led, LOW);
  } else if (Stav == 1) { //blikani
    if ((millis() - prevMillis) > interval) {
      digitalWrite(led, ! digitalRead(led)); // prepnem LED na jeji opak
      prevMillis = millis();
    };
  } else if (Stav == 2) { // sviceni
    digitalWrite(led, HIGH);
  } else { // sem by se to nemelo NIKDY dostat
    Stav = 0; // zachranime situaci
  };
  ////////////////////
  // logika, tlacitka
  ////////////////////
  if (Stav == 0) { // tma
    if (digitalRead(zeleneTlac1) == HIGH) {
      Stav = 1;
      digitalWrite(led, HIGH);
    };
  } else if (Stav == 1) { //blikani
    if (digitalRead(cerveneTlac) == HIGH) {
      Stav = 2;
      digitalWrite(led, HIGH);
      prevMillis = millis();
      cerveneTlacPodruhe = false;
    };
    if (digitalRead(zeleneTlac2) == HIGH) { // prebije pripadne soucasne cervene tlacitko
      Stav = 0;
      digitalWrite(led, LOW);
    };
  } else if (Stav == 2) { // sviceni
    if (digitalRead(cerveneTlac) == LOW) { // pusteni po prvnim zmacknuti
      cerveneTlacPodruhe = true;
    if ( cerveneTlacPodruhe && digitalRead(cerveneTlac) == HIGH) { // druhe zmacknuti misto pouheho drzeni
      Stav = 0;
      digitalWrite(led, LOW);
    };
  } else { // sem by se to nemelo NIKDY dostat
    Stav = 0; // zachranime situaci
  };
} // konec loop


Predpokladam, ze to mas zapojene tak, ze led se rozsvěcí pomocí HIGH (myslím, že vestavěná se naopak rozsvěcí pomocí LOW, pak by se to muselo prohodit)
A že tlačítka máš proti +5V (a pin pripojený přez odpor k zemi)

(Jinak bych dal jednoduše tlačítko na pin proti zemi, v setupu použil INPUT_PULLUP a vyhodnocoval to opačně - tak to dělám normálně já)

PS: a používej "code" pro výpisy programu[/code]