Railnet

Servo, řízené přímo DCC

DCC | Zdeno Janeček, 22. 04. 2014 (8555 zhliadnutí)

Vymyslel jsem elektroniku k servu , kterým se dá ovadat přestavník nebo jiné podobné polohovací zařízení. Chtěl bych popsat zařízení, které je mnohem lepší než klasické modelářské servo, teda aspoň pro železniční modeláře, kteří nejsou spokojeni s původním výrobkem a mají k němu nedůvěru. Ona ta nedůvěra je celkem oprávněná, protože modelářské servo má pro nás spoustu nevýhod. Jako třeba, chvění při nestabilitě napájení, zakmitnutí při zapnutí napájení, obrovská síla, velká rychlost přestavení, citlivost na okolní rušení a ještě pár maličkostí, na které si teď nemůžu vzpomenout. Celkově se jedná o velmi jednoduchý výrobek a tak ho zkusím prezentovat jako stavební návod

Zatím jsem to vymyslel pro obycejné soucástky, ale myslím, že se casem najde nekdo, kdo to prekope na SMD a potom by se to dalo zabudovat prímo do serva a vycnívaly by jen ty dva napájecí kablíky pro DCC. Ono se vlastne nic nezmení, programové vybavení a soucástky zustanou typove stejné, jen to bude v SMD. Já už na to proste nemám oci. Ale i tak jsem to udelal dost malické, 46 x 25 x 11 mm.

Schéma:


Je to vlastne “skoro“ lokomotivní dekodér bez funkcí, pro které nemá Tiny 85 místo.

Zkusím to popsat :
Vstup DCC je na Graetz mostík, kde se DCC usmerní a na stabilizátoru se nastaví napájení, na 5V. Taky je tam odbocka na procesor, který precte a vyhodnotí signál DCC. Na základe prijmutého príkazu, procesor posle príkaz na prestavení serva. Ochranné diody na výstupu výkonového operacního zesilovace chrání pred napetovými špickami a odpor mezi výstupy zmenšuje zákmity , které vznikají pri ovládání indukcní záteže, taky slouží jako zátež pro ACK pri odpojeni motorku. Odpory 3j3 slouží na ochranu proti chodu nakrátko, kdy zabrání vypálení operacního zesilovace. Je nutno osadit takovou hodnotu, aby se neprekrocila hodnota 1.5 A, která je pro zesilovac fatální. Pokud je po usmernení napájení 13V, tak 13 / 6,6 + 3 = 1.5 A. Odpory trošku omezují výkon a rychlost, ale to nám až tak nevadí, protože to potrebujeme. Je nutné použít odpory na aspon 0,6W, kdy pretížení po dobu prestavování naprosto nevadí.
Vývod 1 je RESET a muže být nezapojen, ale pokud bychom chteli další pin, tak je možné ho naprogramovat, ale má to jeden hácek, potom se nedá nic zmenit nebo upgradovat. Zvlášt u SMD je to dost velký problém.
Servo samotné se musí upravit a to tak, že se odstraní elektronika a vyvede se 5 drátu , 2 napájení od motorku a 3 od potenciometru. Zarízení jsem navrhnul tak, aby vubec nezáleželo na hodnote potenciometru.
Výstup bežce potenciometru je priveden na pin PB2 (ADC1) , kde se vyhodnotí uhel natocení. Další dva vývody potenciometru se pripojí na +5V a „zem“ napájení. Vývody motorku se pripojí na JP5, kde je výstup PWM výkonového zesilovace.
Výstup jediného volného pinu je na relé, které prepíná srdcovku a které má navíc jeden prepínací trojpin, treba na indikaci polohy nebo muže prepínat návestidlo mezi dvema polohami. Protože cesticka medi je tenoucká, doporucuji, pripájet drátek 0,5mm po cele délce od výstupu relé, po konektor. Samozrejme, pokud tam zapojíme LEDku, tak je to zbytecné.
Pri zapojení na programovací kolej MUSÍ být odpojen motorek, stací odpojit jeden drát. Odpoved ACK impulsem zabezpecí odpor 270O na výstupu L272. V prípade, že necháte zapojen motorek, muže odejít koncový stupen v ctecce DCC.

Princip a popis funkce:
Signál DCC obsahuje informaci o adrese a príkaz. Po prijmutí správné adresy se vykoná príkaz, který je v bitu.0 , druhého bajtu. Je to tzv párové rízení které nepotrebuje bit.3 druhého bajtu, protože zarízení se vypíná samo. Zarízení umí prijmout príkaz a podle adresy prestaví pomocí PWM servo a vypne ho na základe ctení ADC, kde se vyhodnotí úhel natocení serva.

