Stránka 1 z 2

jednoduchý kód

Napsal: 21 črc 2019, 15:13
od czhory
Dobrý den, koupil jsem Arduino a myslel si, že to zvládnu, ale ejhle... =)

Potřeboval bych poradit s kódem. Uvedu obecný příklad:

Při stisku vstupu č.1 bych chtěl sepnout výstup č.1 na 5s a výstup č.2 na 10s.
A při stisku vstupu č.2 bych chtěl sepnout výstup č.3 na 15s a výstup č.4 na 20s.
A nejlépe, pokud by to šlo, aby se po stisknutí vstupu č.1 dal stisknout už pouze vstup č.2 a naopak (jakési zablokování opakování zmáčknutí toho samého vstupu).

Pomůžete mi prosím? Pomalu se s tím učím, ale nějak jsem se teď zasekl a potřebuji posunout dále.

Moc děkuji.

Re: jednoduchý kód

Napsal: 21 črc 2019, 17:12
od pavel1tu
Nemám čas to testnout ... až večer nebo někdy ...
A vůbec netuším jestli to bude fungovat :lol
Jo a musíš si doinstalovat tuto knihovnu
https://github.com/brunocalou/Timer

Na tlacitko to nebude reagovat pokud casujeme (asi by slo dodělat i stop)
a nebo pokud bylo naposledy stisknute to same tlacitko (jdou na stridacku mackat 1 -2 -1 -2 ......)

Kód: Vybrat vše

// verze 1.03 - opraveny preklepy, decka to i vyzkousely bez relatek jen sledovaly serialmonitor

#include "timer.h"

Timer timer1; // 5s
Timer timer2; // 10s
Timer timer3; // 15s
Timer timer4; // 20s

#define vstup1 6
#define vstup2 7
#define rele1 9
#define rele2 10
#define rele3 11
#define rele4 12

byte PosledniVstup = 0;
byte casujeme = 0;



void Casovac1() {
  Serial.println("Rele 1 OFF");
  digitalWrite(rele1, LOW);
  timer1.stop();
  // casujeme = 0;
}

void Casovac2() {
  Serial.println("Rele 2 OFF");
  digitalWrite(rele2, LOW);
  timer2.stop();
  casujeme = 0;
}

void Casovac3() {
  Serial.println("Rele 3 OFF");
  digitalWrite(rele3, LOW);
  timer3.stop();
  // casujeme = 0;
}

void Casovac4() {
  Serial.println("Rele 4 OFF");
  digitalWrite(rele4, LOW);
  timer4.stop();
  casujeme = 0;
}


void setup() {
  Serial.begin(9600);

  //nastavení vstupu a zapnutí interního pull-up rezistoru
  pinMode(vstup1, INPUT);
  pinMode(vstup2, INPUT);

  //nastavení výstupu
  pinMode(rele1, OUTPUT); 
  pinMode(rele2, OUTPUT); 
  pinMode(rele3, OUTPUT); 
  pinMode(rele4, OUTPUT); 

  //Set the interval in milliseconds
  timer1.setTimeout(5000);
  timer2.setTimeout(10000);
  timer3.setTimeout(15000);
  timer4.setTimeout(20000);


  //Set our callback function
  timer1.setCallback(Casovac1);
  timer2.setCallback(Casovac2);
  timer3.setCallback(Casovac3);
  timer4.setCallback(Casovac4);

  Serial.println("Jsem pripraven na start casovacu ....");
}

void loop()
{
  //Update all the timers at once
  timer1.update();
  timer2.update();
  timer3.update();
  timer4.update();



  if(digitalRead(vstup1) == HIGH && PosledniVstup != 1 && casujeme == 0)
     {
      PosledniVstup = 1;
      casujeme = 1;
      digitalWrite(rele1, HIGH);
      Serial.println("Rele 1 ON");
      digitalWrite(rele2, HIGH);
      Serial.println("Rele 2 ON");
      timer1.start();
      timer2.start();
      delay(200);   // pro jistotu
     }

  if(digitalRead(vstup2) == HIGH && PosledniVstup != 2 && casujeme == 0)
     {
      PosledniVstup = 2;
      casujeme = 1;
      digitalWrite(rele3, HIGH);
      Serial.println("Rele 3 ON");
      digitalWrite(rele4, HIGH);
      Serial.println("Rele 4 ON");
      timer3.start();
      timer4.start();
      delay(200);   // pro jistotu
     }     


  
}


Re: jednoduchý kód

Napsal: 21 črc 2019, 17:47
od pavel1tu
Ještě by to šlo vylepšit a sledovat každý časovač zvlášť (každému přiřadit "váhu" - 1-2-4-8).

Na kroužku si na tom smlsla 11 letá dívenka a 10 hoch ... já jen asi 2x vypomohl.

