Stránka 1 z 2

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

Napsal: 15 led 2016, 13:01
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;
  }

Napsal: 15 led 2016, 17:17
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é.

Napsal: 15 led 2016, 17:38
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é.

Napsal: 15 led 2016, 20:56
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; }
}

Napsal: 16 led 2016, 09:03
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?

Napsal: 16 led 2016, 09:25
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.

Napsal: 16 led 2016, 10:49
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.

Napsal: 16 led 2016, 11:19
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....

Napsal: 16 led 2016, 11:19
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);
  }
}

Napsal: 16 led 2016, 11:22
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
    }

Napsal: 16 led 2016, 11:25
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...

Napsal: 16 led 2016, 11:30
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á.

Napsal: 16 led 2016, 13:35
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]

Napsal: 16 led 2016, 14:23
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".

Napsal: 16 led 2016, 15:45
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.