Jak to funguje :
Na tomto jednoduchém zarízení se dá celkem snadno popsat principy ovládáni DCC a taky trošku okolo programování. Snad to nekoho chytí a bude pokracovat. Není celkem pravda, že všechno už bylo vymyšlené, vývoj jde neustále dopredu a co si sami vyrobíme nebo vymyslíme, to už nám nikdo nevezme. Problém ovšem bude, pokud nepoznáte napríklad binární matematiku a spoustu dalšího. Taky se nebudu zabývat nejnižší vrstvou, jak jsou tvoreny bity „1“ a „0“. Pokud nevíte, treba dostudovat normy NMRA a všelico jiné. To platí pro ty, kterí nechtejí být odkázáni na komercní veci a ostatní nech si to koupí hotové. ;-)

Paket DCC pro príslušenství vypadá takto : {preamble} 0 10AAAAAA 0 1aaaCDDD 0 EEEEEEEE 1

Preambule je indikátor zacátku paketu, protože práve u sériových signálu je problém urcit , kdy vlastne prenos zacíná. Proto musí být na zacátku aspon 10 bitu v hodnote „1“. Pak následuje START bit, který musí být v hodnote „0“. Následuje adresový byte, kde je zapsána adresa s bity A0 až A5.
Ono je to trošku zavádející nepravda, ale za to nemohu, je to bordel zvaný „zpetná kompatibilita“ a nebude to jediné, na co budete, pri prípadném navrhování, nadávat. Takových vecí je tam spousta a nejsou zrovna dobre popsány.
Pak následuje zase START bit v hodnote „0“ a potom datový byte, kde je zbytek adresy A6 – A9, které jsou ovšem invertovány, aby to nebylo až tak jednoduché. Tato vyšší adresa je na pozici b.4 – b.6, v datovém byte. Nižší bity se delí na tzv párové rízení, které je pozustatek na doby minule, teda magnetické prestavníky, které potrebovaly dva rozdílné príkazy na ovládání a ješte navíc casove posunuté zapnutí a vypnutí proudu do jednotlivých vinutí prestavníku. Je to navrhnuté tak, že bit.0 ovládá príkaz, teda hodnota znamená bud rovno „0“ nebo do odbocky „1“. Toto je vlastne jediný bit, který je skutecne príkazový a urcuje, co se má vykonat. Další dva bity urcují, která ze ctyr vyhybek (nebo neco jiné), se vybere pro vykonání príkazu. Jsou to vlastne adresy, které se pridávají pred ty predchozí. Teda jako -1, -2, -3, -4. Nebo se to muže celé posunout a potom je adresový prostor A0 až A10. Já používám tento zpusob a vetšina programátoru asi taky. A ješte navíc jsou invertovány bity A0,A1,a D, kdy hodnota “000“ znamená adresa “7 a odbocení “ a hodnota “111“ znamená adresa “0 a rovno“. Takže je to celkem dobre zamotané a zacátecník se muže picnout. To aby bylo jasné, proc jsem psal, ze to je zavádející nepravda.
---
Takže ve skutecnosti vypadá paket DCC pro príslušenství významove takto :
{>10 x 1} <0> ; <1, 0, A7 , A6 , A5 , A4 , A3 , A2 > ; <0>; < 1 , /A10, , /A9 , /A8 , 1 ,/A1, /A0 , /D> ; <0> ; ; <1> Význam bitu : A = adresa ; / = negované ; D = príkaz ; E = EXOR predchozích bajtu, hodnoty 1 a 0 jsou natvrdo dosazené podle normy NMRA.
Je to porádný zmatek, ale nám už to tak neprijde, naucili jsme se. Ale pokud to zacnu nekomu vysvetlovat, tak mne asi po deseti minutách virtuálne opluje a zmizne. Zvlášt, když je binární matematika pro nej absolutne neznámá a tak se nemá ceho chytit.
Paket DCC, který má stejnou adresu jako má ovladac, zpusobí, že se servo zacne prestavovat príslušným smerem a rychlostí, podle bitu.0 v druhém bajtu. Soucasne se zacne natácet potenciometr a tím se mení napetí na vstupu ADC prevodníku. Pokud napetí dosáhne správné hodnoty, servo se zastaví.
Všechny údaje jsou uloženy v EEPROM pameti, které se porovnávají s príchozím paketem a reálným stavem.