Bylo to pro ně zpestření - nedaří se nám rozchodit data na GSM modulu (už 2 den).

Re: jednoduchý kód

Napsal: 21 črc 2019, 20:39
od czhory
Vypadá to na naprostou špičku =) Moc děkuji jak Vám, tak hlavně těm Vaším programátorům !! A btw. kde se to naučili?
Ještě jednou moc děkuji !!!!

Re: jednoduchý kód

Napsal: 21 črc 2019, 20:42
od pavel1tu
Kamarád už 10 let vede prázdninový příměstský tábor elektroniků.

Posledních 5 let se to zvrhlo na Arduina a programování.

Trochu mu tam vypomáhám a sháním sponzory na HW + sem tam dozor.
To on mne k tomu přivedl.

Re: jednoduchý kód

Napsal: 22 črc 2019, 00:08
od gilhad
Já bych to viděl nějak takhle :)

Kód: Vybrat vše

#define tlacitkoApin 7
// na kterem pinu je tlacitko A (pripojeno proti zemi)

bool tlacitkoAenabled;	// je zrovna povoleno ho zmacknout?
bool tlacitkoAactive;	// probiha prave jeho akce?
unsigned long tlacitkoAfrom; 	// odkdy ta akce probiha?

#define tlacitkoBpin 8
// na kterem pinu je tlacitko B (pripojeno proti zemi)
bool tlacitkoBenabled;	// je zrovna povoleno ho zmacknout?
bool tlacitkoBactive;	// probiha prave jeho akce?
unsigned long tlacitkoBfrom; 	// odkdy ta akce probiha?

// kde je která dioda (prez odpor 330 Ohm proti zemi)
#define ledA1pin 9
#define ledA2pin 10
#define ledB1pin 11
#define ledB2pin 12

// jak dlouho má svítit?
#define timeA1 5000
#define timeA2 10000
#define timeB1 15000
#define timeB2 20000

// Časy a piny jsou zavedeny pomocí #define, protože se nemění a kompilátor ani změnu nepřipustí. Nemluvě o tom, že to šetří RAM.


void setup() {
	pinMode(ledA1pin,OUTPUT);
	digitalWrite(ledA1pin,LOW);	// zaciname se zhasnutou diodou
	
	pinMode(ledA2pin,OUTPUT);
	digitalWrite(ledA2pin,LOW);	// zaciname se zhasnutou diodou
	
	pinMode(ledB1pin,OUTPUT);
	digitalWrite(ledB1pin,LOW);	// zaciname se zhasnutou diodou
	
	pinMode(ledB2pin,OUTPUT);
	digitalWrite(ledB2pin,LOW);	// zaciname se zhasnutou diodou
	
	pinMode(tlacitkoApin, INPUT_PULLUP);	// tahneme vnitrnim odporem nahoru, takze normalne je HIGH, stisknutim se pripoji na zem a je LOW
	pinMode(tlacitkoBpin, INPUT_PULLUP);	// tahneme vnitrnim odporem nahoru, takze normalne je HIGH, stisknutim se pripoji na zem a je LOW
	
	tlacitkoAenabled = true; // smíme ho teď stisknout
	tlacitkoBenabled = true; // smíme ho teď stisknout, kdyby se muselo povinně začínat tlačítkem A, tak tady to tlačítko B zakážeme a budeme čekat, až ho A uvolní
	
	tlacitkoAactive = false; // jeho akce neprobíhá
	tlacitkoBactive = false; // jeho akce neprobíhá
}

