web counter
hit counter

Analoge servosturing

Digitale servosturing

Beladen kolenwagons

Digitale servosturing via Marklin Motorola protocol

Wissels aansturen met een MS1

S88 Terugmelders

Contact:
Geert.Giebens(at)gmail.com

Microcontroller gestuurde servo sturing met behulp van schakelaars of DCC protocol, en instelbaar via één regelbare weerstand, en dit voor 16 analoge servo’s.
 

Versie met schakelaars:

  
Principe werking
    Instelling bereik per servo
    Instelling omlooptijd

  
Wat zit er nog in wat niet besproken is
    De tijdsschaal van de potmeter
    ASM code
    Filmke
    Printschema

Versie waarbij schakelaars vervangen worden door DCC protocol (zie achteraan)

    Doel
    Werking ASM program
    Opbouw DCC signaal om wissels/seinen aan te sturen
    Decodering DCC data packet door microcontroller program
    ASM Code

  

Microcontroller gestuurde servo sturing met behulp van schakelaars, en instelbaar via één regelbare
weerstand, en dit voor 16 analoge servo’s.


Deze versie van microcontroller gestuurde servo sturing is ontstaan op vraag van mijn petekind om de wissels van zijn lego trein met schakelaar om te zetten en het liefst op afstand . Omdat dat manneke nog geen verstand heeft van digitale signalen en/of sturingen, wilde ik wel een schakeling maken om servo’s aan te sturen zonder hulp van een PC, digitale centrale of wat dan ook. Ik heb bij deze versie er ook voor gezorgd dat de omlooptijd (de tijd tussen beide uiterste servo standen) instelbaar is zodat hij ook overweg slagbomen en loods poorten langzaam kan openen of sluiten.Vermits er ook servo’s bestaan die regelbaar zijn met referentiepulsen tussen 0,5ms en 2,5ms, heb ik deze mogelijkheid er ook maar als standaard in geprogrammeerd.

Principe werking:

-Via een schakelcontact kan je de servo omzetten. Schakelaar toe, dan gaat de servo naar links. Schakelaar open, dan gaat de servo naar rechts. (kan natuurlijk ook andersom als je de servo omdraait en ook afhankelijk van type en merk servo, dus eerst even testen maar…) Als de servo zijn positie heeft bereikt dan stoppen ook de pulsen naar de servo. Het is ook mogelijk tegelijkertijd meerdere servo’s om te zetten. In principe zelfs alle 16, maar dit is af te raden, of je moet een flinke (lees krachtige) 5V voeding hebben.



Instelling bereik per servo:

-De truc die ik hiervoor gebruik werkt als volgt. Zet alle 16 schakelaars open. Er zijn twee plaatsen voorzien waar je een brugje kan opsteken. Zet op één van die plaatsen een brugje bijvoorbeeld over S1 linkse stand servo (zie schema). Nu kan je een servo selecteren met één van de 16 schakelaars. Met een potmeter (regelbare weerstand) kan je de linkse positie van deze servo inregelen. Dit gaat ogenblikkelijk, de waarde van de potmeter heeft direct invloed op de uitsturing van die servo. Je kan eventueel een schaal op de potmeter aanbrengen tussen 0ms en 2,5ms. (alles onder de 0,5ms wordt wel afgekapt) Ben je tevreden met de ingestelde waarde, dan open je terug de schakelaar van deze servo. Op het moment dat je de schakelaar opent wordt de linkse positie van de servo opgeslagen in de EEPROM van de microcontroller.

Met S2 kan je nu op dezelfde wijze de rechtste stand inregelen en dit met dezelfde potmeter. Het regelen van een gewenste stand kan enkel maar als één van de bruggen (S1 of S2) gesloten is. Zo niet, dan werkt de sturing zoals beschreven bij principe werking.

Elke servo kan nu apart op de hiervoor besproken wijze ingeregeld worden. Omdat de waarde opgeslagen wordt in EEPROM, zal ook na spanningsonderbreking de servo de door jou ingeregeld posities behouden.



Instelling omlooptijd:

-Sluit je nu elk brugje S1 en S2 te samen, dan kan je de omlooptijd instellen met de potmeter. Dit weer op dezelfde wijze. Je selecteert via een schakelaar een servo en je stelt de omlooptijd in met weeral diezelfde potmeter. Op het moment dat je de schakelaar opent zal de omlooptijd opgeslagen worden in EEPROM. Er is wel een verschil met het inregelen van de linkse en rechtse stand. Bij het inregelen van de omlooptijd doet de servo niets. Je kan pas het effect nagaan als al de brugjes zijn verwijdert en je de servo normaal bediend. Om het toch iets overzichtelijk te houden, kan je de potmeter ook voorzien van een tijdsschaal tussen 4 en 132 seconden. Hoe dat zit met die tijdschaal, komt later…



 

