switch

Odpovědět
daton
Příspěvky: 664
Registrován: 16 bře 2013, 16:12

switch

Příspěvek od daton »

Zdravim všechny
mám zde trochu zajímavý problém, kod níže je pracovní verze přepínače, Spíná jednotlivé smyčky ale druhou smyčku ze čtyř nezobrazí na displeji a k jejímu zadání chce potvrzení což u jiných smyček nechce. Zajímavé je že na displeji se zobrazuje dvakrát přepínač 1 a potom přepínač 3 dvojku jakoby přeskočí. Dle mne je to v přepínání kdy se hodnota stav změní z 5 na 1 ale v druhém zadání se nepřičte. Nevím to ale jistě prosím mohl by jste se někdo mrknout zda tam neuvidíte chybu která by toto podivné chování vysvětlila?

Kód: Vybrat vše

// Arduino Uno - metr superC
//#include <LiquidCrystal.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// nastavena adresa 0x3F a poradi pinu displeje na prevodniku: en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
volatile int stav = 1;                   // stav vyberu z menu
int napeti;                     // pomocna pro mereni napeti
volatile int pryc = LOW;        // pro obslouzeni interruptu
int j =0;


void setup() {
Serial.begin(9600);
  pinMode(A2, INPUT_PULLUP);   // TL enter
  pinMode(A3, INPUT_PULLUP);   // TL dalsi
  pinMode(2, INPUT_PULLUP);    // TL menu pres interrupt
 
  lcd.begin(16, 2);            // zavedeni grafiky do RAM displeje
  lcd.clear();
  lcd.print("Prepinac poloh");   // vypis hlavicky
  lcd.setCursor(0, 1);
  lcd.print("  verze 1.1");
 // attachInterrupt(0, ven, LOW);// interrupt

  delay(2000);
}

boolean ctiTL() {             // cteni tlacitek a posuny v menu
  int TL = 0;
  delay(500);
  do {
    if (digitalRead(A3) == LOW) TL += 1;  // dalsi
    if (digitalRead(A2) == LOW) TL += 2;  // enter
  } while (TL == 0);
  if (TL == 1) {
    stav ++;  
    Serial.print (stav);//kolování stavů na displeji
     Serial.println (TL);
    if (stav > 4) stav = 1;
      
 //   pip(10);
  }
  if (TL == 2) {
    return true;             // byl enter na zvoleny stav
  } else {
    return false;            // nekorektni kombinace ignoruj
  }
}

void loop() {                // hlavni menu funkci
  lcd.clear();
  lcd.print("Vyber funkce:");
  lcd.setCursor(0, 1);
  Serial.println(stav);
  switch (stav) {
    
  
    case 1:                         // přepínač 1
      lcd.print("Prepinac 1");
      if (ctiTL())  
       prep1();
       Serial.println(ctiTL());
      
    
      break;
      
    case 2:                  // Přepínač 2
      lcd.print("Prepinac 2");
      if (ctiTL())
   prep2();
   Serial.println(ctiTL());
      break;
      
    case 3:                  // Přepínač 3
      lcd.print("Prepinac 3");
    
     if (ctiTL())
     prep3(); 
   
      break;
      
    case 4:                  // Přepínač 4
      lcd.print("Prepinac 4");
     if (ctiTL())
     prep4();
      break;
  }
  if (pryc) {
   
    for (int i = 1; i < 5; i++) {
    //  pip(50);
      delay(100);
    }

    pryc = LOW;
  }
}

void prep1() {
  Serial.println("zacina mereni");
   lcd.clear();
 lcd.print("mereni zacina");
 delay(800);
 for (j=1; j<10; j++)
 {digitalWrite (A0, HIGH);
 delay (150);
 digitalWrite (A0, LOW);
  Serial.println("merei na prep 1");
   lcd.clear();
 lcd.print("merei na prep 1");
 delay(140);
 }
 Serial.println("konec mereni");
 lcd.clear();
 lcd.print("mereni probehlo");
 delay(140);
  do {} while (!ctiTL());
 }
 