Použité soucástky :
Servo je klícová soucástka a opravdu nedoporucuji použít to nejmenší a nejlacinejší. Hlavne z toho duvodu, ze tam jsou montovány motorky s velmi nízkým odporem (2 - 4O), které mají obrovský startovací proud a celkem bežne si potáhnou 2A. Vetší serva mají motorky s odporem nad 4O a nejsou až tak kriticky nenažraná. Tyto malé serva lze použít, ale doporucuji osadit ochranné odpory o 2 - 4 O vetší, aby se ochránil zesilovac.
L2722 DIP8 je klasicky (ne MOSFET) výkonový operacní zesilovac, který je celkem vhodný na toto použití. Existují sice jiné H-Bridge zesilovace, ale ty jsou asi 2x dražší a neprinášejí výraznou pridanou hodnotu. Je tu jedna výnimka a to SN754410, který obsahuje dva zesilovace za srovnatelnou cenu, ale zas je 2x vetší.
Atmel Atiny25/45/85 je mikropocítac, který je na toto vynikající, i když pár vývodu mu urcite chybí ;-). Opravdu by mu stacilo jen dva vývody pridat a byl by to super obvod. Je až s podivem, co se do tak malého obvodu dá narvat. Je to silný stroj a dobre se s ním pracuje. Odpory a kondenzátory jsou standard a nepotrebují komentovat, krome vyhlazovacího kondíku za Graetzom, který musí mít kapacitu aspon 330nF. Nedoporucuji tantal nebo elektrolyt, nejlepší je keramika. Odpory jsou 0.4W, krome výstupu na motorek, kde jsou 0.6W.
Relé je 5V obycejné (180 O), nedoporucuji bistabilní, protože potom není možné udržet soulad mezi príkazem a realitou. Pridávám do série odpor 12 - 33O z duvodu ochrany a zmenšení odberu. Treba odzkoušet, kdy relé ješte spolehlive spíná.
Plošný spoj je navrhnutý systémem delících car, protože je odolnejší na pájení a je urcen na vyšší proudy.
Pridal jsem i kresbu v systému spojovacích car, ale tu moc nedoporucuji.

 


Tyto obrázky jsou pouze informativní a nejsou vhodné na kopírování. Pokud si to nekdo bude chtít postavit, pošlu mu návrhy prímo v EAGLE programu, nebo samotný plošný spoj.
Ty dvojtecky jsou urceny na pripájení prívodních drátu, kdy se zakroutí drát do ocka a vývody se zasunou do dírek a pripájejí. Má to dve výhody, nenicí se plošný spoj pri opakovaném pájeni a zároven nemusíte otácet plošný spoj a používat odsávacku. Pásky po bocích jsou urceny na montážní otvory. Konektory pro servo jsou otoceny o 90st. , teda vycnívají do boku.

Skládání a oživování :
Je nutné dukladne zkontrolovat plošný spoj, aby tam nebyly mostíky medi a je celkem vhodné plošný spoj vyleštit do zrcadla. Lépe se s tím potom pracuje a oživuje. Vyvrtají se dírky 0,8mm vrtákem a zacne se osazovat nejnižšími soucástkami. To proto, ze nám nebudou vypadávat pri otocení a pájení. Takže diody, odpory, objímky, Graetz, kondíky a nakonec stabilizátor. Je celkem vhodné použít mikropájku, ale šikovní to dokážou pistolovkou. Kdo není šikovný, tak na to rychle prijde. ;-)
Pred osazením zesilovace a uP durazne doporucuji pripojit DCC a zmerit napájení na stabilizátoru a neuškodí ani pár jiných bodu otestovat, ci tam je to, co tam má být. Já jsem starý profík a nepodcenuji to. I mne se obcas podarí studený spoj nebo zapomenu zaspájkovat vývod.
Pokud jste pracovali peclive, tak obvod pracuje na první zapojení. Jediné, co se muže stát, je opacný chod oproti snímání ADC, takže pokud se servo samo nevypne, je nutné prohodit bud vývody motorku nebo +/- potenciometru a to podle toho, co je snazší.

Cena ovladace komplet se servem :
Tiny85 = 1.7
L2722 = 1.7
Relé = 2.1
78L05 = 1.5
B80 = 1.5
Objímky = 1.5
Servo = 4.0
Dioda 5x = 0.9
Odpory = 0.6
Kondíky = 0,6
Plošák = 2.0
Kablíky = 0,9
------------------------
Cena = 19 Eur bez práce a energií ;-)
Pokud by byl zájem, zkusil bych kompletovat stavebnice soucástek za 20 Eur a poštovné. Pokud uvážíte, že cena treba jen prestavníku Tillig je 15 Eur bez žádné elektroniky, je to na pouvažování. Želva stojí taky 16 Eur bez niceho.

