Doel:€250.00
Donaties:€85.00

Per saldo:€-165.00

Steun ons nu!

Laatst bijgewerkt
op 21-04-2020
Algemeen

De stichting

Recente berichten

Autotransporter autoslaaptrein D141 begin jaren ‘60... door Rob E.
Vandaag om 19:49:23
Mijn eerste H0-modeltreinbaan in aanbouw door Wim Vink
Vandaag om 19:44:37
Onlangs gespot - gefotografeerd, de foto's door mass am see
Vandaag om 19:37:07
Havenbaantje, Duitse havenstad, periode 2e wereldoorlog. door MOVisser
Vandaag om 19:22:09
Doornvliet door cor_b
Vandaag om 19:20:15
Mooi weer om buiten te spelen door sncf231e
Vandaag om 19:09:35
Wasbenzine/residu door Overet
Vandaag om 19:07:54
MB-module: "Charleroi Route de Mons" door Hendrik Jan
Vandaag om 18:51:12
Re: BMB 00-modulebaan, Beveiliging door Hendrik Jan
Vandaag om 18:49:31
Waldberg : Revived. door Rondje_HO
Vandaag om 18:42:39
Amsterdam Weesperpoort als nieuw station door Modellbahnwagen
Vandaag om 18:31:21
Separate centrales voor rijden en wissels: hoe terugmelding te regelen? door FHJ Seller
Vandaag om 18:08:12
Hoe groen was de groene E-loc 1000-? door janw
Vandaag om 18:06:53
's-Heer Heinkenspolder door Reinier Z.
Vandaag om 17:56:44
Rheinburgh, TP V/VI door Dave.......
Vandaag om 17:49:43
Ombouw/Pimpen Bolle neuzen door bollen neus
Vandaag om 17:35:45
NL baan: Frotterdam in h0 door schienenbus2012
Vandaag om 17:29:36
Baan in Los Angeles door Eric B
Vandaag om 16:44:23
Intermodellbau 2020 Dortmund 13-16 augustus door RikM
Vandaag om 16:32:37
FCS, bestaat een Automatisch stop systeem? door Reinier Z.
Vandaag om 16:18:34
Class 66 van Märklin/Trix of van ESU? door RikM
Vandaag om 16:07:06
Coöperatie de Eendracht door Harold Content
Vandaag om 16:06:48
NS modelbaan Hoekdam H0 door Ronald1974
Vandaag om 15:44:10
"Union Pacific's Power Shop", een nieuwe baan in H0 door Ronald Halma
Vandaag om 15:33:28
PREFO Tram Bouwpakket Gezocht door ANDREUS
Vandaag om 14:43:12
Rijtuigen op De Meer door R v/d Hoven
Vandaag om 14:28:18
Trafo na laten kijken? door M@rk
Vandaag om 14:25:55
Toon hier je nieuwe (model-) spooraanwinst(en)... door Arjan6511
Vandaag om 14:21:52
Toon hier je pas gereed gekomen (model-)spoorbouwsels ... door Modellbahnwagen
Vandaag om 14:18:15
Kellerstein; een nieuwe baan in H0 door Arjen52
Vandaag om 14:07:42
  

Auteur Topic: Arduino en Selectrix  (gelezen 20085 keer)

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #90 Gepost op: 17 maart 2020, 16:36:25 »
Oh ja even vergeten. Hoe kom ik vanuit een adres bij de positie in het telegram:
Deel adres door 16. Je hebt nu een deeltal en een rest.  6 - deeltal is de positie in telegram
16 - rest * 16 is nummer telegram.

Groet,

Gerard van der Sel
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

bask185

  • Offline Offline
  • Berichten: 543
Re: Arduino en Selectrix
« Reactie #91 Gepost op: 18 maart 2020, 11:07:20 »
Ik vat hem nog niet helemaal. We zijn er wel bijna. Ik snap nog niet hoe ik nu snelheid en functies moet opgeven.

Citaat
  0  0 0  1  S 1 A3 A2 1 A1 A0 1     synchronisatie 'byte'
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1         7 data 'bytes'
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1   ieder 'byte' is de inhoud
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1         van een adres
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
Ik zie dat het feitelijk 8 bytes zijn van 8 bits met 4 extra '1' bits per byte. Elke byte is voor 1 trein

Wat moet er precies in de synchronisatie byte staan?
Citaat
  0  0 0  1  S 1 A3 A2 1 A1 A0 1
Wat moet ik invullen voor S, A3 - A0 ? Moet S hier ook uit zijn? Hebben we hier hier over een stroomloze periode van 70us? En A3-A0 komen die overeen met het telegram nummer 1-15 ?

Citaat
Verdeling adressen over de verschillende telegrammen:
 telegram  '0' : 111, 95, 79, 63, 47, 31, 15
Als ik het nu goed snap. Moet ik in totaal 16 telegrammen versturen. In elke telegram staat 1 synchronisatie byte en 7 data bytes.  De plaats van een data byte komt overeen met het adres van een trein. Dus alle treinen van adres 0 t/m 111 krijgen in elke cyclus (<- alle 16 telegrammen) slechts 8 bits aan informatie.

Dan heb ik nog een overig vraagje. Ik heb voor mijn zelfgebouwde DCC centrale deze data structuur voor de treinen zelf:
struct trains {
signed char speed;
unsigned char headLight;
unsigned char functions;
unsigned char decoderType;
};
Als ik 128 trein 'objecten' maak, gebruik ik 25% van een UNO's ram geheugen. Ik was er toen vanuit gegaan van 8 functies. Volstaat dit voor jou?

Dan heb ik nog een vraag. Ik kan voor je een interrupt service routine aan de praat krijgen die de blokgolf op je spoor zet. Maar dan hebben we nog het probleem dat we het nog moeten integreren met iets. Hoe wil jij je treinen aansturen? Via seriele instructies? Of wil je een centrale maken van een arduino met lcd scherm en rotary-encoder? Zodat je een soort selectrix only centrale maakt? (hoewel ik kan selectrix ook in mijn DCC centrale integreren en dan heb je DCC en selectrix). Of maak je zelf een handcontroller?

Mijn SW werkt in principe serieel en ik heb er een handcontroller voor gebouwd. Ik heb aan de centrale een bluetooth gehangen waarmee ik ook nog eens met een gratis bluetooth app mijn treinen kan aansturen:

Het werkt opzich wel goed. Met de getallen kies ik een adres, dan kan ik 8 functies + licht bedienen (L). Ik kan de trackpower afschakelen (P) en een noodstop (S) doen. Met <, <<, >> en > kan ik de snelheid instellen. De centrale stuurt feedback teksten terug naar deze app. Ik laat hiermee slechts zien wat mijn mogelijkheden zijn.