void prep2() {                        // nabijeni na 2,5 V
  Serial.println("zacina mereni");
   lcd.clear();
 lcd.print("mereni zacina");
 delay(800);
 for (j=1; j<10; j++)
 {digitalWrite (A0, HIGH);
 delay (150);
 digitalWrite (A0, LOW);
  Serial.println("merei");
   lcd.clear();
 lcd.print("mereni na prep 2");
 delay(140);
 }
 Serial.println("konec mereni");
 lcd.clear();
 lcd.print("mereni probehlo");
 delay(140); 
 do {} while (!ctiTL());
 }

void prep3() { lcd.clear();
 lcd.print("mereni zacina");
 delay(1000);                       // nabijeni na 2,5 V
 for (j=1; j>10; j++)
 {digitalWrite (A0, HIGH);
 delay (150);
 digitalWrite (A0, LOW);
  Serial.println("vybit");
   lcd.clear();
 lcd.print("mereni na prep 3");
 delay(140);} 
 lcd.clear();
 lcd.print("mereni probehlo");
 do {} while (!ctiTL());
 }

void prep4() {                    // formovani bez omezeni
 Serial.println("zacina mereni");
   lcd.clear();
 lcd.print("mereni zacina");
 delay(800);
 for (j=1; j<10; j++)
 {digitalWrite (A0, HIGH);
 delay (150);
 digitalWrite (A0, LOW);
  Serial.println("merei");
   lcd.clear();
 lcd.print("mereni na prep 4");
 delay(140);
 }
 Serial.println("konec mereni");
 lcd.clear();
 lcd.print("mereni probehlo");
 do {} while (!ctiTL()); }                                              // vyskok pres interrupt

/*
void ven() { 
   lcd.clear();                     // vse vypnout a skocit do menuwera
  pryc = HIGH;
 
 lcd.print("reset");
 delay(800);
do {} while (!ctiTL());  
}
*/
AlesH
Příspěvky: 323
Registrován: 25 úno 2013, 09:18

Re: switch

Příspěvek od AlesH »

Řekl bych, že problém může být v příkazu "Serial.println(ctiTL());". Ta funkce "ctiTL()" totiž vždycky čeká na stisk některého z tlačítek a dokud tlačítko není stisknuto, tak se ta funkce neukončí. Takže když stav=1 a stiskneš tlačítko na A3, tak se stav sice změní na 2, ale ještě v témže "case" se spustí řádek "Serial.println(ctiTL());" kde to stále čeká (bez změny zobrazení na displeji) na další stisknutí tlačítka. Když se dočká dalšího stisku tlačítka na A3, tak samozřejmě přejde do stavu 3 a už jseš jinde. (A protože v "case" 3 a 4 už není volání "Serial.println(ctiTL());", tak tam to funguje korektně)

Možná je další nedorozumění i v tom, že pokud za podmínkou "if" nejsou složené závorky, tak se podmíněně provede jen jediný bezprostředně následující příkaz (řádek) a na další řádek skočí program v každém případě (ať je ten řádek v programu odsazen jakkoliv).

To znamená, že zápis:

Kód: Vybrat vše

     if (ctiTL())
       prep1();
       Serial.println(ctiTL());
provede podmíněně funkci "prep1()", ale řádek "Serial.println(ctiTL());" se provede vždy, nezávisle na tom, jaké tlačítko bylo předtím stisknuto.

Pokud bys chtěl, aby se ten "Serial.println(ctiTL());" provedl jen po spuštění funkce prep1() [tedy po stisku tlačítka na A2], tak bys musel napsat:

Kód: Vybrat vše

     if (ctiTL()) {
       prep1();
       Serial.println(ctiTL());
     }
Každopádně je ale volání "Serial.println(ctiTL());" zcela nevhodné a doporučuji ho prostě zrušit (zakomentovat).
daton
Příspěvky: 664
Registrován: 16 bře 2013, 16:12

Re: switch

Příspěvek od daton »

Super moc díky je to ono, nenapadlo mne že by se to mohlo vykonávat myslel jsem že to prostě jen odešle hodnotu na terminál. Dal jsem si to tam abych měl jasné co se děje a ted si uvědomuji že potom to začalo takto dělat a já si to s tím nespojil. Moc díky Aleši.
Ještě bych měl jednu prosbu nerozumím tomu interuptu

Kód: Vybrat vše

