Dotazy začátečníka 2

jova
Příspěvky: 267
Registrován: 16 pro 2013, 11:40

Re: Dotazy začátečníka 2

Příspěvek od jova » 13 zář 2018, 09:49

Podle mě máš chybu v těch proměnných KP3, KP4 nemůžeš je takto specifikovat v tom řádku symbolu. Zkus to takto:

Kód: Vybrat vše

setfreq M16 
symbol BAUD =T9600_16 ;rychlost pro LCD 
symbol R485 =C.0  ;pin uprav podle svého
symbol D485 =C.1  ;pin uprav podle svého

symbol xxx =b0    ;proměnnou uprav podle svého 
symbol KP3 =b1   ;proměnnou uprav podle svého
symbol KP4 =b2   ;proměnnou uprav podle svého


 DopZ3:
 serin[100],R485,BAUD,xxx,KP3,KP4 ; Rychlomer pozaduje informaci 
 low D485 ;prepne modul RS485 na cteni 
 if KP3=$06 or KP3=$07  then goto MCP
 if KP4=$F8 or KP4=$F9 then goto MPP
 goto DopZ3
 
 mcp:
 mpp:

DavidO
Příspěvky: 528
Registrován: 01 kvě 2013, 21:27

Re: Dotazy začátečníka 2

Příspěvek od DavidO » 13 zář 2018, 12:04

Spíš takhle, řekl bych:

Kód: Vybrat vše

DopZ3:
  serin [100,DopZ3],R485,BAUD,xxx,KP3,KP4 ; Rychlomer pozaduje informaci 
  if xxx=$01 then
    if KP3=$06 and KP4=$F9 then 
      goto MCP
    elseif KP3=$07 and KP4=$F8 then 
      goto MPP
    endif
  endif
  goto DopZ3
MCP:
  ; reakce na "rýchlomer žiada údaj verzie MCP" tj. asi nějaké poslání dat do rychloměru
  goto Dop23
MPP:
  ; reakce na "rýchlomer žiada údaj verzie MPP" tj. asi nějaké jiné poslání dat do rychloměru
  goto Dop23
(když by v tom timeoutu nebyl odskok na návěští, tak by pořád opakoval poslední akci)
Za goto MPP by ještě mohlo být vložena obsluha chyby resp. upozornění, že jsem nepřijal ani jeden z těch dvou příkazů ale něco jiného, cca takhle:

Kód: Vybrat vše

DopZ3:
  serin [100,DopZ3],R485,BAUD,xxx,KP3,KP4 ; Rychlomer pozaduje informaci 
  if xxx=$01 then
    if KP3=$06 and KP4=$F9 then 
      goto MCP
    elseif KP3=$07 and KP4=$F8 then 
      goto MPP
    else 
      goto ERROR01
    endif
  else 
    goto ERRORjine
  endif
  goto DopZ3
ERROR01:
  ; reakce na to, že jsem přijal 01 ale pak nebylo 06F9 ani 07F8 (např. vypsat na LCD)
  goto DopZ3
ERRORjine:
  ; reakce na to, že jsem přijal něco, co nezačínalo 01 (např. vypsat na LCD)
  goto DopZ3
MCP:
  ; reakce na "rýchlomer žiada údaj verzie MPP" tj. asi nějaké jiné poslání dat do rychloměru
  goto Dop23
Kromě toho:
- Definice BAUD by měla být rychlost pro rychloměr, ne pro LCD
- Vynechal jsem to přepnutí RS485 na čtení, jestli to tam má být, tak si to doplň, kam potřebuješ. Myslím, že patří ale spíš před serin a po něm zase přepnout na psaní, aby se dalo něco poslat - ale já nevím, jak to máš zapojené. V takovém případě bych to viděl asi takhle:

Kód: Vybrat vše

DopZ3:
  low D485 ;prepne modul RS485 na cteni 
  serin [100,DopZ3],R485,BAUD,xxx,KP3,KP4 ; Rychlomer pozaduje informaci 
  high D485 ;prepne modul RS485 na psani
...
- Pokud celý ten program má dělat i něco dalšího, tak místo všech goto DopZ3 i toho pro timoeut v serin by bylo něco jako goto pokracuj, a pak

Kód: Vybrat vše

pokracuj:
  high D485 ;prepne modul RS485 na psani
  ; dělej cokoli dalšího, co je potřeba, třeba vař kafe nebo zpívej
  goto DopZ3 ; nebo ještě srozumitelněji goto zacatek

DavidO
Příspěvky: 528
Registrován: 01 kvě 2013, 21:27

Re: Dotazy začátečníka 2

Příspěvek od DavidO » 13 zář 2018, 12:10

A ještě, místo těch goto v rozhodování by bylo programátorsky hezčí gosub (+ return místo goto na konci akcí)