Mechanika :
Problém je mechanické zabudování, ale to musíte rešit tak-nejak všude. Uvažuji o bowdenu a lanku, kde na strane serva stací pripájet bowden a na druhé strane lustr svorka na nejaké podložce. Taky není problém ovládat vyhybku prímo ramenem serva, ovladac je naprosto stabilní a bez príkazu se nepohne. Jinak nápadu na mechanické provedení je spousta. Treba na modely.biz.
http://www.navestidla.cz/news/motoricky-prestavnik/ a další.
Jsem elektronik a nereším mechanické veci, Ale myslím si, že každý trošku schopný modelár si poradí, jak to osadit.



Výrobek predstavuje ovladac na digitální provoz pres DCC s malým odberem a vynikající stabilitou.
Vyrobil jsem asi 6 ruzných verzí, než jsem se dostal na to, co mi vyhovuje a myslím, že to bude dobré.
Nejlepší verze je úplne naspodu a vedle je položená 5-cent mince na porovnání velikosti.

Programové vybavení:
Napsání programu a odvšivení bylo celkem jednoduché, až na použití TIMER1, který je dost jiný, jako u jiných procesoru a tak jsem musel nastudovat datasheet, než jsem to zprovoznil k obrazu svému. ;-)
Dost jsem se obával prevodu ADC, ale hned první nápad se osvedcil a tak to bylo celkem jednoduché. Použití reference AVCC má výhodu v tom, že vubec nezáleží na napájení, protože jakákoli zmena se objevuje všude a tak se výsledek prevodu nemení. Jinak napsané, výsledek prevodu je imunní na kolísání napájení. Taky to má výhodu v tom, že je úplne jedno, jakou hodnotu má potenciometr, zapojený v servu. Teda predpokládám, ze nebudete potenciometr vymenovat a necháte tam puvodní, které mají rozsah od 5k do 22k.

Hodnoty v EEPROM :
0 = nedoporucuje se používat
1 = Adresa LOW – 7 bitu
2 = rychlost pohybu serva 5 - 80
7 = home-made -13
8 = verze -01
9 = adresa HIGH -7 bitu
10= levý doraz serva 20
11= pravý doraz serva 120
12= prepnutí srdcovky, polovicka mezi CV10 a CV11
29= univerzální dekodér na programovací koleji -128

Dávám zdrojový kód, upozornuji, že jakákoli zmena muže být fatální.
Program BascomBasic od http://www.mcselec.com/index.php?option=com_docman&task=cat_view&gid=99&Itemid=54