Als je dit wilt laten werken met DCC en weet ik veel wat en je wilt het bedienen met koploper of iTrain of... dan moet je zelf ook aan de gang. Ik weet zelf minder dan niks over loconet, xpressnet, p51 etc etc.

Mvg,

Bas




gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #92 Gepost op: 18 maart 2020, 13:22:09 »
Bas,

Je bent aardig op weg. Echter een Selectrix centrale die hier beschreven wordt is de SX1 centrale. Er zijn commerciele producten geweest die SX1 en DCC combineerden. Op dit moment is er echter SX2 (vrijwel geen enkele selectrix rijder heeft nog een SX1 only centrale actief), dat is een combinatie van SX1 (zeer beperkte decoder aansturing), SX2 (zover mij bekend 16 functies, maar er gaan verhalen van 32 functies) en DCC.

Synchronisatie byte is precies zoals geschreven, je begint met 3 keer een "0" gevolgd door een "1". Hierna volgt op de rails altijd een "1", doordat S alleen via de rails doorgegeven kan worden als er spanning op staat. Dan werderom een "1". A3 - A0 is het telegramnummer van 0 -15.

Voor het SX1 protocol geldt:
bit 0 - 4: Snelheid (0 - 31)
bit 5: Rijrichting
bit 6: Verlichting
bit 7: Extra fucntie (vaak aangeduid met fluit)

Voor extra functie worden in de decoder extra adressen opgegeven, die dan de aansturing van de functies bevatten. Dit is het zogenaamde SX1 extended protocol. Een locomotief kijkt dan op 2 adressen om in totaal 10 functies te hebben.

Overigens de adressen zijn op de rails voor de trein, maar als ze op de SX-bus zitten dan zijn ze voor de trein en assessoires (wissels, seinen, terugmelders). Er was vroeger maar een SX-bus, die was gekoppeld met de rails en de bus onder de baan. De 112 adressen zijn dus voor alles op de modelbaan.
Met de komst van SX2 is daar verandering in gekomen. Nu is er vaak een SX2 trackbus (vaak aangeduid met Sx0) en een SX1 assessoirebus (vaak aangeduid met Sx*).


Vraagje over je structuur: Waarom HeadLights apart? Dit is officieel F0 en zou dus gewoon in bit 0 van je functions kunnen. Verder lijkt hij op mijn structuur onder SX2
struct trains {
unsigned char speed;
unsigned int functions;
unsigned char decoderype; (SX1, SX2 of DCC)
};

Voorlopig ben ik zelf opzoek naar DCC signalen op het spoor. In SX2 is namelijk duidelijk gedefinieerd hoe je SX2, MM en DCC moet combineren. Er zijn twee implementatievormen van de "specificaties". Een die stelt dat er naast de 112 SX1 treinen nog 16 treinen kunnen rijden die of SX2 of MM of DCC zijn. Ikzelf bezit een centrale die een andere "specificatie" implementatie heeft, en daar is het aantal treinen begrensd op 103, maar welk protocol deze gebruiken doet er niet toe. Dus 103 DCC treinen mag ook.

Wat beterft de stap van aansturing rails naar bediening daar wil ik met niet druk om maken. Een goede universele library moet alle soorten bediening aan kunnen. De begrenzing is de decoder in de trein.

Groet,

Gerard van der Sel.

PS: De code voor SX1 is al geschreven en de daarvan afgeleide code voor SX2 bestaat ook al. Alleen het patroon voor de rais in DCC is mij een raadsel. Kun je hiermee helpen?

Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

bask185

  • Offline Offline
  • Berichten: 543
Re: Arduino en Selectrix
« Reactie #93 Gepost op: 18 maart 2020, 14:52:25 »
Citaat
Je bent aardig op weg
Jij ook hoor, jij doet het werk waar ik geen zin in en tijd voor heb  (y)

Ik kan echter nog niet verder, want we weten nog steeds niet hoe we voor sx2 data moeten invoeren. Waarschijnlijk doen ze hetzelfde als DCC en gebruiken ze 3/4 bits om te vertellen wat voor soort instructie het is, gevolgd door 4/5 bits voor de informatie. Maar ik gis nu maar wat. Of wil je alleen Sx1 hebben of wil je beiden hebben?

Citaat
Vraagje over je structuur: Waarom HeadLights apart?
Omdat er geen 9 bits in een byte passen. De functie byte heeft al F1 t/m F8. En aangezien Arduino geen bit variabele type kent, moest ik er een extra byte voor gebruiken. Bedenk dat de lamp bit vroeger in de snelheids byte was verwerkt bij DCC decoders met 14 stapjes.

Als je het interessant vindt. Dit is mijn github pagina. In het bestand DCC.cpp worden de signalen geregeld. Ik heb sinds ik het project in meerdere bestanden heb opgebroken niet meer getest. De code omtrent DCC is ongwijzigd. Als je met DCC bezig ben, is het misschien leuk om te kijken in 'assemblePackets'. Ik schrijf naar mijn mening duidelijke code (ovb  ::) )

De uitlijning is wel crappie, ik gebruik standaard een tab van 4 spaties en github deelt niet mijn 'mening' kwa tabgrootte.

De functie DCCsignals() is een state machine die de boven liggende stateFuncties aanroept. Het idee is dat deze state-machine kan worden uitgebreid voor MM2 en nu ook voor selectrix wat ik niet heb  ;D. Ik zal er ook nog een mooie bollen-diagram bijmaken voor het overzicht  (y)

Ik wilde zelf in het ISR een switch-case maken voor de verschillende decoder typen. Andere gebruiken een vaste ISR tijd van 14us voor alles tegelijk, ik doe dit niet. Het is soms maar net wat je te binnen schiet. Het ISR wordt zo groot, maar slechts een klein blokje wordt dan uitgevoerd.

Mvg,

Bas

EDIT:
Ik zag je PS niet. Ik gebruik zelf een L298N H-brug. De enable pin is bij mn trackPower pin aan = aan. Voor DCC moet ik beide direction pinnen tegelijk toggelen om van polariteit te wisselen. Voor selectrix kan ik of de enable pin 10us laag maken of ik zet beide direction pinnen op 0 (of 1). Dit laatste lijkt mij het makkelijkst.

Ik kan voor nu wel stukje code maken met een ISR waarbij de '0'en en '1'en goed uitgeklokt worden adhv van m'n transmitt buffer array. Alleen die buffer vullen, daar heb ik meer info voor nodig zoals ik heb uitgelegd.

Ik ga ff breien ;)


« Laatst bewerkt op: 18 maart 2020, 15:00:40 door bask185 »

bask185

  • Offline Offline
  • Berichten: 543
