BeneluxSpoor.net forum

Vraag en antwoord => Elektronica en analoog => Topic gestart door: gvandersel op 02 juli 2015, 08:54:01

Titel: Arduino en Selectrix
Bericht door: gvandersel op 02 juli 2015, 08:54:01
All,

Zo de boel is binnen uit China (verstuurd 20 juni 2015):
(https://images.beneluxspoor.net/bnls/Arduino_China.jpg) (https://images.beneluxspoor.net/bnls/Arduino_China.jpg)
Na al het geweld om een Arduino te koppelen met DCC en een analoge baan kan ik als Selectrix rijder niet achter blijven. Als start een Arduino Uno gekocht (zijn zoveel varianten, dat ik met afvraag is het wel een Arduino Uno?). Tevens een experimenteershield waar een klein breadbord op zit. Om ook terugmelding van de Arduino te kunnen krijgen een display eraan en om de Arduino wat te kunnen vertellen een klein toetsenbord. Op internet is iets van een library (http://www.oscale.net/selectrix-arduino) te vinden voor een interface met Selectrix, maar daar staat bij dat deze niet met alle centrales werkt. Dit wordt dan een goed startpunt, om mijn ervaring met de AVR 2313 in te verwerken. Eerst kijken of alles wil werken en dan een knutselbordje maken met de Selectrix interface (goedkope variant).

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: smits66 op 02 juli 2015, 10:09:20
Hoi Gerard

Ik ga dit draadje volgen arduino en selectrix lijkt mij een goede combinatie.
Ik ben nu met zowel de arduino  als met selectrix bezig op mijn baan.

Blijf het draadje volgen.

Mvg Paul
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 02 juli 2015, 14:25:13
Kijk eens aan, helemaal mooi :D Redelijk snel binnen ook :)

zijn zoveel varianten, dat ik met afvraag is het wel een Arduino Uno?

Ja en nee. Ja, het is een Uno want de pinout klopt, heeft een ATmega328 en de Arduino bootloader. Nee, als je hem in China gekocht hebt en/of als je er geen €30,- voor betaald hebt is hij niet door Arduino.cc geproduceerd. (Blijf weg bij Arduino.org, dat zijn boeven (http://hackaday.com/2015/02/25/arduino-v-arduino/)...) Maar dat maakt voor gebruik niets uit. Het design voor de Arduino is open source dus iedereen mag ze produceren en verkopen.


Timo
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 02 juli 2015, 22:01:13
Ik zie dat je een CH340 UNO kloon hebt gekocht, dus met afwijkende USB chip. Als je problemen hebt, drop me dan een berichtje... :)
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 03 juli 2015, 15:19:35
Wow, ik wist dat ik een cloon had, maar dat hij een eigen kenmerk heeft, met specifieke problemen, heb ik weer.
Voorlopig nog niet toe aan het starten van de Uno, eerst de IDE maar eens in de lucht zien te krijgen. Ik zie alleen flitsen van het splash screen, dus van het weekend maar eens een "cmd" window erbij halen. Er schijnt achter de schermen java gebruikt te worden. iTrain werkt normaal dus dat stuk zal wel actief zijn, en ik hoop dat er wat verteld wordt in het "cmd" window en kijken of ik de boel aan de praat kan krijgen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 03 juli 2015, 17:18:56
...ik gebruik de oude versie van de IDE, met die nieuwe heb ik ook problemen... vooral met de AVR programmer aansturing...
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 03 juli 2015, 23:49:48
Verwacht je er problemen mee dan? Enige is dat Windows standaard de driver niet heeft maar om dat nu een probleem te noemen... Windows kan standaard de drivers voor mijn Dell printer ook niet vinden.

Ik heb een hele tijd Arduino IDE 1.0.6 gebruikt omdat dit een erg stabiele versie is. Er waren al wat nieuwe maar Arduino wil nog wel eens iets te snel een versie uitgeven. Maar sinds de release van 1.6.4 gebruik ik die. Deze is net zo stabiel maar bevat eindelijk de nieuwe AVR compiler. 1.6.5 is ook uit maar die heeft weer wat bugjes (maar vooral visueel dit keer).

Het draait inderdaad op Java dus het is slim om te kijken of je netjes de laatste versie (8.45) hebt (en x64 als je een 64-bit OS hebt). Überhaupt slim want er duiken nogal eens wat gaten op in Java...


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 04 juli 2015, 16:05:19
Na een beursbezoekje, was rustig en warm op de beurs, even in de tuin verder. IDE was een JAVA probleem. Een parameter op de commandline, welke ik bewust heb toegevoegd mag niet. Lijdt tot stoppen van de IDE. (Foutzoeken gaat makkelijk in een cmd window met het programma Arduino_debug.exe. Opstart parameter verwijderd en de IDE kwam tot leven.
De UNO erbij gepakt en de kabel in de USB poort geprikt. LED on en LED L allebei aan. ON had ik al uit het schema gehaald maar L was een verrassing. Niet de bekende geluiden dus de voorspelling van HansQ kwam uit. De drivers opgezocht en geinstalleerd. Na het weer inpluggen van de USB steker de bekende geluiden. Even gekeken welke poort het is en deze aan de IDE verteld. De sketch "blink" geopen en de code gecompileerd. Hierna de sketch naar de UNO geupload. En jawel, L begon te knipperen.
Dus de IDE en de UNO zijn beide succesvol ingebruik genomen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Robert E op 04 juli 2015, 21:37:24
Mocht je Eclipse (https://eclipse.org/downloads/) gebruiken voor andere zaken, daar is een Arduino plugin voor

http://www.baeyens.it/eclipse/

Die IDE van Arduino is net een typmachine uit 1600 zoveel lijkt het wel....

Mvg,

Robert
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 06 juli 2015, 08:35:56
Die plugin kende ik niet. Maar dat is leuk, kan ik straks naast de standaard IDE ook ontwikkelen in Visual Studio of Eclipse. Overigens de kleine IDE heeft wel wat. Het is toch al behelpen, met maar 2k RAM ipv etterlijke gigabytes.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: NTeering op 06 juli 2015, 10:21:20
Gerard,

Voor Visual Studio is er de volgende plugin:
http://www.visualmicro.com/

Nico
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 06 juli 2015, 11:00:02
Klopt, via de Nuget manager binnen no time te installeren. Ik had de compiler al gevonden, maar wil mezelf om de eerder genoemde reden met de orginele IDE aan de gang.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 06 juli 2015, 13:25:57
Eerst een stukje theorie voor we aan het echte werk gaan beginnen.
Ik verwacht dat het Selectrix systeem wat minder bekend zal zijn als het DCC systeem.
Het zijn beide systemen om treinen digitaal rond te laten rijden.
Het verschil zit in de signaal vormen en de bussen om de randapparatuur te benaderen.
Ik heb van beide systemen een simpel diagram gemaakt.
(https://images.beneluxspoor.net/bnls/DCC_opbouw.jpg) (https://images.beneluxspoor.net/bnls/DCC_opbouw.jpg)
Eerst het DCC systeem. Dit systeem kent 1 bus, de S88 bus. Deze is uitsluitend voor de terugmelding aan de centrale.
Alleen input signalen komen op deze bus. De randapparatuur (wissels en seinen) worden rechtstreeks op de rails aangesloten.
(https://images.beneluxspoor.net/bnls/SX_opbouw.jpg) (https://images.beneluxspoor.net/bnls/SX_opbouw.jpg)
Het Selectrix systeem kent ook 1 bus, de SX-bus. In tegenstelling tot een DCC systeem, worden hier alle randapparatuur op aangesloten.
Tevens is op deze bus een forse voeding aanwezig (20V, 3A) bestaande uit een afgevlakte gelijkspanning die samen met de treinen gedeeld wordt.
Het is dus niet een gestabiliseerde spanning, dat moet per decoder die is aansloten op de SX-bus zelf gedaan.

De Sx-bus bestaat uit 5 aders, waarvan zoals eerder geschreven twee een voeding zijn. De overige drie lijnen zijn de eigenlijke data lijnen.
Deze drie lijnen zijn de Kloklijn (T0), Transmitlijn (T1) en datalijn (D, receive), alles gezien vanuit de centrale.
Het signaal op de Kloklijn is simpel. Het is een negatieven puls van 10us met een herhalingsfrequentie van 50us.
In deze 50us wordt 1 bit verstuurd van centrale naar ontvanger of omgekeerd. Een complete boodschap bestaat uit 96 bits, waarvan ieder derde bit de logische waarde "1" bevat.
De enige afwijking op deze regel is het derde bit zelf, dit om de boodschappen te kunnen synchroniseren (iedere boodschap begint met "0001").
Op de SX-bus zijn 16 verschillende boodschappen gedefinieerd om alle 112 adressen (0 t/m 111) te kunnen versturen. Het systeem is dan ook een synchroonsysteem, dit in tegenstelling tot een DCC systeem, dat een asynchroon systeem is.
Een totale boodschap staat hieronder afgebeeld en is als volgt opgebouwd:
  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
Hierin is:
0: Logische "0"
1: Logisache "1"
S: Bit dat aangeeft of er spanning op de rails staat ("1") of niet ("0")
Ax: 4 bits die het nummer van de boodschap aangeven (1-complement)
Dx: 8 bits die tesamen de inhoud van een adres vormen

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

Zover de theorie. Ik zal vast wel wat dingen vergeten zijn, of naar aanleiding van vragen van jullie moeten toelichten. Dus de volgende aflevering wordt de hardware.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 06 juli 2015, 17:17:33
Hoi Gerard.... vraagje; heb jij een goeie spec van SX2?
Titel: Re: Arduino en Selectrix
Bericht door: vt175 op 06 juli 2015, 18:06:31
Eerst het DCC systeem. Dit systeem kent 1 bus, de S88 bus. Deze is uitsluitend voor de terugmelding aan de centrale.
Alleen input signalen komen op deze bus. De randapparatuur (wissels en seinen) worden rechtstreeks op de rails aangesloten.

 ??? ??? Volgens mij heeft DCC geen bus gespecificeerd voor terugmelding..... DCC is enkel de norm voor aansturen van lok en stationeren decoders
Om terugmelders en/of randapparatuur aan te sluiten hebben diverse fabrikanten eigen bussystemen ontwikkeld zoals S88, Loconet, Xbus etc
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 06 juli 2015, 18:25:35
Inderdaad, S88 is eigenlijk een M@rklin standaard.... maar wel enorm vaak gecombineerd met DCC...
Titel: Re: Arduino en Selectrix
Bericht door: vt175 op 06 juli 2015, 19:18:03
Inderdaad, S88 is eigenlijk een M@rklin standaard.... maar wel enorm vaak gecombineerd met DCC...

jep en ook met Märklin Digital-Formate (Motorola), mfx en wellicht ook onder selectrix rijders
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 09 juli 2015, 12:55:37
Sorry van de vergissing rond de S88 bus. Als Selectrix rijder ben je zo gewend dat er een weg is van de centrale af en een weg naar de centrale toe dat je "aanpassingen" aan de standaard als onderdeel van de standaard gaat zien. Maar je hebt gelijk het DCC systeem kent volgens de standaard alleen maar de sporen.

Wat betreft de SX2 beschrijving is dat voor mij een net zo groot raadsel als voor jou Hans. Sorry, kan inmiddels wel SX2 decoders programmeren, en heb zelfs een aantal multi-protocol decoders die ook SX2 begrijpen, maar er mee gereden heb ik nog niet.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 09 juli 2015, 13:04:25
We gaan verder met de hardware. De signalen T0, T1 en D zijn alle signalen die voor logisch "0" 0V is en voor logische "1" +5V.
De signalen zijn geen TTL of CMOS compatible signalen, maar in de praktijk blijkt dat CMOS uitgangen (zoals van microcontrollers) direct de bus kunnen interfacen.
Het belangrijkste signaal is het signaal op T0, het kloksignaal. Dit geeft aan wanneer er op de bus geschreven en gelezen moet/kan worden.
Het signaal op T0 ziet er volgens onderstaande afbeelding uit:
(http://home.hccnet.nl/gerard.vd.sel/selectrix/int_3.gif) (http://home.hccnet.nl/gerard.vd.sel/selectrix/int_3.gif)
Een volledige klokpuls duurt 50uS. Geschreven moet er geworden zo snel mogelijk na het naar 0 gaan van T0 (neergaande flank).
Gelezen mag er worden enige tijd na het naar 0 gaan van T0. Wachten op een microcontroller is "duur". Daarom lezen we op de opgaande flank op T0.
Een interface tussen de SX-bus en een microcontroller kan op twee manieren opgebouwd. Zoals het oorspronkelijk door Trix in een centrale is gedaan, met een LM339.
Hierbij ontstaat het volgende schema:
(https://images.beneluxspoor.net/bnls/SXbus_lm339.jpg) (https://images.beneluxspoor.net/bnls/SXbus_lm339.jpg)
De signalen T0 en T1 worden door een opamp gebufferd aangeboden aan een microcontroller. De signalen worden vergeleken met de halve voedingsspanning, zodat eventuele afwijkingen en storing weggefilterd worden.
Het signaal D wordt gemaakt met een transistor en een opamp. Dit signaal mag alleen door de interface beinvloed worden als het juiste adres op de bus actief is.
In rust worden zowel de opamp als de transistor zo aangestuurd, dat deze geen spanning op de de lijn D zetten.
Om de spanning naar +5V te trekken wordt de transistor aangestuurd, terwijl voor het sturen naar 0V de opamp aangestuurd wordt.
Mocht de microcontroller in een toestand komen waarbij beide aangestuurd worden, dan zal de serieschakeling van de twee weerstanden de stroom begrenzen.
De waarde van deze weerstand is door Trix op 100 ohm gedefieerd, om aan de kant van de centrale het signaal goed te verwerken.
Om een microcontroller te laten communiceren met de SX-bus moet de D lijn niet beinvloed kunnen worden door de microcontroller.
Een Atmel microcontroller heeft als een digitale in/uitgang als ingang wordt geschakeld een dermate hoogohmige toestand, dat tussenschakelen van een opamp/transistor niet nodig is.
Hierdoor is het mogelijk om de D lijn direct via een weerstand van 100 ohm te koppelen met een ingang van de microcontroller.
Bij het aansturen van de pin als uitgang moet er even opgelet worden, daar omschakelen van ingang naar uitgang er interne kortsluitingen op kunnen treden.
Hierdoor ontstaat het volgende simpelen schema:
(https://images.beneluxspoor.net/bnls/SXbus_weerstand.jpg) (https://images.beneluxspoor.net/bnls/SXbus_weerstand.jpg)
Gewapend met deze kennis een Arduino erbij gepakt en gekeken welke pennen van de Arduino gebruikt kunnen worden. T0 bepaald wanneer er geschreven en gelezen mag worden.
Het handigst is als dit signaal op een van de pennen INT0 (pen 3) of INT1 (pen 4). De andere signalen T1 en D mogen op een van de andere digitale pennen.
Op de header IOL zijn 8 signalen aanwezig. op pen 3 en pen 4 zijn de INT0 en INT1 aanwezig.
De pennen 1 en 2 zijn Rx en Tx voor het programmeren van de Arduino. De overige pennen kunnen willekeurig gebruikt worden.
(https://images.beneluxspoor.net/bnls/SXbus_Arduino.jpg) (https://images.beneluxspoor.net/bnls/SXbus_Arduino.jpg)
Via de connector IOL voeren we dus de signalen aan de Arduino. pen 3 wordt T0. Pen 4 laten we maar vrij voor een nader die ook een interrupt nodig heeft.
T1 komt dan aan pen 5 en D komt aan pen 6. Als de Arduino zelfstandig werkt op de SX-bus, dan zal deze ook voorzien moeten worden van gegevens.
Hiervoor is het drukknopje S1 aanwezig. Dit gaat naarpen 1 (Rx), omdat deze onder deze omstandigheid toch niet nodig is.
Een LED voor terugmelding aan diegene die de knop bediend heeft sluiten we aan op pen 2 (Tx). Die worden als dan toch niet gebruikt.
Blijft over een reset schakelaar (is wel handig) en een voeding voor de Arduino uit de SX-bus. Gekozen is voor een 7809, daar de voeding voor de arduino tussen de 7V en 12V moet liggen.

Ik verwacht dat er zo een werkbaar geheel is ontstaan. Zijn er nog dingen die ik over het hoofd heb gezien of geen rekening mee heb gehouden? Per solt ben ik net begonnen met het Arduino concept.

Groet,

Gerard van der Sel.
Samen met twee connectoren maakt dit de totale hardware.
Titel: Re: Arduino en Selectrix
Bericht door: Cees Baarda op 10 juli 2015, 11:23:54
Hoi Gerard,

persoonlijk zou ik tussen de bovenste pen van J3 en de + van C3 in het tweede schema nog een diode opnemen om verkeerd aansluiten op te vangen.
Zoals je zegt zijn de TX en RX aansluitingen voor het programmeren van de Arduino. Die zitten ook vast aan de USB chip. Ik zou die zo lang mogelijk niet benutten voor mijn toepassing. Je hebt voorlopig nog zat andere pennen over.

m.vr.gr. Cees.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 10 juli 2015, 13:05:01
Even van achter naar voren reageren.

Misschien moet ik de tekst over de pakketjes nog een keer lezen maar snap er nu geen fluit van  ;D Of bedoel je dat er 16 verschillende pakketadressen zijn waarin in ieder pakket altijd de data voor 7 adressen zit. Dus dat ik "Dx: 8 bits die te samen de inhoud van een adres vormen" moet lezen als "Dx: 8 bits die te samen de inhoud voor een adres vormen". Dus een 8-bit data pakket voor een adres.

De editor van de IDE is inderdaad aardig basic. Maar ze zijn dat wat aan het oppoetsen, in 1.6.5 zie je dat (erg buggy) ook al terug. Zelf schijf ik de meeste code in Notepad++. Dingen als de functie lijst, bookmarks, highlighting, auto compleet enz vind ik erg fijn. Je kunt Notepad++ naadloos laten samenwerken met de IDE (ook al heb ik daar de moeite nog niet voor genomen...).

Vraagje voor de Eclips en VB plugin, link je deze aan de Arduino IDE zodat je die libraries en compiler gebruikt of komt het met een eigen set? Laatste lijkt me erg onhandig omdat je dan niet gelijk loopt met de functies van een officiele IDE. (En dan heb ik het over Arduino.cc, niet de klojo's van Arduino.org).

Voor verkeerd aansluiten zou ik niet zo bang zijn als er met pluggen gewerkt wordt.

TX en RX zijn wel te gebruiken maar wel met beperkingen inderdaad. Op een Pro Mini zit de USB-serial chip niet dus dan is de RX te gebruiken voor een schakelaar. Maar op de Uno zit de USB-serial chip en deze sluit je dan kort met de schakelaar. Niet aan te raden dus. De TX lijn met een LEDje is prima, deze zit standaard zelfs al op de Arduino.

Toevoegen van een reset schakelaar lijkt me ook niet zo nodig, zit al op de Arduino zelf.

Het gebruik van pen nummers van headers is een beetje verwarrend. Het lijkt me logischer om gewoon de Arduino naamgeving aan te houden. Dit is immers al een vertaling van de ATmega pinnen. Anders blijven we omzetten. Viel me vooral op doordat je het hebt over dat interrupts zitten op pen 3 en 4. Dit zijn Arduino pin 2 en 3. Zelfde voor RX en TX op 0 en 1. Ook de namen IOL en POWER zijn zo wat onduidelijk. Tuurlijk werkt het maar het is van buiten nu wat lastiger te volgen.

Voor de voeding zou ik alleen gewoon een 7805 pakken. Dan kan je die ook belasten met eventuele randapparatuur die je met 5V moet voeden. De regulator op de Arduino zelf kan namelijk niet zo veel leveren. En nu zeg je, de Arduino moet een spanning tussen de 7V en 12V hebben dus dat werkt niet. Nouwja, hij heeft die spanning nodig op de DC-jack en Vin pin. Maar voed je hem via de 5V pin mag dit logischerwijze gewoon 5V zijn. De regulator op de Arduino laat je dan ongebruikt.


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 13 juli 2015, 12:14:13
@Timo,
Inderdaad het zijn 16 verschillende pakketten met ieder data voor 7 adressen.

@All,
Wat beterft de opmerkingen over het schema. Dit even op me in laten werken en van het weekend een nieuwe poging gemaakt.
Hier is dan het schema. Ik heb de connector van de voeding vervangen door een directe verbinding naar de connector van de Arduino.
OM het vermogen wat te beperken ga ik in twee stappen van circa 20V naar 5V. Eerst naar 12 en dan naar 5V. De 12 V wordt alleen gebruikt voor de voeding van de 7805.
(https://images.beneluxspoor.net/bnls/SXbus_Arduino_1.jpg) (https://images.beneluxspoor.net/bnls/SXbus_Arduino_1.jpg)
Afijn ik hoop dat het nu er wel mee door kan, kan ik aan het print ontwerp beginnen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 13 juli 2015, 13:44:25
Hoi Gerard.... Suggestie, tenzij je bang bent dat het koud word onder je baan... :)

Misschien es kijken naar een stepdown oplossing? Kijk es naar de Arduino ontwerpen als inspiratie?
Of nog simpeler, neem zoiets: http://www.ebay.nl/itm/291139667384

Zelfs ik ben ermee bezig nu, om 24V naar beneden te brengen naar 5V zonder 80% van het vermogen te verstoken... :)
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 13 juli 2015, 14:46:17
Van mij mag het vandaag vriezen onder de baan. Ik ga er solderen. Kan ik er een paar overnemen om zelf ook eens te experimenteren?

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 13 juli 2015, 15:24:14
Overnemen? Ik heb ze net besteld... lol... Over een week of wat binnen. Ik heb nu wel een paar grotere broertjes... Of losse LM2596-5V's?
Titel: Re: Arduino en Selectrix
Bericht door: Karst Drenth op 13 juli 2015, 15:46:36
Misschien es kijken naar een stepdown oplossing? Kijk es naar de Arduino ontwerpen als inspiratie?
Of nog simpeler, neem zoiets: http://www.ebay.nl/itm/291139667384

Werken perfect, komen ook in de DR5000. 'Slikken' zonder problemen ( Delta T max 10 graden ) een half Ampere van  19 naar 5 V... maarrrr... verkijk je niet op die 3Amp... dat is de 'Absolute Maximum Rating'. Die is alleen te halen bij voldoende koeling en diverse ground-plane voorzieningen in de print ;) :P


Grtzz,

Karst
Titel: Re: Arduino en Selectrix
Bericht door: vt175 op 13 juli 2015, 17:13:14
Werken perfect, komen ook in de DR5000.

Een vraag: wat is de verwachte levensduur? Ik heb weinig vertrouwen in deze goedkope stepdown oplossing uit China, leuk voor je zelf maar in commerciële producten......?  Wat je zelf ook schrijft, de specificaties zijn al erg optimistisch 0,5A ipv 3A, zegt iets over de kwaliteit van de gebruikte componenten.
Titel: Re: Arduino en Selectrix
Bericht door: Karst Drenth op 13 juli 2015, 17:21:42
Ha :)

Het beperkte heeft niet zozeer met de gebruikte componenten, als wel met de print en de dimensionering daarvan. Ik bedoelde uiteraard te zeggen, dat we dezelfde stepdown chip gebruiken. De passieve componenten worden natuurlijk correct gedimensioneerd. En niet dat het elementje in het product 1:1 overgenomen wordt ;)
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 14 juli 2015, 09:17:39
Zo nu weer terug naar het eigenlijke onderwerp. De Selectrix interface voor de Arduino. Er komt dus een gewone 78xx voeding in. Er is ruimte voor een kleine koeling gemaakt, dus 0,75 A is uit deze voeding te halen. Hiermee is de Arduino shield zo goed als vol. Aan de zijde waar bij de Arduino niet de USB aansluiting zit is de print verlengd om de connectoren voor de SX-bus aan te brengen. Hierdoor kan een volgende shield gewoon bovenop deze shield.
De print is dubbelzijdig ontworpen, omdat de chinezen dit standaard leveren. Verder is het wel relaxed ontwerpen, vooral rond de connectoren van de SX-bus.
(https://images.beneluxspoor.net/bnls/SXArduino_comp.jpg) (https://images.beneluxspoor.net/bnls/SXArduino_comp.jpg)
Aan beide zijden is een ground pane aangebracht. Aan de componentenzijde, omdat de koelvlakken aan ground (massa) hangen en zo dus zonder isolatie op de print gemonteerd kunnen worden.
(https://images.beneluxspoor.net/bnls/SXArduino_sol.jpg) (https://images.beneluxspoor.net/bnls/SXArduino_sol.jpg)
Het is gelukt om aan de soldeerzijde alle SX-bus massa aansluitingen zonder spoor onderbreking met elkaar te verbinden via de ground pane.
De print gaat in de loop van de week naar china om een te kijken wat die er van bakken. Bij anderen reeds mooie resulttaten gezien.
In de komende tijd dus verder met het schrijven van de software, want wachten op de print is niet nodig.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 14 juli 2015, 10:35:51
Ziet er goed uit! Alleen dat spoor vlakbij het schroefgat voor een van de 78xxjes is een short-risico? Niet te hard aandraaien, of een kunststof washer gebruiken?
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 17 juli 2015, 11:00:51
Zo mail gehad uit China, de print wordt gemaakt. De opmerking van HansQ is verwerkt.  Het spoor is samen met het spoor rechts onder die ook dicht langs de schroef is gegaan gewijzigd. Jullie zien over een paar weken het resultaat.
Dus verder met wat ik nu nog kan doen, de code. Wel hier is het .h file (class definition)
/*
 * SXArduino.h
 *
 *  Created on: 10.07.2015
 *  Version:    0.1
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on:
 *  Version:
 *
 *  interface hardware needed ! see

 Read SX Signal - SX Clock must be connected to Pin2=INT0 and
 SX Data must be connected to Pin4. For triggering a scope, a signal
 can be generated at Pin3 at a defined base address.
 Pin6 can be connected via a 150 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 SXArduino_H_
#define SXArduino_H_

#include <inttypes.h>

// define arduino pins, ports and bits
#define SX_T0           3     // must be INT1 !!
#define SX_T0_DDR     DDRD
#define SX_T0_PORT   PORTD
#define SX_T0_PORTPIN PORTD3
#define SX_T0_PINREG   PIND

#define SX_T1       5
#define SX_T1_DDR     DDRD
#define SX_T1_PORT   PORTD
#define SX_T1_PORTPIN PORTD5
#define SX_T1_PINREG   PIND

#define SX_D       6
#define SX_D_DDR     DDRD
#define SX_D_PORT     PORTD
#define SX_D_PORTPIN   PORTD6
#define SX_D_PINREG   PIND


// defines for state machine
#define SYNC           0
#define PWR           1
#define ADDR           2
#define DATA           3

#define MAX_DATACOUNT   7     // 7 dataframes in 1 SYNC Channel
#define MAX_DATABITCOUNT 12   // 12 bits in 1 frame

#define MAX_ADDRESS_NUMBER 112   // SX channels

class SXArduino {
public:
SXArduino();
void init(void);
uint8_t get(uint8_t);
uint8_t set(uint8_t, uint8_t);
uint8_t writing();
        uint8_t getPWRBit();
void setPWRBit(uint8_t);
void isr(void);

private:
void readPower(void);
void writePower(void);
void readAdr(void);
void readData(void);
void writeData(void);

uint8_t _baseAdr;                     // base address
uint8_t _dataFrameCount;       // frame counting
uint8_t _address;                     // current address on the bus
uint8_t _state;
uint8_t _bitCount;                    // bit counting

uint8_t _PWRBit;                      // Current state of POWER on track
uint8_t _newPWRBit;               // Command POWER on track

uint8_t _sx_write_address;      // stores address to write to
        uint8_t _sx_write_data;    // data to write
uint8_t _sx_writing;   // active during the actual writing
        volatile uint8_t _sx_write_busy;       // wait to send data, cannot accept new data

uint8_t _clk;
uint8_t _bit;

uint8_t _data;                        // data from the SX-bus (1 adsress)
uint8_t _sxbus[MAX_ADDRESS_NUMBER];   // to store the SX data

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

#endif /* SXArduino_H_ */

Blijft over de implementatie van de class (.cpp file)
/*
 * SXAduino.cpp
 *
 *  Created on: 16.07.2015
 *  Version:    0.1
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on:
 *  Version:
 *
 *  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).
 
 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 "SXArduino.h"


SXArduino::SXArduino() {
  pinMode(SX_T0, INPUT);      // SX-T0 is an input, no pull up to simulate tri-state
  pinMode(SX_T1, INPUT);      // SX-T1 is also an input
  pinMode(SX_D, INPUT);       // SX-D is also an input when not writing to allow other devices to write
}

void SXArduino::init() {
     // initialize function
     // initialize pins and variables

pinMode(SX_T0, INPUT);      // SX-T0 is an input, no pull up to simulate tri-state
pinMode(SX_T1, INPUT);      // SX-T1 is also an input
pinMode(SX_D, INPUT);       // SX-D is also an input when not writing to allow other devices to write

for (int i = 0; i < MAX_ADDRESS_NUMBER; i++) {
      // reset sx variable to zero
  _sxbus[i] = 0;
}

// start always with search for SYNC
_state = SYNC;
_dataFrameCount = 0;
_bitCount = 0;
_sx_writing = 0;
_sx_write_busy = 0;
_newPWRBit = 2;
_PWRBit = 0;                   // At start no power
}


// Read the bit that indicates if there is power on the track and store it.
// After reading the bit start processing the address.
void SXArduino::readPower()  {
if(_bitCount == 0) {
_PWRBit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;
_bitCount++;
} else {
_bitCount = 0;
_state = ADDR;
}   // end if _bitCount
}

// Write the bit that controls the power on the track if the user want to change it.
// After writing the bit the pin is changed from output to input
 void SXArduino::writePower()  {
if(_bitCount == 0) {
if (_newPWRBit != 2) {
bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, _newPWRBit); //  and write the newPWRBit
} else {
_newPWRBit = 2;
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to input
}   // end if _newPWRBit
}   // end if _bitCount
}

// Read the address bits.
// If base-address is read calculate the real address and
// check if we must write
// Proceed to the next stage DATA
void SXArduino::readAdr() {
_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;
switch(_bitCount) {
case 2:  // "Trenbit"
_bitCount++;
break;
case 5: // last "Trenbit"
// advance to next state
// we are processing the 7 data bytes (i.e. 7 SX addresses)
_state = DATA; 
_bitCount = 0;
//  _dataFrameCount is 0.
_address = 111 - _baseAdr;
if ((_address == _sx_write_address) && (_sx_write_busy == 1))  {
_sx_writing = 1;
} else {
_sx_writing = 0;
}
break;
case 0:  // A3
bitWrite(_baseAdr, 3, _bit);
_bitCount++;
break;
case 1:  // A2
bitWrite(_baseAdr, 2, _bit);
_bitCount++;
break;
case 3:  // A1
bitWrite(_baseAdr, 1, _bit);
_bitCount++;
break;
case 4:  // A0
bitWrite(_baseAdr, 0, _bit);
_bitCount++;
break;
}  //end switch/case _bitCount
}

// read 12 bits and convert it to a databyte.
// Read 7 databytes to read all data
// After reading 7 data bytes start searching for SYNC
void SXArduino::readData()  {
_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;
// continue read _data
// a total of 7 DATA blocks will be received
    // for a certain base-address
switch(_bitCount) {
case 2:  // "Trenn_bits"
case 5:
case 8:
_bitCount++;
break; // ignore
case 11: // Last "Trenn_bit"
// save read _data
_sxbus[_address] = _data;
_bitCount = 0;
_data = 0;
        // increment dataFrameCount to move on the next DATA byte
        // check, if we already reached the last DATA block - in this
        // case move on to the next SX-Datenpaket, i.e. look for SYNC
_dataFrameCount++;
if (_dataFrameCount == MAX_DATACOUNT) {
// and move on to SYNC _state
_dataFrameCount = 0;
_state =SYNC;
}
// calc sx address from baseAdr and dataFrameCount
// _address = (6-_dataFrameCount) * 16 + (15 - _baseAdr)
_address = ((6 - _dataFrameCount) << 4) + (15 - _baseAdr);
// check if we want to write
if ((_address == _sx_write_address) && (_sx_write_busy == 1))  {
_sx_writing = 1;
} else {
_sx_writing = 0;
}
break;
// Read the data bits
case 0:   // D0
bitWrite(_data, 0, _bit);
_bitCount++;
break;
case 1:   // D1
bitWrite(_data, 1, _bit);
_bitCount++;
break;
case 3:   // D2
bitWrite(_data, 2, _bit);
_bitCount++;
break;
case 4:   // D3
bitWrite(_data, 3, _bit);
_bitCount++;
break;
case 6:   // D4
bitWrite(_data, 4, _bit);
_bitCount++;
break;
case 7:   // D5
bitWrite(_data, 5, _bit);
_bitCount++;
break;
case 9:   // D6
bitWrite(_data, 6, _bit);
_bitCount++;
break;
case 10:  // D7
bitWrite(_data, 7, _bit);
_bitCount++;
break;
}  //end switch/case _bitCount
}

// write the 8 databits to the 12 bit frame
// When finished writing report it.
void SXArduino::writeData() {
switch(_bitCount) {
case 11:  // Last "Trenn_bit"
_sx_writing = 0;                             // Stop writing``
_sx_write_busy = 0;                          // Report end
case 2:
case 5:
case 8:  // "Trenn_bits"
bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH);      // Switch pin to input
break;
// Write the data bits
case 0:  // D0
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 0));
break;
case 1:  // D1
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 1));
break;
case 3:  // D2
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 2));
break;
case 4:  // D3
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 3));
break;
case 6:  // D4
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 4));
break;
case 7:  // D5
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 5));
break;
case 9:  // D6
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 6));
break;
case 10: // D7
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 7));
break;
}  //end switch/case _bitCount
}


// interrupt service routine (AVR INT1)
// driven by LEVEL CHANGES of the clock signal T0 (SX pin 1)
// LOW: writing
// HIGH: reading and control
void SXArduino::isr() {
     // 4 different states are distinguished
     //     1. SNYC = looking for a SYNC signal
//     2. PWR  = look for PWR bit
     //     3. ADDR = look for base address (0..15)
     //     4. DATA = decode the data-bytes

_clk = (SX_T0_PINREG & _BV(SX_T0_PORTPIN)) > 0;

switch(_state) {
case SYNC:                            // Search for 0 0 0 1
        if (_clk != LOW)  {
_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;   // read pin
if (_bit == LOW) {
_bitCount++;
} else {
if (_bitCount == 3) {     // sync bits 0 0 0 1 found
_state = PWR;         // advance to next state
}  // endif _bitCount
_bitCount = 0;            // reset _bitCounter
}  // endif _bit==LOW
}  // endif _clk!=LOW
break;
case PWR:
if (_clk == LOW)  {
writePower();
} else {
readPower();
}  // endif _clk==LOW
break;
case ADDR:
if (_clk != LOW)  {
readAdr();
}  // endif _clk!=LOW
break;
case DATA:
if (_clk == LOW)  {
if (_sx_writing == 1)  {
writeData();
}
} else {
readData();
}  // endif _clk==LOW
}  //end switch/case _state
}

// functions 'accessing' the SX-bus

// Read data from the array, filled by the isr.
uint8_t SXArduino::get(uint8_t ad) {
     // returns the value of a SX address
if (ad < MAX_ADDRESS_NUMBER)  {
   return _sxbus[ad];
} else  {
   return 0;
}
}

// Start writing data to the SX-bus.
// Check if writing or invalid address.
uint8_t SXArduino::set(uint8_t ad, uint8_t d) {
if (_sx_write_busy == 0)  {
if (ad < MAX_ADDRESS_NUMBER)  {
_sx_write_address = ad;
_sx_write_data = d;
_sx_write_busy = 1;
return 0;
}
return 2;    // address out of range
}
return 1;  // don't accept new data
}

// Check if writing is finished
// (A write lasts between 600usec and 80 msec)
uint8_t SXArduino::writing() {
return _sx_write_busy;
}

// Read POWER status from the SX-bus
uint8_t SXArduino::getPWRBit() {
    return _PWRBit;
}

// Write POWER status to the SX-bus and control a connected central.
void SXArduino::setPWRBit(uint8_t val) {
if (val == 0 || val == 1) {
_newPWRBit = val;
}
}
Zo nu nog een paar dagen testen, waarbij ik zelf voor clock (T0) ga spelen en de T1 lijn ook maar bedien.
Hiervoor een kleine sketch geschreven die regelmatig het innerlijk van de isr terugmeld (hiervoor het .h file aangepast)
Hierbij de sketch:
#include "SXArduino.h"

// SX-bus interface
SXArduino SXbus;                 // Get access to the SX-bus

void sxisr(void) {
    // if you want to understand this, see:
    // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1239522239   
    SXbus.isr();
}

void setup() {
    // put your setup code here, to run once:
    // Serial communication
    Serial.begin(9600);      // open the serial port

    // SX-bus communication
    SXbus.init();
    // CHANGE on INT1 triggers the interrupt routine sxisr (see above)
    attachInterrupt(1, sxisr, CHANGE);
}

void loop() {
    // put your main code here, to run repeatedly:
    Serial.println(SXbus._state);
    Serial.println(SXbus.get(111));
}
Ik heb hier in iedergeval een vraag over, waarom moet het .cpp en .h file in de ide geopend zijn? Zonder die twee kan ik niet compileren.
De directorie structuur is:
sketchSXArduino.ino [file]
libraries  [map]
libraries\SXarduino [map]
libraries\SXarduino\Sxarduino.h [file]
libraries\SXarduino\Sxarduino.cpp [file]
Of te wel wat is er fout ingesteld?

Groet,

Gerard van der Sel.

Titel: Re: Arduino en Selectrix
Bericht door: smits66 op 17 juli 2015, 19:02:02
Hoi Gerard,

Ik heb de sketch en de library's gedownload, en proberen te testen, helaas zit er een fout in de library van SXArduino.h

Foutmelding arduino ide " unit8_t SXArduino::_state is private
  unit8_t _state; "

Citaat
De directorie structuur is:
sketchSXArduino.ino [file]
libraries  [map]
libraries\SXarduino [map]
libraries\SXarduino\Sxarduino.h [file]
libraries\SXarduino\Sxarduino.cpp [file]

Ik denk dat het moet zijn (dit geld voor Linux maar ik denk ook voor Windows)

sketch Arduino.ino

/mijn documenten/sketchbook/SXArduino/SXArduino.ino

En de libraries SXArduino.h en SXArduino.cpp in :

/mijn documenten/sketchbook/libraries/SXArduino/SXArduino.h
/mijn documenten/sketchbook/libraries/SXArduino/SXArduino.cpp

Dan kun je gewoon je sketch compileren.

Als je SXArduino print klaar en getest is, wil ik er alvast een bestellen, tenminste als deze print gebruikt kan worden om verschillende selectrix sturingen mee te kunnen maken, dat is wat ik uit je verhaal begrijp.
 
Kan ik misschien goed combineren met mijn Arduino Analoge modelbaan sturing, met de selectrix te kunnen aansturen.(seinen, wissels ,spoorweg overgangen ,locomotieven enz.)

Mvg Paul
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 18 juli 2015, 10:00:15
Paul,

De sketch is om de library's te testen. Er ziiten zoals geschreven twee wijzigingen in het .h file om het geheel compileerbaar te maken. Deze wijzigingen zijn:
- "private:" uitcommentarieren (// ervoor zetten)
- _state volatile maken (volatile ervoor zetten, zie _sx_writing_busy)
Dan zal het geheel compileren.
Bedankt voor de tips. Ik denk dat ik de fout gevonden heb. Mijn sketch staat op een willekeurige plaats.
Zal de sketch naar de goede plaats verplaatsen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 19 juli 2015, 13:50:05
Hoi Gerard,

Structuur van alles is erg belangrijk. Arduino gaat er standaard vanuit dat je werkt vanuit je Sketchbook. En daarin de structuur hebt als:
[sketchbook]\[sketchname]\[sketchname].ino

Als je iets include dan kijkt Arduino IDE naar drie plaatsen.

Wat me nog opvalt aan de library is dat je niet in zowel de .h als de .cpp #include "Arduino.h" doet. In plaats daarvan include je intypes. Als je gewoon Arduino.h dan is dat niet meer nodig.

En waarom werkt het niet met private? Zelf ben ik overigens geen fan van private zo gebruiken, ik zou gaan voor protected. Dan blijft overerven makkelijk mogelijk.

En als ik zo even snel kijken, horen dan niet nog meer variabele volatile te zijn?



Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 19 juli 2015, 17:36:31
Directorie structuur is inmiddels goed gezet. Moest in preferences de goede directorie aanwijzen.

Waarom bepaalde variabelen private. Je gebruikt OO termen, dus ik zal eerst een kleine toelichting geven voor de meelezers.
Private: alleen te benaderen van uit de eigen class
Protected: alleen te benaderen vanuit de eigen class en de class die deze class als base class gebruikt (inheretance)
Public: iedereen die de class kan benaderen kan hier bij.

Nu het antwoord: De meeste van deze variabelen en functions zijn  onderdeel van de ISR. Als deze van buiten benaderbaar zijn, kan deze in de war raken. Dus ik zet ze private. Verder heeft Protected zetten geen zin. Ik verwachtniet dat deze class ooit geinherrit wordt. En tenzij de variabelen public staan zijn ze toch niet te benaderen. (Bij instantieren is protected hetzelfde als private.)

Tijdens het testen lees ik wat stuurvariabelen van de ISR om de voortgang te volgen. Inmiddels is _bitCount ook volatile geworden.
Waarom zo weinig variabelen volatile. Volgen arduino.cc hoeven alleen de variabelen die zowel door de ISR als het programma gebruikt worden volatile verklaard te worden. Dus waarom meer.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 19 juli 2015, 20:56:22
Je hebt gelijk dat als een variabele alleen vanuit de ISR benadert wordt dat volatile niet nodig is. Daar had ik eigenlijk niet zo op gelet. Zelf had ik denk ik dan een static variable in de IRS gebruikt maar dit is natuurlijk ook prima  (y)

Dat je private kies ipv protected omdat je denkt dat je class nooit geinherrit wordt is misschien wat kort door de bocht. De makers van de Servo classe hadden ook nooit gedacht dat iemand de classe zou willen erven maar daar wilde ik toch graag dingen aan toevoegen. Nu heb ik dat opgelost door mijn eigen branch te maken maar dit had makkelijk met erving gekund. (Nu dit alleen nog eens netjes op GitHub krijgen....)


Timo
Titel: Re: Arduino en Selectrix
Bericht door: smits66 op 20 juli 2015, 00:36:45
Hoi volgers,  Arduino en Selectrix

Hoewel ik nog niet heel erg thuis ben in het programmeren van de Arduino, wil ik een kleine bijdrage leveren om dit project een klein impuls te geven, het is geen programma aanpassing.

Ik heb geprobeerd om een functiedecoder (voor 1 wissel, ik kan er meer tekenen in het schema, echter is het schema voor elke wissel gelijk) te maken die uitwisselbaar is met selectrix

Hiervoor heb ik een selectrix functiedecoder uit elkaar gehaald  :o  om te kijken hoe het werkt, aan de hand van de koperbanen op de functiedecoder heb ik een schema gemaakt van een wisselsturing die op dezelfde manier werkt als de originele selectrix decoder.

Ik wil deze week proberen er een werkende prototype van de Arduino-Selectrix functiedecoder te maken.
Ik moet allen nog bekijken hoe ik deze Arduino-Selectrix functiedecoder een adres kan geven zodat ik met de selectrix cc2000 of via Itrain / Rocrail een adres kan uitlezen.

De processor van de selectrix decoder leest het adres uit aan de hand van 7 input porten via een 7 tal dip-switchen op de print, ik moet nu kijken of ik in de setup van een Arduino sketch een adres kan zetten die de cc2000 kan uitlezen, dit moet via een softwarematige oplossing.

Op de 4-voudige selectrix functiedecoder kun je via aansluiting 1 en 2 een wisselspaning van 12 tot 14 volt zetten, deze word dan gelijkgericht en afgevlakt door de brugcel en condensator,  op de aansluiting 3, 4, 5 sluit je de wissel aan (3 en 5 zijn de spoelen en 4 de gnd)

Het schema :

(https://images.beneluxspoor.net/bnls/ArSlx2Wd_2.png) (https://images.beneluxspoor.net/bnls/ArSlx2Wd_2.png)

Hoe werk het?

Ik stuur transistor T1 via de Arduino port aan,  T1 zal in geleiding komen en 1 van de 2 wissel-spoelen aantrekken, na 250 milliseconden (software matig)  zal de Arduino port weer laag worden en zal T1 niet meer geleiden, zodoende kan de wissel-spoel niet verbranden ,minitrix wissels hebben geen eind afschakeling.  (jip en janneke taal)

Is het schema niet correct dan hoor ik dat graag zodat ik het schema kan aanpassen.

Ik wil verschillende selectrix componenten te proberen te ontwerpen voor Arduino-Selectrix geschikt te maken.

voor zo ver mijn bijdrage.

Mvg Paul   ;)
Titel: Re: Arduino en Selectrix
Bericht door: Calimero op 20 juli 2015, 05:30:54
Zodra er 1 van de torren in geleiding gaat heb je een glas harde kortsluiting (via de diodes).
Titel: Re: Arduino en Selectrix
Bericht door: smits66 op 20 juli 2015, 06:05:26
Hoi, Ronald

Bedankt voor je opmerking .
Ik zie dat de diodes verkeert zitten, dit moeten blus diodes zijn en
moeten parallel over de spoel heen staan, niet in serie met de spoelen.
Ik zal vanavond het schema aanpassen.

Mvg Paul
Titel: Re: Arduino en Selectrix
Bericht door: Calimero op 20 juli 2015, 08:10:52
Ik denk ook dat je de CT (center tap) van de spoel aan de plus moet hangen.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 20 juli 2015, 12:10:34
Paul,

Je gaat aardig vlot. Ik ben de software aan het testen. Heb er al wat kleine foutjes uitgehaald, dus deze versie is zeker niet geschikt om in je projecten te gebruiken. Wat beterft programmeren van randapparatuur aangesloten op de SX-bus. Dit is met geen van de door jouw genoemde programma's te doen. Maar kijk even op www.vandersel.nl (http://www.vandersel.nl) onder Selectrix -> Download. Hier vindt je twee programma's:
- SX-tester: Hiermee kun je beperkt de SX-bus aansturen. Tevens zijn er twee regeleaars voor locomotieven. (Ook bestaat de mogelijkheid een decoder in SX1 formaat met de CC2000 te programmeren).
- InOut: Leest/bestuurt 8 adressen van de SX-bus in een keer.

Hier kan je wel wat mee denk ik.

Als de librarry af is wil ik er twee voorbeeldjes mee maken. De eerste is een seriële interface volgens het protocol dat jij nu gebruikt (de 66842 seriële interface), het tweede loop ik te denken aan een RGBW aansturing. Dit zal een zelfstandig randapparaat zijn dat op de bus kan worden aangesloten. Hierin komt tevens het programmeren van randapparaten aan bod. Ik wil daar eerst nog even met Karst Drenth over e-mailen, want ik wil zijn commando structuur, zoals hij die in zijn RGBW aansturing voor DCC gebruikt, gaan gebruiken. Ik wil even weten hoe hij daar tegenover staat.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 20 juli 2015, 13:35:45
Beide wilde ik gisteravond plaatsen maar ik had mijn vriendin al te weinig aandacht gegeven  :-X

Inderdaad, zo heb je mooi vuurwerk met de diodes en geen spanning op de uitgang.

Overigens denk ik dat je als blusdiodes ook gewoon 1N4148 kunt pakken.

Voor de transistor zou je ook beetje kunnen zoeken of voor een mosfet gaan, net wat je hebt liggen. Ligt er een beetje aan hoe veel stroom je ze wilt laten schakelen. Als je zelf een print laat maken zijn SMD MOSFETs een mooie keuze. Deze zijn erg goedkoop, kunnen vaak rond de 4A aan en op een gemaakte PCB zijn ze prima te solderen.

Maar Paul, wat voor centrale heb je eigenlijk? De Selectrix bus heeft wel wat maar het heeft ook wel weer zijn beperkingen.


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 20 juli 2015, 14:05:51
Paul heeft een CC2000. Naast een handregelaar voor de locomotieven 1 t/m 9, ook de mogelijkheid om locomotieven 1 t/m 9 te programmeren. Heb er zelf jaren mee gereden. Uiteindelijk de centrale afgeschreven toen een van de buz71A voor de zoveelste keer de geest gaf.
Mogelijkheden:
- Rijden van treinen;
- Een SX-bus, welke een kopie van de rails bevat.
Voeding voor treinen en SX-bus is rond de 4A bij 15V ac. Ik heb zelf jaren gereden met een SX-bus power booster, eigen uitvinding ;).
Hierdoor 3,5 A voor treinen en 3,5 A voor de randapparaten.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 20 juli 2015, 14:13:02
Reactie op schema Paul,

Ik zou niet de GND van de SX-bus gebruiken, maar de GND van de Arduino. Deze zijn in principe gelijk, maar het is een beetje krom een schakeling met een Arduino te besturen en vervolgens de GND van een ander systeem te gebruiken.
Dus de twee SX-bus stekkers kun je uit je schema halen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: smits66 op 20 juli 2015, 18:48:57
Hoi

Iedereen bedankt voor de opmerkingen.

Ik heb het schema aangepast, het zou nu moeten werken (moet ook geen schema's gaan tekenen laat op de avond  :P)

(https://images.beneluxspoor.net/bnls/ArSlx2Wd_2.png) (https://images.beneluxspoor.net/bnls/ArSlx2Wd_2.png)

Timo en Gerard,

Ik gebruik de central control 2000 en de loc control 2000 in combinatie met de selectrix computer interface, deze set is via de computer gekoppeld aan Itrain en Rocrail, hoewel ik rocrail nog niet goed werkend heb.

De bezetmelder, functie-decoder en handmatig en halfautomatische trein sturing werkt wel via Itrain, de encoder A + B ben ik nog niet mee bezig, dat komt later.

Gerard , Helaas heb ik niets aan jou programmaatjes deze zijn voor Windows, ik draai Linux op mijn computer.

Ik wacht geduldig af, ik kan de sturing ook testen met de Arduino en later evt selectrix sx bus toevoegen.

Timo,

Ik probeer zo dicht mogelijk bij het originele ontwerp te blijven, bovendien hou ik wel van een robuuste sturing, voor de prijs hoef ik het niet te laten  de BD675 kost 30 a 35 cent de stuk, ik denk dat een mosfet net zo duur of duurder is, de 1n4148 kan ook wel als blus diode gebruiken, echter heb ik nog een stuk of 500, 1N4007 diodes thuis liggen (in schema 1N4004).
Voorlopig ben ik nog niet met een print ontwerp bezig, eerst de sturing goed testen en dan verder ontwerpen.

Mvg Paul
Titel: Re: Arduino en Selectrix
Bericht door: Calimero op 20 juli 2015, 19:28:59
Ik heb de datasheet van de BD675 even bekeken en het lijkt dat deze al een diode ingebouwd heeft, precies zo
als jij de 1N4004 er in hebt zitten. Normaalgesproken is het gebruikelijker om de diodes vanaf de spoel naar de
plus te plaatsen maar dit kan ook. De tegen EMK loopt dan via de elco in de voeding. Mocht die stoor puls  door
die elco toch problemen geven dan weer gewoon (of uit voorzorg) de diodes van de spoel naar de plus plaatsen.
Hoe dichter je ongewenste dingen bij hun bron de kop in drukt hoe beter zou ik denken. De extra diode die in de
tor zit zal geen probleem zijn, beide diodes staan immers in sper, behalve voor de tegen EMK.
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 21 juli 2015, 11:05:48
....daarom zou ik ook verwachten dat de diodes in het schema van Paul over de wisselspoelen geplaatst zouden zijn en niet over de collector-emitters van de darlingtons...
Titel: Re: Arduino en Selectrix
Bericht door: smits66 op 21 juli 2015, 23:33:36
Hoi, mensen

@Hans en Ronald

Bedankt voor de input.

Ik heb het schema aangepast, zoals jullie aangeven. ;)

(https://images.beneluxspoor.net/bnls/ArSlx2Wdr2.png) (https://images.beneluxspoor.net/bnls/ArSlx2Wdr2.png)

De componenten zijn direct overgenomen van de selecttrix functiedecoder 66821 (donkergrijze kast)
Alleen heb ik de weerstand aangepast van 2200 ohm naar 820 ohm.

@Gerard

Gerard vind je het een probleem als ik af en toe een schema en evt toelichting in dit draadje zet, anders zal ik het in mijn eigen draadje zetten" arduino analoge modelbaan sturing".

Ik hoop dat ik met dit draadje "Arduino en selectrix"  mijn modelspoorbaan zowel de digitale als de analoge sturing kan gaan ontwikkelen.

Mvg Paul  :)



Titel: Re: Arduino en Selectrix
Bericht door: Calimero op 21 juli 2015, 23:49:51
Je stuurt de schakeling in met TTL niveau (= 5V) ? Want dan klopt de verlaging naar 820 ohm heel netjes.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 22 juli 2015, 12:43:11
@Calimero:
De uitgang is de Arduino ucontroller, dus 5V "cmos".

@Paul:
Tijdens het grote testen geen problemen mee. Als we midden in een discussie zitten niet graag. Dit soort schakelingen zijn standaard en zul je wel vaker zien.

@All:
Testen loopt lekker. SYNC akkoord, PWR lezen akkoord en ADDR lezen akkoord. Schrijven zodra de print er is. Dat is makkelijker te doen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Calimero op 22 juli 2015, 12:49:52
TTL of 5V cmos maakt niet zo heel veel verschil. Cmos gaat meende ik wat dichter naar de voedingslijnen en
voldoet daarmee ook prima aan de TTL norm. M.a.w. ook bij 5V cmos is die 820 ohm prima.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 22 juli 2015, 13:04:18
TTL en CMOS lijken inderdaad erg veel op elkaar. Een groot verschil is dat de uitgang in "1" toestand haast geen stroom kan leveren. Bij deze schakeling wordt nogal wat stroom verwacht (redelijk aantal mA's). Daarom blij dat het een "CMOS" uitgang is.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 23 juli 2015, 14:40:08
Ik probeer zo dicht mogelijk bij het originele ontwerp te blijven, bovendien hou ik wel van een robuuste sturing, voor de prijs hoef ik het niet te laten  de BD675 kost 30 a 35 cent de stuk, ik denk dat een mosfet net zo duur of duurder is, de 1n4148 kan ook wel als blus diode gebruiken, echter heb ik nog een stuk of 500, 1N4007 diodes thuis liggen (in schema 1N4004).
Voorlopig ben ik nog niet met een print ontwerp bezig, eerst de sturing goed testen en dan verder ontwerpen.

Als je er echt blij wil blijven is daar niets mis mee, werken zal het.  ;) Maar zeker als je in China besteld (eBay) kan je nog best goedkoop uit komen. Bijvoorbeeld de IRF7313 (http://www.ebay.nl/itm/50PCS-IRF7313-IRF7313TRPBF-MOSFET-2N-CH-30V-6-5A-8-SOIC-IR-NEW-GOOD-QUALITY-R10-/301576483566?pt=LH_DefaultDomain_0&hash=item46375bf2ee), hier heb je er mee één per wissel van nodig (dual channel) en kost je 20 cent per wissel. Makkelijk te solderen behuizing, lage Ron (weinig warmte dus) en nog robuuster (6,5A ipv 4A).

Maar absoluut niet dat je het ontwerp aan moet passen of dat het niet werkt maar weet wat er nog meer te krijgen is :)


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 23 juli 2015, 14:48:17
Hm, leuk dingetje. Lijkt me wel wat voor de RGBW aansturing. Bedankt voor de tip.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 24 juli 2015, 08:46:45
Bericht uit China. De print is gemaakt en onderweg.  Hopen dat de print er een beetje leuk uitziet. Dat weten we over een paar weken. Volgende vraag. Op de print komen headers. Lange pinnen aan de onderkant. Wie weet hoe die dingen heten, en waar ze te verkrijgen zijn?

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Fritsprt op 24 juli 2015, 09:39:00
Bedoel je deze?
(https://images.beneluxspoor.net/bnls/Stackable_header.jpg) (https://images.beneluxspoor.net/bnls/Stackable_header.jpg)

Zoek eens op stackable header.

Succes, Frits
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 24 juli 2015, 09:53:39
Ja, die bedoelde ik. Dus bedankt voor de naam. Nu nog waar te koop in lengtes van 20/25 pinnen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Fritsprt op 24 juli 2015, 10:55:23
Hallo Gerard,

Waarom 20 of 25 pins? Voor de Uno heb je 2x 6pin en 2x 8 pin nodig. Op Ebay kan je ze voor weinig kopen. Zowel in 6, 8 en 10 pins uitvoering. Of complete setjes zoals deze (http://www.ebay.com/itm/Stackable-Shield-Header-Set-Kit-6-8-Pin-Tall-For-Arduino-Shield-good-new-/261471095151?pt=LH_DefaultDomain_0&hash=item3ce0e4496f)

Succes Frits
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 24 juli 2015, 12:23:13
Frits,

Ik heb een REV3 Arduino. Deze heeft andere connectoren. De beide connectoren (links en rechts) het dichts bij de voeding hebben 2 pennen meer. Dus die setjes zijn leuk, maar zijn niet voor REV 3 Arduino's, die op dit moment ongeveer iedereen heeft schat ik zo.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Silvolde op 24 juli 2015, 13:17:56
Ja, die bedoelde ik. Dus bedankt voor de naam. Nu nog waar te koop in lengtes van 20/25 pinnen.

Groet,

Gerard van der Sel.

Gerard, kijk hier eens: https://www.reichelt.de/Buchsenleisten/2/index.html?&ACTION=2&LA=2&GROUPID=3221;SID=10VUdiIKwQATIAAEsL3OE8a76ea35b7f3a3799db4e35907fcfbcd

Groet, Rob
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 24 juli 2015, 13:33:03
Die zijn niet stackable! volgens mij heeft Reichelt die niet? Kijk es hier:
http://www.ebay.nl/itm/10PCS-6Pin-2-54-mm-Stackable-11mm-Long-Legs-Female-Header-For-Arduino-Shield-J1-/301630860942
http://www.ebay.nl/itm/10PCS-8Pin-2-54-mm-Stackable-11mm-Long-Legs-Female-Header-For-Arduino-Shield-/351302303115
http://www.ebay.nl/itm/10PCS-10Pin-2-54-mm-Stackable-11mm-Long-Legs-Female-Header-For-Arduino-Shield-J1-/301630866450
Idioot hoge prijzen voor China, maar ik heb ze nog niet veel goedkoper gezien...
Titel: Re: Arduino en Selectrix
Bericht door: Fritsprt op 24 juli 2015, 15:17:06
Gerard, ik kijk net even naar je eerste foto met daarop de rev 3. Hiervoor zijn setjes met 6, 2x 8,en 10 pins header op EBay.

Verstuurd vanaf mijn HTC One X met Tapatalk

Titel: Re: Arduino en Selectrix
Bericht door: Timo op 25 juli 2015, 10:08:05
Die stackable headers zijn wel leuk maar ze zijn niet zo stevig als normale headers (en duurder). De pinnen zijn een stuk slapper. Dat is waarom je op veel shields dus gewoon normale headers hebt. Onder male, boven female, net iets versprongen van elkaar. Maar daar is het een beetje laat voor als de PCB de deur al uit is :p


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 29 september 2015, 09:23:07
Zo, vakantie voorbij, chinezen hebben hun werk gedaan en ook de duitsers aan het werk gezet. Alles is binnen gekomen tijdens mijn verblijf in het buitenland, dus we kunnen vrolijk verder. Nou je vrolijk. Die chinezen copieren alles, zelf de fout in het printontwerp. Een condensator zit verkeerd om, waardoor de +12V hard verbonden zit met de GND.
(https://images.beneluxspoor.net/bnls/OnderdelenArduinoSX.jpg) (https://images.beneluxspoor.net/bnls/OnderdelenArduinoSX.jpg)
Maar een kleine schroeven draaier weet dit in een paar tellen te verhelpen. Even een paar kritische onderdelen op een van de printen gelegd en gekeken of ze passen. Wel die passen maar de weerstanden mag ik bij een volgend ontwerp wel wat groter selecteren. 10 mm is volgens mij een normalen lengte, maar dat is van soldeereiland naar soldeer eiland. terwijl het huis al 10 mm is. Ik ga er 5 in elkaar zetten, waarbij een drietal exemplaren gebouwd naar mij bekende Selectrix rijders gaan om te kijken of ze ook met hun centrales willen werken.
Voorlopig de software ontwikkelen voor het eerste project: een Arduino versie van de seriële interface (66842) echter nu met een USB aansluiting.
Als basis hiervoor het voorbeeld KeyboardSerial gebruikt. Hiermee kan ik de USB poort lezen en schrijven. Helaas geen andere protocollen om de SX-bus aan te sturen, dus als iemand die kent laat maar weten.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 29 september 2015, 10:23:49
Een foutje kan altijd, jammer maar helaas. En voor de onderdelen passen, ik print het altijd vooraf op ware grote uit om te controleren of alle footprints wel kloppen.

Overigens, wat voor een weerstanden gebruik jij  ??? 10mm zou meer dan genoeg moeten zijn voor de standaard 1/4W weerstanden. Zelf maak ik ze altijd 300mil (+-7,6mm) van gat tot gat. Dat pas dan precies als je de leads strak om buigt. Zo doe ik het op experimenteerprint ook altijd (2 gaatjes overslaan onder de weerstand, 100mil per sprong). Of ben jij voor flinkere weerstanden gegaan?


Timo
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 29 september 2015, 18:07:44
Aha! Reichelt labeltjes! :) Toch altijd weer een beetje Sinterklaas, zo'n Reichelt doos... veel soldeer-plezier en succes!
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 05 oktober 2015, 13:48:28
Zaterdag, terwijl de rest van de forum leden op een andere plaats in het dorp was, is de soldeerbout opgewarmd en zijn de onderdelen op een print geplaatst. Dit was snel gedaan, maar enkele zaken moesten toch nog even opgezocht worden (schroeven en moeren M3).
(https://images.beneluxspoor.net/bnls/GebouwdArduinoSXjpg.jpg) (https://images.beneluxspoor.net/bnls/GebouwdArduinoSXjpg.jpg)
De gebouwde versie, nog zonder de connectoren, omdat de gaten te klein zijn. Ga ze zo spoedig mogelijk opboren naar 0,8 mm.
(https://images.beneluxspoor.net/bnls/BovenaanzichtArduinoSXjpg.jpg) (https://images.beneluxspoor.net/bnls/BovenaanzichtArduinoSXjpg.jpg)
(https://images.beneluxspoor.net/bnls/ZijaanzichtArduinoSXjpg.jpg) (https://images.beneluxspoor.net/bnls/ZijaanzichtArduinoSXjpg.jpg)
Op het bovenaanzicht/zijaanzicht is goed te zien dat de weerstanden wel netjes passen, maar niet veel groter hadden moeten zijn  ;D

Wat beterft je vraag Timo, om bepaalde delen van de software niet private, maar protected te zetten heb ik nog eens nagedacht. Wat zou jij dan willen hergebruiken door overerving?

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 05 oktober 2015, 13:51:01
Aha, connectortjes binnengekregen, maar een maatje te groot? :)
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 05 oktober 2015, 15:34:34
Denk eerder gaatjes te klein 0,6 mm. Ik had een template gevonden op Internet met de connectoren en de gaten op de juiste plaats. Nu blijken in iedergeval de gaten van de connectoren te klein. De bevestigingsgaten zitten op het eerste gezicht wel goed.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 06 oktober 2015, 11:06:29
0,6mm is inderdaad wel klein voor pinheaders. Zelf heb ik ze ook met 0,8mm gemaakt, dat is mooi strak. Maar ziet er goed uit!

Wat betref overerven, ik zou op dit moment zo snel niets willen aanpassen aan de library. Maar zou ik of iemand dat in de toekomst willen hoeft er niet gelijk een fork gemaakt te worden. Kan er gewoon een child voor geschreven worden met alle wijzigingen die iemand wil omdat in de child alle parameters van de parent gewoon aanwezig zijn. Het geeft in mijn oen dus iets meer gemak als je misschien eits specifieks zou willen.

Ga je het eigenlijk op iets als GitHub zetten? Dan zouden verbeteringen al makkelijk verwerkt kunnen worden door een pull request.


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 21 oktober 2015, 11:54:54
Zo alles samengebouwd en goed gecontroleerd. Naast de fout van de condensator kan er tenslotte best nog een aanwezig zijn. Alles klopte. Hierna de kale print op de SX-bus aangesloten. Kijken of de juiste spanningen op de juiste plaatsen staat. Ook dit klopte, dus het bordje maar bovenop de Arduino gezet,
(https://images.beneluxspoor.net/bnls/SXArduino_hardware.jpg) (https://images.beneluxspoor.net/bnls/SXArduino_hardware.jpg)
en verbonden met de computer. Eerst weer het demo programma van eerder laten lopen. Dit was eigenlijk een beetje een teleurstelling. De door mij gewenst verandering van waardes bleef uit. Is er iets fout? Na lang nadenken bleek de variabele _state toch niet zo dynamisch als gedacht. Hij doorloopt de waardes 0 t/m 3, waarbij de waardes 0 t/m 2 ongeveer 10% van de tijd aanwezig zijn. De rest van de tijd staat _state op 3. Andere variabele opgezocht die wel het gewenste gedrag heeft. Dat was _numFrame. Verandert iedere 5 msec van waarde en loopt van 0 t/m 15 aangestuurd door de SX-bus. In _state = ADR (waarde 2) wordt deze bepaald. Tijdens het opnieuw draaien van de sketch liep nu de waarde heerlijk chaotisch. Dit komt omdat het uitlezen van _numFrame gebeurd in het tempo van de main loop van de Arduino.
(https://images.beneluxspoor.net/bnls/SXarduino_software.jpg) (https://images.beneluxspoor.net/bnls/SXarduino_software.jpg)
En die is absoluut niet synchroon met de SX-bus.
Hierna het testprogramma laten schrijven naar de SX-bus en met de handterminal op de SX-bus gekeken.
De getallen klopte. Tenslotte de power afhandeling getest. Ook die liep naar behoren. De Arduino kon gewoon de centrale in- en uitschakelen.

De laatste stand:
h file:
/*
 * SXArduino.h
 *
 *  Created on: 10.07.2015
 *  Version:    0.1
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on:
 *  Version:
 *
 *  interface hardware needed ! see

 Read SX Signal - SX Clock must be connected to Pin2=INT0 and
 SX Data must be connected to Pin4. For triggering a scope, a signal
 can be generated at Pin3 at a defined base address.
 Pin6 can be connected via a 150 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 SXArduino_H_
#define SXArduino_H_

#include <Arduino.h>

// define arduino pins, ports and bits
#define SX_T0 3     // must be INT1 !!
#define SX_T0_DDR DDRD
#define SX_T0_PORT PORTD
#define SX_T0_PORTPIN PORTD3
#define SX_T0_PINREG PIND

#define SX_T1 5
#define SX_T1_DDR DDRD
#define SX_T1_PORT PORTD
#define SX_T1_PORTPIN PORTD5
#define SX_T1_PINREG PIND

#define SX_D 6
#define SX_D_DDR DDRD
#define SX_D_PORT PORTD
#define SX_D_PORTPIN PORTD6
#define SX_D_PINREG PIND


// defines for state machine
#define SYNC 0
#define PWR 1
#define ADDR 2
#define DATA 3

#define MAX_DATACOUNT    7    // 7 dataframes in 1 SYNC Channel
#define MAX_DATABITCOUNT 12   // 12 bits in 1 frame

#define MAX_ADDRESS_NUMBER 112   // SX channels

class SXArduino {
public:
SXArduino();
void init(void);
uint8_t get(uint8_t);
uint8_t set(uint8_t, uint8_t);
uint8_t writing();
    uint8_t getPWRBit();
void setPWRBit(uint8_t);
void isr(void);

private:
void readPower(void);
void writePower(void);
void readAdr(void);
void readData(void);
void writeData(void);

uint8_t _numFrame;                    // number frame
uint8_t _dataFrameCount;              // frame counting
uint8_t _address;                     // current address on the bus
volatile uint8_t _state;
uint8_t _bitCount;                    // bit counting

uint8_t _PWRBit;                      // Current state of POWER on track
uint8_t _newPWRBit;                   // Command POWER on track

uint8_t _sx_write_address;      // stores address to write to
    uint8_t _sx_write_data;    // data to write
uint8_t _sx_writing;   // active during the actual writing
    volatile uint8_t _sx_write_busy;      // wait to send data, cannot accept new data

uint8_t _clk;
uint8_t _bit;

uint8_t _data;                        // 1 data uint8_t
uint8_t _sxbus[MAX_ADDRESS_NUMBER];   // to store the SX data

/* SX Timing
1   Bit             50 �s
1   Kanal          600 �s (= 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 /* SXArduino_H_ */


en
cpp file:
/*
 * SXAduino.cpp
 *
 *  Created on: 16.07.2015
 *  Version:    0.1
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on:
 *  Version:
 *
 *  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).
 
 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 "SXArduino.h"


SXArduino::SXArduino() {
    pinMode(SX_T0, INPUT);      // SX-T0 is an input, no pull up to simulate tri-state
    pinMode(SX_T1, INPUT);      // SX-T1 is also an input
    pinMode(SX_D, INPUT);       // SX-D is also an input when not writing to allow other devices to write
}

void SXArduino::init() {
     // initialize function
     // initialize pins and variables

pinMode(SX_T0, INPUT);      // SX-T0 is an input, no pull up to simulate tri-state
pinMode(SX_T1, INPUT);      // SX-T1 is also an input
pinMode(SX_D, INPUT);       // SX-D is also an input when not writing to allow other devices to write

for (int i = 0; i < MAX_ADDRESS_NUMBER; i++) {
          // reset sx variable to zero
_sxbus[i] = 0;
}

// start always with search for SYNC
_state = SYNC;
_dataFrameCount = 0;
_bitCount = 0;
_sx_writing = 0;
_sx_write_busy = 0;
_newPWRBit = 2;
_PWRBit = 0;                   // At start no power
}


// Read the bit that indicates if there is power on the track and store it.
// After reading the bit start processing the address.
void SXArduino::readPower()  {
if(_bitCount == 0) {
_PWRBit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;
_bitCount++;
} else {
_bitCount = 0;
_state = ADDR;
}   // end if _bitCount
}

// Write the bit that controls the power on the track if the user want to change it.
// After writing the bit the pin is changed from output to input
 void SXArduino::writePower()  {
if(_bitCount == 0) {
if (_newPWRBit != 2) {
bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, _newPWRBit); //  and write the newPWRBit
} else {
_newPWRBit = 2;
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to input
}   // end if _newPWRBit
}   // end if _bitCount
}

// Read the address bits.
// If base-address is read calculate the real address and
// check if we must write
// Proceed to the next stage DATA
void SXArduino::readAdr() {
_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;
switch(_bitCount) {
case 0:  // A3
bitWrite(_numFrame, 3, _bit);
_bitCount++;
break;
case 1:  // A2
bitWrite(_numFrame, 2, _bit);
_bitCount++;
break;
case 3:  // A1
bitWrite(_numFrame, 1, _bit);
_bitCount++;
break;
case 4:  // A0
bitWrite(_numFrame, 0, _bit);
_bitCount++;
break;
case 2:  // "Trenbit"
_bitCount++;
break;
case 5: // last "Trenbit"
// advance to next state
// we are processing the 7 data bytes (i.e. 7 SX addresses)
_state = DATA; 
_bitCount = 0;
//  _dataFrameCount is 0.
_address = (MAX_ADDRESS_NUMBER - 1) - _numFrame;
if ((_address == _sx_write_address) && (_sx_write_busy == 1))  {
_sx_writing = 1;
} else {
_sx_writing = 0;
}
break;
}  //end switch/case _bitCount
}

// read 12 bits and convert it to a databyte.
// Read 7 databytes to read all data
// After reading 7 data bytes start searching for SYNC
void SXArduino::readData()  {
_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;
// continue read _data
// a total of 7 DATA blocks will be received
    // for a certain base-address
switch(_bitCount) {
// Read the data bits
case 0:   // D0
bitWrite(_data, 0, _bit);
_bitCount++;
break;
case 1:   // D1
bitWrite(_data, 1, _bit);
_bitCount++;
break;
case 3:   // D2
bitWrite(_data, 2, _bit);
_bitCount++;
break;
case 4:   // D3
bitWrite(_data, 3, _bit);
_bitCount++;
break;
case 6:   // D4
bitWrite(_data, 4, _bit);
_bitCount++;
break;
case 7:   // D5
bitWrite(_data, 5, _bit);
_bitCount++;
break;
case 9:   // D6
bitWrite(_data, 6, _bit);
_bitCount++;
break;
case 10:  // D7
bitWrite(_data, 7, _bit);
_bitCount++;
break;
case 2:  // "Trenn_bits"
case 5:
case 8:
_bitCount++;
break; // ignore
case 11: // Last "Trenn_bit"
// save read _data
_sxbus[_address] = _data;
// setup for next read
_bitCount = 0;
_data = 0;
        // increment dataFrameCount to move on the next DATA byte
        // check, if we already reached the last DATA block - in this
        // case move on to the next SX-Datenpaket, i.e. look for SYNC
_dataFrameCount++;
if (_dataFrameCount == MAX_DATACOUNT) {
// and move on to SYNC _state
_dataFrameCount = 0;
_state = SYNC;
} else {
// calc sx address from numFrame and dataFrameCount
// _address = (6-_dataFrameCount) * 16 + (15 - _numFrame)
_address = ((6 - _dataFrameCount) << 4) + (15 - _numFrame);
// check if we want to write
if ((_address == _sx_write_address) && (_sx_write_busy == 1))  {
_sx_writing = 1;
} else {
_sx_writing = 0;
}
}
break;
}  //end switch/case _bitCount
}

// write the 8 databits to the 12 bit frame
// When finished writing report it.
void SXArduino::writeData() {
switch(_bitCount) {
default:  // Last "Trenn_bit"
_sx_writing = 0;                             // Stop writing``
_sx_write_busy = 0;                          // Report end
case 2:  // "Trenn_bits"
case 5:
case 8:
bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH);      // Switch pin to input
break;
// Write the data bits
case 0:  // D0
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 0));
break;
case 1:  // D1
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 1));
break;
case 3:  // D2
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 2));
break;
case 4:  // D3
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 3));
break;
case 6:  // D4
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 4));
break;
case 7:  // D5
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 5));
break;
case 9:  // D6
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 6));
break;
case 10: // D7
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 7));
break;
}  //end switch/case _bitCount
}


// interrupt service routine (AVR INT1)
// driven by LEVEL CHANGES of the clock signal T0 (SX pin 1)
// LOW: writing
// HIGH: reading and control
void SXArduino::isr() {
     // 4 different states are distinguished
     //     1. SNYC = looking for a SYNC signal
//     2. PWR  = look for PWR bit
     //     3. ADDR = look for number frame (0..15)
     //     4. DATA = decode the data-bytes

_clk = (SX_T0_PINREG & _BV(SX_T0_PORTPIN)) > 0;

switch(_state) {
case SYNC:                            // Search for 0 0 0 1
        if (_clk != LOW)  {
_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;   // read pin
if (_bit == LOW) {
_bitCount++;
} else {
if (_bitCount == 3) {     // sync bits 0 0 0 1 found
_state = PWR;         // advance to next state
}  // endif _bitCount
_bitCount = 0;            // reset _bitCounter and start over
}  // endif _bit==LOW
}  // endif _clk!=LOW
break;
case PWR:
if (_clk == LOW)  {
writePower();
} else {
readPower();
}  // endif _clk==LOW
break;
case ADDR:
if (_clk != LOW)  {
readAdr();
}  // endif _clk!=LOW
break;
case DATA:
if (_clk == LOW)  {
if (_sx_writing == 1)  {
writeData();
}
} else {
readData();
}  // endif _clk==LOW
break;
default:
_state = SYNC;     // Error restart
_dataFrameCount = 0;
_bitCount = 0;
_sx_writing = 0;
_sx_write_busy = 0;
_newPWRBit = 2;
_PWRBit = 0;
break;
}  //end switch/case _state
}

// functions 'accessing' the SX-bus

// Read data from the array, filled by the isr.
uint8_t SXArduino::get(uint8_t ad) {
     // returns the value of a SX address
if (ad < MAX_ADDRESS_NUMBER)  {
   return _sxbus[ad];
} else  {
   return 0;
}
}

// Start writing data to the SX-bus.
// Check if writing or invalid address.
// (A write lasts between 600 us and 80 ms)
uint8_t SXArduino::set(uint8_t adr, uint8_t dt) {
if (_sx_write_busy == 0)  {
if (adr < MAX_ADDRESS_NUMBER)  {
_sx_write_address = adr;
_sx_write_data = dt;
_sx_write_busy = 1;
return 0;    // success
}
return 2;    // address out of range
}
return 1;  // writing busy
}

// Check if writing is finished
// (A write lasts between 600 us and 80 ms)
uint8_t SXArduino::writing() {
return _sx_write_busy;
}

// Read POWER status from the SX-bus
uint8_t SXArduino::getPWRBit() {
    return _PWRBit;
}

// Write POWER status to the SX-bus and control a connected central.
void SXArduino::setPWRBit(uint8_t val) {
if (val == 0 || val == 1) {
_newPWRBit = val;
}
}

Nu ben ik op zoek naar Selectrix rijders die een Arduino hebben. Zouden zij voor mij een gemonteerd bordje willen ontvangen en een testprogramma doorlopen, om te controleren of de software naast de RMX centrale ook met andere centrales werkt.
Kun je je melden als je zin hebt en aangeven welke centrale je hebt?

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 01 december 2015, 11:20:15
Het is een beetje stil geweest in dit draadje. Dit komt doordat de ontwikkeling van de library in ene op een ander spoor is terecht gekomen. De eisen aan de library zijn iets opgeschroefd. Ik wil in een cyclus (80 msec) alle adressen kunnen lezen en schrijven. Het eerste experiment is helaas mislukt. De Arduino kon het niet bijbenen. De teruggelezen geschreven data was niet gelijk. De verstoring was niet constant, maar vaak genoeg om een onbetrouwbaar verkeer tussen Arduino en SX-bus te hebben. Inmiddels heb ik de library in notepad++ geladen en nog eens goed gezocht naar optimalisaties. Uiteindelijk gevonden en inmiddels is er een nieuwe versie van de library die de SX-bus wel kan bijhouden. Afgelopen weekend heeft de Arduino een uur staan draaien en gedurende dat uur geen enkele fout gegenereerd. Er vinden achter de schermen nog wat aanvullende testen plaats, ik wil onder andere alle 112 adressen lezen en schrijven in een cyclus voor een bepaalde tijd.
Als deze testen gelukt zijn en de testers laten het weer werken op hun centrales dan geef ik ook deze library vrij en zal ik hem in een gitthub plaatsen.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 08 januari 2016, 10:29:24
Volgers,

Zo de testen zitten erop.  Alle testers bedankt. Voor zover ik kan beoordelen uit de testresultaten is de interface nu met centrales van alle grote fabrikanten getest, en werken de software en het bordje samen en goed. De library is iets gegroeid tijdens de testen, en kan nu iets meer.
Nu is mogelijk:
- Lezen in een cyclus van alle adressen (was al mogelijk)
- Schrijven in een cyclus van alle adressen (was een adres)
- lezen van melding of er spanning op de rails staat (was al mogelijk)
- aan en uitschakelen van de railspanning (was al mogelijk)
- Melding dat alle adressen gelezen/geschreven zijn (is te gebruiken als een timer, daar deze melding iedere 76,8 ms komt)
- Meding dat een specifiek adres gelezen is.
De code is inmiddesl ook op GITHUB te vinden en wel bij een initiatief dat ik zeer omarm opensx (http://opensx.net/). Een actie gelijk de openDCC website. Inmiddels is daar de SXArduino  (https://github.com/opensx/SXArduino)software te vinden. Hieronder is de daar te downloaden software:
h-file:
/*
 * SXArduino.h
 *
 *  Version:    3.0
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on: 19-12.2015
 *  Version: 3.0
 *  Changes: Added some comment. Given its version number.
 *
 *  Changed on: 30.11.2015
 *  Version: 0.5
 *  Changes: Reading and writing to multiple addresses in one cycle, resolved timing issues.
 *
 *  Changed on: 14.11.2015
 *  Version: 0.4
 *  Changes: Reading and writing to multiple addresses in one cycle.
  *
 *  Changed on: 27.10.2015
 *  Version: 0.3
 *  Changes: onWait() added to synchronise with the SXbus.
 *
 *  Changed on: 27.09.2015
 *  Version: 0.2
 *  Changes: Minor changes
 *
 *  Changed on: 10.07.2015
 *  Version: 0.1
 *  Changes: Initial version
 *
 *  interface hardware needed ! see

 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 SXArduino_H_
#define SXArduino_H_

#include <Arduino.h>

// define arduino pins, ports and bits
// depends on the hardware used.
#define SX_T0 3                      // Clock
#define SX_T0_DDR DDRD
#define SX_T0_PORT PORTD
#define SX_T0_PORTPIN PORTD3
#define SX_T0_PINREG PIND

#define SX_T1 5                      // Data read
#define SX_T1_DDR DDRD
#define SX_T1_PORT PORTD
#define SX_T1_PORTPIN PORTD5
#define SX_T1_PINREG PIND

#define SX_D 6                      // Data write
#define SX_D_DDR DDRD
#define SX_D_PORT PORTD
#define SX_D_PORTPIN PORTD6
#define SX_D_PINREG PIND


// 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_STOP         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   // SX channels

#define NO_WRITE 256         // No data to write

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

private:
void initVar();
uint8_t calcIndex(uint8_t adr);

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_PWR;                      // current state of POWER on track
uint8_t _sx_newPWR;                   // command POWER on track

uint8_t _sx_read_data;                // read data
    uint8_t _sx_write_data;    // data to write
uint8_t _sx_index;                    // current index in the array
uint8_t _sx_writing;   // active during the actual writing

uint8_t _sx_bit;                      // value data bit (T1)
uint8_t _sx_sync;                     // set if Frame 0 is processed

uint8_t _sxbusrcev[SX_ADDRESS_NUMBER];   // to store the received SX data
uint16_t _sxbussnd[SX_ADDRESS_NUMBER];   // to store the SX data to send

/* 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 /* SXArduino_H_ */

en het bijbehorende cpp-file:
/*
 * SXAduino.cpp
 *
 *  Version:    3.0
 *  Copyright:  Gerard van der Sel
 *
 *  Changed on: 19-12.2015
 *  Version: 3.0
 *  Changes: Added some comment. Given its version number.
 *
 *  Changed on: 30.11.2015
 *  Version: 0.5
 *  Changes: Reading and writing to multiple addresses in one cycle, resolved timing issues.
 *
 *  Changed on: 14.11.2015
 *  Version: 0.4
 *  Changes: Reading and writing to multiple addresses in one cycle.
 *
 *  Changed on: 27.10.2015
 *  Version: 0.3
 *  Changes: onWait() added to synchronise with the SXbus.
 *
 *  Changed on: 27.09.2015
 *  Version: 0.2
 *  Changes: Minor changes
 *
 *  Changed on: 10.07.2015
 *  Version: 0.1
 *  Changes: Initial version
 *
 *  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
  -- ------------------- ------------------- ------------------- ---------

       ^                   ^                   ^                   ^
       P                   P                   P                   P

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 "SXArduino.h"

SXArduino::SXArduino() {
    pinMode(SX_T0, INPUT);      // SX-T0 is an input, no pull up to simulate tri-state
    pinMode(SX_T1, INPUT);      // SX-T1 is also an input
    pinMode(SX_D, INPUT);       // SX-D is also an input when not writing to allow other devices to write
}

void SXArduino::init() {
     // initialize function
     // initialize pins and variables

pinMode(SX_T0, INPUT);      // SX-T0 is an input, no pull up to simulate tri-state
pinMode(SX_T1, INPUT);      // SX-T1 is also an input
pinMode(SX_D, INPUT);       // SX-D is also an input when not writing to allow other devices to write

for (int i = 0; i < SX_ADDRESS_NUMBER; i++) {
_sxbusrcev[i] = 0;                                     // reset sx received data to zero
_sxbussnd[i] = NO_WRITE;                               // set sx data to send to NO_WRITE
}
initVar();                                                 // Start looking for SYNC
}

void SXArduino:: initVar() {
// start always with search for header
_sx_state = SYNC;                                          // First look for SYNC pattern
_sx_dataFrameCount = SX_DATACOUNT;                         // Read all dataframes
_sx_sepCount = SX_SEPLEN;                                  // Distanse between two separators
_sx_byteCount = SX_STOP;                                   // Check for SX_STOP bits of "0"
_sx_numFrame = 0;                                          // Set frame 0
_sx_index = 0;                                             // Set index 0

// no writing to the SX bus
_sx_writing = 0;                                           // Set no write

// Powerbit send and receive
_sx_newPWR = 2;                                            // Don't write power bit
_sx_PWR = 0;                                               // At start no power

// reset sync bit
_sx_sync = 0;                                              // Clear sync-flag
}

// interrupt service routine (AVR INT1)
// driven by RISING EDGES of the SX clock signal T0 (SX pin 1)
void SXArduino::isr() {
_sx_bit = (SX_T1_PINREG & _BV(SX_T1_PORTPIN)) > 0;         // read pin

switch (_sx_state) {
// Find sync pattern "0001" to start reading and writing
case SYNC:
if (_sx_bit == LOW) {                              // Sync bits "0"
if (_sx_byteCount > 0) {                       // If more then 3
_sx_byteCount--;
}
} else {
if (_sx_byteCount == 0) {                      // High, read 3 bits?
_sx_state = PWR;                           // Setup for POWER bit
_sx_sepCount = SX_SEPLEN - 1;              // Set _sx_sepCount and continue
}
_sx_byteCount = SX_STOP;                       // Error, setup for restart
}
break;
// Read (and write) the power bit.
case PWR:
_sx_sepCount--;
if (_sx_sepCount == 0) {                           // Skip the separator
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW);    // Switch pin to input
_sx_state = ADDR;                              // Setup for next state ADDR
_sx_byteCount = SX_BYTELEN / 2;
_sx_sepCount = SX_SEPLEN;
_sx_numFrame = 0;
} else {
if (_sx_newPWR < 2) {                         // Set power from me
bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH);    // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, _sx_newPWR); // and write newPWR
}   // end if _sx_newPWR
_sx_newPWR = 2;                            // Power set
_sx_PWR = _sx_bit;                             // Get power status from central
}
break;
// Read the address bits.
case ADDR: 
_sx_sepCount--;
if (_sx_sepCount == 0) {                           // Skip the separator
_sx_sepCount = SX_SEPLEN;
} else {
_sx_numFrame = (_sx_numFrame * 2) + _sx_bit;   // Read bit into framenumber
}
_sx_byteCount--;
if (_sx_byteCount == 0) {                          // Addres part is processed
// Advance to the next state
_sx_state = DATA;                              // Setup for DATA read
_sx_byteCount = SX_BYTELEN;
_sx_index =  _sx_numFrame * 7;                 // Calculate index
// Check if we want to write and prepare it
if (_sxbussnd[_sx_index] < NO_WRITE) {
_sx_write_data = _sxbussnd[_sx_index];     // Get data to write
_sx_writing = 1;                           // Write
_sxbussnd[_sx_index] |= NO_WRITE;          // Report bye written to SX-bus
} else {
_sx_writing = 0;                           // No write
}
if (_sx_numFrame == 0) {
_sx_sync = 1;                              // Signal frame 0 for sync purposes
}
}
break;
// Read (and write) the data bits
case DATA:
_sx_sepCount--;
if (_sx_sepCount == 0) {                           // Skip the separator
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW);         // Switch pin to input
_sx_sepCount = SX_SEPLEN;
} else {
if (_sx_writing == 1)  {                        // If we want to write
bitWrite(SX_D_DDR, SX_D_PORTPIN, HIGH); // Switch pin to output
bitWrite(SX_D_PORT, SX_D_PORTPIN, bitRead(_sx_write_data, 0));
_sx_write_data = _sx_write_data / 2;        // Prepare for next write
}
_sx_read_data = (_sx_read_data / 2);            // Prepare for reading data
bitWrite(_sx_read_data, 7, _sx_bit);            // Insert the bit
}
_sx_byteCount--;
if (_sx_byteCount == 0) {                           // All bits done
// save read _data
_sxbusrcev[_sx_index] = _sx_read_data;          // Save read data in array
// Setup for next read/write
_sx_byteCount = SX_BYTELEN;
_sx_index++;
// Decrement dataFrameCount
// check, if we already reached the last DATA block - in this
// case move on to the next SX-Datenpaket, i.e. look for SYNC
_sx_dataFrameCount--;
if (_sx_dataFrameCount == 0) {
// Move on to find SYNC pattern
_sx_dataFrameCount = SX_DATACOUNT;
_sx_state = SYNC;
_sx_byteCount = SX_STOP;
_sx_writing = 0;
} else {
// Check if we want to write
if (_sxbussnd[_sx_index] < NO_WRITE) {
_sx_write_data = _sxbussnd[_sx_index];  // Get data to write
_sx_writing = 1;                        // Write
_sxbussnd[_sx_index] |= NO_WRITE;       // Report bye written to SX-bus
} else {
_sx_writing = 0;                        // No write
}
}
}
break;
default:
bitWrite(SX_D_DDR, SX_D_PORTPIN, LOW);     // Switch pin to input
initVar();                                          // Start looking for SYNC
break;
}  //end switch/case _sx_state
}

// Convert from SX-bus addresses to index in array.
uint8_t SXArduino::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.
int SXArduino::get(uint8_t adr) {
     // returns the value of a SX address
if (adr < SX_ADDRESS_NUMBER)  {
return _sxbusrcev[calcIndex(adr)];
} else  {
return -1;                                              // Save value
}
}

// Write data to the array, writing to the SX-bus is done by the isr.
// Check if invalid address.
uint8_t SXArduino::set(uint8_t adr, uint8_t dt) {
if (adr < SX_ADDRESS_NUMBER)  {
_sxbussnd[calcIndex(adr)] = dt;
return 0;    // success
}
return 1;    // address out of range
}

// Checks if the isr has written the data to the SX-bus
uint8_t SXArduino::isSet(uint8_t adr) {
if (adr < SX_ADDRESS_NUMBER)  {
if (_sxbussnd[calcIndex(adr)] < NO_WRITE) {
return 2;   // not written
} else {
return 0;   // written
}
}
return 1;    // address out of range
}

// Read POWER status from the SX-bus
uint8_t SXArduino::getPWR() {
    return _sx_PWR;
}

// Write POWER status to the SX-bus and control a connected central.
void SXArduino::setPWR(uint8_t val) {
if (val == 0 || val == 1) {
_sx_newPWR = val;
}
}

// Every time frame 0 is passed sync bit is set by isr.
uint8_t SXArduino::inSync() {
if (_sx_sync == 1) {
_sx_sync = 0;              // reset sync bit to check for next pass
return 1;                  // report frame 0 found
}
return 0;
}


Ik hoop dat de Selectrix rijders / Arduino gebruikers nuttige zaken met deze library kunnen gaan doen. Ik zal in dit draadje een 3 tal projecten uitwerken.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 08 januari 2016, 10:32:58
Volgers,

De software die door de testers is gebruikt is ook niet meer de oorspronkelijke software. Voor diegene die de testen willen controleren hierbij de laatste versie van de testsoftware:
/*
 *   Test sketch for SX-bus interface for the ARduino
 *   All addresses are written with a value.
 *   In the background an ISR is running to send those values to the SX-bus.
 *   While sending the bus is read and put in a buffer
 *   
 *   Watch out: Adresses 104 to 111 are used. To avoid this set noCC2000 to false
 */

#include "SXArduino.h"
#include "Arduino.h"

// SX-bus interface
SXArduino SXbus;                 // Get access to the SX-bus
uint8_t valrcv;
uint8_t valsnd;
int waitSX;
int waitLussen;
int waitloop;
int burst;                      // pauze
int adr;
bool noCC2000;

void sxisr(void) {
    // if you want to understand this, see:
    // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1239522239   
    SXbus.isr();
}

void setup() {
    // put your setup code here, to run once:
    // Serial communication
    Serial.begin(230400);      // open the serial port

    // SX-bus communication
    SXbus.init();
    // CHANGE on INT1 triggers the interrupt routine sxisr (see above)
    attachInterrupt(1, sxisr, CHANGE);

    // Init prog
    waitSX = 0;
    waitLussen = 0;
    valsnd = 0;
    waitloop = 0;
    noCC2000 = true;   // false 0 ... 103, true 0 ... 111
    burst = 5;         // 5 slagen pauze (= 5 * 77 = 385 msec)
}

uint8_t getSXbusval(int adr) {
    return SXbus.get(adr);
}

uint8_t getSXbuspower() {
    return SXbus.getPWR();
}

void setSXbusval(uint8_t adr, uint8_t val) {
    SXbus.set(adr, val);
}

void setSXbuspower(uint8_t onoff) {
    SXbus.setPWR(onoff);
}

void loop() {
    // put your main code here, to run repeatedly:
    if (SXbus.inSync() == 1) {                         //  Iedere 76,8 msec true
        // fill bytes conform SX messages
        for (int j = 0; j < 16; j++) {                 // 16 frames
            Serial.print("Data: ");
            for (int i = 0; i < 7; i++) {              //  7 databytes per frame
                adr = ((6 - i) << 4) + (15 - j);
                if ((adr < 104) || (noCC2000)) {       // Exclude the addresses used by CC2000
                    if (waitLussen == 0) {
                        Serial.print(valsnd);
                        Serial.print("=");
                        setSXbusval(adr, valsnd);
                        valsnd++;
                    }
                    valrcv = getSXbusval(adr);
                    Serial.print(valrcv);
                    if (i < 6) {
                        Serial.print(", ");
                    }
                }
            }
            Serial.println();
        }
        if (burst < waitLussen) {
            waitLussen = 0;
        } else {
            waitLussen++;
        }
        Serial.print("Power: ");
        if (getSXbuspower() == 1) {
            Serial.println("On");
        } else {
            Serial.println("Off");
        }
 
        waitSX++;
        if (waitSX > 5) {   // 5 x 80 ms = 400 ms wachttijd
            waitSX = 0;
            Serial.print("Switch power ");         
            if (getSXbuspower() == 1) {
                setSXbuspower(0);
                Serial.println("off");         
            } else {
                setSXbuspower(1);         
                Serial.println("on");
            }
        }
        waitloop = 0;
    } else {
        if (waitloop == 0) {
            Serial.println("Waiting.... ");                   // 15 tekens (incl CR+LF)
        }
        waitloop++;                                           // max 63 tekens totaal => 32 msec bij 19200 baud
    }
}

Er bevinden zich  in setup twee variabelen die even afhankelijk van je eigen situatie moet instellen:
noCC2000: Deze variabel regelt het gebruik van de adressen 104 t/m 111. Bij gebruik van bepaalde centrales (waaronder de oorspronkelijke CC2000) zijn deze adressen verboden.
Burst: Regelt hoe vaak naar de SX-bus geschreven wordt. Een waarde van 1 zorgt er voor dat in iedere cyclus alle waarden vervangen worden een hogere waarden zal cycli overslaan.

De bausrate staat vrij hoog, dit is noodzakelijk om de output van de testsoftware binnen 76,8msec op de PC te hebben, daar er na deze 76,8 msec nieuwe waarden zijn.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 08 januari 2016, 10:39:00
Volgers,

Tenslotte hebben we de bovenstaande library geschreven om voor nuttige zaken te gebruiken. Het eerste project dat ermee gerealiseerd is, is een Arduino versie van de seriele interfaces van het Selectrix systeem (de 66824 en 66842). Deze beide interfaces werken nog met de vertrouwde RS232 poort, nu met deze Arduino versie wordt er gewerkt met een USB poort.
De code voor de interface is ook op Github te vinden onder examples, en is alsvolgt:
/*
   SX interface (66824 or 66842)

   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)
               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 127: 0 trackpower off
                              128 trackpower on
      in case of a read: byte is discarded

   Note: For this sketch to run, don't solder switch and LED on de SXArduino board
*/

#include "Arduino.h"
#include "SXArduino.h"

SXArduino SXbus;         // Interface to the SX-bus
boolean cmdAdr;          // Received byte is a command
boolean cmdWrite;        // Write command
uint8_t address;         // Address for reading or writing
uint8_t rcvdData;

void sxisr(void) {
    // if you want to understand this, see:
    // http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1239522239   
    SXbus.isr();
}


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

    // initialize SX-bus
    SXbus.init();
    // Changes on INT1 triggers the interrupt routine sxisr (see above)
    attachInterrupt(1, sxisr, CHANGE);

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

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)SXbus.get(rcvdData));
                } else {   // Illegal address, power?
                    if (rcvdData == 127) {
                        Serial.print((char)(SXbus.getPWR() * 128));
                    }
                }
            }
            cmdAdr = false;
        } else {
            // Second byte data
            if (cmdWrite) {
                if (address < 112) {
                    SXbus.set(address, rcvdData);
                } else {
                    if (address == 127) {
                        if ((rcvdData & 128) == 0) {
                            SXbus.setPWR(0);
                        } else {
                            SXbus.setPWR(1);
                        }
                    }
                }
                cmdWrite = false;
            }
            cmdAdr = true;
        }
    }
}

void loop() {
  // put your main code here, to run repeatedly:
  // Nothing to do.
}
Het gebruikte protocol is eigenlijk heel eenvoudig:
Verstuur een byte met daarin het adres (0 - 111). Als je de waarde wil lezen, stuur dan nog een willekeurig byte. De interface zal de waarde die op de bus staat terugsturen. Om te schrijven stuur een byte met het adres (0-111) plus 128 (msb set). Stuur vervolgens de waarde die je wilt schrijven (0-255). Er zal geen antwoord van de interface komen. Het stuur programma moet dus altijd twee bytes versturen.
Om te controleren of er spanning op de rails staat of niet, dan wel dit met een programma in te schakelen, wordt standaard adres 127 gebruikt. Met de waarde 128 wordt aangegeven dat er spanning op de rails staat/dan wel moet komen, terwijl 0 ervoor zorgt dat de spanning van de rails wordt afgeschakeld.

Als volgend project wil ik laten zien hoe eenvoudig het is om een tableau te maken dat wissels en seinen kan aansturen en tevens de terugmeldingen weergeeft (als er tenminste terugmeldingen op de baan aanwezig zijn) en een iets sneller projet: het aansturen van een RGBW (rood, groen, blauw en wit) LED strip vanuit de SX-bus met de Arduino. Mochten er andere verzoeken zijn, schroom dan niet om die hier te stellen. Andere vragen naar aanleiding van de berichten zijn natuurlijk welkom.

Groet,

Gerard van der Sel.

PS: Een windows pogramma om met deze software te werken is te vinden op mijn website (zie wereldbol hiernaast) onder selectrix, download
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 13 januari 2016, 12:10:02

Nu we onbeperkt toegang hebben tot de SX-bus, wordt het tijd dat we de Arduino wat nuttigs gaan laten doen. Wissels normaal of met servo's, seinen en via de centrale treinen alles is mogelijk. Gezien de worsteling van velen hier op het forum met een schakeltableau lijkt het mij leuk om hier mee te beginnen. Er zijn twee wegen te beandelen:
Ik ga voor de tweede optie, gezien de prijs van een Arduino. Hoeveel pennen zijn er nu nog beschikbaar op de Arduino:
Dat zijn:
De laatste kunnen weggelaten worden, als je er als gebruiker voor kiest om de configuratie "vast" in het programma te zetten. Dit geeft dan twee extra in/uit gangen voor het schakeltableau. Dus in totaal 16 in/uit gangen. Nu proberen de elektronica zo te maken dat er 16 LEDs en 16 drukknoppen aangesloten kunnen worden.
Eerst het schema per ingang:
(https://images.beneluxspoor.net/bnls/Schakelbord.jpg) (https://images.beneluxspoor.net/bnls/Schakelbord.jpg)
Pin X is de uit / ingang van de Arduino (open deur)
S1 is een drukknop (geen schakelaar), waarmee bv het wissel omgelegd kan worden.
R2 is een weerstand, die biij indrukken van S1 de pin voldoende laag trekt, om een "0" aan de ingang te krijgen. Mocht er gedrukt worden terwijl de LED aangestuurd wordt, dan zal de weerstand de uitgang beschremen tegen kortsluiting.
De combinatie R1 en LED1 is standaard. De weerstand mag niet veel lager, omdat dan de spanning op de pin tehoog wordt als de schakelaar ingedrukt wordt. Verhogen om de LED wat te dimmen kan geen kwaad.
Om dit allemaal aan te sturen heb ik een library geschreven die allerlei functionaliteit ondersteund.
Voor de led alleen het invers aansturen, voor de schakelaar:
De code hiervoor is getest voor twee LEDs/schakelaars. Ik zal binnenkort  nog 14 extra maken, zodat alle 16 de poorten gebruikt kunnen worden. Voorlopig is hier de library (cpp file:):
/*
 * Schakelbord.cpp
 *
 *  Created on: 15-01-2015
 *  Version: 0.1
 *  Changes: Initial version
 *
 *  interface hardware needed !
 */
#include <Arduino.h>

#include "Schakelbord.h"

Schakelbord::Schakelbord(int Pin): _pin(Pin) {
    pinMode(_pin, OUTPUT);
digitalWrite(_pin, HIGH);    // LED off
_stand = 0;
_pulse = 0;
_dender = SETDENDER;        // Set waittime back to start.
}

Schakelbord::Schakelbord() {
_stand = 0;
_pulse = 0;
_dender = SETDENDER;        // Set waittime back to start.
}

// Initialize pin for reading switch and driving LED
void Schakelbord::pin(int Pin) {
_pin = Pin;
    pinMode(_pin, OUTPUT);
digitalWrite(_pin, HIGH);    // LED off
_stand = 0;
_pulse = 0;
    _dender = SETDENDER;        // Set waittime back to start.
}


// Lees de stand van de schakelaar/drukknop
int Schakelbord::read() {
int temp;

// Set pin to input and read
    pinMode(_pin, INPUT);
    temp = digitalRead(_pin);
// Set pin to output and restore
    pinMode(_pin, OUTPUT);
set(_stand);
if (temp == 0) {
_dender = SETDENDER;     // Set waittime back to start.
} else {
if (_dender != 0) {
_dender--;            // Continue waiting,
temp = 0;             // Report open switch
}
}
return temp;
}

int Schakelbord::pulse() {
    int temp;
int result;

temp = read();
_pulse = _pulse ^ temp;     // Last 0 and new 1 and last 1 and new 0 both give 1
result = _pulse & temp;     // But only if new 1 then result = 1
_pulse = temp;
return result;
}

// Set LED on or off
void Schakelbord::set(int stand) {
if (_invers) {
if (stand == 0) {
digitalWrite(_pin, LOW);      // LED on
} else {
digitalWrite(_pin, HIGH);     // LED off
}
} else {
if (stand == 0) {
digitalWrite(_pin, HIGH);     // LED off
} else {
digitalWrite(_pin, LOW);      // LED on
}
}
_stand = stand;
}

// Get state LED
int Schakelbord::get() {
return _stand;
}

void Schakelbord::setInvers(bool value) {
_invers = value;
}

// Get SX_bus parameters
bool Schakelbord::getProcessed() {
return _processed;
}

void Schakelbord::setProcessed(bool value) {
_processed = value;
}

int Schakelbord::getAdresLED() {
return _adresLED;
}

void Schakelbord::setAdresLED(int value) {
_adresLED = value;
}

int Schakelbord::getBitLED() {
return _bitLED;
}

void Schakelbord::setBitLED(int value) {
_bitLED = value;
}

int Schakelbord::getAdresSwitch() {
return _adresSwitch;
}

void Schakelbord::setAdresSwitch(int value) {
_adresSwitch = value;
}

int Schakelbord::getBitSwitch() {
return _bitSwitch;
}
void Schakelbord::setBitSwitch(int) {
_bitSwitch = value;
}
en het H-file:
/*
 * Schakelbord.h
 *
 *  Created on: 27.09.2015
 *  Version: 0.1
 *  Changes: Initial version
 *
 *  interface hardware needed !
 */
#ifndef Schakelbord_H_
#define Schakelbord_H_

class Schakelbord {
public:
  Schakelbord(int);  // Constructor with pinnumber
  Schakelbord();     // Empty constructor
  void pin(int);     //  Initialise pin``
  int read();        //    Read value switch
  int pulse();       //    Read value switch and make it a pulse
  void set(int);     //    Set LED on/off_type
  int get();         //    Get state LED
  void setInvers(bool);
  bool getProcessed();
  void setProcessed(bool);
  int getAdresLED();
  void setAdresLED(int);
  int getBitLED();
  void setBitLED(int);
  int getAdresSwitch();
  void setAdresSwitch(int);
  int getBitSwitch();
  void setBitSwitch(int);
 
protected:

private:
  const int SETDENDER = 3;
  int _pin;
  int _stand;
  int _dender;
  bool _invers;
  int _pulse;
  int _adresLED;
  int _bitLED;
  int _adresSwitch;
  int _bitSwitch;
  bool _processed;
};

#endif /* Schakelbord_H_ */

Zo de andere 14 in elkaar zetten, en dan komt de sketch.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 13 januari 2016, 12:38:37
Hoi Gerard,

Als je de led dooft door de pullup te activeren ipv de uitgang hoog te trekken sla je twee vliegen in één klap. Als eerste kan je dan R2 achterwegen laten, kortsluiting is niet mogelijk. En nu vertrouw je er nu op dat de led de uitgang nu altijd hoog trekt. Waarschijnlijk gaat dat wel goed maar zeker als je een witte led ofzo gebruikt is dat wel een erg zwakke pullup. Dus als je ook daar de pullup activeert ben je wat zekerder en is het ook mogelijk de led te laten zitten als je dat voor een uitgang niet zou willen.

Ennuh
// Set LED on or off
void Schakelbord::set(int stand) {
  if (_invers) {
    digitalWrite(_pin, stand);
  }
  else{
    digitalWrite(_pin, !stand);
  }
  _stand = stand;
}
;D Andere was zo langdradig  :P :P :P


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 13 januari 2016, 13:43:38
Is een idee dat ik uit moet proberen. Stuit me wel tegen de borst een uitgang kortsluiten naar ground. Ik verwacht dat het misgaat, want de LED wordt 90% van de tijd geactiveerd.

Was even vergeten dat digitalWrite een macro is. De Arduino zelf heeft alleen maar instructies om de uitgang hoog of laag te maken.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 13 januari 2016, 18:40:24
digitalWrite is geen macro maar gewoon een functie.

De Arduino zelf heeft alleen maar instructies om de uitgang hoog of laag te maken.
Wat bedoel je hiermee? Zijn digitale uitgnagen dus ja, hoog of laag. Maar je kunt ze ook gewoon on the fly schakelen naar een input.

Is een idee dat ik uit moet proberen. Stuit me wel tegen de borst een uitgang kortsluiten naar ground. Ik verwacht dat het misgaat, want de LED wordt 90% van de tijd geactiveerd.
Hoezo zou dit mis gaan? Als de led geactiveerd is dan is de pin toch ook gewoon al laag? Enige effect is dat de knop nu iets meer effect heeft op de led. Nu heeft het alleen tijdens het pollen even effect dus afhankelijk van hoe vaak je pollt.


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 14 januari 2016, 10:58:19
digitalWrite is geen macro maar gewoon een functie.
Wat bedoel je hiermee? Zijn digitale uitgnagen dus ja, hoog of laag. Maar je kunt ze ook gewoon on the fly schakelen naar een input.
Ik ken de Arduino nog maar kort, maar heb al een aantal jaren ATtiny2313 erop zitten. Deze allemaal in assembler geprogrammeerd. Recent ook de SXArduino library bekeken op assembler niveau om vast te stellen wat de belasting. Wat ik bedoel is dat er alleen maar een instructie is om een uitgang te setten (SBI P,b) of te clearen (CBI P,b). Stukken waarbij als parameter de waarde van een poort meegegeven worden zijn dus complexere code. Aangezien ik de assembly vrij goed ken, begin ik af en toe zelf voor compiler te spelen en doe alvast wat zaken die in de macro gebeuren.
Hoezo zou dit mis gaan? Als de led geactiveerd is dan is de pin toch ook gewoon al laag? Enige effect is dat de knop nu iets meer effect heeft op de led. Nu heeft het alleen tijdens het pollen even effect dus afhankelijk van hoe vaak je pollt.
Ik denk dat ik je niet goed begrijp. Maar als ik het goed begrepen heb stel jij het volgende voor:
// Lees de stand van de schakelaar/drukknop
int Schakelbord::read() {
int temp;

// Set pin to input and read
        pinMode(_pin, INPUT);
digitalWrite(_pin, HIGH);                    // Set pullup on      <-- Toevoeging
        temp = digitalRead(_pin);
// Set pin to output and restore
        pinMode(_pin, OUTPUT);
set(_stand);
// Ontdender de terugmelding
if (temp == 0) {
_dender = SETDENDER;            // Set waittime back to start.
} else {
if (_dender != 0) {
_dender--;            // Continue waiting,
temp = 0;             // Report open switch
}
}
return temp;
}
Maar corrigeer me als ik je fout begrepen heb.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 14 januari 2016, 11:38:57
Aangezien ik de assembly vrij goed ken, begin ik af en toe zelf voor compiler te spelen en doe alvast wat zaken die in de macro functie gebeuren.
Hehe, in de meeste gevallen is de compiler aardig goed dus is het vaak beter om niet de compiler te slim af te zijn. Meestal heeft dat toch niet het gewenste effect... Compiler zal er waarschijnlijk gewoon een compare met 0 van maken ofzo. Of, als je gewoon een bool gebruikt kan dat direct als input voor de vergelijking dienen.

Maar corrigeer me als ik je fout begrepen heb.
Bij deze.  ;D Nee ik bedoel het volgende:
// Lees de stand van de schakelaar/drukknop
bool Schakelbord::read() {
bool temp; //bool is groot genoeg ;)

// Set pin to input and read
    pinMode(_pin, INPUT_PULLUP);
    temp = digitalRead(_pin);
   
// Just restore
  //pinMode(_pin, OUTPUT);
set(_stand);
 
if (temp == 0) {
_dender = SETDENDER;     // Set waittime back to start.
} else {
if (_dender != 0) {
_dender--;            // Continue waiting,
temp = 0;             // Report open switch
}
}
return temp;
}

// Set LED on or off
void Schakelbord::set(int stand) {
  //Zou er overigens er een bool van maken ipv een int...
  //Overigens zouden volgens mij alle int's vervangen kunnen worden door een bool of byte
 
_stand = stand;
 
  if(_invers){
    stand != stand;
  }
 
  if(stand){
    digitalWrite(_pin, LOW);  //Need this order! Otherwise the output is pulled
    pinMode(_pin, OUTPUT);    //high for a short time => shortcircuit possible
  }
  else{
    pinMode(_pin, INPUT_PULLUP);
  }
  /*if (_invers) {
if (stand == 0) {
digitalWrite(_pin, LOW);      // LED on
} else {
digitalWrite(_pin, HIGH);     // LED off
}
} else {
if (stand == 0) {
digitalWrite(_pin, HIGH);     // LED off
} else {
digitalWrite(_pin, LOW);      // LED on
}
}
_stand = stand;*/
}
Je stelt de pin dus nooit in als output die HIGH is. Je wisselt tussen output HIGH (led aan) en input met pullup (led uit).

Overigens is digitalWrite(pin, HIGH) na pinMode(pin, INPUT) de oude pullup methode. Werkt nog steeds maar kan ook direct met pinMode(pin, PULLUP). En omdat pinMode(pin, OUTPUT) het out register NIET aanpast is het dus hier nodig eerst deze laag te maken voor naar pinout te wisselen. pinMode(pin, OUTPUT) als de pullup aan staat resulteert in een output die HIGH is. En dat willen we hier voorkomen (geeft kortsluiting als de knop is ingedrukt).

Zoals ik in de code al aan gaf is eigenlijk geen enkel gebruik van int gerechtvaardigd...  ::) In geval van stand enzo voldoet een bool en in andere gevallen een byte (uint8_t). Scheelt aardig wat geheugen en ook best was code slagen.

Ow, en de code ziet er wat raar uit omdat jij hard taps gebruikt in je code en ik 2 spaces (Arduino standaard). In de editor ziet dat er hetzelfde uit maar het forum maakt een tab 4 spaces breed... Zucht...


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 14 januari 2016, 13:05:37
Zal geen tabs meer gebruiken, hoef je niet meer te zuchten. Kijken of Notepad++ dat ook snapt bij autoindenting.
Nu snap ik je. Zal het eens door de compiler halen en kijken wat die ervan bakt. Dit is een veiliger methode van werken dan die ik gemaakt had. De pin is alleen uitgang als die laag is, en dan is het potentiaal "hetzelfde" als bij ingedrukte schakelaar. Hierdoor is de kans op kortsluiting inderdaad nog kleiner geworden.
int is inderdaad 16 bit. Werken daarmee scheelt maar 3 of 4 ticks ten opzichte van een byte (u_int8 of bool). Compiler gebruikt R26/R27 (register X) als ALU. Deze is geoptimaliseerd voor 16 bit gebruik (vrijwel alle bewerkingen 1 clock tick).

Je code geaccepteerd.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: Timo op 14 januari 2016, 13:35:47
Zuchten was niet om jou hoor Gerard! Meer om het forum die dus de opmaak verdraait. Schrijf zelf ook in Notepad++ en die ondersteund dat. Vinkje bij Tab settings => Replace by space. Mag je ook gewoon de tab toets blijven gebruiken.

Is ook niet dat het een fout is en het ander goed maar meer een coding style. En aangezien 2 spaces als tab door arduino wordt gebruikt en omdat het wat compacter is dan 4 spaces heb ik het zo staan. Maar goed, net zoiets als de bracket na de functie of op een nieuwe regel etc. Bij het Multipass project ging het er de eerste week over welke coding style te gebruiken  ;D

Maar inderdaad, pin als HIGH output komt nooit voor dus kan er geen kortsluiting zijn. En het werkt nu met of zonder de led op de uitgang. Mooi dat het nu duidelijk is  (y)

Van de int optimalisatie ben jij meer op de hoogte dan in. Zelden in ASM geschreven en in ieder geval nooit voor een ATmega. Maar is het nog steeds geoptimaliseerd als het signed is? Maar goed, het scheelt ook RAM en die is natuurlijk ook beperkt (ook al ben ik nog nooit ook maar in de buurt van max gekomen...)


Timo
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 14 januari 2016, 14:08:44
Signed / Unsigned maakt niets uit. Bij signed is niet de C-flag maar de V-flag de melder. En verder probeer altijd checks met 0 te doen. Register R1 wordt speciaal daarvoor met 0 gevuld. Dit vind ik weer overdreven, daar een AND, OR of TST net zo snel op 0 kan testen als CP r,1 r2, waarbij r2 altijd R1 is.
Wat RAM betreft. Ik ben op deATtiny2313 met 168 bytes ook altijd ruim uit de voeten gekomen. Ik verzuip in deze 2k.

Groet en bedankt,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: fredjansen op 13 maart 2020, 20:21:53
Vraagje van meer algemene aard.

Bestaat er al een selectrix centrale op basis van een arduino ?

ik heb het forum wat doorgelezen en kom af en toe wel artikelen tegen maar ik krijg de indruk dat er nog niet iets is nabouwbaars is.

wie geeft mij wat licht op deze zaak ?
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 16 maart 2020, 16:30:19
Officieel niet. Maar een goede knutselaar maakt wel eens wat.

Groeten,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: bask185 op 16 maart 2020, 21:12:04
Vraagje van meer algemene aard.

Bestaat er al een selectrix centrale op basis van een arduino ?

ik heb het forum wat doorgelezen en kom af en toe wel artikelen tegen maar ik krijg de indruk dat er nog niet iets is nabouwbaars is.

wie geeft mij wat licht op deze zaak ?
Pluis het protocol voor me uit en ik regel code voor je  ;)
Titel: Re: Arduino en Selectrix
Bericht door: HansQ op 16 maart 2020, 21:16:51
https://morop.org/downloads/nem/de/nem680_d.pdf
https://morop.org/downloads/nem/de/nem681_d.pdf
Titel: Re: Arduino en Selectrix
Bericht door: bask185 op 16 maart 2020, 21:52:10
Top  (y)

Nou Gerard het zijn korte documentjes dus ik denk dat je er niet veel werk aan heb.

Mijn duits is roestig, ik moet MM2 ook nog doen en ik heb een chronisch gebrek aan tijd (maarja wie niet?). Als jij deze vertaalt in begrijpbaar Nederlands kan ik het coderen.

Ik heb vluchtig gekeken, ik snap het onderscheid tussen de '0'en en '1'en niet. Hoe verstuur ik een 0, hoe een 1 en hoe zijn die data pakketten precies opgebouwd?
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel op 17 maart 2020, 16:32:25
Vrij simpel  ;D
Hoe verstuur ik een "1": wissel van polariteit.
Hoe verstuur ik een "0": wissel niet van polariteit
Hoe zijn de datapakketten opgebouwd:
96 bits, die als volgt georganiseerd zijn:
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

Ga ervan uit dat het laatste bit een "1" was bij het opstarten.
Let erop dat er iedere 50usec gedurende 10usec 0V op de rails staat. Het leifst wordt dit gedaan door de rails kort te sluiten.

Groet,

Gerard van der Sel.
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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
Titel: Re: Arduino en Selectrix
Bericht door: bask185 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:
(https://i.imgur.com/AEYxoCR.png)
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



Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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?

Titel: Re: Arduino en Selectrix
Bericht door: bask185 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 (https://github.com/bask185/DCC-MM2-controller) 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 ;)


Titel: Re: Arduino en Selectrix
Bericht door: bask185 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)
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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:

}
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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;
}
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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_ */
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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.
Titel: Re: Arduino en Selectrix
Bericht door: bask185 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
Titel: Re: Arduino en Selectrix
Bericht door: Dompie op 08 april 2020, 20:27:52
Gerard, gaaf stuk werk zeg!!

Johan
Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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.
Titel: Re: Arduino en Selectrix
Bericht door: bask185 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




Titel: Re: Arduino en Selectrix
Bericht door: gvandersel 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.