S88 met arduino

Hardware geleverd door Arduino
Berichten: 5
Geregistreerd: 19 Dec 2016, 21:10

S88 met arduino

Berichtdoor jola » 19 Dec 2016, 21:32

Voor mijn modelspoor heb ik een S88 gemaakt, dat is een stukje hardware voor het registreren van bezetmeldpunten. Het bevat 16 identieke ingangen. Nu doet het vreemde feit zich voor dat er 15 ingangen perfect werken maar eentje niet. Ze zijn aangesloten op de pins 0,1,4,5,6,7,8,9,10,11,A0,A1,A2,A3,A4,A5.
Pin 0 (RX/D0) is de boosdoener, deze werkt niet. Nu is het origineel met een Arduino Zero gemaakt en die van mijn is een Arduino Nano, kan dat soms het verschil zijn?
Ik hoop dat het een beetje begrijpelijk is want het is wat moeilijker als je niet weet wat een S88 is.

Met vriendelijk groet,

Jos

Advertisement

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: S88 met arduino

Berichtdoor Koepel » 19 Dec 2016, 22:00

Je kunt een link geven naar dingen die je noemt, zoals bijvoorbeeld zo iets : http://www.funkyrail.nl/fr-digitaal.htm#bezet.
Je zou ook het schema van de S88 kunnen laten zien, zodat we kunnen kijken wat voor soort uitgangen het zijn die naar de Arduino gaan.

Bij een Arduino Uno, Nano en (Pro) Micro zit de RX en TX op pin 0 en 1. Die worden gebruikt om de sketch te uploaden en voor de seriële monitor. Pin 13 is lastig gebruiken als ingang voor een Arduino Nano omdat er een led aan hangt. Bij een Arduino Uno versie R3 kan pin 13 wel gewoon als ingang gebruikt worden.

De pinnen A6 en A7 van een Arduino Nano zijn alleen analoge ingangen. Die twee kun je niet gebruiken als digitale ingangen.

Ik zou pin 0 en 1 niet gebruiken, omdat het altijd handig is om wat gegevens naar de seriële monitor te sturen.
Wat doe je met pin 2, 3, 12 ?

Een Arduino Leonardo of een (Pro) Micro heeft een interne verbinding naar de computer. Daar kun je dus alle pinnen gebruiken. De Arduino Micro heeft 20 digitale ingangen, die allemaal vrij zijn. En in noodgevallen kun je nog verder gaan, omdat er op de ICSP header nog meer pinnen zitten.

Berichten: 5
Geregistreerd: 19 Dec 2016, 21:10

Re: S88 met arduino

Berichtdoor jola » 19 Dec 2016, 22:21

Alle 16 genoemde ingangen zijn standaard +5V en worden 0V bij een bezetmelding.
Het programma:

/*
S88 occupancy sensor interface to Command Station (in my case an ESU ECoS2)

Software by Ruud Boer, November 2014.
Freely distributable for private, non commercial, use.

Connections for S88 bus:
s88 pin 1 Data - Arduino pin 13 = Data_Out to Oommand Station, or to the previous Arduino in the chain
s88 pin 2 GND - Arduino GND
s88 pin 3 Clock - Arduino pin 2, interrupt 0
s88 pin 4 PS - Arduino pin 3, interrupt 1
S66 pin 5 Reset (not used here) - Arduino pin 12, used as DATA IN from previous Arduino DATA OUT
s88 pin 6 V+ - Arduino 5V

IMPORTANT: To avoid S88 signals to jitter, it is best to put DATA_in pin 12 to GND on the last Arduino in the chain.

Connections for sensors: see table in void Setup() at line 35.
REMARK1: Inputs have the internal pullup resistor active, the sensors must pull the input to GND.
REMARK2: How short a pulse is allowed from the sensors before it is not seen?
A test showed that the main loop where all sensors are read runs once every 76 microseconds.
If a train runs over the reed switch with a speed of 1m/s, which is over 300 km/hr, that translates to 1 mm/ms.
So even if the reed switch would be on only for a 1 mm travel distance, then still the Arduino
will read that info more than 10 times!

*/

int clockCounter=0;
long loopCounter=0; //used in lines 55 and 88, see there for explanation
unsigned int sensors=0;
unsigned int data=0xffff;
const byte dataIn=12; //data input from next Arduino in S88 chain
const byte dataOut=13; //data output pin=13
boolean loadSensors=false; //flag that says to load sensor bits into dataOut bits