Re: Arduino en Selectrix
« Reactie #94 Gepost op: 18 maart 2020, 15:52:54 »
Ik heb gebreid. Veel code van mn DCC project kunnen recyclen.

#define SX_BIT 800 // 50us
#define SX_PAUSE 160 // 10us

enum states {
SXbitBusy,
SXpause,
};

unsigned char transmittBuffer[8];
unsigned char *ptr;
unsigned char packetSentFlag = false;

ISR(TIMER1_COMPB_vect) {
static unsigned char bitMask = 0x80; // of byte
static unsigned char state = SXpause;

switch(state) {

case SXbitBusy: // bit is actief hier
state = SXpause;
OCR1A = SX_BIT;

PORTD |= 0b00100000; // set enable pin on, ends pause

if(*ptr & bitMask) PORTD ^= 0b11000000; // toggle direction if the bit is 1

if(bitMask == 0x01 && ptr == (&transmittBuffer[0] + 7)) { // als alle 8 bytes uitgelokt zijn.. (
ptr = &transmittBuffer[0]; // reset deze pointer
bitMask = 0x80; // reset bit mask
bitClear(TIMSK1,OCIE1B); // set interrupt uit (volgende pakket moet worden samengesteld)
packetSentFlag = true; // sein je hoofd programma dat pakket is uitgeklokt
}
else {
bitMask >>= 1;      // = 0b10000000 Deze shift naar rechts
if(!bitMask) {      // als bit mask 0 is..
bitMask = 0x80; // maak er weer 0b10000000 van
ptr++;          // hoog de pointer op voor de volgende byte in het array
}
}
break;

case SXpause:
state = SXbitBusy;
OCR1A = SXpause:

PORTD &= ~0b00100000; // set enable pin off, starts pause
break;
}
}

void initISR() { // initialize the timer
cli();
bitSet(TCCR1A,WGM10);
bitSet(TCCR1A,WGM11);
bitSet(TCCR1B,WGM12);
bitSet(TCCR1B,WGM13);
bitSet(TCCR1A,COM1B1);
bitSet(TCCR1A,COM1B0);
bitClear(TCCR1B,CS12); // set prescale on 1
bitClear(TCCR1B,CS11);
bitSet(TCCR1B,CS10);
OCR1A= 100; // interval tijd begint 1 malig op 100 * 16us omdat.. zomaar
cli();
}
Werking:
In de setup roep je initISR() aan. Dit stelt je ISR in.

En dan:
Je vult het transmittBuffer array met dat wat je wilt versturen. Als je dat gedaan heb, zetten we het ISR aan met:
bitSet(TIMSK1,OCIE1B);
Dan wacht je en wacht je totdat op een gegeven moment de variabele 'packetSentFlag ' true is. Als deze true is, zet hem dan weer op false. Vul je buffer met de volgende informatie (volgende telegram?) en opnieuw zet je:
bitSet(TIMSK1,OCIE1B);

Het ISR schakelt zichzelf uit nadat een pakket is uitgeklokt. De *ptr moet ook naar het adres van transmittBuffer wijzen. Deze pointer wordt gebruikt om door het array heen te loopen.

Als we beginnen met het uitklokken van iets, zet ik toch de enable pin aan. En als de te versturen bit een 1 is, dan toggle ik tegelijk beide direction pinnen. Als de pauze begint, zet ik de enable pin uit. Ik heb thuis geen digitale scoop dus ik kan niks voor je testen.

Ik gebruik overigens directe port instructies om de IO aan te sturen. DigitalWrite is te langzaam voor ons. Port D pin 5 is de enable, port D pinnen 6 en 7 zijn de direction pinnen. D6 moet ongelijk zijn D7 bij de initialisatie.

Als je nu de trackpower wil afschakelen, zet dan ook het ISR uit met:
bitClear(TIMSK1,OCIE1B);

Bij vragen of verdere wensen ben ik tot je beschikking. Ik ga dit in ieder geval in mijn DCC centrale knutselen wanneer we weten hoe SX2 werkt.

Het ISR met DCC staat nog steeds op de git hub pagina. Daar kan je in ieder geval zien, hoe ik de transmit buffer vul en hoe ik hem uitklok (werkt praktisch hetzelfde)

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #95 Gepost op: 08 april 2020, 14:01:37 »
Het heeft even geduurd, maar moest wat zaken opruimen en controleren.
Hierbij de software om een SX1 centrale te maken.
De Arduino kan met dit programma uit 1995 (ja, geschikt voor windows 95) aangestuurd worden:
http://home.hccnet.nl/gerard.vd.sel/selectrix/programmas/SX_tester.zip

Goed eerst de ino:
/*
   SX1 centrale

   Creator: Gerard van der Sel
   Version: 1.1
   Date: 27-12-2015
   
   This software emulates a SX interface on the Arduino.
   Extra hardware needed is de SX-Arduino board which contains the hardware to communicate with the SX-bus.

   Protocol used by the SX-Interface (66824 or 66842)
   2 byte message:
   First byte contains command and address:
      Command is located in bit 7 of first byte:
      0: Read address
      1: Write address
      Address: 0 to 111 (valid adresses on the SX-bus)
               126 bus selection
               127 controls track power
   Second byte contains data in case of a write command
      in case of a valid address: 0 to 255
      in case of address 126: 0 => select SX0 (track)
                              1 => select SX1
      in case of address 127: 0 trackpower off
                              128 trackpower on
      in case of a read: byte is discarded

*/

#include <Arduino.h>
#include "SXcentrale.h"

SXcentrale SXcntrl;      // Interface to the SX-bus and track
boolean cmdAdr;          // Received byte is a command
boolean cmdWrite;        // Write command
uint8_t address;         // Address for reading or writing
uint8_t rcvdData;
uint8_t selbus;          // Selected bus

ISR(TIMER1_OVF_vect) {   // interrupt service routine
    SXcntrl.isr();
}

void setup() {
    // put your setup code here, to run once:
    // initialize serial:
    Serial.begin(19200);

    // initialize SX-bus
    SXcntrl.init();

    // initialize application
    cmdAdr = true;
    cmdWrite = false;
    selbus = 0;
}

