Začátečník arduino - pomoct s tlačítky - bazén (přesunuto)

Raspberry, Arduino, Mini-PC a další

Moderátor: Moderátoři

Zpráva
Autor
Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#16 Příspěvek od Atlan »

0 a 1 su inak rx tx pre programovanie takze ked tam nahravas program.
Na zakmity by som sa vybodol. Ked tam budes mat displej alebo niecocpodobne kym sa znova otestuju tlacidla prejde 50ms, ak nie kludne tam daj taky delay nic sa nestane obsluha to nezisti.
Navyse pre kludne pouzivanie by si mal vstupycosetrit RC clenom tak ze zakmity uz budu nepodstatne.

Uživatelský avatar
Rellik
Příspěvky: 610
Registrován: 17 úno 2017, 01:00
Bydliště: Staré Město (UH)

#17 Příspěvek od Rellik »

No tlačítka jsem teda nějak vyřešil. Dnes jsem se pokoušel to přepsat do jedné funkce abych nemusel psát pro každé tlačítko víceméně to samé, jen s jinými hodnotami, ale nejde mi to. Vycházel jsem ze znalosti PHP a zkoušel to takto:

Kód: Vybrat vše

const int G = A0; // 3x LED
const int Y = A1;
const int B = A2;
int zelena;
int modra;
const int Tl1 = 2; // tlačítka
const int Tl2 = 3;
int ledState = LOW;
int gState = LOW;
int bState = LOW;
unsigned long previousMillis = 0;
const long interval = 500; 
unsigned long times;
unsigned long prevtime = 0;


int Tl1State;
int Tl2State;
int lastTl1State = LOW;
int lastTl2State = LOW;
int out = LOW;

long lastDebounceTime = 0;  
long debounceDelay = 50; 


void setup() {
    Serial.begin(9600);
    pinMode(G,OUTPUT);
    pinMode(Y,OUTPUT);
    pinMode(B,OUTPUT);
    pinMode(Tl1,INPUT_PULLUP);
    pinMode(Tl2,INPUT_PULLUP);
}

void loop(){
buttons("zelena", "Tl1", "Tl1State", "lastTl1State", "G");
}

//buttons("zelena", "Tl1", "Tl1State", "lastTl1State", "G");
void buttons(String barva, String input, String inputState, String lastInputState, String output) {
  
  barva = digitalRead(input);
// zelená dioda
   if(barva != HIGH) { 
              barva = LOW;
   } 
                       
   if(barva != lastInputState) {
              lastDebounceTime = millis();
              if (inputState == HIGH) {
                            out = !out;
                                     } 
   }
                                
   if ((millis() - lastDebounceTime) > debounceDelay) {
                 inputState = barva;
 }

 //
digitalWrite(output, out);
lastInputState = barva;
}
digitalWrite(output, out);
lastInputState = barva;
}
Snad se ten kód dá trochu pochopit... :)
Prostě pokud zavolám funkci
buttons("zapni", "LED");

tak se v příslušné funkci buttons(X,Y) dosadí X=zapni a Y= LED.
Čímdál víc vidím, že to nebude tak jednoduché jak se to na první pohled zdálo...
Pokud chci něco rozumného "vygooglit", tak najdu max jak blikat z ledkou nebo jak se připojovat k internetu. Jedno je pro naprosté začátečníky a to druhé pro "normální" používání k ničemu... Nechápu proč by se všechno muselo hned připojovat k internetu... No ale to už jsem zašel mimo...

Poradí někdo jak jít na ty vlastní funkce a přiřazovat ty proměnné?
Díky :)

EDIT: v tom kódu je definovaných víc věcí, zkouším to na jednom programu co mi funguje...

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#18 Příspěvek od FHonza »

Upřímně, teď tomu kódu vůbec nerozumím. To přece nemůže jít ani přeložit. Zkus prosím namalovat stavový automat, který si představuješ (třeba jako vývojový diagram) a dej ho sem.

Uživatelský avatar
Rellik
Příspěvky: 610
Registrován: 17 úno 2017, 01:00
Bydliště: Staré Město (UH)

#19 Příspěvek od Rellik »

Zjednoduším to bez definicí a setupu:

Kód: Vybrat vše

void loop(){
// zavolání funkce s parametry
funkce("zapni", "LED");

}