Howky
Příspěvky: 56
Registrován: 07 dub 2016, 15:41

Re: Dotazy začátečníka 2

Příspěvek od Howky » 13 zář 2018, 18:21

Tak jsem to vyzkoušel pánové od obou , a bohužel program vždy zamrzl :/ rychloměr přestal odpovídat :/

Rychloměr je originál co se používá na lokomotivách. Takže neřeším naštěstí ovládání pro LCD, to si řeší rychloměr sám, já mu vlastně posílám jen zprávy, které on vyžaduje :) on si je přebere, a jeho šváb už ovládá zbytek :) LCD, krokové motory ledky apod :)


Ale co se tak dívám, nějak se mu nelíbí ty proměné pro ty zprávy :(

Zatím to tak vypadá že požaduje, zprávu ve formátu přesně :/

Výběr zprávy

Zpravy:
serin[100],R485,BAUD,($01,$01,$FE) goto a přesun na jinou část programu
serin[100],R485,BAUD,($01,$02,$FD) goto a přesun na jinou část programu
serin[100],R485,BAUD,($01,$03,$FC) goto a přesun na jinou část programu
serin[100],R485,BAUD,($01,$04,$FB) goto a přesun na jinou část programu
serin[100],R485,BAUD,($01,$05,$FA) goto a přesun na jinou část programu
serin[100],R485,BAUD,($01,$06,$F9) goto a přesun na jinou část programu
serin[100],R485,BAUD,($01,$07,$F8) goto a přesun na jinou část programu
goto Zpravy

A teď by to chtělo, aby když přijde jedna z těch zpráv, aby si ji ten program vybral, a skočil na její pokračování a provedl další úkony.
Ale to už jsem psal :)

On se na tu doplňkovou zprávu zeptá jen když potřebuje, jinak jede ve svém programu, kdy mu posílám např, čas, rychlost atd.
A když chci zobrazit dejme tomu nějakou jinou informaci , kterou neposílám běžně, tak on se na ni zeptá viz ten zápis Zpravy :)

jova
Příspěvky: 267
Registrován: 16 pro 2013, 11:40

Re: Dotazy začátečníka 2

Příspěvek od jova » 13 zář 2018, 20:50

Jsem z toho tvého popisu trochu zmatený. Když budu vycházet ze situace, že ty zprávy do tvého picaxe posílá ten rychloměr a ten picaxe je má třídit, tak by měl fungovat podle mého tahle část programu pro čtení zpráv a jejich vyhodnocení:

Kód: Vybrat vše

Zpravy:
serin[100],R485,BAUD,b0,b1,b2 ; Rychlomer pozaduje informaci 
if b0=$01 and b1=$01 and b2=$FE then goto aa 
if b0=$01 and b1=$02 and b2=$FD then goto bb
if b0=$01 and b1=$03 and b2=$FC then goto cc
if b0=$01 and b1=$04 and b2=$FB then goto dd
if b0=$01 and b1=$05 and b2=$FA then goto ee
if b0=$01 and b1=$06 and b2=$F9 then goto ff
if b0=$01 and b1=$07 and b2=$F8 then goto gg
goto Zprávy

aa:
bb:
cc:
dd:
ee:
ff:
gg:
Ale musí se tam do té smyčky zabudovat i zbytek tvého programu, nebo jí opouštět a zase se vracet na čtení, aby se ten program nezacyklil jenom v tom čtení (nezamrzl). Samozřejmě se i z těch odskoků aa, bb ... se musí program zase vrátit zpět na to čtení.

DavidO
Příspěvky: 528
Registrován: 01 kvě 2013, 21:27

Re: Dotazy začátečníka 2

Příspěvek od DavidO » 14 zář 2018, 00:06

Vždyť už jsem ten mechanismus psal:
Přijmout tři znaky (s timeoutem, tím se jakž-takž dá udělat synchronizace, i když to není 100pro ale pro pražáky dobrý), zkontrolovat, že první je 01, a pak podle zbylých dvou rozhodnout, co dělat.
Důsledně používat elseif.
Místo goto sem a pak goto zase jinam a goto na začátek ... lidi, prosím, když už ten verk nemá procedury a funkce, používejte aspoň gosub, jinak si v tom uděláte bordel.

Rychloměru se nemá co nelíbit nějaká proměnná, to je záležitost picaxe a do toho rychloměr nevidí. Tím pádem nechápu, co tou větou chceš říct.

Sekvencí serin [100], něco serin [100] něco atd. si děláš zbytečný problém, protože to znamená, že čekáš na první zprávu 100ms a když nepřijde, čekáš na druhou zprávu 100ms a když nepřijde, čekáš na třetí ... ale co když ti při čekání na druhou přijde sedmá? Smolík, nic nemáš.