void serialEvent() {
    // Read all the data
    while (Serial.available()) {
        rcvdData = (uint8_t)Serial.read();
        // First byte is a command, decode it
        if (cmdAdr) {
            // If byte value > 127 a write command, data in second byte
            if (rcvdData > 127) {
                cmdWrite = true;
                address = rcvdData - 128;  // address is received data - 128
            } else {  // Read command, perform it
                if (rcvdData < 112) {    // Get address data
                    Serial.print((char)SXcntrl.get(selbus, rcvdData));
                } else {   // Illegal address, power or select bus?
                    if (rcvdData == 126) {
                        Serial.print((char)selbus);
                    }
                    if (rcvdData == 127) {
                        Serial.print((char)(SXcntrl.getPWR() * 128));
                    }
                }
            }
            cmdAdr = false;
        } else {
            // Second byte data
            if (cmdWrite) {
                if (address < 112) {
                    SXcntrl.set(selbus, address, rcvdData);
                } else {
                    if (address == 126) {
                        if (rcvdData < 4) {
                            selbus = rcvdData;
                        }
                    }                 
                    if (address == 127) {
                        if ((rcvdData & 128) == 0) {
                            SXcntrl.setPWR(0);
                        } else {
                            SXcntrl.setPWR(1);
                        }
                    }
                }
                cmdWrite = false;
            }
            cmdAdr = true;
        }
    }
}

void loop() {
  // put your main code here, to run repeatedly:

}
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #96 Gepost op: 08 april 2020, 14:02:43 »
Vervolg het cpp file:
/*
 * SXmaster.cpp
 *
 *  Version:    0.1
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on:
 *  Version:
 *  Changes:
 *
 *
 *  interface hardware needed !

 Interface SX-bus
 - SX T0 (Clock) must be connected to Pin 3 (IOL, INT1);
 - SX T1 must be connected to Pin 5 (IOL, T1);
 - SX D must be connected to Pin 6 (IOL, AIN0).
 
 SX-bus interface (NEM 682)

De clock lijn (T0) is verbonden met een interruptingang, zodat op
 de flanken van dit signaal een interrupt gegenereerd kan worden.
 Hierna kan data gelezen worden van T1 of data geschreven worden naar D.

 Klok:
  --    ----------------    ----------------    ----------------    ------
    |  |                |  |                |  |                |  |
     --                  --                  --                  --

 Data:
  -- ------------------- ------------------- ------------------- ---------
    X                   X                   X                   X
  -- ------------------- ------------------- ------------------- ---------

    ^  ^                ^  ^                ^  ^                ^  ^
    W  R                W  R                W  R                W  R

Opbouw telegram (96 bits):
  0  0 0  1  S 1 A3 A2 1 A1 A0 1     synchronisatie 'byte'
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1         7 data 'bytes'
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1   ieder 'byte' is de inhoud
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1         van een adres
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1
 D0 D1 1 D2 D3 1 D4 D5 1 D6 D7 1

 0 = Logische 0
 1 = Logische 1
 S = Spanning rails (0 = uit, 1= aan)
 Ax = Gezamelijk het nummer van het telegram
 Dx = D0 t/m D7 vormen de data op een Selectrix adres.

 Verdeling adressen over de verschillende telegrammen:
 telegram  '0' : 111, 95, 79, 63, 47, 31, 15
 telegram  '1' : 110, 94, 78, 62, 46, 30, 14
 telegram  '2' : 109, 93, 77, 61, 45, 29, 13
 telegram  '3' : 108, 92, 76, 60, 44, 28, 12
 telegram  '4' : 107, 91, 75, 59, 43, 27, 11
 telegram  '5' : 106, 90, 74, 58, 42, 26, 10
 telegram  '6' : 105, 89, 73, 57, 41, 25,  9
 telegram  '7' : 104, 88, 72, 56, 40, 24,  8
 telegram  '8' : 103, 87, 71, 55, 39, 23,  7
 telegram  '9' : 102, 86, 70, 54, 38, 22,  6
 telegram '10' : 101, 85, 69, 53, 37, 21,  5
 telegram '11' : 100, 84, 68, 52, 36, 20,  4
 telegram '12' :  99, 83, 67, 51, 35, 19,  3
 telegram '13' :  98, 82, 66, 50, 34, 18,  2
 telegram '14' :  97, 81, 65, 49, 33, 17,  1
 telegram '15' :  96, 80, 64, 48, 32, 16,  0

This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

 */
 
#include <Arduino.h>

#include "SXcentrale.h"

SXcentrale::SXcentrale() {
     // initialize pins and variables
    pinMode(SX_T0, OUTPUT);                                  // SX-T0 is an output
digitalWrite(SX_T0, HIGH);
    pinMode(SX0_T1, OUTPUT);                                  // SX0_T1 is also an output
digitalWrite(SX0_T1, HIGH);
    pinMode(SX1_T1, OUTPUT);                                  // SX1_T1 is also an output
digitalWrite(SX1_T1, HIGH);
    pinMode(SX0_D, INPUT_PULLUP);                            // SX0_D is an input
    pinMode(SX1_D, INPUT_PULLUP);                            // SX1_D is also an input
}

// initialize function
void SXcentrale::init() {
    // initialize timer1
uint8_t oldSREG = SREG;
    noInterrupts();                                             // disable all interrupts
    // Set timer1 to the correct value for our interrupt interval
    TCCR1A = 0;
    TCCR1B = (1 << CS10);
//     TCCR1B = (1 << CS12);                                       // Debug only
    TCNT1 = Timer1_40;                                          // preload timer with 40usec delay
    TIMSK1 |= (1 << TOIE1);                                     // enable timer overflow interrupt
SREG = oldSREG;                                             // restore interrupts

     // initialize pins and variables
    pinMode(SX_T0, OUTPUT);                                  // SX-T0 is an output
digitalWrite(SX_T0, LOW);
    pinMode(SX0_T1, OUTPUT);                                  // SX0_T1 is also an output
digitalWrite(SX0_T1, LOW);
    pinMode(SX1_T1, OUTPUT);                                  // SX1_T1 is also an output
digitalWrite(SX1_T1, LOW);
    pinMode(SX0_D, INPUT_PULLUP);                            // SX0_D is an input
    pinMode(SX1_D, INPUT_PULLUP);                            // SX1_D is also an input

for (int i = 0; i < SX_ADDRESS_NUMBER; i++) {
_sxbusSX0[i] = 0;                                      // reset sxbus data to zero
_sxbusSX1[i] = 0;
}
initVar();                                                 // Start looking for SYNC
}

void SXcentrale::initVar() {
// start always with sending of header
_sx_state = SYNC;                                          // First send SYNC pattern
_sx_dataFrameCount = SX_DATACOUNT;                         // Send all dataframes
_sx_sepCount = SX_SEPLEN;                                  // Distanse between two separators
_sx_byteCount = SX_SYNC0;                                  // Check for SX_SYNC0 bits of "0"
_sx_numFrame = 15;                                         // Set frame to max to start with 0.
_sx_intstate = 0;                                          // Start with clock pulse

_sx_read_sepCount= SX_SEPLEN;                              // Distanse between two separators
_sx_read_byteCount = 0;                                    // bit counting (byte)

  _sx_bitTrack = 0;

// SX bus bits
_sx_bitsendSX0 = 1;    // Start with a "1"
_sx_bitresvSX0 = 1;
_sx_bitsendSX1 = 1;
_sx_bitresvSX1 = 1;

// Powerbit
_sx_PWR = 0;                                               // At start no power

// Syncbit
_sx_sync = 0;                                              // Clear sync-flag
}