void setup() {
pinMode(2, INPUT_PULLUP);
attachInterrupt(0,clock,RISING); //pin 2 = clock interrupt
pinMode(3, INPUT_PULLUP);
attachInterrupt(1,PS,RISING); //pin 3 = PS interrupt
pinMode(dataIn,INPUT_PULLUP); //pin 12 = data in from next Arduino S88 in chain
pinMode(dataOut, OUTPUT); //pin 13 = data out to ECoS or to previous Arduino in S88 chain
digitalWrite(dataOut, LOW); //LED off
pinMode(A0, INPUT_PULLUP); //sensor 01
pinMode(A1, INPUT_PULLUP); //sensor 02
pinMode(A2, INPUT_PULLUP); //sensor 03
pinMode(A3, INPUT_PULLUP); //sensor 04
pinMode(A4, INPUT_PULLUP); //sensor 05
pinMode(A5, INPUT_PULLUP); //sensor 06
pinMode(0, INPUT_PULLUP); //sensor 07
pinMode(1, INPUT_PULLUP); //sensor 08
pinMode(4, INPUT_PULLUP); //sensor 09
pinMode(5, INPUT_PULLUP); //sensor 10
pinMode(6, INPUT_PULLUP); //sensor 11
pinMode(7, INPUT_PULLUP); //sensor 12
pinMode(8, INPUT_PULLUP); //sensor 13
pinMode(9, INPUT_PULLUP); //sensor 14
pinMode(10, INPUT_PULLUP); //sensor 15
pinMode(11, INPUT_PULLUP); //sensor 16
}

void loop() {
if (loopCounter==600){bitSet(sensors,0);}
/*
For an unknown reason the ECoS sets the first 8 bits to 1 after startup / reset of the S88 Arduino's.
When one of the sensor inputs is changed, from there on everything goes well.
Therefore, over here we give sensor bit 0 an automatic change after 30 seconds, when the ECoS is fully started.
The 1 second is created via 'loopCounter', which increments in the PS interrupt (line 88).
There are appr0ximately 20 PS pulses per second, therefore we use 20x30=600 in the if statement.
*/
if (!digitalRead(A0)) {bitSet(sensors,0);}
if (!digitalRead(A1)) {bitSet(sensors,1);}
if (!digitalRead(A2)) {bitSet(sensors,2);}
if (!digitalRead(A3)) {bitSet(sensors,3);}
if (!digitalRead(A4)) {bitSet(sensors,4);}
if (!digitalRead(A5)) {bitSet(sensors,5);}
if (!digitalRead(0)) {bitSet(sensors,6);}
if (!digitalRead(1)) {bitSet(sensors,7);}
if (!digitalRead(4)) {bitSet(sensors,8);}
if (!digitalRead(5)) {bitSet(sensors,9);}
if (!digitalRead(6)) {bitSet(sensors,10);}
if (!digitalRead(7)) {bitSet(sensors,11);}
if (!digitalRead(8)) {bitSet(sensors,12);}
if (!digitalRead(9)) {bitSet(sensors,13);}
if (!digitalRead(10)) {bitSet(sensors,14);}
if (!digitalRead(11)) {bitSet(sensors,15);}
}

void PS() {
clockCounter=0;
data=sensors;
sensors=0;
loopCounter++; //Increment loopCounter to cretae a timer. See line 55 for explanation.
}

void clock() {
digitalWrite(dataOut,bitRead(data,clockCounter));
delayMicroseconds(16); //Delay makes reading output signal from next Arduino in chain more reliable.
bitWrite(data,clockCounter,digitalRead(dataIn));
clockCounter =(clockCounter +1) % 16;
}

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: S88 met arduino

Berichtdoor Koepel » 19 Dec 2016, 23:13

Graag zou ik meer gegevens willen hebben.

Dat de ingangen van je blokken een 0 of 5V zijn, dat lijkt me logisch, maar ik zou zelf de mogelijkheid willen hebben om in het schema te kijken hoe sterk die signalen zijn. Het schema mag gerust een schets op papier zijn, waar je foto van maakt.

Dus Ruud Boer schreef die code voor een Arduino Zero ? Staat het op internet ? kun je er een link naar geven ?