Howky
Příspěvky: 56
Registrován: 07 dub 2016, 15:41

Re: Dotazy začátečníka 2

Příspěvek od Howky » 14 zář 2018, 02:35

Tak nakonec zapsáno takto a funguje : díky za rady :)

DopZ3:
serin[1000],R485,BAUD,b9,b10,b11,b12 ; Rychlomer pozaduje informaci
if b10=$01 then goto Statistika1 ; Statistika 1 - klavesa 8
if b10=$02 then goto Statistika2 ; Statistika 2 - klavesa 9
if b10=$03 then goto CasLZ ; Cas letni-Zimni - klavesa 3
if b10=$04 or b10=$05 then goto ZP00 ; Simulovana rychlost nebo zapis chranenych a nechranenych dat
if b10=$06 then goto MCP ; verze MCP
if b10=$07 then goto MPP ; verze MPP
goto Program:

jova
Příspěvky: 267
Registrován: 16 pro 2013, 11:40

Re: Dotazy začátečníka 2

Příspěvek od jova » 14 zář 2018, 08:20

DavidO píše:
14 zář 2018, 00:06
...
Důsledně používat elseif.
...
Mohl bych se jako začátečník zeptat, proč by se ten příkaz měl důsledně dodržovat? Už jsem se nad tím pozastavil u tvého předešlého příspěvku kde jsi použil obdobnou strukturu programu viz následující jednoduchý příklad:

Kód: Vybrat vše

start:
b0= b0+1
b1=b1+1
if b1>5then
  if b0<8then 
   goto aa
  elseif b0>7then 
   goto bb
 endif
endif
goto start 
aa:pause 1000 goto start
bb:pause 1000 goto start
Kdežto já navrhnul něco podobného tomuto:

Kód: Vybrat vše

start:
b0=b0+1
b1=b1+1
if b1>5then
if b0<8then goto aa 
if b0>7then goto bb 
endif
goto start
aa:pause 1000 goto start
bb:pause 1000 goto start
Mám pocit, že oba programy jsou, co se týká funkce rovnocenné a tím příkazem elseif se program zbytečně jen prodlužuje o 8 bytů. Nebo je tam nějaký důvod který mi uniká?
Obdobné je to s tím příkazem gosub/goto. Když ten program upravím takto:

Kód: Vybrat vše

