Arduino menu -k čemu flagy a jak zkrátit čekání pro přepnutí

Raspberry, Arduino, Mini-PC a další

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

Arduino menu -k čemu flagy a jak zkrátit čekání pro přepnutí

#1 Příspěvek od saitt »

Ahoj,jsem začátečník... mám tu program na menu s LCD , trochu sem ho přibarvil tlačítky a teploměrem.... nechápu : 1, k čemu je tady ten flag t_tlUp (to je flag pro tlačítko nahoru )
tl_up je pak samotné tlačítko-???myslím si dobře že to brání ke startu if hned od začátku co je tlačítko zmáčknuto...

Kód: Vybrat vše

void changeMenu() {
  if (!digitalRead(tlUp)) t_tlUp = 1;
  if (!digitalRead(tlDown)) t_tlDown = 1;
  if (digitalRead(tlUp) && t_tlUp) {
    t_tlUp = 0;
    lcd.clear();
    menu++;
    if (menu > pocetmenumax) menu = 1;
  }
  if (digitalRead(tlDown) && t_tlDown) {
    t_tlDown = 0;
    lcd.clear();
    menu--;
    if (menu < pocetmenumin)menu = 4;
  }
}
a další věc za 2,
čekám na zmáčknutí tlačítka pro přepnutí menu ,ale když ho trefím v nésprávný čas ,než se mi zmeří teplota tak se nic neděje....

Kód: Vybrat vše


void menu3() {
  lcd.setCursor(0, 0);
  lcd.print("Teplota :");
  
  int rawvolts = analogRead(analog0);
  float volts = rawvolts/205.0;
  float tempCelsius = 100.0 * volts -52;
  lcd.setCursor(0,1);
  lcd.print(tempCelsius);
  lcd.setCursor(6,1);
  lcd.print("C");
  delay(250);
  lcd.clear();
}
jednoduše mi přepíná menu zase funkce jiná a tady čekám na dokončení čtení teplota a prodlevu při velké prodlevě to nejde přepnout...nějaký nápad jak to přepnout v průběhu čtení teploty.kdykoliv?

Kód: Vybrat vše

void loop() {
  changeMenu();
  dispMenu();
}
//fce meni menu,flagy asi brani o5tovnemu spustenivcyklu
void changeMenu() {
  if (!digitalRead(tlUp)) t_tlUp = 1;
  if (!digitalRead(tlDown)) t_tlDown = 1;
  if (digitalRead(tlUp) && t_tlUp) {
    t_tlUp = 0;
    lcd.clear();
    menu++;
    if (menu > pocetmenumax) menu = 1;
  }
  if (digitalRead(tlDown) && t_tlDown) {
    t_tlDown = 0;
    lcd.clear();
    menu--;
    if (menu < pocetmenumin)menu = 4;
  }
}
//tady probiha prepinani
void dispMenu() {
  switch (menu) {
    case 1:
      menu1();
      break;
    case 2:
      menu2();
      break;
    case 3:
      menu3();
      break;
    case 4:
      menu4();
      break;
  }

Uživatelský avatar
Zmije
Příspěvky: 1513
Registrován: 30 čer 2005, 02:00
Bydliště: Pardubický kraj

#2 Příspěvek od Zmije »

1) Hodnota menu se mění jen při náběžné hraně, pokud by se měnila při jedné úrovní, tak by se menu při držení tlačítka měnilo rychlostí odpovídající rychlosti volání changeMenu().

2) Tady jsou vpodstatě tři možnosti, buď zrychlit měření, tak aby reakční doba byla v pořádku, nebo použít odložené zpracování, nebo multitasking (nějaký rtos) což je v tomto případě zbytečně složité.

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#3 Příspěvek od saitt »

Díky Zmije.
1,Myslel jsem ,že je to k tomuhle aby se to nevykonávalo dokola.
2,proboha říkám sem začátečník jak se dělají ty dvě poslední možnosti nevím,
ale měření sem zpomalil kvůli LCD ,nešlo to ani číst ,jak to bylo rychlé.

Uživatelský avatar
pavoucisit
Příspěvky: 176
Registrován: 02 lis 2008, 01:00
Bydliště: Havířov

#4 Příspěvek od pavoucisit »

Ahoj, viz bod 2 , celé to kazí delay(); čeká to zbytečně ¼ sekundy a po tuto dobu nic neuděláš. Návod jak vynechat delay pomocí millis http://www.pistek.eu/blog/2013/08/15/ar ... ni-millis/