Wat zit er nog in wat niet besproken is:

Bij eerste gebruik microcontroller is de waarde in de EEPROM bij gesloten stand schakelaar 1,5ms, de middenstand dus. Als je dus even de schakelaar open en terug dicht doet, staat de servo in de middenstand. Dit kan handig zijn om de servo-arm te bevestigen.
 


De tijdsschaal van de potmeter:

Eén en dezelfde potmeter wordt gebruikt voor zowel het instellen van de uiterste servostanden als voor de omlooptijd. Voor het instellen van de uiterste standen heeft de potmeter de volgende schaal: bij 0 Ohm (0%)=0,0ms bij 10kOhm (100%)= 2,54ms. Nu alles onder 0,50ms en boven 2,50ms wordt softwarematig begrenst. Dus de eerste 20% van de potmeter geeft altijd pulsen van 0,5ms. Je moet wel opletten indien je servo’s gebruikt die werken tussen referentiepulsen tussen 1,00ms en 2,00ms. Regel je buiten deze tijdsschaal dan kan de servo eventueel raar beginnen te doen.

De tijdsschaal van de omlooptijd gaat van 4s (0%) tot 132s (100%), MAAR dit geld enkel maar voor servo’s die ingesteld zijn met referentiepulsen tussen de twee uiterste tijden, nl. 0,50ms en 2,50ms. Heb je bv. servo’s die werken tussen 1,00ms en 2,00ms dan is de schaal nog maar de helft, nl. regelbaar tussen 2s en 66s.

ASM code:   Hier te vinden
 

Filmke:  Hier

Op het filmke zie verschillende instellingen van 8 servo's. Zowel in uiterste standen als in omlooptijd. De laatste servo's bewegen wel degelijk, maar doen er 128s over om uit te wijken.

 

Printschema: (bovenzijde)

 

 

Versie waarbij schakelaars vervangen worden door DCC protocol:

Doel:

Via DCC protocol 16 servo’s aan te sturen voor o.a. wissel aandrijving. Het program is een aanpassing van een servo stuurprogram waarbij de servo omgezet kan worden door de positie van een schakelaar te verzetten. De schakelaar is hierbij vervangen door DCC protocol aansturing. Het DCC signaal zal een Flip Flop omzetten die de schakelaar vervangt. Omdat nu 16 schakelaar ingangen vrij komen op de µC zijn deze beschikbaar voor andere toepassingen. Ik heb er voor gekozen deze als uitgang  beschikbaar te maken met een on/off functie, ook aangestuurd door het DCC protocol. Ik heb deze relais uitgang genoemd. Totaal zitten we nu al aan 16 servo’s en 16 relais = 32 uitgangen. Elk DCC adres kan 4 servo’s of 4 relais aansturen. Dit komt er op neer dat we 8 DCC adressen nodig hebben om alles aan te sturen. Nu één van de problemen die 2 railers kunnen hebben is puntstuk polarisatie. De relais uitgang kan hiervoor gebruikt worden. Een relais met een wisselcontact is het best hiervoor geschikt. Het handige van dit program is dat je hetzelfde DCC adres kan gebruiken voor servo aansturing als voor relais aansturing. Als je een servo omzet via een DCC adres, dan kan je een daarbij behorende relais via hetzelfde DCC adres gelijktijdig mee omzetten. Maar het staat vrij het DCC adres zelf te kiezen voor elke functie. Voorlopig moeten de DCC adressen in het ASM programma zelf ingevoerd worden voordat deze omgezet wordt in HEX code die de µC begrijpt. In een later stadium kan het zijn dat deze programmeerbaar worden via CV adressering. We zien wel later… 

De instelling MIN-MAX bereik servo en omlooptijd is dezelfde als deze bediend door schakelaars. (zie hiervoor) Enkel moet je er nu voor zorgen dat alle servo’s in de MIN puls stand staan en je een servo kiest voor instelling door deze naar MAX puls te selecteren. De relais uitgangen spelen bij deze instellingen hier geen rol en mogen blijven staan in hun huidige stand.

 

Werking ASM program:

We halen hier een blokschema bij om het programma verloop te volgen. Maar om dit in enkel eenvoudige stappen uit te leggen, is dit niet. Ik zal eerst elk blokje verklaren wat het doet.

INIT: bij opstart µC moeten eerste wat instellingen gebeuren. Daarna gaat het programma over in een oneindige MAIN lus.