'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------
'------------------------------------------------------------------------------  
'program na obsluhu modelarskeho serva trochu jinak. Ridici signal je DCC a  
'servo ma jen dve koncove polohy, ktera jsou definovana poteciometrem v servu  
'a hodnotami v EEPROM 'Dalsi podrobnosti jsou uvedeny u kazdeho prikazu.   
'********* platne ***************** 
  $regfile = "attiny25.dat"             'chip = 1E930B
  $crystal = 8000000
  $hwstack = 40
  $swstack = 40
  $framesize = 28 
 'rozmisteni pinu:  
 'portb.0 = prijem DCC, portb.1 = rele, portb.2 = vstup potenciometru  
 'portb.3 = vystup PWM, portb.4 = vystup PWM
  Portb = &B00010
   Ddrb = &B11010 
  Dim Dcc(6) As Byte                    'prijem DCC, az 6-byte paket
  Dim Acc As Byte                       'vseobecne
  Dim Chk As Byte                       'kontrolni soucet pro prijem
  Dim Pream As Byte                     'hodnota preambule
  Dim Longpr As Byte                    'hodnota dlouhe prambule
  Dim Rada As Byte                      'ukazovatko pro cteni DCC
  Dim Druh As Byte                      'druh paketu 3,4,5,6 byte v paketu
  Dim Work As Byte                      'vseobecny
  Dim Bcc As Byte                       'vseobecny
  Dim Ccc As Byte                       'vseobecny
  Dim Adral As Byte                     'buffer pro servo
  Dim Adrah As Byte                     'buffer pro servo
  Dim Aadc As Byte                      'ulozeni hodnoty z ADC
  Dim Respak As Byte                    'pocet reset-paketu 
  Dim Nc As Eram Byte                   'nedoporuceno pouzivat
  Dim Adrl As Eram Byte At 1            'LOW adresa, podle normy NMRA
  Dim Rych As Eram Byte At 2            'rychlost pohybu serva
  Dim Adrh As Eram Byte At 9            'HIGH adresa, podle normy NMRA
  Dim Dor1 As Eram Byte At 11           'levy doraz serva
  Dim Dor2 As Eram Byte At 12           'pravy doraz serva
  Dim Dor3 As Eram Byte At 13           'prepnuti rele, polovice mezi Dor1,2
  Dim Voln As Eram Byte At 14           'volne
  Dim Po15 As Eram Byte At 15           'povoleni zapisu
  Dim Po16 As Eram Byte At 16           'pevna hodnota pro povoleni zapisu
  Dim Knf As Eram Byte At 29            'univerzalni dekoder = 128 
 'prijem DCC pres preruseni PCINT na pinb.0
  On Pcint0 Hrana , Nosave
  Pcmsk = 1
  Enable Pcint0 
 'nastaveni ADC pro cteni polohy pot. v servu pres pinb.2
  Config Adc = Free , Prescaler = 128 , Reference = Avcc
  On Adc Zmerat Nosave
  Set Admux.5
  Set Admux.0
  Set Didr0.3
  Enable Adc
  Start Adc 
 'pocitadlo casu pro DCC, pokud pretece, restart nacitavani DCC
  Config Timer0 = Timer , Prescale = 64
  On Ovf0 Moc Nosave
  Enable Ovf0 
 'ovladani PWM pro motorek serva. 125nS x 65536 = 122Hz je kmitocet PWM
  Config Timer1 = Timer , Prescale = 256
  On Ovf1 Casa Nosave
  On Oc1b Casb Nosave
  Ocr1b = Rych
  Enable Ovf1
  Enable Oc1b 
 'ulozeni dorazu do bafru
  Adral = Adrl
  Adrah = Adrh
  Enable Interrupts 
 'gpior0.0 = priznak hotoveho paketu  
 'gpior0.1 = NC  
 'gpior0.2 = pohyb serva doleva  
 'gpior0.3 = pohyb serva doprava  
 'gpior1.0 = priznak pulbit "0"  
 'gpior1.1 = priznak pulbit "1"    
 '------------------------------------------------------------------------------    
 '------ hlavni program --------------------------------------------------------
 '------------------------------------------------------------------------------
  Do
  'zpracovani paketu DCC
    sbic   gpior0,0
    rcall  prijmi 
  'vypinani pohybu serva je automaticke, dosazenim nastavene krajni polohy
   If Aadc > Dor2 Then
      Reset Gpior0.3
   End If
   If Aadc < Dor1 Then
      Reset Gpior0.2
   End If 
  'prepinani srdcovky a zpetneho hlaseni pres rele, pomoci Dor3,ktere by melo 'byt nastavene na polovicku mezi Dor1 a DOR2.
   If Aadc > Dor3 Then
     Set Portb.1
   Else
     Reset Portb.1
   End If 
  Loop
'------------------------------------------------------------------------------  
'----- podprogramy ------------------------------------------------------------
'------------------------------------------------------------------------------  
'---------------------------------
 Prijmi:
 'nulovani priznaku hotoveho paketu
   Reset Gpior0.0
  'kontrola CHEKSUM pomoci EXOR celeho paketu DCC,   'v DRUH je pocet bajtu v paketu. Paket muze byt 3-6 bajtovy
    Chk = 0
   For Acc = 1 To Druh
     Chk = Chk Xor Dcc(acc)
   Next Acc
   If Chk <> 0 Then Return              'vysledek musi byt 0 
  'pocitani reset paketu, pokud jiny paket, respak = 0
   If Dcc(1) = 0 Then
    If Dcc(2) = 0 Then
      Incr Respak
      Return
    End If
   End If 
 'zpracovani paketu podle jeho delky, ktera je ulozena v promenne DRUH
   Select Case Druh
     Case 3 : Gosub Troj
     Case 4 : Gosub Ctyr
     Case 5 : Gosub Pet
     Case 6 : Gosub Sest
   End Select
   Druh = 0                             'nulovani druhu paketu
   Respak = 0
   Return
 '----------------- 
 'preamble 0 10AAAAAA 0 1AAACDDD 0 EEEEEEEE  1 
 'testovani adresy a porovnani s EEPROM na pozici 1 a 9 
 'testuje se cely bajt i s prednastavenymi bity.
  Troj:
   'kontrola adresy A0-A5
    If Dcc(1) <> Adral Then Return
   'kontrola adresy A6 az A8 + parove rizeni
     Work = Adrah And 254
     Acc = Dcc(2) And 254
    If Work <> Acc Then Return
 '------------------------------ 
 'zapnuti PWM na pohyb vpravo a vlevo. 
 'Je pouzite PWM trosku jinak, nez je zvykem. Zakladni stav je "0" na obou 
 'vystupech pro L272. Cas Oc0b nahazuje prislusny port a Ovf0 ho shazuje. 
 'Proto nemusim prepocitavat hodnotu PWM pro kazdy chod, oba jsou stejne. 
 'Nahazujem / shazujem oba smery,protoze neni zarucene,ze prijde, za chodu, opacny prikaz
     Work = Dcc(2)
     If Work.0 = 0 Then
      Set Gpior0.3
      Reset Gpior0.2
     Else
      Reset Gpior0.3
      Set Gpior0.2
     End If
   Return
 '---------------------------------  
 'Long-preamble 0 0111CCAA 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1  
 'je to bezadresovy prikaz, pokud prijde, musi se vykonat.  
 'Je to na programovaci koleji.   
 '---------------
  Ctyr:
 'musi byt dlouha preambule
  If Longpr < 20 Then Return 
 'musi byt aspon tri reset pakety
  If Respak < 3 Then Return
   Respak = 0 
 'zde se to rozdeli podle bitu CC v prvnim byte
    Acc = Dcc(1) And &B1111_1100        'maska na bity A9,A8
   If Acc = 116 Then Gosub Verify       '0111_0100 = 116
   If Acc = 120 Then Gosub Bitmani      '0111_1000 = 120
   If Acc = 124 Then Gosub Writes       '0111_1100 = 124
  Return