Já bych to třeba řešil inkrementací z a podmínkou if při dosažení hodnoty 250 bych hodnotu zobrazil a na konci zobrazení z=0
void menu3() {
z=z++;
int rawvolts = analogRead(analog0);

if (z==250){
lcd.setCursor(0, 0);
lcd.print("Teplota :");
float volts = rawvolts/205.0;
float tempCelsius = 100.0 * volts -52;
lcd.setCursor(0,1);
lcd.print(tempCelsius);
lcd.setCursor(6,1);
lcd.print("C");
delay(250);
lcd.clear();
z=0; }
}

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#5 Příspěvek od saitt »

Z vámi uvedeného odkazu nechápu to použití millis.
Podle mě se vždy spustí první if .

Kód: Vybrat vše

void loop(){
  aktualniMillis = millis(); //podivam se na hodinky
  if(led_svetlo){ //potrebuju LED zhasnout nebo rosvitit?
    if(aktualniMillis - predchoziMillis > 500) { //pokud zhasnout ubehlu uz 500ms od posledni akce?
            predchoziMillis = aktualniMillis; //v tento cas jsem provedl posledni akci
            led_svetlo=LOW; //zhasni led
    }
  }else if(aktualniMillis - predchoziMillis > 1000) { //pokud zhasnout ubehlu uz 1000ms od posledni akce?
            predchoziMillis = aktualniMillis; //v tento cas jsem provedl posledni akci
            led_svetlo=HIGH; //rozsvit led
  }
  digitalWrite(led, led_svetlo); //aktualizace stavu LED
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial.write(inByte);
  }
}
začne to - (aktualniMillis - predchoziMillis) = 501 pak predchoziMillis = 501
pak třeba - ( 1002 - 501)=501 pak predchoziMillis 1002
pak -(1503 - 1002) = 501 zase první if ......predchoziMillis =1503
---vždy bude asi splněna první podmínka if
Nechápu kdy by mělo dojít k else if...vždy se spustí první if-což určuje pdomínka v závorce,nebo se pletu?

Uživatelský avatar
Cowley
Příspěvky: 3087
Registrován: 04 úno 2005, 01:00

#6 Příspěvek od Cowley »

Koukas spatne.
Else if se vztahuje k prvni podmince (svetlo jiz sviti), pokud ta nebude splnena, provede se podminka za else if.
Pokud bude splnena, udela se vnorena podminka IF pokud bude svetlo svitit dele jak 500.

Efektem je tedy blikani 501/1001.

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#7 Příspěvek od saitt »

Chápu ,že else if se provede když není splněna podmínka if a je splněna podmínka else if ,ale proměná poslednimillis bude třeba v jednom za splnění if cyklu rovna 501 v prvním případě ,pak časovač millis doteče na 1002 a máme tady proměnou poslednimillis která se rovná aktuální millis tzn. že v cyklu kdy bude millis časovač na 1002 je podmínka prvního if splněna tj větší než 500,např 1002 -501 je 501 a zase mi nabíhá první if tohle nemohu z tohohle pohledu pochopit musím se přece dívat na hodnotu poslednimillis do které se mi ukládá aktuální millis.

ještě jednou

1 cyklus
poslednimillis 0
aktuální millis 501
---tzn. if je větší než 500

X cyklus

poslednimillis 501
aktualnimillis 1002
1002-501 je 500-první if zase ukládám hodnotu posledni millis na 1002.

z cyklus
poslednimillis 1002
aktualnimillis 1503
1503-1002 je 501 zase jede první if
....atd.prosím o vyluštění :-) záhady vždy to nejdřív dojde k hodnotě větší než 500 a ne hodnotě větší než 1000 protože ukládám do globální proměnné poslední hodnotu času.

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#8 Příspěvek od saitt »

Tak přátelé myslim že sem sem dal špatný kus písma ,Zapoměl jsem na první if které konrtoluje zhasnutí světla v IDE jsem dal autoformat a bylo to jasné .
celé to je takle.

Kód: Vybrat vše

unsigned long aktualniMillis; //aktualni cas
unsigned long predchoziMillis; //cas poseldni akce
boolean led_svetlo; // promenna pro stav LED
int led = 13; //port pro LED

void setup() {
  pinMode(led, OUTPUT);
}
  void loop() {
    aktualniMillis = millis(); //podivam se na hodinky
    if (led_svetlo) { //potrebuju LED zhasnout nebo rosvitit?
      if (aktualniMillis - predchoziMillis > 500) { //pokud zhasnout ubehlu uz 500ms od posledni akce?
        predchoziMillis = aktualniMillis; //v tento cas jsem provedl posledni akci
        led_svetlo = LOW; //zhasni led
      }
    } else if (aktualniMillis - predchoziMillis > 1000) { //pokud zhasnout ubehlu uz 1000ms od posledni akce?
      predchoziMillis = aktualniMillis; //v tento cas jsem provedl posledni akci
      led_svetlo = HIGH; //rozsvit led
    }
    digitalWrite(led, led_svetlo); //aktualizace stavu LED

  }
