Stránka 1 z 2

nefungující omezení proměnné

Napsal: 19 bře 2019, 21:18
od Vítek
zdravím,

v jednom ze svých projektů potřebuji omezit hodnotu proměnné W0 (pontb) k vytváření hodnoty pro příkaz pwmduty na hodnoty od 1 do 1023, horní hranice bez problémů funguje a zvětšování se čísla se vždy zastaví na 1023, ale ta spodní nedělá absolutně nic a číslo vždy dojde až na nulu a poté na číslo 65527.

tady je kus kódu ve kterém je problém:

Kód: Vybrat vše

lustrop:
irin [3000,ovladac],ir,irb
select case irb
case 17
let pontb=pontb-10 min 1

case 16
let pontb=pontb+10 max 1023

case 73
pontb=1023

case 74
pontb=0

end select

let irb=0
pwmduty lustr,pontb
goto lustrop
myslím že je to zbytečné, ale raději zde přiložím i celý kód, ale místy je trochu zmatený:

Kód: Vybrat vše

;p - program
;b - promená

;out:
symbol lustr=B.1
symbol modra=C.3
symbol zluta=c.2

symbol dvV=B.5
symbol peV=B.4

symbol rep=B.3
symbol ledz=C.4
symbol ledc=C.0
;in:
symbol pont=B.6
symbol ir=B.0

symbol tl1=pinC.7
symbol tl2=pinC.6
symbol tl3=pinB.7

;proměnné:
symbol irb=B3
symbol pontb=W0
symbol ovl=B4 ;1=deska 2=ovladac tv 3=pic ovl (250=stisk)








init:
let ovl=1
pwmout C.2,150,100 ; inicializuj modul pwm
pwmout C.3,150,100
pwmout B.1,150,100


start:
select case ovl
case 1
gosub deska

case 2
gosub ovladac

end select
goto start


deska:
readadc10 pont, pontb
if tl3=1 then let ovl=250 gosub lustrp endif
if tl1=1 then let ovl=250 gosub modrap endif
if tl2=1 then let ovl=250 gosub zlutap endif

if ovl=250 then let ovl=1 goto deska end if
irin [200],ir,irb
if irb=21 then let ovl=2 low ledz high ledc sound rep,(50,50) endif
return

ovladac:
irin [50],ir,irb
select case irb

case 1
high dvV
sound rep,(100,10)
let irb=0

case 2
low dvV
sound rep,(100,50)
let irb=0

case 4
high peV
sound rep,(100,10)
let irb=0

case 5
low peV
sound rep,(100,50)
let irb=0

case 6
gosub modraop

case 7
gosub zlutaop

case 8
gosub lustrop

end select

if tl1=1 then let ovl=1 let irb=0 low ledc high ledz sound rep,(50,50) endif

return


lustrp:
pwmduty lustr,pontb ; nastav činitel plnění
return

modrap:
pwmduty modra,pontb ; nastav činitel plnění
return

zlutap:
pwmduty zluta,pontb ; nastav činitel plnění
return

modraop:
irin [3000,ovladac],ir,irb
debug
select case irb

case 17
let pontb=pontb-10 min 1
debug

case 16
let pontb=pontb+10 max 1023

case 73
pontb=1023

case 74
pontb=0

end select

let irb=0
pwmduty modra,pontb
goto modraop

zlutaop:
irin [3000,ovladac],ir,irb
select case irb
case 17
let pontb=pontb-10 min 1

case 16
let pontb=pontb+10 max 1023

case 73
pontb=1023

case 74
pontb=0

end select
let irb=0
pwmduty zluta,pontb
goto zlutaop

lustrop:
irin [3000,ovladac],ir,irb
select case irb
case 17
let pontb=pontb-10 min 1

case 16
let pontb=pontb+10 max 1023

case 73
pontb=1023

case 74
pontb=0

end select
let irb=0
pwmduty lustr,pontb
goto lustrop

Re: nefungující omezení proměnné

Napsal: 19 bře 2019, 21:48
od Vítek
Teď jsem ještě zkoušel pro omezení další čísla a nejnižší které funguje je číslo 10, to je ale moc vysoké na to, abych jej mohl použít.

Re: nefungující omezení proměnné