// attachInterrupt(0, ven, LOW);// interrupt
mělo by to přerušit jakoukoliv činnost jak to vlastně v tom programu pracuje? V příkladu výše je to zakomentované protože to hází chybu a opět nevím kde hledat, což je zaviněno i tím že jsem tu funkci zatím nepoužil.
Moc díky za čas a vědomosti :)
AlesH
Příspěvky: 323
Registrován: 25 úno 2013, 09:18

Re: switch

Příspěvek od AlesH »

"attachInterrupt(0, ven, LOW);" nastavuje přerušení tak, že kdykoliv se na přerušovacím vstupu 0 (u Arduina Uno je to digitální pin 2) objeví logická 0 (LOW), tak se spustí funkce "ven()" [nezávisle na tom, kde se zrovna nachází vykonávání programu ve smyčce loop()]. Chybu to hází proto, že tu funkci "ven()" máš v programu zakomentovanou, takže ten "attachInterrupt" ji pak nemůže najít. Výhodou nastavení přerušení je to, že přerušovací vstup je pak testován procesorem automaticky a není třeba ho opakovaně testovat v programu (ve smyčce). V původním programu to asi mělo nějak hlídat dokončení měření (a pak se na displeji vrátit do menu).

https://www.arduino.cc/en/Reference/AttachInterrupt
daton
Příspěvky: 664
Registrován: 16 bře 2013, 16:12

Re: switch

Příspěvek od daton »

Aha díky za vysvětlení, znamená to tedy že když v´budu mít v programu následující kod tak by to nemělo házet žádnou chybu ?

Kód: Vybrat vše

volatile int pryc = LOW;
        
void setup() {
   attachInterrupt(0, ven, LOW);
   
   void ven() {                  
  pryc = HIGH;
  Serial.print("vše ukončeno");
  loop();    }
Myslím když to bude v okolním kodu, tak toto stačí pro přerušení a k restartu hlavní smyčky? Nebo je třeba ještě něco?
Moc díky za odpověď.
AlesH
Příspěvky: 323
Registrován: 25 úno 2013, 09:18

Re: switch

Příspěvek od AlesH »

Funkce ven() musí být definována (zapsána) mimo funkce setup() i mimo loop() [nesmí být zapsána uvnitř nich, ale může být až za nimi, třeba až na konci programu tam kde jsi to měl zakomentováno]. Aby to celé fungovalo, tak je samozřejmě ještě třeba něco fyzicky (drátem) připojit na input pin 2 (kde funguje ten interrupt 0). V tom původním článku o měření kapacity je tam zřejmě připojeno tlačítko s názvem "menu" (spíná směrem k "zemi").
Vladimir66
Příspěvky: 385
Registrován: 02 dub 2014, 15:30

Re: switch

Příspěvek od Vladimir66 »

Ahoj,

nejsem programator a urcite ti poradi ostatni.
na prvni pohled ale vidim chyby v zavorkach.
kazdy void ma svoji prvni a posledni zavorku :)
kod, ktery mi to prelozilo je takovy:

Kód: Vybrat vše

volatile int pryc = LOW;
       
void setup() {
   attachInterrupt(0, ven, LOW);
  } 
   void ven() {                 
  pryc = HIGH;
  Serial.print("vše ukončeno");
  }
void  loop()   {
  }
ja chci ale rici, ze davat do preruseni "Serial.print..." muze byt nekdy problem, protoze to "dlouho" trva.
kod v preruseni by mel byt co nejkratsi.
nerikam, ze je to tento pripad. jen na to bacha.
-V66
Vladimir66
Příspěvky: 385
Registrován: 02 dub 2014, 15:30

Re: switch

Příspěvek od Vladimir66 »

promin, to preruseni by melo byt az za loop.
takto se vykona setup - ven - loop

lepsi je setup - loop (ten zacykli) - ven (vykona se az pri vyvolani preruseni)

Kód: Vybrat vše

volatile int pryc = LOW;
       
void setup() {
   attachInterrupt(0, ven, LOW);
  }

void  loop()  {
 
  }
 
  void ven() {                 
  pryc = HIGH;
  Serial.print("vše ukončeno");
  }
  
  
  
  
daton
Příspěvky: 664
Registrován: 16 bře 2013, 16:12

Re: switch

Příspěvek od daton »

Moc dík za informace budu experimentovat a snad se to třeba i naučím :D .
Odpovědět