// Local functions
// Write signals to the track (PX protocol)
void SXcentrale::writeTrack(uint8_t clockbit) {
  if (_sx_PWR == 0) {
    // Power off, stop generating signals
    bitWrite(SX_TRACKE_PORT, SX_TRACKE_PORTPIN, LOW);
    bitWrite(SX_TRACKG1_PORT, SX_TRACKG1_PORTPIN, LOW);
    bitWrite(SX_TRACKG2_PORT, SX_TRACKG2_PORTPIN, LOW);   
  } else {
    // Enable output amplifier, to generate signals on track.
    bitWrite(SX_TRACKE_PORT, SX_TRACKE_PORTPIN, HIGH);
    if (clockbit == 0) {
      // Clockpuls on track
      bitWrite(SX_TRACKG1_PORT, SX_TRACKG1_PORTPIN, LOW);
      bitWrite(SX_TRACKG2_PORT, SX_TRACKG2_PORTPIN, LOW);   
    } else {
      // Calculate value to track
      _sx_bitTrack ^= _sx_bitsendSX0;
      // Send to track
      bitWrite(SX_TRACKG1_PORT, SX_TRACKG1_PORTPIN, _sx_bitTrack);
      bitWrite(SX_TRACKG2_PORT, SX_TRACKG2_PORTPIN, !_sx_bitTrack);
    }
  }
}

// Write clock line (inverted)
void SXcentrale::writeT0(uint8_t val) {
bitWrite(SX_T0_PORT, SX_T0_PORTPIN, !val);
}

// Write transmit line (inverted)
void SXcentrale::writeT1() {
bitWrite(SX0_T1_PORT, SX0_T1_PORTPIN, !_sx_bitsendSX0);
bitWrite(SX1_T1_PORT, SX1_T1_PORTPIN, !_sx_bitsendSX1);
}

// Read data line
void SXcentrale::readD() {
_sx_bitresvSX0 = (SX0_D_INPORT & _BV(SX0_D_INPORTPIN)) > 0;
_sx_bitresvSX1 = (SX1_D_INPORT & _BV(SX1_D_INPORTPIN)) > 0;
// _sx_bitresvSX2 = (SX2_D_INPORT & _BV(SX2_D_INPORTPIN)) > 0;
// _sx_bitresvSX3 = (SX3_D_INPORT & _BV(SX3_D_INPORTPIN)) > 0;
}

// Interrupt service routine (AVR OVERFLOW T1)
void SXcentrale::isr() {
if (_sx_intstate) {
// 40 usec fase (clock high)
    writeTrack(1);
writeT0(1);
_sx_intstate = false;
TCNT1 += Timer1_40;                                 // reload timer
// Start processing the bits
// First process the bus readings
if (_sx_read_byteCount != 0) {                  // All bits done
_sx_read_sepCount--;
if (_sx_read_sepCount == 0) {                   // Read the separator
_sx_read_sepCount = SX_SEPLEN;
} else {
_sx_read_dataSX0 = (_sx_read_dataSX0 >> 1); // Prepare for reading data
bitWrite(_sx_read_dataSX0, 7, _sx_bitresvSX0); // Insert the bit
_sx_read_dataSX1 = (_sx_read_dataSX1 >> 1);
bitWrite(_sx_read_dataSX1, 7, _sx_bitresvSX1);
}
_sx_read_byteCount--;
if (_sx_read_byteCount == 0) {                  // All bits done
// save read _data
if (_sxbusSX0[_sx_read_index] < NO_WRITE) {
_sxbusSX0[_sx_read_index] = _sx_read_dataSX0; // Save read data in array
_sxbusSX0[_sx_read_index] &= 0xff;
}
if (_sxbusSX1[_sx_read_index] < NO_WRITE) {
_sxbusSX1[_sx_read_index] = _sx_read_dataSX1;
_sxbusSX1[_sx_read_index] &= 0xff;
}
_sx_read_index++;                           // Point to next byte
}
}
// Next calculate new bus data
switch (_sx_state) {
// Write sync pattern "0001" to start
case SYNC:
if (_sx_byteCount == 0) {
_sx_bitsendSX0 = 1;
_sx_bitsendSX1 = 1;
_sx_state = PWR;                        // Setup for POWER bit
_sx_sepCount = SX_SEPLEN - 1;           // Set _sx_sepCount and continue
} else {
_sx_bitsendSX0 = 0;
_sx_bitsendSX1 = 0;
_sx_byteCount--;
}
break;
// Write the power bit plus separator.
case PWR:
_sx_sepCount--;
if (_sx_sepCount == 0) {                    // The separator
_sx_bitsendSX0 = 1;
_sx_bitsendSX1 = 1;
_sx_state = ADDR;                       // Setup for next state ADDR
_sx_byteCount = SX_BYTELEN / 2;
_sx_sepCount = SX_SEPLEN;
// Increment frame number
_sx_numFrame++;
_sx_numFrame &= 0x0f;
_sx_write_dataSX0 = _sx_numFrame;
if (_sx_numFrame == 0) {
_sx_sync = 1;                       // Signal frame 0 for sync purposes
}
} else {
_sx_bitsendSX0 = _sx_PWR;
_sx_bitsendSX1 = _sx_PWR;
}
break;
// Write the address bits.
case ADDR:
// But first read powerbit(s)
if (_sx_byteCount == (SX_BYTELEN / 2)) {
if (_sx_PWR == 0) {
_sx_PWR = _sx_bitresvSX0 | _sx_bitresvSX1;  // | _sx_bitresvSX2 | _sx_bitresvSX3;
} else {
_sx_PWR = _sx_bitresvSX0 & _sx_bitresvSX1;  // & _sx_bitresvSX2 & _sx_bitresvSX3;
}
}
_sx_sepCount--;
if (_sx_sepCount == 0) {                    // Set the separator
_sx_bitsendSX0 = 1;
_sx_bitsendSX1 = 1;
_sx_sepCount = SX_SEPLEN;
} else {
_sx_bitsendSX0 = bitRead(_sx_write_dataSX0, 3);
_sx_bitsendSX1 = _sx_bitsendSX0;
_sx_write_dataSX0 = _sx_write_dataSX0 * 2;
}
_sx_byteCount--;
if (_sx_byteCount == 0) {                   // Addres part is processed
// Advance to the next state
_sx_state = DATA;                       // Setup for DATA write
_sx_dataFrameCount = SX_DATACOUNT;
_sx_byteCount = SX_BYTELEN;
_sx_index = _sx_numFrame * 7;           // Calculate index
_sx_read_index =  _sx_index;
_sx_write_dataSX0 = _sxbusSX0[_sx_index]; // Get data to write
_sxbusSX0[_sx_index] &= 0xff;           // Report written
_sx_write_dataSX1 = _sxbusSX1[_sx_index];
_sxbusSX1[_sx_index] &= 0xff;
}
break;
// Write the data bits
case DATA:
// Start reading databits
if (_sx_byteCount == SX_BYTELEN - 1) {
_sx_read_byteCount = SX_BYTELEN;        // Start reading
}
_sx_sepCount--;
if (_sx_sepCount == 0) {                    // Set the separator
_sx_bitsendSX0 = 1;
_sx_bitsendSX1 = 1;
_sx_sepCount = SX_SEPLEN;
} else {
_sx_bitsendSX0 = bitRead(_sx_write_dataSX0, 0);
_sx_write_dataSX0 = _sx_write_dataSX0 >> 1;
_sx_bitsendSX1 = bitRead(_sx_write_dataSX1, 0);
_sx_write_dataSX1 = _sx_write_dataSX1 >> 1;
}
_sx_byteCount--;
if (_sx_byteCount == 0) {                   // All bits done
// Setup for next read/write
_sx_byteCount = SX_BYTELEN;
_sx_index++;
_sx_write_dataSX0 = _sxbusSX0[_sx_index]; // Get data to write
_sxbusSX0[_sx_index] &= 0xff;           // Report written
_sx_write_dataSX1 = _sxbusSX1[_sx_index];
_sxbusSX1[_sx_index] &= 0xff;
_sx_dataFrameCount--;
if (_sx_dataFrameCount == 0) {
// Move on to find SYNC pattern
_sx_state = SYNC;
_sx_byteCount = SX_SYNC0;
}
}
break;
default:
initVar();                                  // Restart sending SYNC
writeT0(1);
writeT1();
break;
}  //end switch/case _sx_state
} else {
// 10 usec fase (clock low)
  readD();                                      // Read datalines
    writeTrack(0);
writeT1();                                      // Write datalines
writeT0(0);                 // Clock low
_sx_intstate = true;
TCNT1 += Timer1_10;                             // reload timer
}
}