Nezkopíroval jsem tady If led světlo které je jinak uzavřené k tomu patří ten else if a né k if co je nad else if. Tady to slouží jako taková výhybka pomocí světlo svítí a nebo ne....
Naposledy upravil(a) saitt dne 16 led 2016, 11:20, celkem upraveno 1 x.

Uživatelský avatar
Cowley
Příspěvky: 3087
Registrován: 04 úno 2005, 01:00

#9 Příspěvek od Cowley »

Doplnim poznamkami do kodu:

Kód: Vybrat vše

void loop(){
  aktualniMillis = millis(); //nakopiruju aktualni cas
  if(led_svetlo){ //dotaz: sviti svetlo?
// ted se bude delat to, pokud sviti a budeme se prubezne ptat...
    if(aktualniMillis - predchoziMillis > 500) { //dotaz: sviti jiz dele jak 500 od posledniho nakopirovani?
            predchoziMillis = aktualniMillis; //pokud ANO: nastav si cas posledni zmeny
            led_svetlo=LOW; //zhasni led
    }
  }else if(aktualniMillis - predchoziMillis > 1000) { //a pokud nesviti svetlo a od posledni akce Ubehlo vice jak 1000
            predchoziMillis = aktualniMillis; //pokud ANO: nastav si cas posledni zmeny
            led_svetlo=HIGH; //rozsvit led
  }
  digitalWrite(led, led_svetlo); //aktualizace stavu LED
  if (Serial.available()) {
    int inByte = Serial.read();
    Serial.write(inByte);
  }
}

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#10 Příspěvek od saitt »

Tohle je rozhodující if (led_svetlo) ,přehlédl jsem to.... omlouvám se
pro vysvětlení uvažoval jsem jenom

Kód: Vybrat vše

 if (aktualniMillis - predchoziMillis > 500) { //pokud zhasnout ubehlu uz 500ms od posledni akce?
        predchoziMillis = aktualniMillis; //v tento cas jsem provedl posledni akci
        led_svetlo = LOW; //zhasni led
      }
else if (aktualniMillis - predchoziMillis > 1000) { //pokud zhasnout ubehlu uz 1000ms od posledni akce?
      predchoziMillis = aktualniMillis; //v tento cas jsem provedl posledni akci
      led_svetlo = HIGH; //rozsvit led
    }

Uživatelský avatar
Cowley
Příspěvky: 3087
Registrován: 04 úno 2005, 01:00

#11 Příspěvek od Cowley »

saitt píše:Tohle je rozhodující if (led_svetlo) ,přehlédl jsem to.... omlouvám se
Spis pocty, umisteni a vyznam zavorek, ktere ukazuji co k cemu patri... a pred else if jsou 2.
A i v prvnim prispevku jsou a byly dve, zadne kopirovani na to nemelo vliv...
Uz v 9:25 jsem na to upozornoval...

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#12 Příspěvek od saitt »

jj dal jsem Autoformat a pěkně se to zobrazilo tj.odsazeni.
....Tak jsem to zkoušel a hodnota na displeji LCD s použitím funkce millis je nečitelná.
Přílohy
arduino1.jpg
(168.18 KiB) Staženo 119 x

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#13 Příspěvek od saitt »

Tak už jsem něco zkoušel...problém je ,že v menu 3 pokud odkomentuju lcd.clear() tak mi displey začne blikat chtěl bych dosáhnout vymazání LCD pokud by se tam objevila např hodnota 100 stupnu a pak třeba 99 zustalo by tam 990 stupňů což je trošku hodně...

Kód: Vybrat vše

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#define tlUp 14
#define tlDown 15
#define tlLeft 16
#define tlRight 17
#define tlacitko5 18
#define led1 19
#define led2 20
#define analog0 A0
boolean t_tlUp, t_tlDown, t_tlLeft, t_tlRight;
int pocetmenumax = 4;
int pocetmenumin = 1;
char menu = 1;
char set1 = 0, set2 = 0;
boolean merim=1;
  long cas ;
  long aktualnicas;
  