MAIN: Hoofdlus die sequentieel diverse taken uitvoert. MAIN lus zal elke 20ms een lus doorlopen. Die 20ms komt overeen met de frequentie waarbij de servo’s (bij omzetting) referentiepulsen ontvangen, 20ms = 50Hz.  Het MAIN program zal subroutine ADC oproepen, 16 keer MACRO SERVO en 16 keer MACRO REALAIS. Is de 20ms nog niet voorbij (het overgrote deel van de tijd) dan zal MAIN program subroutine LOOP PULS oproepen. Hier wordt het DCC signaal gedecodeerd.

ADC: opgeroepen door MAIN: elke 20ms wordt de spanning  van een externe potmeter (0-5V) omgezet naar een binaire waarde. Deze waarde wordt gebruikt voor instelling MIN; MAX -bereik en omlooptijd servo in MACRO SERVO.

SERVO : is een macro die per servo uitgang nagaat of de servo omgezet moet worden. De communicatie tussen het gedecodeerde DCC  protocol en het SERVO program gebeurd door een Flip-Flop bit nl. FF1-16 . Moet de servo omgezet worden, dan zal de servo macro pulsen beginnen uit te sturen. Tijdens  zulke puls zal SERVO program ook  subroutine LOOP PULS oproepen, tot de puls voorbij is.

RELAIS: is een macro die de een Relais uitgang aanstuurt afhankelijk van input via FFR1-16 bit gezet door DCC protocol.

LOOP PULS: is een subroutine opgeroepen door macro SERVO of MAIN program en gaat na of er een DCC data pakket klaar staat voor decodering. Zo ja, dan zal deze, als het adres met één van de 8 overeenkomt, een FF bit omzetten voor communicatie tussen macro SERVO of RELAIS.

DECDCCWD: LOOP PULS subroutine gebruikt ook een macro program DECDCCWD om een deel van het data pakket om te zetten naar een nieuwe stand van de Flip-Flop bit.

ISR: Interface Service Routine, dit is het tijd kritische deel van heel het programma. Hier wordt de puls duur van de servo verwerkt en het DCC signaal ingelezen en opgeslagen in 3 bytes. ISR kan op elk moment ogenblikkelijk het programma verloop onderbreken om een taak uit te voeren. Het ISR program wordt opgeroepen door een timer die afloopt of dat er iets aangeboden wordt op DCC IN pin.

  

Opbouw DCC signaal om wissels/seinen aan te sturen:

Electrical Standards NMRA S 9.1 beschrijft hoe een logische ‘1’ en ‘0’ en de tolerantie daarop opgebouwd moet zijn. Praktisch samengevat komt het er neer dat een logische ‘1’ door de centrale wordt doorgestuurd als een  negatieve puls van 58µs gevolgd door een positieve puls van 58µs. Een logische ‘0’ wordt doorgestuurd als een negatieve puls van 100µs of meer gevolgd door een positieve puls van 100µs of meer.  Onthoud dat een logische ‘0’ dubbel zo lang duurt als een logische ‘1’. De bits worden uiteindelijk gebruikt om data packets (=meerde bytes) door te sturen.

Communications Standards  NMRA S 9.2 beschrijft hoe het DCC data packets opgebouwd moet zijn, en in welke volgorde deze verzonden moeten worden.
De ontvanger (decoder) moet eerst weten  of de centrale een DCC data packet door gaat sturen. Dit doet de centrale door eerst 10 of meer preamble ‘1’ bits door te sturen gevolgd door een logische ‘0’ bit. Waarom 10 of meer, alhoewel dit niet echt omschreven staat in de NMRA standards, heeft dit te maken met het feit dat de databits die volgen na de preamblebits nooit meer dan 8 opeenvolgende logische ‘1’ bits kunnen bevatten. Met uitzondering van ‘idle packet’ die er ergens  9 heeft.

Nu de decoder minstens 10 preamblebits heeft geteld gevolgd door een logische ‘0’  ontvangt deze nu 8  adresbits ‘AAAAAAAA’ gevolgd door een logische ‘0’ bit. Hierna ontvangt de decoder 8 databits DDDDDDDD gevolgd door een logische ‘0’ bit. Nu bespreken we hier enkel het Basic Accessory Decoder Packet Format. Bij dit packet volgt nu 8 errorbits EEEEEEEE gevolgd door een logische ‘1’.  Die afsluitende logische ‘1’ geeft aan dat er geen databits meer volgen en de 8 bits ervoor errorbits zijn.

We hebben nu een reeks bits ontvangen van de volgende vorm:

(1111…)1111111111 0 AAAAAAAA 0 DDDDDDDD 0 EEEEEEEE 1