// Convert from SX-bus addresses to index in array.
uint8_t SXcentrale::calcIndex(uint8_t SXadr) {
uint8_t frame = 15 - (SXadr & 15);                      // Get the frame number
uint8_t offset = 6 - (SXadr >> 4);                      // Get the offset in the frame
return frame * 7 + offset;                              // Calculate the index in the array
}

// functions 'accessing' the SX-bus

// Read data from the array, filled by the isr.
// In:
// bus: 0 - 3, bus to read from.
// adr: 0 - 111, address value read from.
// Return value:
// -1: Address out of range
// -3: SX-bus out of range
// 0 - 255: Value from SX-bus
int SXcentrale::get(uint8_t bus, uint8_t adr) {
     // returns the value of a SX address
if (adr < SX_ADDRESS_NUMBER)  {
switch (bus) {
case 0:
return _sxbusSX0[calcIndex(adr)] & 0xff; // Return value
case 1:
return _sxbusSX1[calcIndex(adr)] & 0xff;
// case 2:
// return _sxbusSX2[calcIndex(adr)] & 0xff;
// case 3:
// return _sxbusSX3[calcIndex(adr)] & 0xff;
default:
return -3;      // Report bus out of range
}
}
return -1;                                           // Report address out of range
}

// Write data to the array, writing to the SX-bus is done by the isr.
// In:
// bus: 0 - 3, bus to send value to.
// adr: 0 - 111, address value send to.
// dt: 0 - 255, value send
// Return value:
//  0: Success
// -1: Address out of range
// -3: SX-bus out of range
int SXcentrale::set(uint8_t bus, uint8_t adr, uint8_t dt) {
if (adr < SX_ADDRESS_NUMBER)  {
switch (bus) {
case 0:
_sxbusSX0[calcIndex(adr)] = dt + NO_WRITE; // Make sure it is transmitted
break;
case 1:
_sxbusSX1[calcIndex(adr)] = dt + NO_WRITE;
break;
// case 2:
// _sxbusSX2[calcIndex(adr)] = dt + NO_WRITE;
// break;
// case 3:
// _sxbusSX3[calcIndex(adr)] = dt + NO_WRITE;
// break;
default:
return -3;    // bus number out of range
}
return 0;    // success
}
return -1;    // address out of range
}

// Read POWER status from the SX-bus
// Return value:
//  0: Power off
//  1: Power on
uint8_t SXcentrale::getPWR() {
    return _sx_PWR;
}

// Write POWER status to the SX-bus and control a connected central.
// Return value:
//  0: Success
// -2: Illegal power value
int SXcentrale::setPWR(uint8_t val) {
if (val == 0 || val == 1) {
_sx_PWR = val;
return 0;
}
return -2;
}

// Every time frame 0 is passed sync bit is set by isr.
// Return value:
//  0: Bus out of sync
//  1: Bus in sync
uint8_t SXcentrale::inSync() {
if (_sx_sync == 1) {
_sx_sync = 0;              // reset sync bit to check for next pass
return 1;                  // report frame 0 found
}
return 0;
}
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #97 Gepost op: 08 april 2020, 14:03:24 »
En tot slot het h-file:
/*
 * SXcentrale.cpp
 *
 *  Version:    0.1
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on:
 *  Version:
 *  Changes:
 *
 *
 *  interface hardware needed !

 Read SX Signal - SX Clock must be connected to Pin3 = INT1 and
 SX Data must be connected to Pin 5. Both are connected through a resistor off 22 kilo ohm.
 Pin 6 can be connected via a 100 ohm resistor to the write line
 of the SX bus
 
 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.
 
 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.
 
 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA


 */

#ifndef SXcentrale_H_
#define SXcentrale_H_

#include <Arduino.h>

// Define arduino pins and ports
// The io pins for the busses
#define SX_T0 3                      // Clock (for all)
#define SX_T0_PORT PORTD
#define SX_T0_PORTPIN PORTD3

#define SX0_T1 4                      // Data write
#define SX0_T1_PORT PORTD
#define SX0_T1_PORTPIN PORTD4

#define SX0_D 5                      // Data read
#define SX0_D_INPORT PIND
#define SX0_D_INPORTPIN PIND5

#define SX1_T1 6                      // Data write
#define SX1_T1_PORT PORTD
#define SX1_T1_PORTPIN PORTD6

#define SX1_D 7                      // Data read
#define SX1_D_INPORT PIND
#define SX1_D_INPORTPIN PIND7