funkce(X, Y){
Serial.print(X); // vypíše zapni
Serial.print(Y); // vypíše LED
}
Teď už to snad bude pochopitelnější... :) Jak říkám vycházím z mě známého jazyka PHP a myslím tím něco takového: https://www.itnetwork.cz/php/zaklady/tu ... ich-funkci

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#20 Příspěvek od AB1 »

V definici funkce musí být její typ.
Pokud nic nevrací, tak je typu void.

Předávané parametry musí mít uvedený typ.
(to, myslím, platí i v php)

Kód: Vybrat vše

void setup() 
{
   Serial.begin(9600);
   // zavolání funkce s parametry 
   funkce("zapni\n", "LED\n"); 
}
//----------------------------
void loop()
{ 
} 
//----------------------------
void funkce(char* X, char* Y)
{ 
   Serial.print(X); // vypíše zapni 
   Serial.print(Y); // vypíše LED 
}

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#21 Příspěvek od FHonza »

Zapomeň na PHP :) Wiring je "dialektem" C/C++ a na rozdíl od PHP je to typový programovací jazyk.

Proto nejde

void buttons(... String input ...
{
barva = digitalRead(input);
...

funkce digitalRead() očekává jako parametr int.

Uživatelský avatar
fero_b
Příspěvky: 582
Registrován: 17 kvě 2004, 02:00
Bydliště: Kosice

#22 Příspěvek od fero_b »

Doporucujem najprv trocha pocvicit nejake programy v C, programovanie mikrokontrolerov ma svoje specifika, ale ak nespravis architekturu programu spravne ale budes vsetko placat hlava nehlava do hlavnej slucky, ta zabudni na pouzitelny vysledok..

Uživatelský avatar
Rellik
Příspěvky: 610
Registrován: 17 úno 2017, 01:00
Bydliště: Staré Město (UH)

#23 Příspěvek od Rellik »

No dobrá jak sem si to přestavoval, to zřejmě nepůjde. V tom případě jiný dotaz. Mám dvě tlačítka, jedno rozsvítí jen diodu, druhé rozsvítí diodu + spustí podprogram, kde další dioda bliká. Pokud to ovšem dalším klikem chci ukončit, tak jsou u té blikací diody dva stavy. Pokud to vypnu když dioda nesvítí, tak se nic neděje, pokud to ovšem ukončím když blikající dioda zrovna svítí, tak zůstane svítit (ne blikat) i když je tlačítko ve stavu "vypnuto". Jak ošetřit kód aby ten podprogram vypnul taky?

Kód: Vybrat vše

const int G = A0; // LED
const int Y = A1;
const int B = A2;
int zelena, modra;
int ledState, gState, bState = LOW;

unsigned long previousMillis = 0; // čas
const long interval = 500; 
unsigned long times;
unsigned long prevtime = 0;

const int Tl1 = 2; // tlačítka
const int Tl2 = 3;
int Tl1State, Tl2State;
int lastTl1State,lastTl2State = LOW;
long lastDebounceTime = 0;  
long debounceDelay = 50; 


void setup() {
    Serial.begin(9600);
    pinMode(G,OUTPUT);
    pinMode(Y,OUTPUT);
    pinMode(B,OUTPUT);
    pinMode(Tl1,INPUT_PULLUP);
    pinMode(Tl2,INPUT_PULLUP);
}

void loop() {
  zelena = digitalRead(Tl1);
  modra = digitalRead(Tl2);
//--------------------První tlačítko---------------
// zelená dioda
   if(zelena != HIGH) { 
              zelena = LOW;
   } 
                       
   if(zelena != lastTl1State) {
              lastDebounceTime = millis();
              if (Tl1State == HIGH) {
                            gState = !gState;
                                     } 
   }
                                
   if ((millis() - lastDebounceTime) > debounceDelay) {
                 Tl1State = zelena;
 }

digitalWrite(G, gState);
lastTl1State = zelena;
//-------------------Druhé tlačítko---------------
// modrá dioda
   if(modra != HIGH) { 
              modra = LOW;
              } 
                       
   if(modra != lastTl2State) {
              lastDebounceTime = millis();
              if (Tl2State == HIGH) {
                            bState = !bState;
                                     } 
              }
                                
   if ((millis() - lastDebounceTime) > debounceDelay) {
                 Tl2State = modra;
                  }

digitalWrite(B, bState);
lastTl2State = modra;

if(bState == HIGH) {
      HlavniProg(); 
    }

}

// program co se spustí po zapnutí druhého tlačítka (blikající dioda)...
void HlavniProg() {
 unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(Y, ledState);
  }
}

Uživatelský avatar
fero_b
Příspěvky: 582
Registrován: 17 kvě 2004, 02:00
Bydliště: Kosice

#24 Příspěvek od fero_b »

kazdy program je v podstate stavovy automat, ktory v zavislosti v akom stave sa nachadza tak moze nejake tlacitko robit nieco uplne ine. Uvediem priklad z tvojho programu, posledna podmienka if (bState == HIGH) { HlavniProgram}, teda ak nejaka premenna odrazajuca stav premennej bState je High tak to zacne volat funkciu v podmienke. A ty uz zacinas narazat na to ze tvoj stavovy automat zacina mat dalsi stav a chces nieco vykonat len ked ledka nesvieti, alebo ked svieti, taka by zhasla....a ty nad tym uz nevies udrzat mentalnu kontrolu. Este dopises 10 riadkov a si strateny.. Takze sa vratim s5 ku architekture. CPU je dostatocne rychle aby vykonavalo kazdu ulohu nejaku chvilu a tebe sa to bude javit ako keby vsetko islo plynule... takze ty potrebujes zopar veci:

1) snimat klavesnicu
2) blikat s ledkou