'----------------- 
 'tu se verifikuje jeden byte EEPROM
  Verify:
    Gosub Tiny25
    Readeeprom Work , Acc
    If Work <> Dcc(3) Then Return       'nezhoda, konec 
  'odpovida impulsem >60mA po dobu 6mS
   Odpoved:
    Set Portb.3
    Waitms 6                            'ACK
    Reset Portb.3
  Return
'-----------------
  Writes:
   'zapis do EEPROM
    Gosub Tiny25
    Writeeeprom Dcc(3) , Acc
   Goto Odpoved
 '-----------------
  Bitmani:
 'pouzivam pouze verify bit, zapis jde pres write byte
 'Long-preamble 0 011110AA 0 AAAAAAAA 0 1110dDDD 0 EEEEEEEE 1
   Gosub Tiny25
   Readeeprom Work , Acc                'vytahnuti dat z EEPROM
   Bcc = Dcc(3) And 7                   'poradi bitu v bajtu
   Acc.0 = Work.bcc                     'vycte bit
   Ccc = Dcc(3)
   If Ccc.3 = Acc.0 Then Gosub Odpoved
  Return
 '-----------------------------  
	'Tiny25 ma jen 128 byte EEPROM, pokud pouzijete vyssi typ,treba to zaREMovat
  Tiny25:
   Acc = Dcc(2) And 127
  Return 
'---------------------------- 
'preamble 0 0aaa_aaaa 0 1110CCVV 0 VVVVVVVV 0 DDDDDDDD 0 EEEEEEEE 1 
'10AAAAAA + 1AAACDDD
  Pet:
    Acc = Adrl
    Bcc = Adrh
    Shift Acc , Left , 2
    Acc.0 = Bcc.1
    Acc.1 = Bcc.2
    Reset Acc.7
    If Dcc(1) <> Acc Then Return  
  Return
'---------------------------- 
'pream 0 11aa_aaaa 0 aaaa_aaaa 0 1110CCVV 0 VVVVVVVV 0 DDDDDDDD 0 EEEEEEEE 1
  Sest:
    'neaplikovane
  Return
'------------------------------------------------------------------------------
'------ podprogramy od preruseni ----------------------------------------------
'------------------------------------------------------------------------------  
'zmerilo hodnotu na PINB.2 a prevede na binární cislo a zapise do "Aadc"
 Zmerat:
   push  r20
    in   r20,adch
    sts {aadc},r20
   pop   r20
 reti
'----------------- 
'podle priznaku se nahazuje PWM
Casa:
  sbic  gpior0,2
   sbi  portb,3
  sbic  gpior0,3
   sbi  portb,4
  Return
'----------------- 
'zde se zhazuje PWM.
 Casb:
   cbi  portb,3
   cbi  portb,4
  Return
'----------------- 
'pokud pretece TIMER0, tak je to brutal chyba. Neni asi DCC nebo je analog.
 Moc:
  push    r20
    ldi   r20,0                         'nemeni SREG
    sts  {rada},r20                     'zruseni nacitavani paketu DCC
    sts  {pream},r20
  pop    r20
 reti
