Doel:€250.00
Donaties:€130.00

Per saldo:€-120.00

Steun ons nu!

Laatst bijgewerkt
op 24-04-2024

Vacature: secretaris bestuur
Algemeen

De stichting

Recente berichten

Bouw NS C 8605, BC 6012 en C 6820 door prutser
Vandaag om 23:33:55
Schrootplaats door defender
Vandaag om 23:32:48
EifelBurgenBahn door Reinout van Rees
Vandaag om 23:09:03
NS 6000 (in schaal 0) door FritsT
Vandaag om 23:04:33
diorama, voor lange treinen. door Wim Vink
Vandaag om 23:01:07
Toon hier je pas gereed gekomen (model-)spoorbouwsels ... door Bob R.
Vandaag om 22:40:14
Kleine Baan in H0 (≤ 0.5m²) door Jack Black (NS1220)
Vandaag om 22:31:45
Nederland jaren 50 op basis van mijn roots door defender
Vandaag om 22:23:03
hoe diep is de kuil van een 23 meter draaischijf door peterha
Vandaag om 22:20:53
Ijzeren Rijn: militair transport door ijzeren rijn
Vandaag om 22:10:05
Baan 'begroenen', hoe, wat en waarmee? door Frank 123
Vandaag om 21:56:33
Mallnitzer Tauernbahnstrecke ÖBB N Spoor door Schachbrett
Vandaag om 21:39:10
Toon hier je nieuwe (model-) spooraanwinst(en)... door DavidNS400 Grote sik
Vandaag om 21:38:25
Mijn eerste H0-modeltreinbaan in aanbouw door Schachbrett
Vandaag om 21:09:44
Pfarrerwinkel bahn door Schachbrett
Vandaag om 21:08:37
Bahnbetriebswerk "Altendorf" door basjuh1981
Vandaag om 20:53:29
Station Roodeschool door Torikoos
Vandaag om 20:52:40
US diorama in H0 door basjuh1981
Vandaag om 20:51:10
Bouw van tijdperk 1 HSM en SS rijtuigen door MathynK
Vandaag om 20:11:23
Les Billards du Vivarais door Frank 123
Vandaag om 20:07:55
Piko lok digitaal rijdt direct weg door Ronaldk
Vandaag om 19:59:22
Gewoon wat busfoto's door Keska
Vandaag om 19:20:28
Aachenau West door wob
Vandaag om 19:10:24
Modelbaan schaal H0 niet geheel sluiten in pc prog door MartinRT
Vandaag om 19:04:37
19 Toen door defender
Vandaag om 19:01:10
20 en 21 april MobExpo door class 37
Vandaag om 18:16:26
Bouw van postrijtuig P 7911-7920 (plan C) van FRIE door Rob Bennis
Vandaag om 17:45:39
Al mijn goede ideeën... door maartenvdb
Vandaag om 17:22:59
Raadplaatje door Benelux795
Vandaag om 17:18:39
18 t/m 21 april Intermodellbau '24 Dortmund door Ronald Halma
Vandaag om 15:58:27
  

Auteur Topic: Arduino en Selectrix  (gelezen 26908 keer)

HansQ

  • Offline Offline
  • Berichten: 2032
  • Daar waar de rook is, is de kortsluiting...
HansQ, RailClub Utrecht
spoor N modulebouw, electronica, Selectrix

Fritsprt

  • Offline Offline
  • Berichten: 2615
Re: Arduino en Selectrix
« Reactie #61 Gepost 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

Groet Frits

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino en Selectrix
« Reactie #62 Gepost 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
Verzonden vanaf mijn desktop met Firefox

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #63 Gepost 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.

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.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino en Selectrix
« Reactie #64 Gepost 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
Verzonden vanaf mijn desktop met Firefox

HansQ

  • Offline Offline
  • Berichten: 2032
  • Daar waar de rook is, is de kortsluiting...
Re: Arduino en Selectrix
« Reactie #65 Gepost 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!
HansQ, RailClub Utrecht
spoor N modulebouw, electronica, Selectrix

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #66 Gepost 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).

De gebouwde versie, nog zonder de connectoren, omdat de gaten te klein zijn. Ga ze zo spoedig mogelijk opboren naar 0,8 mm.


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.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

HansQ

  • Offline Offline
  • Berichten: 2032
  • Daar waar de rook is, is de kortsluiting...
Re: Arduino en Selectrix
« Reactie #67 Gepost op: 05 oktober 2015, 13:51:01 »
Aha, connectortjes binnengekregen, maar een maatje te groot? :)
HansQ, RailClub Utrecht
spoor N modulebouw, electronica, Selectrix

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #68 Gepost 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.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino en Selectrix
« Reactie #69 Gepost 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
Verzonden vanaf mijn desktop met Firefox

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #70 Gepost 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,

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.

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.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #71 Gepost 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.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #72 Gepost 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. Een actie gelijk de openDCC website. Inmiddels is daar de 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.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #73 Gepost 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.
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3602
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino en Selectrix
« Reactie #74 Gepost 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
« Laatst bewerkt op: 08 januari 2016, 10:45:18 door gvandersel »
Holzburg (IIIb/IVa) schaal N.
Kijk ook eens bij de bouw en lees de avonturen.