H0 Modelspoor Forum

Modelbaanbouw voor de liefhebber => Eigen bouwprojecten => Topic gestart door: Theo op 10 februari 2022, 14:12:37

Titel: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 10 februari 2022, 14:12:37
Al hoewel we met het onderwerp in een ander topic bezig waren is het toch handiger om een nieuw topic te starten.
De gedachte was kunnen we met een eigen gemaakt format een DDC code inlezen en hiermee zelf decoders en dergelijke maken.
Dit kan met een Arduino of met een PIC.
Omdat ik wat meer ervaring heb met een PIC zal ik hiermee eerst aan de slag gaan, als het allemaal lukt zal de laatste fase zijn de code ook om te zetten naar een Arduino.
Maar het begint met het inlezen van de code die op de rails staat, hiervoor is wel wat te vinden op internet.
Je komt al snel op de volgende schakeling.
(https://i.postimg.cc/VNZLr7PG/Opto-Coupler.jpg)
Het signaal (een blok wisselspanning) van de rails wordt omgezet in een gelijk spanning die de PIC kan inlezen (een blok gelijkspanning).
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Bert op 10 februari 2022, 19:10:28
Fijn initiatief! Heb niet de kennis wat bij te dragen, volg het wel graag
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 10 februari 2022, 20:27:35
Als je op verschillende site kijkt, hebben ze het allemaal over blokken die van hoog naar laag gaan (en omgekeerd) als er data wordt doorgegeven,
Wat ik er niet uit kan halen hoe het signaal is als er geen code wordt doorgegeven, is er dan rust?
Misschien weten digitale rijders dit??

Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Jan Trein op 11 februari 2022, 00:34:56
Ik heb het gevoel dat jouw vraag beantwoord wordt op  Strekdambaan DCC-protocollen (https://strekdambaan.nl/Strekdambaan-overzicht/DCC-protocollen/)

Citaat
Since most devices are paired, the convention is that bit "0" of the second byte is used
to distinguish between which of a pair of outputs the accessory decoder is activating or deactivating.

Ik maak eruit op dat er nooit "rust" is (permanente polling) maar dat bepaalde bits "0" of "1" zijn.

Maar misschien bedoel je iets heel anders ...
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 11 februari 2022, 11:06:46
Ik vroeg me af als er tijdens rust ook nog verandering van polariteit was?

Ik ga maar met deze DCC protocol beginnen.
(https://i.postimg.cc/rpJtkH9z/38bits-DCC.jpg)
Het bestaat uit 38 bits op de rails.
Nadat dit signaal de optocoupler is gepasseerd krijg je een gelijkspannings bloksignaal.
De eerste 10 bits zijn allemaal "1", hiermee wordt aangegeven dat er een signaal opkomst is.
Dan komt er een "0" als scheiding, bit 11.
Daarna de 8 bits die het adres aangeven.
Weer een ''0'" als scheiding, bit 20
Dan weer 8 bits die de opdracht doorgeven.
Weer een "0" als scheiding, bit 29
Dan volgen weer 8 bits ter controle of alles goed is aangekomen.
Als laatste de afsluit bit een "1", bit 38
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 12 februari 2022, 15:32:02
Tussen 2 signalen zit minimaal 5 ms rust en in de ruststand blijft de spanning constant.
(https://i.postimg.cc/5yjC3G2Y/Totaalsignaal.jpg)
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 13 februari 2022, 15:32:49
Om een goed werkende PIC te krijgen moet je hem eerst kunnen uittesten.
Daarvoor heb ik de volgende opstelling ontworpen, twee PIC's, een die een bekend (zelf gemaakt) DCC signaal uitzendt en de andere PIC die het signaal inleest. Dit gaat over het draadje "SLijn".
(https://i.postimg.cc/jSZ6W4DL/Testopstelling.jpg)
Met de generator wordt het adres 187 gemaakt en de instructie 191 (taak genoemd).
De generator stuurt het volgende uit:
1111111111 0 10111011 0 10111111 0 00000000 1
start               adres           instructie         

In de generator PIC zit de volgende code:


Include 16f628a

pragma target clock 20_000_000              -- oscillator frequency
pragma target OSC      HS                        -- crystal or resonator
pragma target WDT      DISABLED             -- watchdog
pragma target BROWNOUT DISABLED        -- no brownout reset
pragma target LVP      DISABLED               -- no low voltage programming
pragma target MCLR     EXTERNAL             -- external reset
pragma target fuses    0x3D02
const Serial_HW_Baudrate  = 19200
include serial_hardware

Include Delay

enable_digital_io()                              -- make all pins digital I/O

alias Slijn is pin_A1            pin_A1_direction = OUTPUT
alias StartKnop is pin_A2    pin_A2_direction = INPUT

Procedure Maak (byte in a) is
Slijn = High
If a==1 then Delay_10us(5) else Delay_10us(10) end if
Slijn = Low
If a==1 then Delay_10us(5) else Delay_10us(10) end if
End procedure




forever loop
Slijn = Low

While StartKnop==Low loop   end loop     -- Wacht totdat de startknop wordt ingedrukt

Delay_1s(1)                                           -- Nog even een seconde wachten en dan beginnen

            -- Preamble 10 keer een '1' dus 1111111111
Maak(1) Maak(1) Maak(1) Maak(1) Maak(1) Maak(1) Maak(1) Maak(1) Maak(1) Maak(1)
Maak(0)

             -- Adres 8 bits, hier bv 10111011 =>  128 + 0 + 32 + 16 + 8 + 0  + 2 + 1 = 187
Maak(1) Maak(0) Maak(1) Maak(1) Maak(1) Maak(0) Maak(1) Maak(1)
Maak(0)

              -- instructie 8 bits hier bv 10111111  ==> 128 + 0 + 32 + 16 + 8 + 4 + 2 +1 =  191
Maak(1) Maak(0) Maak(1) Maak(1) Maak(1) Maak(1) Maak(1) Maak(1)
Maak(0)

               --  error controle  8 bits hier bv 00000000
Maak(0) Maak(0) Maak(0) Maak(0) Maak(0) Maak(0) Maak(0) Maak(0)
Maak(1)

   
end loop


Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 14 februari 2022, 21:57:46
Ben ook nog even aan het stoeien geweest met de Arduino code voor de generator.
Op de Arduino Nano zit al een LED op pin 13, dus deze kan je gelijk gebruiken.
Het is mijn eerste Arduino programma of sketch.



int Slijn = 13;

void setup()
{ pinMode(Slijn, OUTPUT); }


int Maak(int tel)
{ if (tel=1)
  {digitalWrite(Slijn, HIGH);  delayMicroseconds(50);   digitalWrite(Slijn, LOW);   delayMicroseconds(50);}
   else 
  {digitalWrite(Slijn, HIGH);  delayMicroseconds(100);  digitalWrite(Slijn, LOW);   delayMicroseconds(100);}
}


void loop()
{ digitalWrite(Slijn, LOW); delay(1000);  // Nog even een seconde wachten en dan beginnen

  // Preamble 10 keer een '1' dus 1111111111
  Maak(1); Maak(1); Maak(1); Maak(1); Maak(1); Maak(1); Maak(1); Maak(1); Maak(1); Maak(1);
  Maak(0);

  // Adres 8 bits, hier bv 10111011 =>  128 + 0 + 32 + 16 + 8 + 0 + 2 + 1 = 187
  Maak(1); Maak(0); Maak(1); Maak(1); Maak(1); Maak(0); Maak(1); Maak(1);
  Maak(0);

  // Instructie 8 bits hier bv 10111111  ==> 128 + 0 + 32 + 16 + 8 + 4 + 2 +1 =  191
  Maak(1); Maak(0); Maak(1); Maak(1); Maak(1); Maak(1); Maak(1); Maak(1);
  Maak(0);

  // Error controle  8 bits hier bv 00000000
  Maak(0); Maak(0); Maak(0); Maak(0); Maak(0); Maak(0); Maak(0); Maak(0);
  Maak(1);
 
  delay(10000); // wacht 10 seconde
}

Morgen ga ik de proefopstelling maken.
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 15 februari 2022, 11:17:47
De testopstelling.
(https://i.postimg.cc/W3ZvzpS4/IMG-5338.jpg)

Met de groene LED geeft weer of het adres en de taak juist zijn binnen gekomen en zijn herkent.
De 16F628a PIC heeft in de B-bank 8 pinnen vrij, je kan er dus 8 relais er mee aansturen.

(https://i.postimg.cc/zGDpGdpb/relaisblok.jpg)
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 16 februari 2022, 11:43:47
De code voor de PIC 16F628a (geschreven in JALEdit):

Include 16f628a

pragma target clock 20_000_000                   -- oscillator frequency
pragma target OSC      HS                             -- crystal or resonator
pragma target WDT      DISABLED                  -- watchdog
pragma target BROWNOUT DISABLED             -- no brownout reset
pragma target LVP      DISABLED                    -- no low voltage programming
pragma target MCLR     EXTERNAL                  -- external reset

pragma target fuses    0x3D02
const Serial_HW_Baudrate  = 19200
include serial_hardware

Include Delay

enable_digital_io()                                                         -- make all pins digital I/O

alias Slijn is pin_A2        pin_A2_direction = INPUT           -- pin A2 instellen
alias LED   is pin_B4       pin_B4_direction = OUTPUT        -- pin B4 instellen

var byte N, Tijd, S, Adres, Taak, Fout

N=0  Tijd=0   LED=low

forever loop
Tijd=0
While Slijn==low  loop end loop                              -- wacht op het volgende signaal
While Slijn==high loop Tijd=Tijd+1 Delay_10us(1) end loop    -- het signaal is er, nu de tijd opmeten

  If Tijd>7 & Tijd<14 then S=0  end if                       -- het is een 0
  If Tijd>2 & Tijd<8  then S=1  end if                        -- het is een 1
 
  If Tijd>15 then N=0 end if                                     -- dit signaal kan niet

If N==37 then    -- taak uitvoeren als het adres en de taak juist zijn.
         N=0
         If 187==Adres then LED=High Delay_1S(1) LED=Low  Delay_1S(1) end if
         If 191==Taak  then LED=High Delay_1S(2) LED=Low   Delay_1S(1) end if
         end if

If N==36 then Fout=Fout+1*S   N=N+1 end if
If N==35 then Fout=Fout+2*S   N=N+1 end if
If N==34 then Fout=Fout+4*S   N=N+1 end if
If N==33 then Fout=Fout+8*S   N=N+1 end if
If N==32 then Fout=Fout+16*S  N=N+1 end if
If N==31 then Fout=Fout+32*S  N=N+1 end if
If N==30 then Fout=Fout+64*S  N=N+1 end if
If N==29 then Fout=Fout+128*S N=N+1 end if

If N==28 & S==0 then N=N+1  Fout=0  end if

If N==27 then Taak=Taak+1*S   N=N+1 end if
If N==26 then Taak=Taak+2*S   N=N+1 end if
If N==25 then Taak=Taak+4*S   N=N+1 end if
If N==24 then Taak=Taak+8*S   N=N+1 end if
If N==23 then Taak=Taak+16*S  N=N+1 end if
If N==22 then Taak=Taak+32*S  N=N+1 end if
If N==21 then Taak=Taak+64*S  N=N+1 end if
If N==20 then Taak=Taak+128*S N=N+1 end if

If N==19 & S==0 then N=N+1 Taak=0  end if

If N==18 then Adres=Adres+1*S   N=N+1 end if
If N==17 then Adres=Adres+2*S   N=N+1 end if
If N==16 then Adres=Adres+4*S   N=N+1 end if
If N==15 then Adres=Adres+8*S   N=N+1 end if
If N==14 then Adres=Adres+16*S  N=N+1 end if
If N==13 then Adres=Adres+32*S  N=N+1 end if
If N==12 then Adres=Adres+64*S  N=N+1 end if
If N==11 then Adres=Adres+128*S N=N+1 end if

If N==10 & S==0 then N=N+1 Adres=0  end if

If N<10 & S==0 then  N=0    end if
If N<10 & S==1 then  N=N+1  end if

end loop

Nu nog aan het stoeien om deze code ook te schrijven voor de Arduino.
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 17 februari 2022, 09:47:42
En de Arduino op de testbank.
(https://i.postimg.cc/Yqn8gHgg/Arduino-Test.jpg)

Maar helaas bleek de Arduino wat minder nauwkeurig te werken, 60 % van de metingen werd goed gelezen en afgehandeld.
Bij 40% miste de Arduino een bit zodat op het adres of de taak niet goed werd gelezen.
De PIC 16F618a werkte 100%, daar heb ik geen enkele fout gemeten.
Misschien is er nog wat aan te passen aan de leestijden bij de Arduino?

De code in de Arduino is zowat hetzelfde als die van de PIC.

int ledPin = 13;  // LED connected to digital pin 13
int InPin7 = 7;   // connected to digital pin 7

int N = 0;
int S = 0;
int Tijd  = 0;
int Adres = 0;
int Fout  = 0;
int Taak  = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin 13 as output
  pinMode(InPin7, INPUT);       // sets the digital pin 7 as input
}

void loop()
{
Tijd=0;
while(digitalRead(InPin7)==LOW)  {}                                         // wachten op hoog signaal
while(digitalRead(InPin7)==HIGH) {Tijd=Tijd+1; delayMicroseconds(10);}      // er is een hoog signaal, nu de tijd meten

    if (Tijd>7 & Tijd<14) {S=0;}                                    // dit moet een 0 zijn
    if (Tijd>2 & Tijd <8)  {S=1;}                                    // dit moet een 1 zijn  De smile moet 8 zijn!!!!!!!!

if (N==37) {N=0;            // Als het adres en/of de taak klopt, doe dan ...........
            if (187==Adres) {digitalWrite(ledPin,HIGH); delay(1000); digitalWrite(ledPin,LOW); delay(1000);}
            if (191==Taak)  {digitalWrite(ledPin,HIGH); delay(2000); digitalWrite(ledPin,LOW); delay(1000);}
           }

if (N==36) {Fout=Fout+1*S;   N=N+1;}
if (N==35) {Fout=Fout+2*S;   N=N+1;}
if (N==34) {Fout=Fout+4*S;   N=N+1;}
if (N==33) {Fout=Fout+8*S;   N=N+1;}
if (N==32) {Fout=Fout+16*S;  N=N+1;}
if (N==31) {Fout=Fout+32*S;  N=N+1;}
if (N==30) {Fout=Fout+64*S;  N=N+1;}
if (N==29) {Fout=Fout+128*S; N=N+1;}

if (N==28 & S==0) {Fout=0; N=N+1;}

if (N==27) {Taak=Taak+1*S;   N=N+1;}
if (N==26) {Taak=Taak+2*S;   N=N+1;}
if (N==25) {Taak=Taak+4*S;   N=N+1;}
if (N==24) {Taak=Taak+8*S;   N=N+1;}
if (N==23) {Taak=Taak+16*S;  N=N+1;}
if (N==22) {Taak=Taak+32*S;  N=N+1;}
if (N==21) {Taak=Taak+64*S;  N=N+1;}
if (N==20) {Taak=Taak+128*S; N=N+1;}

if (N==19 & S==0) {Taak=0; N=N+1;}

if (N==18) {Adres=Adres+1*S;    N=N+1;}
if (N==17) {Adres=Adres+2*S;    N=N+1;}
if (N==16) {Adres=Adres+4*S;    N=N+1;}
if (N==15) {Adres=Adres+8*S;    N=N+1;}
if (N==14) {Adres=Adres+16*S;   N=N+1;}
if (N==13) {Adres=Adres+32*S;   N=N+1;}
if (N==12) {Adres=Adres+64*S;   N=N+1;}
if (N==11) {Adres=Adres+128*S;  N=N+1;}

if (N==10 & S==0) {N=N+1; Adres=0;}

if (N<10 & S==0) {N=0;}
if (N<10 & S==1) {N=N+1;} 
}

Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 18 februari 2022, 16:20:41
Ik heb de inleestijden bij de Arduino wat minder gevoelig gezet, nu werkt hij wel.

int ledPin = 13;  // LED connected to digital pin 13
int InPin7 = 7;   // connected to digital pin 7

int N = 0;
int S = 0;
int Tijd  = 0;
int Adres = 0;
int Fout  = 0;
int Taak  = 0;

void setup()
{
  pinMode(ledPin, OUTPUT);      // sets the digital pin 13 as output
  pinMode(InPin7, INPUT);       // sets the digital pin 7 as input
}

void loop()
{
Tijd=0;
while(digitalRead(InPin7)==LOW)  {}                                         // wachten op hoog signaal
while(digitalRead(InPin7)==HIGH) {Tijd=Tijd+1; delayMicroseconds(10);}      // er is een hoog signaal, nu de tijd meten
    S=0;
    if (Tijd<7) {S=1;}

if (N==37) {N=0;            // Als het adres en/of de taak klopt, doe dan ...........
            if (187==Adres) {digitalWrite(ledPin,HIGH); delay(1000); digitalWrite(ledPin,LOW); delay(1000);}
            if (191==Taak)  {digitalWrite(ledPin,HIGH); delay(2000); digitalWrite(ledPin,LOW); delay(1000);}
           }

if (N==36) {Fout=Fout+1*S;   N=N+1;}
if (N==35) {Fout=Fout+2*S;   N=N+1;}
if (N==34) {Fout=Fout+4*S;   N=N+1;}
if (N==33) {Fout=Fout+8*S;   N=N+1;}
if (N==32) {Fout=Fout+16*S;  N=N+1;}
if (N==31) {Fout=Fout+32*S;  N=N+1;}
if (N==30) {Fout=Fout+64*S;  N=N+1;}
if (N==29) {Fout=Fout+128*S; N=N+1;}

if (N==28 & S==0) {Fout=0; N=N+1;}

if (N==27) {Taak=Taak+1*S;   N=N+1;}
if (N==26) {Taak=Taak+2*S;   N=N+1;}
if (N==25) {Taak=Taak+4*S;   N=N+1;}
if (N==24) {Taak=Taak+8*S;   N=N+1;}
if (N==23) {Taak=Taak+16*S;  N=N+1;}
if (N==22) {Taak=Taak+32*S;  N=N+1;}
if (N==21) {Taak=Taak+64*S;  N=N+1;}
if (N==20) {Taak=Taak+128*S; N=N+1;}

if (N==19 & S==0) {Taak=0; N=N+1;}

if (N==18) {Adres=Adres+1*S;    N=N+1;}
if (N==17) {Adres=Adres+2*S;    N=N+1;}
if (N==16) {Adres=Adres+4*S;    N=N+1;}
if (N==15) {Adres=Adres+8*S;    N=N+1;}
if (N==14) {Adres=Adres+16*S;   N=N+1;}
if (N==13) {Adres=Adres+32*S;   N=N+1;}
if (N==12) {Adres=Adres+64*S;   N=N+1;}
if (N==11) {Adres=Adres+128*S;  N=N+1;}

if (N==10 & S==0) {N=N+1; Adres=0;}

if (N<10 & S==0) {N=0;}
if (N<10 & S==1) {N=N+1;} 
}
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Bert op 18 februari 2022, 17:07:59
Mooie stappen maak je!
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 20 februari 2022, 21:00:12
Gewoon een beetje stoeien met DCC en de Arduino.
Wat ook nog kan, is je DCC zichtbaar maken met de Arduino, in de Arduino zit een plotterfunctie die je kan gebruiken als oscilloscoop.
(https://i.postimg.cc/fRmyG9Tc/plotter.jpg)

Het voordeel bij een Arduino is dat je de oscilloscoop kan starten en stoppen op jouw gewenst moment, de scan-tijd kan instellen enz.
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Jan Trein op 7 maart 2022, 19:04:45
De eerste 10 bits zijn allemaal "1", hiermee wordt aangegeven dat er een signaal opkomst is.
Dan komt er een "0" als scheiding, bit 11.
Daarna de 8 bits die het adres aangeven.
Weer een ''0'" als scheiding, bit 20
Dan weer 8 bits die de opdracht doorgeven.
Weer een "0" als scheiding, bit 29
Dan volgen weer 8 bits ter controle of alles goed is aangekomen.
Als laatste de afsluit bit een "1", bit 38
In C: je hebt een struct van 38 bits ...
Vreemd, je zou 32 of 40 of 48 bits verwachten.
Of komt er misschien nog iets achteraan?
Titel: Re: DDC protocol inlezen met PIC of Arduino
Bericht door: Theo op 8 maart 2022, 20:43:33
Nee, in z'n reeks heb je niet altijd een reeks van opbouw. Alleen de data waar het omgaat is vaak 8 bits.
Tussen deze databits zit meestal wel een scheidings bit.
Het is maar net hoe ze het protocol hebben gemaakt.
Zo moet het startsignaal minimaal 10 keer als een "1" zijn.

Het ging er bij ook vooral om om te kijken of z'n signaal was te onderscheppen met een Arduino of met een PIC.