// The io pins for the trackamplifier
#define SX_TRACKE             A1
#define SX_TRACKE_PORT        PORTC
#define SX_TRACKE_PORTPIN     PORTC1
#define SX_TRACKG1            A2
#define SX_TRACKG1_PORT       PORTC
#define SX_TRACKG1_PORTPIN    PORTC2
#define SX_TRACKG2            A3
#define SX_TRACKG2_PORT       PORTC
#define SX_TRACKG2_PORTPIN    PORTC3

// defines for state machine
#define DATA 0               // For performance DATA first
#define SYNC 1               // (Gives fastest code)
#define PWR     2
#define ADDR    3

// defines for Selectrix constants
#define SX_SYNC0        3                  // 3 "0" bits achter elkaar
#define SX_DATACOUNT    7                  // 7 dataframes in 1 SYNC Channel
#define SX_SEPLEN       3                  // 3 bit in a separated part
#define SX_BYTELEN     12                  // 12 bits for one byte

#define SX_ADDRESS_NUMBER 112              // number SX channels

#define NO_WRITE 256                       // No data to write

#define Timer1_10 -160                     // 10 usec delay
#define Timer1_40 -640                     // 40 usec delay
// #define Timer1_10 30000                     // 10 usec delay (debug, also set CS12)
// #define Timer1_40 30000                     // 40 usec delay (debug, also set CS12)


class SXcentrale {
public:
SXcentrale();
void init(void);
int get(uint8_t, uint8_t);
int set(uint8_t, uint8_t, uint8_t);
    uint8_t getPWR(void);
int setPWR(uint8_t);
void isr(void);
uint8_t inSync(void);

private:
  void writeTrack(uint8_t clockbit);
    void writeT0(uint8_t val);
void writeT1();
void readD();
void initVar();
uint8_t calcIndex(uint8_t adr);

bool _sx_intstate;                  // interrupt timing
int timer1_counter;

uint8_t _sx_numFrame;                  // number frame
uint8_t _sx_dataFrameCount;            // frame counting
uint8_t _sx_state;
uint8_t _sx_sepCount;                  // bit counting (seperator)
uint8_t _sx_byteCount;                 // bit counting (byte)
uint8_t _sx_index;                     // current index in the array
uint8_t _sx_PWR;                       // current state of POWER on track

uint8_t _sx_read_sepCount;             // bit counting (seperator)
uint8_t _sx_read_byteCount;            // bit counting (byte)
uint8_t _sx_read_index;                // current index in the array

uint8_t _sx_sync;                      // set if Frame 0 is processed

  uint8_t _sx_bitTrack;
    uint8_t _sx_bitsendSX0;        // read databit
    uint8_t _sx_bitresvSX0;              // write databit
uint8_t _sx_read_dataSX0;              // read data
    uint8_t _sx_write_dataSX0;         // data to write
int _sxbusSX0[SX_ADDRESS_NUMBER];      // to store the SX-bus data

    uint8_t _sx_bitsendSX1;          // read databit
    uint8_t _sx_bitresvSX1;              // write databit
uint8_t _sx_read_dataSX1;              // read data
    uint8_t _sx_write_dataSX1;         // data to write
int _sxbusSX1[SX_ADDRESS_NUMBER];      // to store the SX-bus data

/* SX Timing
1   Bit             50 us
1   Kanal          600 us (= 12 Bit)
1   Grundrahmen    ca. 4,8 ms
1   Gesamtrahmen   ca.  80 ms (= 16 Grundrahmen) 
0  0  0  1  S   1  A3  A2  1  A1  A0  1 == sync frame of 12 bits
*/
};