Napsal: 19 bře 2019, 21:49
od DavidO
Vyhodnocení příkazu let pontb=pontb-10 min 1 se dělá striktně odleva. Takže se nejdřív spočte pontb-10, což pro čísla menší než 10 podteče pod nulu a tedy se zalomí přes 65535, a teprve pak se kontroluje, jestli to není míň, než 1. A to není a výsledek se nechá těch 655xx. Takhle to dopadne pro skoro všechna počáteční čísla, až na násobky desítky, kdy se postupně po těch desítkách sleze až na něco mezi 1-9 a v dalším kroku vyjde něco mezi 65527 a 65535. Pokud se náhodou povede, že se začínalo na celých desítkách, tak to po desítkách sleze k nule, ta je menší než 1 a tedy se z toho udělá jednička, no a v dalším kroku se spočte 1-10 a jsme tam, co jsme byli.

Re: nefungující omezení proměnné

Napsal: 19 bře 2019, 21:55
od DavidO
Nestačilo by

Kód: Vybrat vše

IF pontb > 10 THEN 
pontb = pontb-10
ENDIF
?
Není to sice na jeden řádek, ale to ve výsledné velikosti kódu nehraje roli. Holt on Picaxe basic není úplně geniální jazyk, no.

Re: nefungující omezení proměnné

Napsal: 19 bře 2019, 22:12
od Vítek
Bohužel nestačilo, to že to není na jeden řádek nevadí, ale minimální hodnota je 11 a led pásky, které tento kus programu stmívá se zhasnou až na hodnotě 0

Re: nefungující omezení proměnné

Napsal: 20 bře 2019, 01:26
od gilhad
Tak pred to jeste dej test na hodnoty pod 11:

Kód: Vybrat vše

IF pontb < 11 THEN 
pontb = 1
ENDIF
; tim se udela to min 1 pro cisla, kde 10 nejde plne odecist aniz by to podteklo

IF pontb > 10 THEN 
pontb = pontb-10
ENDIF
; jinak se to zmensi o 10 a bude to urcite vetsi rovno jedne



Re: nefungující omezení proměnné

Napsal: 20 bře 2019, 18:30
od Vítek
gilhad píše: 20 bře 2019, 01:26

Kód: Vybrat vše

IF pontb < 11 THEN 
pontb = 1
ENDIF
; tim se udela to min 1 pro cisla, kde 10 nejde plne odecist aniz by to podteklo

IF pontb > 10 THEN 
pontb = pontb-10
ENDIF
; jinak se to zmensi o 10 a bude to urcite vetsi rovno jedne


Děkuji všem za ochotu, toto již funguje jen jsem musel změnit pontb = 1 na pontb = 0, aby světlo úplně zhaslo.
kdyby někoho zajímala celá současná verze programu zde je:

Kód: Vybrat vše

;p - program
;b - promená
;out:
symbol lustr=B.1    ;ledpásek (přes tranzistor)
symbol modra=C.3  ;bílý ledpásek do modra (přes tranzistor)
symbol zluta=c.2     ;bílý ledpásek do žluta nádechem (přes tranzistor)

symbol dvV=B.5 ;relé ovládající výstup 5V
symbol peV=B.4 ;relé ovládající výstup 12V

symbol rep=B.3 ;piezo reproduktor
symbol ledz=C.4 ;červená led
symbol ledc=C.0 ;zelená led
;in:
symbol pont=B.6 ;vstup potenciometru
symbol ir=B.0 ;vstup infrapřijímače

symbol tl1=pinC.7 ;tlečitko, stisk=1
symbol tl2=pinC.6 ;tlečitko, stisk=1
symbol tl3=pinB.7 ;tlečitko, stisk=1

;proměnné:
symbol irb=B3
symbol pontb=W0
symbol ovl=B4 ;1=deska 2=ovladac tv 3=pic ovl (250=stisk)








init:
let ovl=1
pwmout C.2,150,100 ; inicializuj modul pwm
pwmout C.3,150,100
pwmout B.1,150,100


start:
select case ovl
case 1
gosub deska

case 2
gosub ovladac

end select
goto start


deska:
readadc10 pont, pontb
if tl3=1 then let ovl=250 gosub lustrp endif
if tl1=1 then let ovl=250 gosub modrap endif
if tl2=1 then let ovl=250 gosub zlutap endif