takze snimanie klavesnice je periodicky dej, ktory chces vykonavat v pravidelnych intervaloch, blikanie ledky je napodobne velmi jednoducha cinnost, staci aby v spravny okamih procesor zdvihol stav na drote a potom ho zas zhodil.. zvysok casu procak nema co robit...V zasade CPU vacsinu casu otaca hlavnou sluckou a periodicky si odskoci do prerusenia, kde sa pozrie na stav tlacidiel a napise to (ak je stlacene alebo pustene) do nejakych premennych. Tieto premenne su potom kontrolovane hlavnou sluckou a vykonaju akciu...Periodicke prerusenie je dobry sposob ako robit nieco v presne stanovenych casovych okamzikoch. Priklad chcem blikas s LEDkou tak ze pol sekundy bude zasvietena a pol sekundy bude zhasnuta..
Urobis jednu globalnu premennu typu integer - pocitadlo preruseni. Ked ti prerusenie chodi kazdych 50ms, tak musis naratat do 10 aby presla pol sekunda, vtedy zmenis stav ledky na opacny


stavy celeho automatu si znacim bitovo a potom ich aj bitovo testujem.
(zopar globalnych bytov) Mozes si to pisat aj do bytov to ti zozere troska viac ramky.. NEPOUZIVAT ZIADNE FUNKCIE DELAY. Snimanie klavesnice som popisal skor (pripadne si to precitaj este raz, a pogoogli, porozmyslaj ako som to myslel)

priklad: uzivatel stlaci tlacidlo 1) a chcem aby sa o pol sekundy nieco stalo.


uint_8 status = 0; //inicializaciu toho treba dat do init
uint_8 timer_counter;


#define POL_SEC_FLAG 0b00000001


//toto spravis v hlavnej slucke ako reakciu na tlacidlo 1
//je to signal preruseniu, ze ma zacat ratat do 10 povedzme

timer_counter = 10;
status |= POL_SEC_FLAG;


//v preruseni bude napisane:

if (status & POL_SEC_FLAG){
if (timer_counter >0){
timer_counter--;
}else{
//ZASVIET LEDKU
status = &~POL_SEC_FLAG; //akcia bola spravena, zhodime vlajocku
}
}

}

Uživatelský avatar
AB1
Příspěvky: 312
Registrován: 23 lis 2009, 01:00

#25 Příspěvek od AB1 »

Používej k debouncování jednoduchý delay().
Počítám, že bude ještě dlouho trvat, než ti zpoždění bude vadit.
Teď v začátcích by ti to jenom komplikovalo život.

Nenazývej svoji vlastní funkci Hlavní().
Za hlavní funkci se tady považuje smyčka loop().

Podívej se na příklad níže.
(po stisku tlačítka Led bliká, po dalším zhasne, atd.)

Kód: Vybrat vše

#define Yellow_led 13
#define TL2        12
 
unsigned long currentMillis, previousMillis; 
unsigned int  interval=500;
boolean       TL2_state; 

