Wiring, C++, C, Java, ...
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 12 čer 2018, 02:55
Zdravim. Rád bych se zeptal zda mi bude fungovat tento časový spínač.
Kód: Vybrat vše
void timeSwitch(){ //casovy spinac okruhu
bool h12;
bool PM;
for(int i=1; i<4; i++) { //smycka pro vyhodnoceni casu sepnuti pro tri okruhy
if(Clock.getHour(h12, PM)== EEPROM.read(20+i)&& Clock.getMinute()== EEPROM.read(30+i)
&& EEPROM.read(40+i)>0) { //pokud EEPROM.read = 0 okruh je vypnuty
Ok[i] = true; //povoli sepnuti v nastaveny cas
}
}
if(Ok1==true) { //paklize nadesel cas sepnuti okruhu1
for(int o1=EEPROM.read(41); o1>0; o1--) { //delicka dnu sepnuti(denne,obden atd)
if(o1!=1) { //dokud nebude o1 = 1
Ok1=false; //sepnuti okruhu 1 bude zakazano
}
break; //preruseni smycky do dalsiho casoveho okna
}
}
if(Ok2==true) {
for(int o2=EEPROM.read(42); o2>0; o2--) {
if(o2!=1) {
Ok2=false;
}
break;
}
}
if(Ok3==true) {
for(int o3=EEPROM.read(43); o3>0; o3--) {
if(o3!=1) {
Ok3=false;
}
break;
}
}
}
Jde o to,že podle nastavení může spínat denně,nebo obden nebo až jednou týdně. Smyčkou for s příkazem break; doufám,že toho dosáhnu.na praktické testování pokus omyl je to ale příliš dlouhý interval a tak prosím někoho kdo ví o radu zda to opravdu udělá co čekám.
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 12 čer 2018, 13:22
Asi uz vidim chybu. Break; by mělo být pod podmínkou if(o1! =1) aby v případě že bude dosaženo cíle cyklus for() doběhl a mohl začít znovu?
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 13 čer 2018, 21:51
Asi je špatně celá myšlenka.
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 14 čer 2018, 02:30
Tak jsem to přepsal a púvodní problém je vyřešen. jenže nastal další.
Potřebuji od sepnutí relé prodlevu která je uložená v eeprom a nechce mi to porovnávat millis s hodnotou z eeprom.
kód:
Kód: Vybrat vše
void timeSwitch(){ //casovy spinac okruhu
bool h12;
bool PM;
if ((unsigned long)(millis() - readingTswitch >= 61000)) { //cas 1min 1sec do dalsiho porovnani po shodě
for(int i=1; i<4; i++) { //smycka pro vyhodnoceni casu sepnuti pro tri okruhy
if(Clock.getHour(h12, PM)== EEPROM.read(20+i)&& Clock.getMinute()== EEPROM.read(30+i)
&& EEPROM.read(40+i)>0) { //pokud EEPROM.read = 0 okruh je vypnuty
Ok[i] = true; //povoli sepnuti v nastaveny cas
readingTswitch = millis();
}
}
}
if(Ok[1]==true && o1>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o1--; //odecti den
Ok[1]=false; //zakaz zalivku
}
if(Ok[2]==true && o2>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o2--; //odecti den
Ok[2]=false; //zakaz zalivku
}
if(Ok[3]==true && o3>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o3--; //odecti den
Ok[3]=false; //zakaz zalivku
}
if(Ok[1]==true) {
digitalWrite(Okr1,HIGH);
Okr1Timeout=millis();
Ok[1]=false;
o1=EEPROM.read(41);
}
if (millis() >= ((unsigned long)(6000*EEPROM.read(51)+Okr1Timeout))) { //TADY JE PROBLÉM
digitalWrite(Okr1,LOW);
}
}
Tam co je napsáno TADY PROBLÉM
Pokud tam dám jen 6000+Okr1Timeout,funguje to. Když to ale vynásobim EEPROM.read,tak to nefunguje. Podmínka je tedy splněna a relé zůstane LOW.
Co v tom nevidim,nebo spíš nevim? Díky za radu.
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 14 čer 2018, 16:21
Teď jsem zkusil uložit násobek EEPROM.read*6000 do unsigned long proměnné. EEPROM obsahuje číslo 10,takže by tam mělo být 60000,ale je tam těch 4294967295 co se vejde do unsigned long. Kde dělám chybu?
-
gilhad
- Příspěvky: 786
- Registrován: 07 bře 2018, 11:22
- Reputation: 0
Příspěvek
od gilhad » 14 čer 2018, 16:25
Nevim, ale u podobnych radovanek jsem narazil na to, ze uvnitr zavorek se mi to pretypovalo nejak, neco nejak se spocetlo a pak se pretypoval az cely vysledek. Pro zacatek bych teda na ty unsigned long pretypoval i kazdou hodnotu v te zavorce i celou zavorku. ten EEPROM.read je napriklad byte, 6000 je signed int (-32k ... +32k) , takze bych se vubec nedivil kdyby ten soucin treba pro hodnotu 10 v EEPROM vysel zaporny (60k>32K, jde tedy o preteceni a je otazkou, jak se k tomu prekladac postavi, nejspis to zignoruje a vyjde mu zaporne cislo) a odecetl se ti. nebo udelal libovolnou jinou zajimavou zlotrilost.
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 14 čer 2018, 16:33
Zkusil jsem ještě úplně vynechat cokoli neprůhledného a zadeklaroval unsigned long Epr1=10*6000. Prostá čísla kde bych nečekal žádnou zradu a přesto je v té proměnné 4294967295. To už přece s datovými typy nemůže mít nic do činění.
Aha teď jsem si ještě jednou přečetl Tvůj příspěvek a i prostá čísla v programu překladač natypuje podle velikosti?
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 15 čer 2018, 08:31
Díky. To bylo ono. Teď už to funguje jak má. Jen se ještě zeptám jestli je rozumné řešit časový interval až 240 minut pomocí millis() tak jak to tam mám napsané s ohledem na přetečení,protože tam neporovnávám s rozdílem,ale se součtem.
To místo označené TADY PROBLÉM
Díky.
kód:
Kód: Vybrat vše
void timeSwitch(){ //casovy spinac okruhu
bool h12;
bool PM;
unsigned long Epr1=((unsigned long)EEPROM.read(51)*6000UL);
if ((unsigned long)(millis() - readingTswitch >= 61000)) { //cas 1min 1sec do dalsiho porovnani po shodě
for(int i=1; i<4; i++) { //smycka pro vyhodnoceni casu sepnuti pro tri okruhy
if(Clock.getHour(h12, PM)== EEPROM.read(20+i)&& Clock.getMinute()== EEPROM.read(30+i)
&& EEPROM.read(40+i)>0) { //pokud EEPROM.read = 0 okruh je vypnuty
Ok[i] = true; //povoli sepnuti v nastaveny cas
readingTswitch = millis();
}
}
}
if(Ok[1]==true && o1>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o1--; //odecti den
Ok[1]=false; //zakaz zalivku
}
if(Ok[2]==true && o2>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o2--; //odecti den
Ok[2]=false; //zakaz zalivku
}
if(Ok[3]==true && o3>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o3--; //odecti den
Ok[3]=false; //zakaz zalivku
}
if(Ok[1]==true) {
digitalWrite(Okr1,HIGH);
Okr1Timeout=millis();
Ok[1]=false;
o1=EEPROM.read(41);
}
if(digitalRead (Okr1)) {
if ((unsigned long)millis() >= Epr1+Okr1Timeout) { //TADY JE PROBLÉM
digitalWrite(Okr1,LOW);
Serial.println(Epr1);
}
}
}
Až budu mít dokončenou alespoň základní porovnávací logiku,dám to do projektů a postupně to budu dokončovat.
-
rejze69
- Příspěvky: 174
- Registrován: 02 dub 2018, 18:56
- Reputation: 0
Příspěvek
od rejze69 » 17 čer 2018, 01:19
Nakonec jsem se rozhodl to napsat bez millis() raději s RTC. První co mne napadlo bylo převést nastavené minuty na hodiny a minuty a sečíst to do proměnné s aktuálním časem.Tu potom porovnat a po dosažení shody ukončit zálivku. Jenže se mi to zdálo zbytečně složitý a plán ukončil tím převodem. Ten je sám o sobě jednoduchej a kdyby to někdo potřeboval:
Kód: Vybrat vše
if(minuty<60) {
minu=minuty;
}
else {
for(int i=minuty; i>=60; i=i-60) {
hod++;
minu=i-60;
}
}
Doufám že jsem tam nic nespletl,protože jsem to vyzkoušený smazal.
Nakonec jsem to vyřešil odpočtem rovnou těch minut podle RTC. Je to tam okomentovaný,funguje to a je to jednodušší než obě předchozí řešení.
Kód: Vybrat vše
void timeSwitch(){ //casovy spinac okruhu
bool h12;
bool PM;
if ((unsigned long)(millis() - readingTswitch >= 61000)) { //cas 1min 1sec do dalsiho porovnani po shodě
for(int i=1; i<4; i++) { //smycka pro vyhodnoceni casu sepnuti pro tri okruhy
if(Clock.getHour(h12, PM)== EEPROM.read(20+i)&& Clock.getMinute()== EEPROM.read(30+i)
&& EEPROM.read(40+i)>0) { //pokud EEPROM.read = 0 okruh je vypnuty
Ok[i] = true; //povoli sepnuti v nastaveny cas
readingTswitch = millis(); //povoleni dalsiho porovnani
}
}
}
if(Ok[1]==true && o1>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o1--; //odecti den
Ok[1]=false; //zakaz zalivku
}
if(Ok[2]==true && o2>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o2--; //odecti den
Ok[2]=false; //zakaz zalivku
}
if(Ok[3]==true && o3>1) { //paklize nadesel cas sepnuti okruhu1 a neuplynuly dny mezi zalivkami
o3--; //odecti den
Ok[3]=false; //zakaz zalivku
}
if(Ok[1]==true) { //Po predchozich porovnanich trva stav true
digitalWrite(Okr1,HIGH); //Sepni zavlazovani okruhu
mPrev[1]=Clock.getMinute(); //ulozeni aktualni minuty
m[1]=EEPROM.read(51); //Nacteni nastavene doby zalivky v minutach
Ok[1]=false; //vynulovani okruhu pro pristi cyklus
o1=EEPROM.read(41); //nacteni prednastavene frkvence dnu zalivky pro pristi cyklus
}
if(digitalRead (Okr1)) { //pokud je sepnuto rele okruhu
if (mPrev[1] != Clock.getMinute()) { //kdyz se neshoduji aktualni minuty s predchozimi,uplynula minuta
m[1]--; //sniz pocet minut do konce zalivky
mPrev[1]=Clock.getMinute(); //znovu uloz aktualni minutu pro dalsi porovnani
}
if(m[1]<=0) { //kdyz dosahne pocet minut do konce zalivky nuly
digitalWrite(Okr1,LOW); //Vypni rele (ukonci zalivku okruhu )
}
}
if(Ok[2]==true) {
digitalWrite(Okr2,HIGH);
mPrev[2]=Clock.getMinute();
m[2]=EEPROM.read(52);
Ok[2]=false;
o1=EEPROM.read(42);
}
if(digitalRead (Okr2)) {
if (mPrev[2] != Clock.getMinute()) {
m[2]--;
mPrev[2]=Clock.getMinute();
}
if(m[2]<=0) {
digitalWrite(Okr2,LOW);
}
}
if(Ok[3]==true) {
digitalWrite(Okr3,HIGH);
mPrev[3]=Clock.getMinute();
m[3]=EEPROM.read(53);
Ok[3]=false;
o3=EEPROM.read(43);
}
if(digitalRead (Okr3)) {
if (mPrev[3] != Clock.getMinute()) {
m[3]--;
mPrev[3]=Clock.getMinute();
}
if(m[3]<=0) {
digitalWrite(Okr3,LOW);
}
}
}
Kdo je online
Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 14 hostů