if ovl=250 then let ovl=1 goto deska end if
irin [200],ir,irb
if irb=21 then let ovl=2 low ledz high ledc sound rep,(50,50) endif
return

ovladac:
irin [50],ir,irb
select case irb

case 1
high dvV
sound rep,(100,10)
let irb=0

case 2
low dvV
sound rep,(100,50)
let irb=0

case 4
high peV
sound rep,(100,10)
let irb=0

case 5
low peV
sound rep,(100,50)
let irb=0

case 6
gosub modraop

case 7
gosub zlutaop

case 8
gosub lustrop

end select

if tl1=1 then let ovl=1 let irb=0 low ledc high ledz sound rep,(50,50) endif

return


lustrp:
pwmduty lustr,pontb ; nastav činitel plnění
return

modrap:
pwmduty modra,pontb ; nastav činitel plnění
return

zlutap:
pwmduty zluta,pontb ; nastav činitel plnění
return

modraop:
irin [3000,ovladac],ir,irb
select case irb

case 17
IF pontb < 11 THEN let pontb=0 ENDIF
IF pontb > 10 THEN let pontb=pontb-10 ENDIF

case 16
let pontb=pontb+10 max 1023

case 73
pontb=1023

case 74
pontb=0

end select

let irb=0
pwmduty modra,pontb
goto modraop



zlutaop:
irin [3000,ovladac],ir,irb
select case irb
case 17
if pontb < 11 THEN let pontb=0 endif
if pontb > 10 THEN let pontb=pontb-10 endif

case 16
let pontb=pontb+10 max 1023

case 73
pontb=1023

case 74
pontb=0

end select
let irb=0
pwmduty zluta,pontb
goto zlutaop




lustrop:
irin [3000,ovladac],ir,irb
select case irb
case 17
if pontb < 11 THEN let pontb=0 endif
if pontb > 10 THEN let pontb=pontb-10 endif

case 16
let pontb=pontb+10 max 1023

case 73
pontb=1023

case 74
pontb=0

end select
let irb=0
pwmduty lustr,pontb
goto lustrop

Re: nefungující omezení proměnné

Napsal: 20 bře 2019, 18:41
od Vladimir66
hloupy dotaz:
muze se pouzit namisto " let pontb=pontb-10 min 1 " toto " let pontb=pontb-10 min 0 "
(kdyz se zhasina na nulu a ne na jednicku)

tak nic, uz vyreseno :)

Re: nefungující omezení proměnné

Napsal: 20 bře 2019, 21:02
od Vítek
Samozřejmě, zhasíná li se na nule, je potřeba použít let pontb=pontb-10 min 0, ale tady je problém v tom, že to přeteče jak psal DavidO:
DavidO píše: 19 bře 2019, 21:49 Vyhodnocení příkazu let pontb=pontb-10 min 1 se dělá striktně odleva. Takže se nejdřív spočte pontb-10, což pro čísla menší než 10 podteče pod nulu a tedy se zalomí přes 65535, a teprve pak se kontroluje, jestli to není míň, než 1. A to není a výsledek se nechá těch 655xx. Takhle to dopadne pro skoro všechna počáteční čísla, až na násobky desítky, kdy se postupně po těch desítkách sleze až na něco mezi 1-9 a v dalším kroku vyjde něco mezi 65527 a 65535. Pokud se náhodou povede, že se začínalo na celých desítkách, tak to po desítkách sleze k nule, ta je menší než 1 a tedy se z toho udělá jednička, no a v dalším kroku se spočte 1-10 a jsme tam, co jsme byli.
mám-li v pontb třeba 5 vypadá to takto: 5-10=65530 a to je víc než 10

Re: nefungující omezení proměnné

Napsal: 20 bře 2019, 22:21
od DavidO
Vítek píše: 19 bře 2019, 22:12 Bohužel nestačilo, to že to není na jeden řádek nevadí, ale minimální hodnota je 11 a led pásky, které tento kus programu stmívá se zhasnou až na hodnotě 0
Žádnej problém. Zapiš to tak, jak o tom přemýšlíš - jestli to je větší jak 10 tak se to o 10 sníží,. a když ne, tak se to srazí na nulu:

Kód: Vybrat vše

IF pontb > 10 THEN 
pontb = pontb-1
ELSE
pontb = 0
ENDIF