//-------------------------------
void setup() 
{
    pinMode(Yellow_led,OUTPUT); 
    pinMode(TL2,INPUT_PULLUP); 
}
//-------------------------------
void loop()
{
  currentMillis = millis();
  
  if (currentMillis - previousMillis >= interval) 
  {
     blink();                         //call blink() every 500 ms
     previousMillis = currentMillis;
  }
  
  if ((digitalRead(TL2) == 0))        //if button pressed
  {
     delay(50);                       //debounce
     TL2_state = !TL2_state;          //toggle the state 
     while((digitalRead(TL2) == 0));  //wait for button released
     delay(50);                       //debounce
   } 
}   
//----------------------------

void blink()
{ 
    if(TL2_state == 1)
       digitalWrite(Yellow_led,(!digitalRead(Yellow_led)) ); //toggle Led
    else
       digitalWrite(Yellow_led, LOW);
 }  

Uživatelský avatar
Rellik
Příspěvky: 610
Registrován: 17 úno 2017, 01:00
Bydliště: Staré Město (UH)

#26 Příspěvek od Rellik »

Hoši moc díky za rady. Moc si toho cením...
Co se týká "hlavní" funkce, tak je to jen začátek celého projektu. Pak to bude pojmenované přímo funkcí, kterou to bude dělat (pokud se mi to teda podaří)...

Ve výsledku tam blikat nic nebude. Mám to jen na zkoušku. V podstatě by to jedno tlačítko mělo sepnout dva výstupy. Jeden by měl být sepnutý cca 60 minut a druhý jen 40 sekund.

Jinak jsem se díval i na to přerušení, což by asi (určitě) bylo nejlepší řešení, protože pokud bude nějaká "externí" akce (tlačítka), tak by se měl hlavní program (časové spínání relé a hlídání teploty) přerušit a běžet program co je pod tím tlačítkem...

Uživatelský avatar
Rellik
Příspěvky: 610
Registrován: 17 úno 2017, 01:00
Bydliště: Staré Město (UH)

#27 Příspěvek od Rellik »

Mám dotaz ještě ohledně těch tlačítek. Když vynechám programové ošetření zákmitů a udělám ho HW tak to bude lepší ne? Z toho pak vyplývá další otázka ohledně zapojení.
1/ každé tlačítko má svůj pin - fungovat bude bez problému
2/ všechny tlačítka jsou na "jednom" drátu - dají se nějak adresovat?

To druhé bude asi blbost co? :)
Přílohy
Screenshot_20171210_092601.png
(9.97 KiB) Staženo 121 x

Uživatelský avatar
fero_b
Příspěvky: 582
Registrován: 17 kvě 2004, 02:00
Bydliště: Kosice

#28 Příspěvek od fero_b »

To druhe je znacna blbost:) ked mas len zopar tlacidiel, a nie je problem s poctom pinov, ta pouzi zapojenie c.1...spravne HW osetrenie zakmitov tlacidiel sa robi schmitovym ko.
http://www.ct2.wz.cz/Studium/schmitt.htm

Ak mas vela tlacidiel a malo drotov pouziva sa matica, zopar drotov z CPU vysiela a zopar prijima a su prekrizene do matice, kod daneho tlacidla je potom kombinaciu vysielacich a prijimanych drotikov. Ale to ti netreba.

Edit: pozeram lepsie na tvoje zapojenie, ha zvyknem tlacidla nejakym pull up odporom opriet o 5v, aby si procakom v pripade nezatlacenia nemal len tak drotik v lufte (zbyknu byt v cpu pull upy) ale na mojom poslednom projekte s tym bol problem, kazdopadne 5k6 oproti log "1" neuskodi..

Uživatelský avatar
FHonza
Příspěvky: 1443
Registrován: 20 lis 2012, 01:00
Bydliště: Praha

#29 Příspěvek od FHonza »

Místo externích pull-up lze použít i zabudované interní. V Arduinu:

Kód: Vybrat vše

pinMode(pin,INPUT_PULLUP);

Uživatelský avatar
Atlan
Příspěvky: 4499
Registrován: 10 kvě 2004, 02:00
Bydliště: Košice

#30 Příspěvek od Atlan »

Lenze tie interne nemusia byt dostatocne tvrde.

Ide klavesnicu pripojit na AD prevodnik 2 vodicmi. Stlacenim tlacidla sa meni odporovy delic a tym nasnimane napatie. Jednotlivym napatiem priradis hodnoty tlacidiel.
Bezne sa to na arduine vyuziva.

Odpovědět

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