Voor de eenvoud noem ik bits AAAAAAAA het adresbyte; bits DDDDDDDD het databyte en bits EEEEEEEE het errorbyte. De errorbyte wordt gebruikt in een test om na te gaan of er geen overdrachtsfouten zijn geslopen in de ontvangen bytes. De test bestaat er uit dat AAAAAAAA XOR DDDDDDDD XOR EEEEEEEE = 0 (XOR= Exclusieve OR).

NMRA Standaard RP 9.2.1 geeft aan wat de inhoud van de adresbye en databyte  moet zijn. Omdat we ons enkel concentreren op Basic Accessory Decoders, gaan we deze ontleden.

Het adresbyte is als volgt opgebouwd: 10AAAAAA.

Adres AAAAAA kan een waarde hebben tussen ‘000000’ en ‘111111’ of decimaal 0 en 63.

Bit 7 en 6 = ‘10’ geven aan dat dit adres dient voor Accessory Decoders.


Het databyte is als volgt opgebouwd: 1AAACDDD.

Bit 7 is altijd ‘1’.

AAA bits zijn bedoeld voor bijkomende adresbits. Plaats men deze voor de 6 adresbits die we uit de adresbyte halen, dan kunnen we  8*64= 512 adressen instellen. Maar, deze 3 adresbits die we uit de databyte halen worden als 1 complement doorgestuurd. Wat zoveel wil zeggen dat een logische ‘0’ een logische ‘1’ wordt en andersom. Volgens de standaard wordt hier enkel verwezen dat dit zo is ‘By convention’. Volgens mij is dit een handige truc om de 3 bijkomende adresbits, die meestal ‘0’ zijn, sneller door te sturen als je er een logische ‘1’ van maakt, en de decoder deze laat inverteren.

C bit is voor activatie C=’1’ of deactivatie C=’0’ van bijvoorbeeld een wisselspoel;  seinarm enz…. Als er een deactivatietijd in de decoder al ingesteld staat, dan is deactivatie via C=’0’ niet meer nodig. Bij servo aansturing is deactivatie zelfs helemaal niet nodig zoals we verder zullen zien.

DDD bits zijn eigenlijk ook adresbits, maar dan wel voor welke wisselspoel de activatie, deactivatie bedoeld is. Een decoder kan 4 wissels omzetten en elke wissel heeft 2 spoelen. Dit geeft dus 8 spoelen die elk via DDD bits geselecteerd kunnen worden. De twee hoogste bits D2 en D1 selecteren welke van de vier wissels er gekozen moet worden, en D0 zet de wissel linksom of rechtdoor (afhankelijk van de wisselopstelling…). Bij servo’s is dit een gelijkaardige adressering, enkel wordt er via D0 aangegeven of de servo naar MIN pulsen moet gaan of naar MAX pulsen. (zie verder)
 

Decodering DCC data packet door microcontroller program:

De decodering gebeurd op twee fronten. Enerzijds zal het ISR program de DCC bits inlezen en al nagaan of er minstens 10 pramble ‘1’ bits ontvangen zijn voorafgaand de eerste logische ‘0’ bit. Daarna zal het ISR de 8 adresbits inlezen in variabele AAAAAAAA gevolgd door een logische ‘0’. Hierna zal het ISR de 8 databits inlezen in variabele DDDDDDDD gevolgd door een logische ‘0’. Ten slotte zal het ISR de 8 errorbits inlezen in variabele EEEEEEEE gevolgd door een logische ‘1’. Zijn al deze voorwaarden voldaan, dan zal het ISR dit via een flag aangeven dat er een correct DCC data packet is ingelezen. Is er één van deze voorwaarde niet voldaan, dan zal het ISR terug de preablebits beginnen tellen.

Subroutine LOOP PULS die frequent door MAIN en MACRO SERVO opgeroepen wordt, zal als de flag gezet is de data verder decoderen. Is er soms een overdrachtsfout opgetreden, te testen via errorbits, is adresbit 7 en 8 = ‘10’, is Databit 7 =’1’ en is C bit= ‘1’. Zo ja, dan zal deze subroutine nagaan of het adres overeenkomt met één van de 8 mogelijke DCC adressen. Is er een adres dat overeenkomt, dan zal MACRO DECDCCWD opgeroepen worden om de drie DDD bits de decoderen om zo één van de 4 Flip Flops te setten of resetten. Het is via deze Flip-Flops waardoor MACRO SERVO en RELAIS  weet wat deze moet doen.

 

Meer uitleg volgt later. De ASM code zegt voorlopig genoeg. De code kan ten alle tijden aangepast worden....

Code:  ASM-Code