Pin 2 en 3 zijn inderdaad interrupt ingangen. En pin 12 wordt als data input en pin 13 wordt als data output gebruikt. Dat is logisch gebruik van die pinnen. Dan zit alles dus vol :(

Pin 0 en 1 kunnen 'override' worden, maar dan is het niet meer mogelijk om een sketch te uploaden.
Ik zie nog niet meteen een mogelijkheid om dat eenvoudig op te lossen.

Wat dacht je van een schuifregister ?
Kijk hier eens naar : http://www.gammon.com.au/forum/?id=11979.
De code in de sketch is eenvoudig, en je kunt eenvoudig meerdere 74HC165 achter elkaar schakelen voor heel veel ingangen.
Het is ook mogelijk om de analoge pinnen A6 en A7 te gebruiken met analogRead() en dan omzetten naar een digitale waarde. Dat is wel langzamer, dat zou invloed kunnen hebben op de hele sketch.
Tot slot is de Arduino Micro is ook nog steeds een goed alternatief.

Een digitalRead() kost ongeveer 3.5µs, en een analogRead() kost ongeveer 112µs. Dat is dus heel wat langzamer.
Die 16 keer digitalRead() kost bij elkaar dus 56µs. Als de volgorde niet uitmaakt, dan kan dat gemakkelijk onder de 10µs gebracht worden door poorten B,C en D direct te lezen en dan de bits zo te schuiven dat ze een 16 bits integer worden.

In de sketch zie ik een aantal problemen. Met name de synchronisatie van de 16 bits, en het het gebruik van variabelen in de interrupt routine die geen 'volatile' zijn gemaakt, en uit meerdere bytes bestaan en dus onderbroken kunnen worden.
De Arduino Zero heeft een 32-bits SAMD21 Cortex M0+ processor, en de ATmega328P is een 8-bits microcontroller. Dus op de Arduino Nano kan het schrijven van 32-bits long waarde drie keer onderbroken worden door een interrupt :geek:

Berichten: 5
Geregistreerd: 19 Dec 2016, 21:10

Re: S88 met arduino

Berichtdoor jola » 20 Dec 2016, 00:02

Ik vind het alleen vreemd dat alles goed gaat behalve bij de RX/D0.

Ik weet niet hoe ik een plaatje kan uploaden in dit forum.

Een link naar de maker:
https://rudysmodelrailway.wordpress.com/2014/10/03/arduino-used-as-an-s88-occupancy-detector-board/

Morgen zal ik eerst nog wat uitproberen en dan zien we wel verder.

Gebruikers-avatar
Berichten: 2655
Geregistreerd: 06 Aug 2016, 01:03

Re: S88 met arduino

Berichtdoor Koepel » 20 Dec 2016, 01:51

Bedankt, nu weet ik iets meer. De ingangen zijn dus optocouplers met een 10k pullup weerstand. Dat is dus een vrij zwak signaal.

Wanneer je op 'upload' klikt dan get het via de usb kabel naar de usb-serial chip op het Nano board, vervolgens via pin 0 en 1 naar de bootloader, die sketch in de microcontroller programmeert.
Halverwege deze pagina "https://www.arduino.cc/en/Main/ArduinoBoardNano" zie je een link naar het schema. Als je het schema bekijkt, dan zie je dat pin 0 (RX) en pin 1 (TX) via 1k weerstanden naar de usb-serial chip gaan. Pin 0 en 1 zijn namelijk de seriële poort van de microcontroller, en die word gebruikt om de sketch te uploaden en ook voor de seriële monitor (maar die gebruik je niet in de sketch).

Pin 0 en 1 zijn dus al in gebruik. Maar omdat het via de 1k weerstanden gaat, kun je met een sterk signaal daar overheen. Dan werkt echter het uploaden niet meer. Aan de TX hangt de ingang van de usb-serial chip, dus dat is geen probleem. Aan de RX hangt echter de uitgang van de usb-serial chip, en daarom kan jouw signaal met de 10k pullup weerstand niet tegen het signaal van usb-serial chip op die met 1k verbonden is aan pin 0.

Ik weet niet hoe ik het nog duidelijker kan maken.

Dit heb je met een Arduino Micro allemaal niet. Daar zijn pin 0 en 1 helemaal vrij.

Berichten: 5
Geregistreerd: 19 Dec 2016, 21:10

Re: S88 met arduino

Berichtdoor jola » 20 Dec 2016, 11:35

Om het nog erger te maken heb ik een ander ingangscircuit (ik werk met 3-rail en gebruik geen optocouplers) met een seriediode. Ik heb even de spanningen gemeten op de ingangen van de Arduino: A0 t/m A5 worden 0,64V, TX wordt 1,17V en als klap op de vuurpijl RX wordt 2,7V. Geen wonder dat het niet werkt!
Bedankt voor de moeite, het is me nu volkomen duidelijk.

Mvg, Jos

Berichten: 5
Geregistreerd: 19 Dec 2016, 21:10

Re: S88 met arduino

Berichtdoor jola » 21 Dec 2016, 15:13

Ik heb het eenvoudig kunnen oplossen door een emittervolger ertussen te zetten, dus door 1 PNP transistor en 1 weerstand te gebruiken per S88 werkt het zo als het moet.

Bedankt voor de hulp.

Mvg, Jos

Berichten: 4064
Geregistreerd: 16 Okt 2013, 14:31
Woonplaats: s hertogenbosch

Re: S88 met arduino

Berichtdoor shooter » 22 Dec 2016, 20:39

dat heeft allemaal te maken met de elektronica die op de printjes zit voor de seriele communicatie, en inderdaad een simpele tor is voldoende om dat op te lossen.
persoonlijk zou ik naar een schuifregister of een I2C oplossing gaan, want dan kun je ineens veel meer bezetmeldingen aan op een station.
paul deelen
shooter@home.nl

Terug naar Arduino hardware

Wie is er online?

Gebruikers in dit forum: Geen geregistreerde gebruikers en 10 gasten