#endif /* SXcentrale_H_ */
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #98 Gepost op: 08 april 2020, 14:10:14 »
De data naar de bus 0 gaat ook naar de rails.
Werking is als volgt:
Er worden in principe twee SX1 bussen opgewekt. Deze kunnen gewoon naar buiten uitgevoerd worden over de standaard 5 polige stekkers. Tussen T1 en D een weerstand 470 ohm, om de werking van de SX-bus goed te maken. Verder wordt er voor de clock line (T0) een weerstand van 220 ohm geadviseerd, terwijl de T1 een weerstand van 100 ohm dient te hebben.
Als "booster" is niet een standaard booster te gebruiken, daar er iedere 50 usec gedurende 10 usec beide spoorstaven kortgesloten dienen te zijn. (Als beide spoorstaven naar 0 getrokken worden, dan kan met skotly diodes ook een "kortsluiting" gesymuleerd worden.)
Een tekening met een kortsluit MOSFET is te vinden op de site van Uwe Magnus (http://www.uwe-magnus.de/) onder Zentrale.

Ik hoor van jullie

Groet,

Gerard van der Sel.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

bask185

  • Offline Offline
  • Berichten: 543
Re: Arduino en Selectrix
« Reactie #99 Gepost op: 08 april 2020, 15:28:27 »
Gerard!!

Goed bezig geweest, maar ik heb vraagjes:
- werkt het nu ook?
- Hoe stuur je je treinen aan? zelf bouw handcontroller? bestaande controller? dat ene computerprogramma  :-\ ? smart phone?
- heb je de SW zelf geschreven?
- Je kan nog geen SX2?, weten we daar al wat meer over?
- wat heb je qua hardware gebouwd? Heb je de schema's van die Duitse site overgenomen?
- Is het niet makkelijker om je timer 1 ISR in je cpp file te zetten?

Ik ben overigens helemaal onbekend met wat voor hardware trix heeft gebruikt. Ik weet daarom niet wat "Deze kunnen gewoon naar buiten uitgevoerd worden over de standaard 5 polige stekkers." is? Als je zelf hardware heb gebouwd, waar gaat die 5 polige kabel dan naar toe? Ik snap naar je spoor. Maar hoe zit dat met die kabel precies? Heb je een speciaal koppelstuk voor tussen je spoor en die kabel???


Mvg,

Bas

P.S.
Ik kan het niet helpen maar ik merk 'inconsistensies' op in de indents van je code. Ik zie tabs en spaties door elkaar. Ik zal niet klagen over het gebruik van afkortingen  :P

Dompie

  • HerIntreder
  • Offline Offline
  • Berichten: 147
Re: Arduino en Selectrix
« Reactie #100 Gepost op: 08 april 2020, 20:27:52 »
Gerard, gaaf stuk werk zeg!!

Johan
N Selectrix/Müt - TrainController7Gold met +4D Sound, +SmartHand - Stärz SX-hardware

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #101 Gepost op: 09 april 2020, 07:54:50 »
Bas,

Antwoorden op je vragen:
- werkt het nu ook?
Nu, maart april 2020, weet ik niet, destijds in 2018 heeft het gewerkt. Zelfs met mijn oudste decoder (echte Trix decoder)
- Hoe stuur je je treinen aan? zelf bouw handcontroller? bestaande controller? dat ene computerprogramma  :-\ ? smart phone?
De in de ino beschreven seriele interface is een standaard (lees commercieel verkrijgbare) interface. Je kunt met deze software de centrale zo onder koploper/iTrain of een ander bsturings programma hangen.
- heb je de SW zelf geschreven?
100% zelf geschreven. (Het is mijn opleiding en beroep)
- Je kan nog geen SX2?, weten we daar al wat meer over?
Er zijn op het internet twee documenten te vinden over SX2 (ik heb ze beide op de hardeschijf en in dropbox). Dus daar hoef je je niet druk over te maken
- wat heb je qua hardware gebouwd? Heb je de schema's van die Duitse site overgenomen?
In eerste instantie is het schema van die duitse site overgenomen. Naderhand heb ik de L6203 vervangen door vier MosFets (2x N channel en 2x P channel). Echter de poging om er 4x N channel van te maken is mislukt.
- Is het niet makkelijker om je timer 1 ISR in je cpp file te zetten?
Hoe bedoel je? De regels:
ISR(TIMER1_OVF_vect) {   // interrupt service routine
    SXcntrl.isr();
}
verplaatsen naar het cpp file?
Als je problemen wilt krijgen moet je dat doen. Dan is je objecten structuur niet goed en is er grote kans op problemen. Zo ben je van alle problemen af en is het in mijn ogen netjes geregeld.
Initialisatie timer in de desbetreffende cpp en in de ino een overgnag van de het basis object naar het implementatie object.

<Citaat>
Ik ben overigens helemaal onbekend met wat voor hardware trix heeft gebruikt. Ik weet daarom niet wat "Deze kunnen gewoon naar buiten uitgevoerd worden over de standaard 5 polige stekkers." is? Als je zelf hardware heb gebouwd, waar gaat die 5 polige kabel dan naar toe? Ik snap naar je spoor. Maar hoe zit dat met die kabel precies? Heb je een speciaal koppelstuk voor tussen je spoor en die kabel???
</Citaat>

Je bent inderdaad totaal onbekend met het Selectrix systeem. Laat ik proberen het verschil tussen DCC en Selectrix uit te leggen (sorry alvast als ik het wat zwart/wit uitleg):
DCC: aansturings protocol voor treinen, wissels en seinen. Geen terugmelding mogelijk.
Selectrix: besturings protocol voor treinen, wissels, seinen en terugmelding, door de mee gedefieerde SX-bus.

Even een verder toelichting:
Een Selectrix centrale moet naast het rail signaal ook een bus signaal opwekken. In 1980 (begintijd) zat het rail signaal gekoppeld aan het bus signaal. Als je op de bus op een adres waar een locomotief zat de data veranderde, veranderde ook het gedrag van de locomotief. Een voorbeeld. Selectrix heeft de snelheid in de bits 0 - 4 zitten. Als je dus de waarde van de bits 0 - 4 verandert op de bus, zal de snelheid van de locomotief op de rails veranderen. Dit is zover mij bekend niet mogelijk met het DCC protocol.
In de bovenstaande code is dat dus ook mogelijk.

De bus is uitgevoerd als een 5 polige verbinding. Fysiek is dat de goede oude Din steker uit de audio wereld (wordt daar al lang niet meer gebruikt).
Op deze bus zijn de signalen T0, T1 en D te vinden naast een voeding van circa 20V ongestabiliseerde gelijkspanning.
T0 is het clocksignaal 10 usec laag en 40 usec hoog
T1 is de data van de centrale naar de wissel/sein decoder.
D is de data van de terugmelder/handregelaar naar de centrale.
T0 en T1 zijn spanning gestuurde signalen, grof van CMOS level bij 5V.
D is een stroomgestuurd signaal, waarbij de stroom bepaald of je de waarde van T1 kunt overnemen.   

En je railsignaal is alleen van centrale naar locomotief decoders. Dit staat keurig beschreven in de diverse normen die al eerder genoemd zijn.

SX2: Tipje van de sluier oplichten.
Ik heb het laatste halfjaar met een aantal duitsers rond Munchen het SX2 protocol voor de wissel/sein/terugmeld en regelaar uitgezocht (zoals ik het noem de slave). Deze werkt nu voor alle centrales die het SX2 protocol ondersteunen. Van daaruit is het vrij gemakkelijk om daar weer de bus  aansturing van te maken. Echter om daar weer het railsignaal van te maken is niet zo gemakkelijk.
Je moet dan ook fysiek doen wat je in het SX2 gedeelte beloofd. Je railsignaal omzetten van Selectrix naar DCC of MM.

Genoeg voor nu.

Groet,

Gerard van der Sel.
« Laatst bewerkt op: 09 april 2020, 08:05:57 door gvandersel »
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

bask185

  • Offline Offline
  • Berichten: 543
Re: Arduino en Selectrix
« Reactie #102 Gepost op: 09 april 2020, 09:09:57 »
Citaat
Dan is je objecten structuur niet goed en is er grote kans op problemen. Zo ben je van alle problemen af en is het in mijn ogen netjes geregeld.
O ja je hebt een class gebruikt, ja dat verklaart wel het e.e.a.  (y). Ik zit weer lekker op te letten. Ik zou eigenlijk niet eens weten hoe je een ISR in een classe zou moeten bouwen  ??? Met meerdere objecten lijkt me dat onmogelijk  ???

Op werk programmeren we 8051 dingetjes in assembly maar ook in C. En om ISR gerelateerde problemen te voorkomen doen we eigenlijk nooit functies aanroepen vanuit interrupts, vandaar. Het kan enigszins wel maar better safe than sorry. + we hebben natuurlijk geen classes  ;D

Als een class gebruikt wordt om er slechts 1 object mee te maken dan ben ik zelf niet geneigd om een class te maken. Dan kan je voor je private variabelen gewoon static variabelen gebruiken die beperkt zijn tot hun .cpp bestand. Het is natuurlijk net wat je smaak is. Theekan, koffiekan, canbus!

@fredjansen Ik was alweer vergeten hoe we hier waren gekomen in de eerste. Maar jij stelde een bepaalde vraag een tijdje terug en ik geloof dat je nu voldoende antwoord heb op je vraag?

Mvg,

Bas





gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3509
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #103 Gepost op: 09 april 2020, 09:52:05 »
Fred had al eerder een antwoord, maar zag de hardware van de Duitser niet zitten.

De SX2 documenten:
https://www.dropbox.com/s/jxxtwgze0auxrl7/FCC_Interface_Doku.pdf?dl=0
https://www.dropbox.com/s/r46pakvd80bwpfk/SX-2-Definition.pdf?dl=0

HansQ jij hebt deze twee ook al enige tijd.

Groet,

Gerard van der Sel.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.