////MAIN c0dE
//tady  je tlacitko5 vyrazeno
void setup() {
  for (int i = 14; i < 18; i++) {
    pinMode(i, INPUT);
    Serial.println(i);
  }
  pinMode(led1, OUTPUT);

  pinMode(led2, OUTPUT);
  lcd.begin(16, 2);
  Serial.begin(9600);
  Serial.println("RESTART");
  //flags
  t_tlUp = 0;
  t_tlDown = 0;
  t_tlLeft = 0;
  t_tlRight = 0;


}
void loop() {
  changeMenu();
  dispMenu();
}
//fce meni menu,flagy asi brani o5tovnemu spustenivcyklu
void changeMenu() {
  if (!digitalRead(tlUp)) t_tlUp = 1;
  if (!digitalRead(tlDown)) t_tlDown = 1;
  if (digitalRead(tlUp) && t_tlUp) {
    t_tlUp = 0;
    lcd.clear();
    menu++;
    if (menu > pocetmenumax) menu = 1;
  }
  if (digitalRead(tlDown) && t_tlDown) {
    t_tlDown = 0;
    lcd.clear();
    menu--;
    if (menu < pocetmenumin)menu = 4;
  }
}
//tady probiha prepinani
void dispMenu() {
  switch (menu) {
    case 1:
      menu1();
      break;
    case 2:
      menu2();
      break;
    case 3:
      menu3();
      break;
    case 4:
      menu4();
      break;
  }
}
//menu
void menu1() {
  lcd.setCursor(0, 0);
  lcd.print("LCD 1");
}
//meneni setu dvou led
void menu2() {
  lcd.setCursor(0, 0);
  lcd.print("LCD 2/LED");
  if (!digitalRead(tlLeft)) t_tlLeft = 1;
  if (!digitalRead(tlRight)) t_tlRight = 1;
  if (digitalRead(tlLeft) && t_tlLeft) {
    t_tlLeft = 0;
    set1++;
    if (set1 > 2) set1 = 1;

  }
  if (digitalRead(tlRight) && t_tlRight) {
    t_tlRight = 0;
    set2++;
    if (set2 > 2) set2 = 1;

  }
  switch (set1) {
    case 0:
      lcd.setCursor(0, 1);
      lcd.print("L1 off");
      digitalWrite(led1, LOW);
      break;
    case 1:
      lcd.setCursor(0, 1);
      lcd.print("L1 on ");
      digitalWrite(led1, HIGH);
      break;
    case 2:
      lcd.setCursor(0, 1);
      lcd.print("L1 off");
      digitalWrite(led1, LOW);
      break;
  }
  switch (set2) {
    case 0:
      lcd.setCursor(8, 1);
      lcd.print("L2 off");
      digitalWrite(led2, LOW);
      break;
    case 1:
      lcd.setCursor(8, 1);
      lcd.print("L2 on ");
      digitalWrite(led2, HIGH);
      break;
    case 2:
      lcd.setCursor(8, 1);
      lcd.print("L2 off");
      digitalWrite(led2, LOW);
      break;
  }
}

void menu3() {
  lcd.setCursor(0, 0);
  lcd.print("Teplota :");
aktualnicas =millis();
  
  if (merim) {
    if (aktualnicas- cas > 500) {
      cas =aktualnicas;
      int rawvolts = analogRead(analog0);
      float volts = rawvolts / 205.0;
      float tempCelsius = 100.0 * volts - 52;

      lcd.setCursor(0, 1);
      lcd.print(tempCelsius);
      lcd.setCursor(6, 1);
      lcd.print("C");
      //delay(10000);
      merim = LOW;
      

    }
  }
//zde je problem
  else if (aktualnicas- cas > 500 ) {
    cas =aktualnicas;
 //lcd.setCursor(14, 1);
     // lcd.print("t");
    //delay(1000);
    //lcd.clear();
    merim=HIGH;
  }

}

void menu4() {
  lcd.setCursor(0, 0);
  lcd.print("LCD 4");
}

[/code]

Uživatelský avatar
Cowley
Příspěvky: 3087
Registrován: 04 úno 2005, 01:00

#14 Příspěvek od Cowley »

Mozna nerozumim presne problemu, ale co ti brani prepisovat pred vlastnim zobrazenim jen danou pozici na displeji treba tremi mezerami, ktere zajisti odmazani nepotrebnych drive zobrazenych znaku a nepouzivat cely Clear.
A aby to nepoblikavalo, tak sledovat zmeny v dane promenne a zobrazit danou hodnotu jen jednou (nebo alespon jen jednou za cas) a ne vzdy kdyz jde program ve smycce "okolo".

Uživatelský avatar
saitt
Příspěvky: 107
Registrován: 11 lis 2015, 01:00
Bydliště: Ostrava

#15 Příspěvek od saitt »

Tohle by přece mělo jednou za čas zobrazovat hodnotu teploty jednou za čas ... používal jsem předtím výpis hodnoty a delay a vymazat LCD a celé od začátku...
Takle se to zobrazuje celkem dobře ale lcd.clear nelze použít v různých variantách ....takže by to mělo třeba zobrazit 100 stupnu a výmaz ,nová hodnata 99 stupnu a výmaz.
Takže se to bude muset řešit asi přes ty prázdný místa,každopádně Díky za rady ani sem nedoufal,že se tady najde někdo přes Arduino.

Odpovědět

Zpět na „Miniaturní počítače (Arduino, Raspberry a další)“