'----------------- 
'obsluha prijmu DCC paketu 'nejdelsi prubeh trva 8uS
 Hrana:
   push  r20
   in    r20,sreg
   push  r20
   push  r21
   push  r22
   push  r23
 'vytahneme hodnoty TIMER0 do r20 a nasledne vynulujeme TIMER0
    in   r20,tcnt0
    ldi  r22,0                          'nova hodnota TIMER0
   !out  tcnt0,r22
 'hodnoty z TIMER0 testujeme na "< 40uS < 70uS < 100uS < 3,2mS <"  
 'hodnoty 40uS - 70uS jsou pulbit "1" a hodnoty 100uS - 3,2mS jsou pulbit "0"  
 'hodnota nad 3,2mS je zakazana
    cpi   r20,6                         'test mensi nez 48uS
   brsh   vetsi40                       'vetsi nez 48uS
   !out  tcnt0,r20
  rjmp    konec
   Vetsi40:
    cpi   r20,9                         'test vetsi nez 72uS
   brsh   vetsi70                       'vetsi nez 72uS
   rjmp   puljedna                      'pul bit "1"
   Vetsi70:
    cpi   r20,12                        'test na vetsi nez 96uS
   brsh   pulnula                       'pulbit "0"
   !out  tcnt0,r20
   rjmp   konec                         'mensi nez 96uS, pryc 
 'zde se zpracuji pulbity "0"
   Pulnula:
    sbic  gpior1,0
   rjmp   nula
    cbi   gpior1,1                      'vynulovani protibitu "1"
    sbi   gpior1,0                      'nastaveni na druhy pulbit "0"
 rjmp     konec
 'zde se zpracuji pulbity "1"
   Puljedna:
    sbic  gpior1,1
   rjmp   jedna
    cbi   gpior1,0
    sbi   gpior1,1
 rjmp     konec 
 'zde se prijme "1" a rozdeli na prislusne byte anebo se pricte bit preambule
   Jedna:
    cbi   gpior1,1
    ldi   r22,1                         '"1"pro prenos bitu do bajtu
    lds   r20,{rada}
    cpi   r20,0
   brne   zpracuj 
    lds   r21,{pream}
    inc   r21
    sts  {pream},r21
 rjmp     konec
 'zde se prijme "0" a rozdeli se na byte nebo se zkontroluje prambule a pokud  
 'je delsi nez 10 bitu, tak se zapne nacitavani dalsich byte paketu DC   
 'je to vlastne START bit, pokud nasleduje za preambuli
   Nula:
    cbi   gpior1,0
    ldi   r22,0                         '"0"pro prenos bitu do bajtu
    lds   r20,{rada}
    cpi   r20,0                         'test tvoreni paketu DCC
   brne   zpracuj                       'skok na tvoreni paketu DCC 
    lds   r21,{pream}                   'nacteni preambule
    cpi   r21,10                        'test preambule na vetsi nez 10 "1"
  brlo    spatne1                       'je mene nez 10, chyba
    Sts  {longpr},r21                   'zapis preambule na dalsi pouziti >20
    ldi   r20,1                         'jdeme na tvoreni paketu DCC
    sts  {rada},r20
    clr   r20
    sts  {pream},r20
 rjmp     konec 
 'zde se skladaji jednotlive byte z osmi bitu. Mezi nimi je START bit, ktery  
 'musi byt "0". Pokud neni, je to chyba a cely paket se zahodi.   
 'protoze neexistuje pole bitu, musi se pouzit promenna RADA, ktera presne   
 'urcuje, kam se prijaty bit zaradi.
   Zpracuj:
    inc   r20
    sts  {rada},r20
    cpi   r20,10                        '2 az 9 = 8 bitu v prvnim byte
   brsh   start1
 'zde se zarotuje do byte DCC(1) prijaty bit
    lds   r21,{dcc}                     'nacteni byte DCC z pameti
    lsr   r22                           'vysunuti bit.0 z r22 do Carry
    rol   r21                           'zasunuti Carry do r21.7
    sts  {dcc},r21                      'zapsani DCC do pameti
 rjmp     konec
  Spatne1:
 rjmp spatne 
 'zde se vyhodnoti START bit mezi prvnim a druhym byte, musi byt "0"
   Start1:                              'start bit mezi prvnim a druhym byte
   brne   byte2                         'pokud neni r22="0", neni to START bit
    cpi   r22,0                         'test prijateho bitu na "0"
   brne   spatne1                       'pokud neni "0", restart paketu
 rjmp     konec                         'v poradku, jdeme na dalsi bajt 
   Byte2:
    cpi   r20,19                        '11 az 18 = 8 bitu v druhem bajtu
   brsh   start2
 'zde se zarotuje do byte DCC(2) prijaty bit
    lds   r21,{dcc+1}                   'nacteni byte DCC z pameti
    lsr   r22                           'vysunuti bit.0 z r22 do Carry
    rol   r21                           'zasunuti Carry do r21.0
    sts  {dcc+1},r21                    'zapsani DCC do pameti
 rjmp     konec 
 'zde se vyhodnoti START bit mezi druhym a tretim byte, musi byt "0"
   Start2:
   brne   byte3
    cpi   r22,0                         'test prijateho bitu na "0"
   brne   spatne                        'pokud neni "0", restart paketu
 rjmp     konec                         'v poradku, jdeme na dalsi bajt
   Byte3:
    cpi   r20,28                        '20 az 27 = 8 bitu v tretim bajtu
   brsh   start3 
 'zde se zarotuje do byte DCC(3) prijaty bit
    lds   r21,{dcc+2}                   'nacteni byte DCC z pameti
    lsr   r22                           'vysunuti bit.0 z r22 do Carry
    Rol   r21                           'zasunuti Carry do r21.0
    sts  {dcc+2},r21                    'zapsani DCC do pameti
 rjmp     konec 
 'tady je to slozitejsi, prijaty bit "1" znamena konec trojpaketu a pokud je "0"  
 'tak se pokracuje na dalsi byte
   Start3:
   brne   byte4
    ldi   r23,3                         'trojpaket
    cpi   r22,1                         'test na START nebo STOP bit
   breq   dobre                         'test konce paketu
 rjmp     konec                         'neni to konec, jedeme na dalsi byte
   Byte4:
    cpi   r20,37                        '28 az 36 = 8 bitu v ctvrtem bajtu
   brsh   start4 
 'zde se zarotuje do byte DCC(4) prijaty bit
    lds   r21,{dcc+3}                   'nacteni byte DCC z pameti
    lsr   r22                           'vysunuti bit.0 z r22 do Carry
    Rol   r21                           'zasunuti Carry do r21.0
    sts  {dcc+3},r21                    'zapsani DCC do pameti
 rjmp     konec 
 'tady je to slozitejsi,prijaty bit "1" znamena konec ctvorpaketu a pokud je "0"  
 'tak se pokracuje na dalsi byte
   Start4:
   brne   byte5
    ldi   r23,4                         'ctvorpaket
    cpi   r22,1                         'test na START nebo STOP bit
   breq   dobre                         'test konce paketu
 rjmp     konec                         'neni to konec, jedeme na dalsi byte 
   Byte5:
    cpi   r20,46                        '37 az 45 = 8 bitu v patem bajtu
   brsh   start5
 'zde se zarotuje do byte DCC(5) prijaty bit
    lds   r21,{dcc+4}                   'nacteni byte DCC z pameti
    lsr   r22                           'vysunuti bit.0 z r22 do Carry
    Rol   r21                           'zasunuti Carry do r21.0
    sts  {dcc+4},r21                    'zapsani DCC do pameti
 rjmp     konec 
 'tady je to slozitejsi,prijaty bit "1" znamena konec petpaketu
   Start5:
   brne   byte6
    ldi   r23,5                         'petipaket
    cpi   r22,1                         'test na START nebo STOP bit
   breq   dobre                         'test konce paketu
 rjmp     konec 
   Byte6:
    cpi   r20,55
   brsh   start6
 'zde se zarotuje do byte DCC(6) prijaty bit
    lds   r21,{dcc+5}                   'nacteni byte DCC z pameti
    lsr   r22                           'vysunuti bit.0 z r22 do Carry
    rol   r21                           'zasunuti Carry do r21.0
    sts  {dcc+5},r21                    'zapsani DCC do pameti
 rjmp     konec 
   Start6:
    ldi   r23,6
  Dobre:
    sbi   gpior0,0                      'konec paketu, nastaven priznak
    sts  {druh},r23                     'zapis druhu paketu do DRUH
  Spatne:
    clr   r20
    sts  {rada},r20                     'zruseni nacitavani paketu DCC
    sts  {pream},r20
 Konec:
   pop   r23
   pop   r22
   pop   r21
   pop   r20
  !out   sreg,r20
   pop   r20
 Return
'------------------------------------------------------------------------------
 $eepromhex
 $eeprom
 Data 0
 '    adrl  rych                home  ver   adrh
 Data &H81 , 40 , 0 , 0 , 0 , 0 , 13 , 1 , &HF8 , 0
 '    ld    pd    pr   15  16
 Data 60 , 180 , 120 , 1 , 1 , 0 , 0 , 0 , 0 , 0
 '                                    knf
 Data 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 128 , 0
 $data
[Akt. známka: 0,33 / Počet hlasov: 9] -      + 

K tomuto článku nebol doposiaľ priradený žiadny komentár!

Pridať nový komentár