start:
b0=b0+1
b1=b1+1
if b1>5then
if b0<8then gosub aa 
if b0>7then gosub bb 
endif
goto start
aa:pause 1000 return
bb:pause 1000 return
Je o dalších 9 bytů delší, tvá varianta s gosub/return dokonce o 10 :(
Dost ve svém programu bojuji s jeho délkou a tak mi každé ušetřené místo v paměti pomůže.

DavidO
Příspěvky: 528
Registrován: 01 kvě 2013, 21:27

Re: Dotazy začátečníka 2

Příspěvek od DavidO » 14 zář 2018, 13:52

Pokusím se to naznačit, ale bude to dlouhé. Je to spíš na povídání o tom, jak psát dobrý kód a to je na dlouhý lokte (a já se tady dotknu jen malilinkaté části).

elseif je užitečná konstrukce při běhu, protože se zbytečně nevyhodnocují podmínky, které jistě nemohly nastat, když je už vyloučila předchozí větev ifu. Představ si, že by bylo if a=1 a za tím 100 dalších podobných, jako if a=3 and b=62, if a=17 and c=107 atd. , čili nejde to udělat tabulkou, ale když už se jedna z nich ujme, tak ty další už jistě ne. Kdyby tam bylo vždycky if, tak se musí všechny ify projet od začátku až do konce, i když už je jasné, že se ty za vykonaným opravdu nemůžou uplatnit. S elseif se ten konec přeskočí. Jakmile se jedna ujme, vykoná se a zbytek se vůbec nezkouší, přeskočí. Pokud seznam ručně srovnám, aby na začátku byla nejpravděpodobnější varianta, nebude se za běhu zbytečně ztrácet čas a výpočetní výkon.

Nezdůvodněné anebo dokonce nezřízené používání goto vede ke špatně čitelnému a tedy špatně udržovatelnému kódu, často i k špatně laditelnému a více chybovému kódu a někdy i k chybám, které se projeví jen za velmi specifických okolností a velmi těžko se odhalují. V případě kompilace může používání goto znesnadnit práci kompilátoru. Nepoužívat goto když to není nezbytné nebo dobře zdůvodněné je jedno z takových základních pravidel v programování. Už před 50 lety Dijkstra konstatoval v analýze jakéhosi reálného projektu, že kvalita programu je nepřímo úměrná používání goto, což je sice poněkud zjednodušené, ale zároveň dost dobře ilustrativní. Když se goto namlátí do kódu na vyřešení kdejaké patálie, vznikne příšernost a prostor pro chyby je prostě větší. Celkově se roky vede debata, jestli goto ano nebo ne. Nicméně dá se říct, že jednoduché věci se dají psát i bez goto a naopak jsou rozumné případy, kdy se použitím goto leccos zjednoduší. Zastánci "bez goto si programování neumím představit" budou argumentovat konstrukcemi, kde odstranění goto způsobí třeba duplicitu kódu (a to je obecně špatně), zarytí odpůrci goto budou argumentovat triviálními případy, kde to goto potřeba opravdu není.
S tím, jak se vyvíjejí programovací jazyky, potřeba goto tak nějak klesá. Třeba Fortranu má oproti C/C++/C# jen velmi omezené možnosti pro smyčky a tak ve Fortranu vhodně ložené goto mohlo dost pomoct. Ale i tak se občas i dnes dobře hodí (např. při postupné alokaci a uvolňování prostředků při selhání to dokonce může, když se to napíše správně, kód výrazně zpřehlednit). Já se kloním ke "goto nezatracovat, ale používat opravdu s rozmyslem".

Ale zpět k Picaxe - je to jednoduchý, omezený jazyk, který se interpretuje, čili není tam kompilátor, který by mohl dělat nějaké zajímavé optimalizace, tak ho to rušit nebude. goto tam má své místo, ale není potřeba všude, Picaxe má dostatečné konstrukce, aby to goto nebylo nutné všude. Naštěstí má dost málo paměti, takže se tam programátor nemůže moc rozmáchnout a kód je obvykle "zkouknutelný" docela dobře, ale bohužel má dost paměti na to, aby tam programátor mohl udělat dost velkej bordel, ve kterém se půjde vyznat jen těžko.

Používání gosub/return místo goto ... goto start zpřehledňuje kód, usnadňuje pochopení toku. V případě, že se nějaká část volá víckrát z různých míst to v podstatě ani nejde rozumně udělat jinak. Ten tvůj příklad je docela modelový, dá se to přepsat bez goto a s elseif a bude to dělat to samé (a dokonce tam to gosub ani nemusí být potřeba, pokud ty části za návěštími aa a bb nevoláš víckrát)

Velikost výsledného programu by nemělo být absolutní měřítko kvality. Někdy je potřeba šetřit místem, ale běžně by se to nemělo dělat za každou cenu (a navíc to velmi často signalizuje jiné problémy, třeba programátorské ne-šikovnosti nebo i chyby). Strukturované programování s voláním podprogramů místo skákání goto tam a pak zas jinam výrazně usnadňuje práci. Goto obvykle narušuje logickou strukturu, takže srozumitelnost jde do háje. Co se týče těch elifů, tak tady v případě té komunikace může dokonce dojít i k tomu, že časová nadbytečnost za běhu způsobí, že nějakou zprávu nepřijmu, protože na ten další serin dojde až později právě proto, že se testovaly ify, které se nevykonaly (a bylo jisté, že se nevykonají).

... tolik úvodem. :D

DavidO
Příspěvky: 528
Registrován: 01 kvě 2013, 21:27

Re: Dotazy začátečníka 2

Příspěvek od DavidO » 14 zář 2018, 13:58

Howky píše:
14 zář 2018, 02:35
Tak nakonec zapsáno takto a funguje : díky za rady :)

DopZ3:
serin[1000],R485,BAUD,b9,b10,b11,b12 ; Rychlomer pozaduje informaci
if b10=$01 then goto Statistika1 ; Statistika 1 - klavesa 8
if b10=$02 then goto Statistika2 ; Statistika 2 - klavesa 9
if b10=$03 then goto CasLZ ; Cas letni-Zimni - klavesa 3
if b10=$04 or b10=$05 then goto ZP00 ; Simulovana rychlost nebo zapis chranenych a nechranenych dat
if b10=$06 then goto MCP ; verze MCP
if b10=$07 then goto MPP ; verze MPP
goto Program:
POZOR, když to skončí na timeout, uděláš znovu posledně vykonanou akci (už jsem to tu psal). POdle toho, co ti "zbylo v b10 odminula".
Není to taky zcela korektní, protože netestuješ, že to je zpráva celá od začátku (je b9 opravdu 01? Když bys kvůli postupnému testování v minulém kroce nechytil tu úvodní 01, tak do b9 přečteš druhý byte, do b10 třetí atd. a vyhodnocení bude blbě)

A v souladu s mým minulým příspěvkem, tady třeba to goto potřeba není. if má možnost při splnění podmínky vykonat i celý blok příkazů, což se tu vyloženě nabízí. A ty elseif taky.

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 0 hostů