void loop() {
	unsigned long CurrentMillis=millis();	// jaký je čas (a předejdeme zmatkům, kdyby se zrovna překlápěl) - viz též https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
	
	if (tlacitkoAenabled && !tlacitkoAactive && digitalRead(tlacitkoApin)==LOW) {	// je povoleno ho stisknout, jeho akce ještě neběží a fakt je stisknuté - čas zahájit akci
		tlacitkoAactive = true; 	// akce běží
		tlacitkoAfrom = CurrentMillis; 	// od teď
		tlacitkoAenabled = false; 	// už se nesmí zmáčknout znovu
		tlacitkoBenabled = true; 	// ale B se od teď stisknout smí (takže akce se mohou částečně překrývat)
	};
	
	if (tlacitkoBenabled && !tlacitkoBactive && digitalRead(tlacitkoBpin)==LOW) {	// je povoleno ho stisknout, jeho akce ještě neběží a fakt je stisknuté - čas zahájit akci
		tlacitkoBactive = true; 	// akce běží
		tlacitkoBfrom = CurrentMillis; 	// od teď
		tlacitkoBenabled = false; 	// už se nesmí zmáčknout znovu
		tlacitkoAenabled = true; 	// ale A se od teď stisknout smí (takže akce se mohou částečně překrývat)
	};
	
	if (tlacitkoAactive) { // řešíme akci A
		digitalWrite(ledA1pin, (CurrentMillis - tlacitkoAfrom) < timeA1);	// pravda pouze od stisknutí, do vypršení času, jinak LED zhasne (false == 0 )
		digitalWrite(ledA2pin, (CurrentMillis - tlacitkoAfrom) < timeA2);	// pravda pouze od stisknutí, do vypršení času, jinak LED zhasne (false == 0 )
		// pozor, trik - ty nerovnosti nahoře a dole nejsou nikdy splněné naráz, takže vím, že diody zhasnou dřív než skončíme akci
		if ( ((CurrentMillis - tlacitkoAfrom) >= timeA1 ) &&  ((CurrentMillis - tlacitkoAfrom) >= timeA2 ) ) {	// už není co dělat, uklidíme
			tlacitkoAactive = false; // jeho akce neprobíhá
			// kdyby akce nesměly běžet naráz, tak povolíme druhé tlačítko až tady
		};
	};
	
	if (tlacitkoBactive) { // řešíme akci B
		digitalWrite(ledB1pin, (CurrentMillis - tlacitkoBfrom) < timeB1);	// pravda pouze od stisknutí, do vypršení času, jinak LED zhasne (false == 0 )
		digitalWrite(ledB2pin, (CurrentMillis - tlacitkoBfrom) < timeB2);	// pravda pouze od stisknutí, do vypršení času, jinak LED zhasne (false == 0 )
		if ( ((CurrentMillis - tlacitkoBfrom) >= timeB1 ) &&  ((CurrentMillis - tlacitkoBfrom) >= timeB2 ) ) {	// už není co dělat, uklidíme
			tlacitkoBactive = false; // jeho akce neprobíhá
			// kdyby akce nesměly běžet naráz, tak povolíme druhé tlačítko až tady
		};
	};
	
}


Re: jednoduchý kód

Napsal: 22 črc 2019, 06:16
od pavel1tu
gilhad píše:
22 črc 2019, 00:08
Já bych to viděl nějak takhle :)
Proto jsem to nechal vyřešit s knihovnou,
aby to bylo pro začátečníka přehlednější a mohl si to snáze upravit

No uznávám popisky v kodu chybí, ale je to tak přehledné, že až zbytečné ....

Re: jednoduchý kód

Napsal: 22 črc 2019, 09:42
od gilhad
Nevím, mě tam ta knihovna s callbacky naopak přijde jako trochu složitější koncept, oproti prostému počítání času, navíc to s ní vychází delší (a to nepočítám kód té knihovny) a kód se čato "ztrácí z dohledu", takže IMHO začátečník hůř zjistí, co se mu tam vlastně na pozadí děje.

A asi by bylo dobré si u těch vstupů opravdu zapnout ten interní pull-up, když to je i v komentáři. Takhle ta tlačítka zůstávají ve stavu vysokého odporu a není zaručeno, co bude vracet digitalRead, pokud je tlačítko puštěné :) A je potřeba opravdu používat delay "pro jistotu"? Pokud není v té knihovně nějaká chyba, tak by to snad potřeba být nemělo a používání delay beru jako nutné zlo (a Arduino zlozvyk) jen tam, kde to nejde rozumně jinak a program musí být opravdu zablokován.

Re: jednoduchý kód

Napsal: 22 črc 2019, 10:50
od pavel1tu
Nepruď :-D

Ten pullup tam byl, původně.
Ale nevím co půjde na vstupy (plus, minus), tak se zrušil, ne v popisu což je chyba. A já se mu osobně vyhýbám, ošetřuji raději vstupy svým odporem, kondikem.

Knihovnu mám dlouhodobě prověřenou, funguje skvěle a jen nahrazuje ten opruz s milis.
Těch 200ms delay jde smazat - nic to neovlivní v takto jednoduchém programu. Ani nevím proč tam je :-) - přehlédl jsem ho

PS: dělali to děti, tak to beru jako OK, sám bych to neudělal jinak a měli to za hodinu včetně sestavení a vyzkoušení

Re: jednoduchý kód

Napsal: 22 črc 2019, 11:22
od gilhad
Ale jo :) Já to taky psal z jedný vody na plot :)

Ale zatímco ty tu knihovnu znáš a já odhadnu, co asi tak dělá, tak tázající je začátečník a tohle skoro jistě neví.

Takže teď má na výběr dva fungující styly a má o čem přemýšlet (ono to obojí vyjde skoro nastejno a nejspíš to pod kapotou dělá skoro to samé), místo aby měl jednu zjevenou pravdu, kterou by nabifloval, ale nikoli nutně pochopil. A ukázat, že je víc jak jedna možná cesta je IMHO docela vhodné už od začátku.