Doel:€250.00
Donaties:€88.00

Per saldo:€-162.00

Steun ons nu!

Laatst bijgewerkt
op 03-06-2025

Vacature: secretaris bestuur
Algemeen

De stichting

Recente berichten

Mijn eerste H0-modeltreinbaan in aanbouw door Frank103
Vandaag om 17:56:15
Microstepper motoren voor armseinpalen door AP3737
Vandaag om 17:54:02
Bezetmelder brug in rolbrug blijft actief als rolbrug gestopt is door Roelof Hartholt
Vandaag om 17:53:46
Raadplaatje door henk
Vandaag om 17:51:55
Wèhnich - Eén onbeduidend baantje op 1200 bij 1200mm door Prutsert
Vandaag om 17:31:09
Roco 69139 NS Plan V SOUND AC door VAM65
Vandaag om 17:25:53
Sfeer op je modelbaan door Stieven76
Vandaag om 17:24:50
Centraal Zwitserland: Trein, tram, kabelbaan en gondels. door Jan Bennink
Vandaag om 17:23:26
Acherntal H0. (TP III/TP IV) door Ronald69
Vandaag om 17:10:54
Roco Plan T door 008200
Vandaag om 16:56:37
Bahnstrecke 5867 door Frank 123
Vandaag om 16:24:13
Rheinburg, TP V/VI door Dave.......
Vandaag om 16:10:26
De bouw van mijn modelbaan in Thailand door wob
Vandaag om 16:06:34
Länderbahn en Reichsbahn locomotieven. door wob
Vandaag om 16:02:16
Bentheimer Eisenbahn, gisteren, vandaag en morgen. door saskia
Vandaag om 15:53:42
Stationsplein Baden Baden door Dion
Vandaag om 15:30:55
NS 1700 transfers door Gerco van Beelen
Vandaag om 15:12:09
Noorwegen - interessante spoorzaken langs vakantieroute door Dion
Vandaag om 15:05:44
Gezocht info en foto's van standaard dwarsliggerwagen door j.ossebaar
Vandaag om 15:03:34
Draaischijf uit de 3D-printer en met Arduino besturing door Joz
Vandaag om 14:14:39
Fleischmania Nostalgia door hervé
Vandaag om 14:01:26
Defensie wil oude koplopers ombouwen tot hospitaaltrein door spoorzeven
Vandaag om 13:43:53
Onlangs gespot - gefotografeerd, de foto's door thevandijks
Vandaag om 12:39:54
ongeremde Sikken/wagens in goederentreinen door j.ossebaar
Vandaag om 11:51:04
Pimpen Rivarossi DD-AR door Chiel
Vandaag om 11:49:12
Kreisbahn nach Bad Bimmelberg (0,42m2) door GD
Vandaag om 11:21:39
Camp 3 door GD
Vandaag om 11:19:31
"moderne" kolenbakken en kolenwagens in Nederland. door ES44C4
Vandaag om 08:34:16
Swalbenburg, N modulebaan door NS264
19 July 2025, 23:46:32
Brawa goederenwagen Kassel ( Cassel ) h0 door hervé
19 July 2025, 23:10:30
  

Auteur Topic: Arduino analoge(!) modelbaan sturing  (gelezen 146446 keer)

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino analoge(!) modelbaan sturing
« Reactie #270 Gepost op: 04 November 2015, 20:23:26 »
Hoi Paul,

Okay, ik ga er weer even voor zitten. Veel opmerkingen en vragen dus mag ik ook weer veel tekst en code maken  ;D Ben toch eens benieuwd wanneer het forum gaat roepen dat een post van mij te lang is :p

Welke verwarring bedoelde je? Of bedoel je omdat je verschillende "slaves" wilt maken?

En ga je dan de wissel functie weer van de blokkaart af halen?

Millis is niet zo lastig. Het is overigens niet waar dat je dit alleen in de loop zou kunnen gebruiken. Wat doe je als je een eitje wilt koken en tegelijk de broodjes wilt afbakken? Juist, je zet twee timers (of onthoudt twee tijden). In programma is dat niet anders. Je moet dus meerdere variabele hebben die de verschillende tijden bijhouden.

Hier een voorbeeldje. Dit laat twee ledjes knipperen met twee verschillende intervals. Maar ook nog een met een ander interval voor aan dan voor uit. En nog een derde die aan gaat voor 30 seconden na het indrukken van een knop (en dit lijkt dus al op een wissel ;) )
#include <Bounce2.h>

const byte LedPins[] = {13, 12}; //Pinnen voor de knipper ledjes (even lang aan als uit)
const byte FlasherPin = 10; //Pin voor de flasher, andere aan dan uit tijd
const byte KnopjePin = 9; //Pin voor het drukknopjes (tussen de pin en GND)
const byte TimedLedPin = 8; //Pin voor het ledje wat je an kunt doen met het knopje

const unsigned int LedIntervals[] = {500, 1200}; //aan/uit interval voor led1, led 2 enz
const unsigned int FlasherIntervals[] = {1900, 100}; //1900ms uit, 100ms aan
const unsigned int TimedLedInterval = 30000; //uit na zoveel ms

Bounce knopje;

void setup(){
  //Alle pins met ledjes moeten natuurlijk output zijn
  for(byte i = 0; i < sizeof(LedPins); i++){
    pinMode(LedPins[i], OUTPUT);
  }
 
  pinMode(FlasherPin, OUTPUT); //Flasher ook output
  pinMode(TimedLedPin, OUTPUT);//en deze ook
 
  knopje.attach(KnopjePin, INPUT_PULLUP); //Verbind de pin met het object en zet pull up aan
 
}

void loop(){
  updateLed(0); //Een ledje laten knipperen
  updateLed(1); //En nog één!
 
  updateFlasher(); //En nu nog eentje laten met verschillende aan en uit tijden
 
  timedLedUpdate(); //En nog een ledje (maar zou net zo goed een wissel kunnen zijn ;) ), aan met knop, vanzelf uit
}

//Laat ledjes knipperen. Even lang aan als uit. Werkt voor hoevel ledjes je in LedPins en LedIntervals definieert
void updateLed(byte ledNummer){
  static unsigned long vorigeMillis[sizeof(LedPins)]; //om de laatste keer te onthouden (wanneer keek ik op de klok?)
 
  //Controleer of interval om is. MOET op deze manier
  if(millis() - vorigeMillis[ledNummer] >= LedIntervals[ledNummer]){
    vorigeMillis[ledNummer] = millis(); //sla op dat we weer iets doen
   
    digitalToggle(LedPins[ledNummer]); //Wissel led (HIGH <-> LOW)
  }
}

//functie om een pin te wisselen (LOW <-> HIGH)
void digitalToggle(byte pin){
  digitalWrite(pin, !digitalRead(pin));
}

void updateFlasher(){
  static unsigned long vorigeMillis = 0; //Laate keer iets gedaan, ondertussen bekende variabele ;)
 
  //Checken of het interval om is. We gebruiken een interval voor uit (FlasherIntervals[0]) en een voor aan FlasherIntervals[1]
  //Door dus digitalRead() te bruiken komt hier al 0 of 1 uit al naar gelang of de flasher aan of uit is
  if(millis() - vorigeMillis >= FlasherIntervals[digitalRead(FlasherPin)]){
    vorigeMillis = millis();  //Sla op dat we eits doen
   
    digitalToggle(FlasherPin); //wissel led(HIGH <-> LOW)
  }
}


//Timed ledje, gaat aan met knopje en weer uit na een ingestelde tijd
void timedLedUpdate(){
  static unsigned long ledjeAanMillis = 0;
 
  //Beginnen we met kijken of het knopje is ingedrukt want ja, dan moet het ledje aan
  knopje.update(); //Lees het knopje
 
  //Is het knopje ingedrukt?
  if(knopje.fell() ){
    digitalWrite(TimedLedPin, HIGH); //zet het ledje aan
    ledjeAanMillis = millis();  //sla op wanneer je it gedaan hebt
  }
 
  //nu we dat gedaan hebben, is het misschien tijd om het ledje uit te zetten? Moet hij wel aan staan natuurlijk!
 
  //Staat ledje aan? (Ja, je kan gewoon een digitalRead op een output doen, geen probleem :) )
  if(digitalRead(TimedLedPin)){
    //Ledje is dus aan, maar moet hij al uit?
    if(millis() - ledjeAanMillis >= TimedLedInterval){
      digitalWrite(TimedLedPin, LOW);
    }
  }
}

Ik heb er ook voor gekozen alle "vorigeMillis" variabele onder te brengen in de functie zelf. Ze zijn steeds alleen daar nodig dus is het zinloos ze global te maken. Variabele steeds zo dicht mogelijk declareren waar ze nodig zijn. Omdat ze wel onthouden moeten blijven tussen de verschillende aanroepen van de functies zijn ze static.

Nog een kleine aanvulling. inteerup

SlavePinx zijn duur puur om het voor jou inzichtelijk te maken? Denk ook hier eens aan een array. Meer dezelfde dingen (meerdere SlavePin) kunnen makkelijker in een array. Scheelt je veel code typen ;) Zelfde voor je sein en wissel pinnen.

Let er overigens op dat je variabele in de functie declaraties geen constanten zijn. De hoofdletters zijn daar dus ongewenst.
Niet void setWissel(byte Wnummer, bool Wrichting)
Maar void setWissel(byte wNummer, bool wRichting)
Maar je doet dit eigenlijk steeds in elke functie declaratie. Het zou wel gewoon werken maar die hoofdletter is er eigenlijk voor jou als geheugensteun dat het een constante is en dat je deze niet niet zou kunnen aanpassen.

Ook heb je in de blokkaart:
void setWissel(byte Wnummer, bool Wrichting) {

  if (Wnummer == 1) {

    if (Wrichting == 0) {

      digitalWrite(Wissel1rPin, HIGH);
      delay(750); // Normaal staat de waarde op 500)
      digitalWrite(Wissel1rPin, LOW);
    }
  }

  if (Wnummer == 1) {

    if (Wrichting == 1) {

      digitalWrite(Wissel1aPin, HIGH);
      delay(750); // Normaal staat de waarde op 500)
      digitalWrite(Wissel1aPin, LOW);
    }
  }
} // einde functie setWissel
De check Wrichting == 1 is nogal overbodig. Als het niet 0 is zoals al gecontroleerd dan moet wel 1 zijn ;) De tweede Wnummer == 1 is ook niet nodig.
Dus:
void setWissel(byte Wnummer, bool Wrichting) {

  if (Wnummer == 1) {

    if (Wrichting == 0) {

      digitalWrite(Wissel1rPin, HIGH);
      delay(750); // Normaal staat de waarde op 500) <--------------- Dit is dus typisch iets om een const variabele voor aan te maken!
      digitalWrite(Wissel1rPin, LOW);
    }
    else{

      digitalWrite(Wissel1aPin, HIGH);
      delay(750); // Normaal staat de waarde op 500)
      digitalWrite(Wissel1aPin, LOW);
    }
  }
} // einde functie setWissel
En nu nog zonder delay  ;D

En eigenlijk doe je zo'n zelfde redundant ding met je CwRichting en CcwRichting. Het is nogal dubbel werk om beide bij te houden. Zou hetzelfde zijn als je op gaat schrijven dat het waar is dat je je glas leeg hebt gedronken en ook opschrijft dat het niet waar is dat je je glas niet hebt opgedronken. Je kan af met 1 variable, bijvoorbeeld cwRichting. Ook hier zonder grote C omdat het geen const is.

In je centrale maak je de globals char Slave en char I2CByte aan. Buiten dat ze geen const zijn dus kleine letter (en weer, die hoofdletter zou juist een geheugensteun voor JOU moeten zijn ;) ) gebruik je ze ook maar in één functie en hoeft het tussen de verschillende runs van die functie (loop() in dit geval) ook niet onthouden te worden. Je kan ze dus beter maken in de fucntie zelf (loop() ). En voor voor beide doe je dit ook! In loop staat namelijk bijvoorbeeld:
char Slave = Wire.read(); // receive a byte as character
Hiermee maak je gewoon een lokale variabele Slave aan. In je code heb je dus twee verschillende variabele die beide Slave heten maar verschillende waardes hebben! Alleen wordt bij het aanroepen steeds eerst gekeken of een variabele lokaal gevonden kan worden, zo niet wordt global gekeken.

Hieronder een voorbeeld om dat duidelijk te maken.
int myVar = 1;

void setup(){
  Serial.begin(115200);
}

void loop(){
  int myVar = 50;
 
  Serial.println(myVar); //print de lokale variabele
  Serial.println(::myVar); //print de global variabele (geef je aan met de :: )
  delay(1000);
}
Dit zal elke seconde
50
1
printen in de serail monitor. Het zijn dus echt twee variabele!

Als ik het goed heb kan ik 127 slave units met de I2C  gebruiken.
Klopt, het adres van een I2C is 7 bits lang en 0 mag niet gebuikt worden => houd je 127 over. Let wel dat je LCD hier dus ook al een adres van inpikt.

En dan door op de adressen. Je hebt
Wire.begin(5); // Stelt de communicatie met de AAMS centrale in.
Waarom is dit niet een variabele? Want later wil je die 5 weer gebruiken.

En dan waar je hem later gebruikt, je stuurt het terug aan de centrale. Maar dit zou niet perse het adres hoeven zijn. Aangezien je de request al aan het juiste adres. Iedere vorm van ACK zou dus okay zijn. En misschien is het commando terug koppelen wel de beste ACK zijn, dan pas weet je het 100% zeker. ;)

En dan over het programmeren. Als jij al 10 blokkaarten hebt en je past toch de code aan (uitbreiding of misschien bugfix) dan zal je nu steeds het I2C adress van alle modules moeten aanpassen. De handeling wordt dan:
- Module aan PC
- Juiste adres instellen in de code
- Programmeren
- Volgende module aan PC
- Juiste adres instellen in de code
- Programmeren
- Enz

Met het stukje code wat ik gaf hoe je dat alleen de eerste keer te doen. Daarna staat het adres "vast" in het EEPROM en zal dus bewaard blijven. Het adres in de code doet er dan niet meer toe (tenzij je met #define FORCEER_NIEUW_ADRES aangeeft dat je een nieuw adres wilt geven) en hoef je deze dus bij het herprogrammeren niet steeds aan te passen voor elke module die je aankoppelt. Je kan gewoon steeds gelijk op "Upload" klikken zonder ook maar iets in de code te wijzigen, adres komt toch wel uit EEPROM. Maakt het leven weer wat makkelijker.

Het lijkt er sterk op dat een delay(200)  zonder dat de Arduino moet wachten tot de delay(200) is afgelopen andere commando's kan uitvoeren,
Ik zie even niet welke delay je bedoelt (zie geen delay(200) ). Maar ja, de library zal je volgende commando wel afvangen (heeft niet voor niet een buffer van 32 bytes) maar zal deze pas uitvoeren als de delay over is.

Sterker nog, de onReceive en onRequest zijn interrupt functies. Deze zullen de normale functies inderdaad direct onderbreken om de taken uit te voeren. Dus ook een delay in de loop (of andere functies die vanuit de loop worden aangeroepen). Maar ze zullen elkaar of zichzelf niet onderbreken. De volgende onReceive kan pas beginnen als de huidige is afgelopen. Dus staat daar een delay in dan wordt die gewoon afgewacht.

En nog sterker, de Wire library zal de I2C bus pas vrijgeven als de hele functie voor onRequest of onRecive is afgerond. Heb je daar dus een delay staan wordt de I2C lijn al die tijd bezet gehouden  :-\ En dat is zelfs zo erg dat de master/centrale die met een Wire.write() of Wire.requestFrom() daar zal blijven wachten omdat de Wire.write() en Wire.requestFrom() pas stoppen als de I2C slave de bus weer vrij geven! Je delay dendert dus zelfs door naar de master/centrale  ::) ::) ::)

Hieruit kan je twee dingen leren:
1) Die delays zijn echt ongewenst  8)
2) De Wire llibrary laat beetje te wensen over (maar goed, is verder wel mee te werken)
3) Je wilt interrupts zo snel mogelijk afhandelen en weer door. Beter zou dus zijn om bij Wire.onReceive () het daar verstuurde commando op te slaan, een flag (bool nieuwCommando) te zetten om aan te geven dat je een nieuw commando hebt en dan gelijk de onReceive() te verlaten. Vervolgens kijk je in de loop() steeds of je een nieuw commando hebt ontvangen, zo ja, lees je het commando en voer je de juiste taak uit.

Nu gaf je aan dat Engels een beetje een probleem is maar hierbij toch twee linkjes. Misschien zijn ze dan wat lastig te lezen maar geven wel weg waar het om draait. Google Translate kan denk ik al een heel eind helpen.

Over het laatste stuk over de communicatie tussen PC en centrale (eigenlijk dus het protocol) kom ik later nog op terug. Dit gaat denk ik makkelijker als ik hier ook een stukje code als voorbeeld/opzet voor maak. Maar ik heb al genoeg code en tekst geschreven (meer dan een uur verder) dus ik plaats eerst dit eens. Misschien dat ik vanavond of morgen dat nog kan doen.


Timo
« Laatst bewerkt op: 04 November 2015, 20:29:58 door Timo »
Verzonden vanaf mijn desktop met Firefox

smits66

  • Offline Offline
  • Berichten: 543
  • Schaal 1:160, Arduino
Re: Arduino analoge(!) modelbaan sturing
« Reactie #271 Gepost op: 05 November 2015, 23:32:22 »
Hoi volgers,

Ik ben verder gaan zoeken naar een goede manier om een Serial communicatie wat makkelijker te maken.

Ik heb het volgend programma gemaakt, de vraag is gaat dit werken, een droge test met LEDS werkt goed,
afgezien van het feit de de poorten actief hoog zijn, terwijl ik de poorten actief laag wil hebben,
zet ik de poorten in de setup op LOW dan werk het geheel niet. ??? :P


Programmeer code :

byte BlokPin[] = {11, 10, 9, 8};
byte State;
//int current;

void setup() {
 
  pinMode(BlokPin[0], OUTPUT);
  pinMode(BlokPin[1], OUTPUT);
  pinMode(BlokPin[2], OUTPUT);
  pinMode(BlokPin[3], OUTPUT);
 
 
  Serial.begin(9600);
}

void loop() {

  if (Serial.available() > 0) {
   
    if (Serial.peek() == 'A') {
      Serial.read();
      State = Serial.parseInt();
      Serial.read();
      digitalWrite(BlokPin[0], State);
    }
    if (Serial.peek() == 'B') {
      Serial.read();
      State = Serial.parseInt();
      digitalWrite(BlokPin[1], State);
    }
    if (Serial.peek() == 'C') {
      Serial.read();
      State = Serial.parseInt();
      digitalWrite(BlokPin[2], State);
    }
    if (Serial.peek() == 'D') {
     
      Serial.read();
      State = Serial.parseInt();
      digitalWrite(BlokPin[3], State);
     
    }
    while (Serial.available() > 0 ) {
      Serial.read();
    }
  }
}

@Timo

Bedankt voor je input!  (y)

Ik heb nog een heel klein vraagje Kan ik de code van de millis ook in een Event routine gebruiken, zoals ik die in de Blokkaarten gebruik. ::)
De bovenstaande code (stiekem afgekeken en aangepast :-X ;D), is dat een goede stap in de juiste richting ,
of zoek ik het in een verkeerde hoek? ::) ,of maak ik het mij zelf weer moeilijk ::) :P

Ik hoor het wel, commentaar/meedenken  is altijd welkom. ;D

Mvg Paul  :D
« Laatst bewerkt op: 05 November 2015, 23:35:16 door smits66 »
Üdvözlet Paul Smits.


bouw draadje "Laubenstein"

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino analoge(!) modelbaan sturing
« Reactie #272 Gepost op: 10 November 2015, 11:26:16 »
Hoi Paul,

millis() kan je werkelijk overal toepassen. Alleen zorg wel dat je event routines voor wire kort zijn. Misschien zou ik ze zelf niet eens gebruiken maar het gewoon met Wire.available() controleren.

Het is een stap in de goede richting! Alleen dat gedoe met parseInt() is nogal omslachtig. Beste is gewoon te stoppen met het versturen van getallen als ASCII op de computer. Maar stuur gewoon één byte. Een byte heeft van zichzelf al 256 mogelijkheden. Terwijl als je het met ASCII doet je 3 bytes aan het versturen bent (met maar 10 mogelijke waardes) en vervolgens doe je op de Arduino weer alle moeite er een byte van te maken. Dus ik weet niet hoe de code van het programma er uit ziet maar het kan nooit lastig zijn die aan te passen tot het zenden van een byte.

Je krijgt dan iets als
byte BlokPins[] = {11, 10, 9, 8};

void setup() {
 
  for(byte i = 0; i < sizeof(BlokPins); i++){
    pinMode(BlokPins[i], OUTPUT);
  }
 
  Serial.begin(9600); //tijd voor 115200?
}

void loop() {
  checkIngekomenSerial();
 
}

void checkIngekomenSerial(){
  // Ga dan uit dat de serial commando's eruit zien als
  // [commando letter] [adres]
  // Waarbij ieder [] één byte is. Dus geen adressen in ASCII zenden ;)
  if (Serial.available() >= 2) {   
    switch(Serial.read()){
      case 'W':
        //Schakel een wissel recht
        //Ga even uit dat de functie schakeWissel(wisselnummer, richting) bestaat
        schakelWissel(Serial.read(), RECHT);
        break;
      //schakel een wissel afbuigend
      case 'w':
        schakelWissel(Serial.read(), AFBUIGEN);
        break;
      //Maak blok vrij
      case 'b':
        setBlok(Serial.read(), VRIJ);
        break;
      case 'B':
        setBlok(Serial.read(), BEZET);
        break;
    }
  }
}

Zie je ook gelijk dat een for loopje lekker makkelijk is om alle pinnen van een array goed te zetten ;)

Verder zat ik te denken. Op zich is er geen noodzaak om netjes op nummerende adressen te hebben voor wissels, blokken enz. Waarom stuur je vanuit de PC niet gewoon een I2C adres en een "device adres" (nummer hoeveel op de blokkaart). Dus
[commando letter] [module/I2C adres] [device adres]
Alles tussen de [] is steeds één byte.

Voorbeeld om wissel 1 op module 28 recht te zetten zou dan zijn:
[W] [28] [1]

Nadeel is dat je twee adressen op moet slaan in je programma... Voordeel is wel dat je flexibel bent met hoeveel wissels er aan één module hangen.

Andere optie zou zijn om een vast bereik te bedenken, bijvoorbeeld 8 wissels per module. Wissel 140 is dan automatisch module 140 / 8 = 17 en wissel 140 % 8 = 4.

In ieder geval, code zou dan iets kunnen zijn als
byte BlokPins[] = {11, 10, 9, 8};

const unsigned int SerialInterval = 200;

void setup() {
 
  for(byte i = 0; i < sizeof(BlokPins); i++){
    pinMode(BlokPins[i], OUTPUT);
  }
 
  Serial.begin(9600); //tijd voor 115200?
}

void loop() {
  checkIngekomenSerial();
 
}

void checkIngekomenSerial(){
  static unsigned int lastCommandMillis = 0;
  unsigned int nowMillis = millis();
 
  // Ga dan uit dat de serial commando's eruit zien als
  // [commando letter] [module adres] [device adres]
  // Waarbij ieder [] één byte is. Dus geen adressen in ASCII zenden ;)
 
  //Kijk of er een commando is binnen gekomen
  if(Serial.available() >= 3){
    //Okay, 3 byte dus een commando, update de tijd dat er een geldig commando was
    lastCommandMillis = millis();
   
    //Eerst commando van 3 bytes even opslaan
    for(byte i = 0; i < 3; i++){
      laatsteCommando[i] = Serial.read();
    }
   
    //Nu over I2C versturen
    Wire.beginTransmission(laatsteCommando[1]); //bevat het adres
    Wire.write(laatsteCommando[0]); //type commando
    Wire.write(laatsteCommando[2]); //device adres
    Wire.endTransmission();         //En de bus sluiten
  }
 
  //Is het anders tijd voor het legen van de buffer?
  //Gebeurd als er SerialInterval lang geen geldig commando is ontvangen
  else if(Serial.available() && (nowMillis - lastCommandMillis >= SerialInterval){
    while(Serial.available()){
      Serial.read();
    }
  }
 
  //Om te zorgen dat de buffer niet geleegd word als we na een lange tijd weer beginnen met het zenden van een commando
  //updaten we de tijd ook als de buffer gewoon leeg is. Kan ook gezien worden als geldig
  //commando voor do niets ;)
  else if(!Serial.available()){
    lastCommandMillis = millis();
  }
}

Dit stuurt dan ook alle binnengekomen data door naar de juiste slave en slaat het ook nog lokaal op voor gebruik op de master.

Ook zit er een voorbeeldje in om de buffer van serial te legen als er te lang geen commando is ontvangen bijvoorbeeld omdat het PC programma herstart is enz. Omdat ik daar nu een waarde van 200ms heb gebruikt is het wel noodzaak dat checkIngekomenSerial vaker dan eens elke 200ms gedaan wordt. Met andere woorden, geen delay ;)

Maw, keuzes. Hoe wil jij de nummering van de modules / wissels / blokken / seinen enz gaan doen?


Timo
Verzonden vanaf mijn desktop met Firefox

smits66

  • Offline Offline
  • Berichten: 543
  • Schaal 1:160, Arduino
Re: Arduino analoge(!) modelbaan sturing
« Reactie #273 Gepost op: 03 January 2016, 00:55:07 »
Hoi Volgers,

Allereerst wens ik jullie en goed en mooi 2016 toe. (y)

@Timo, bedank voor je input

Ik krijg het onderstaand programma niet werkend.

Als ik bv W1 invoer gebeurd er niets, ik heb de code uitgebreid met de twee functie's zoals je in het voorbeeld heb gezet, wat doe ik fout ???.

Het voorbeeld programma :

Citaat
byte BlokPins[] = {11, 10, 9, 8};

void setup() {
 
  for(byte i = 0; i < sizeof(BlokPins); i++){
    pinMode(BlokPins, OUTPUT);
  }
 
  Serial.begin(9600); //tijd voor 115200?
}

void loop() {
  checkIngekomenSerial();
 
}

void checkIngekomenSerial(){
  // Ga dan uit dat de serial commando's eruit zien als
  // [commando letter] [adres]
  // Waarbij ieder [] één byte is. Dus geen adressen in ASCII zenden ;)
  if (Serial.available() >= 2) {   
    switch(Serial.read()){
      case 'W':
        //Schakel een wissel recht
        //Ga even uit dat de functie schakeWissel(wisselnummer, richting) bestaat
        schakelWissel(Serial.read(), RECHT);
        break;
      //schakel een wissel afbuigend
      case 'w':
        schakelWissel(Serial.read(), AFBUIGEN);
        break;
      //Maak blok vrij
      case 'b':
        setBlok(Serial.read(), VRIJ);
        break;
      case 'B':
        setBlok(Serial.read(), BEZET);
        break;
    }
  }
}
 

Ik hoop dat je me daar nog eens mee wil helpen,  alle hulp welkom.

@Allen

Het is alweer een tijd geleden dat ik wat in mijn draadje hebt gezet.
Ik ben nog steeds bezig met mijn AAMS sturing, er zijn al diverse projecten in dit topic gezet met betrekking tot het AAMS systeem.(zie dit draadje)

Het laatste project was om meerdere Arduino nano's met elkaar te communiceren via I2C, het werkte goed en de communicatie tussen de Arduino nano's ging verrassend simpel, het nadeel van die constructie was dat naarmate er meer Arduino nano's bij werden gemaakt  werd het op een gegeven moment onoverzichtelijk.



Ik ben weer even gaan zoeken in mijn onderdelen kwam ik in een verloren hoekje ::) een AT MEGA 2650 met een L293 motorshield,  wat losse relais en wat sensor printjes tegen en een 2x16 LCD, ik kreeg meteen het idee dat ik daar wel eens een Modelbaan sturing "AAMS" mee kon maken, zo gedacht zo gedaan :P

Het voordeel van een mega 2650 is de overvloed aan i/o pins.

16 analog in.
53 digital in/out
4 hardwarematig Seriële poorten Rx/Tx

Het L293 motorshield bevat vier sturingen voor een dc motor met een max van 600 mA per motor uitgang, dat is voldoende om een n-spoor loc te laten rijden

3x een IR sensor ,twee gebruikt.

Daar kan ik wel wat mee, om een eenvoudige AAMS sturing mee te maken.

Het eerste resultaat.



Het motorshield l293 maakt gebruik van adafruit motorshield library, deze library heb ik aangepast voor mijn eigen sturing, deze library in nog niet voledig aangepast maar zoveel dat ik er een AAMS sturing mee kan maken.
Op de foto zijn de IR Sensoren nog niet aangesloten.

Ik heb ondertussen een redelijk goede sturing, alleen moet ik nog wat sleutelen aan het optrekken van de trein, ook aan de sensoren moet nog wel wat gesleuteld worden.

De sensoren werken nu als volgt : als beide sensoren een lagere waarde hebben dan 60 zal de trein stoppen en de seinen op rood springen, zolang de sensoren een hogere waarde meten dan 230 zal de trein blijven rijden.

Een filmpje van deze werkende sturing https://youtu.be/XLGttOrHeEY
 
Mocht er nog interesse in mijn "Hobby" programma zijn hoor ik dat wel en zal het op het forum zetten.

Mvg Paul  ;D


 
« Laatst bewerkt op: 03 January 2016, 15:22:33 door smits66 »
Üdvözlet Paul Smits.


bouw draadje "Laubenstein"

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino analoge(!) modelbaan sturing
« Reactie #274 Gepost op: 03 January 2016, 16:14:27 »
Hoi Paul,

Allereerst de beste wensen! Leuk om te zien dat het ook in 2016 weer door gaat ;)

Misschien kan je je code op PastBin zetten? Voor grote lappen code wat overzichtelijker, mede omdat je Syntax Highlighting (C++) aan kunt zetten.

Zelf nog even naar de code gekeken. (Overigens, let er op dat je code op eht forum in [code ] tags zet en niet in [quote ] tags. Zie je wat er nu gebeurd is?  ;) ) Je moet wel bedenken dat het steeds een soort pseudo code is en alleen de basis weergeeft en je de rest nog aan moet vullen. Ik heb het even aangevuld tot werkende code. De functies die ik gemaakt hebt stuurt het alleen terug naar de computer.

PastBin
byte BlokPins[] = {11, 10, 9, 8};

#define RECHT     0
#define AFBUIGEN  1
#define VRIJ      0
#define BEZET     1

void setup() {
 
  for(byte i = 0; i < sizeof(BlokPins); i++){
    pinMode(BlokPins[i], OUTPUT);
  }
 
  Serial.begin(115200); //tijd voor 115200?
}

void loop() {
  checkIngekomenSerial();
 
}

void checkIngekomenSerial(){
  // Ga dan uit dat de serial commando's eruit zien als
  // [commando letter] [adres]
  // Waarbij ieder [] één byte is. Dus geen adressen in ASCII zenden ;)
  if (Serial.available() >= 2) {   
    switch(Serial.read()){
      case 'W':
        //Schakel een wissel recht
        //Ga even uit dat de functie schakeWissel(wisselnummer, richting) bestaat
        schakelWissel(Serial.read(), RECHT);
        break;
      //schakel een wissel afbuigend
      case 'w':
        schakelWissel(Serial.read(), AFBUIGEN);
        break;
      //Maak blok vrij
      case 'b':
        setBlok(Serial.read(), VRIJ);
        break;
      case 'B':
        setBlok(Serial.read(), BEZET);
        break;
    }
  }
}


void schakelWissel(byte address, bool state){
  Serial.print("Wissel ");
  Serial.print(address);
  if(state){
    Serial.println(" afbuigen");
  }
  else{
    Serial.println(" recht");
  }
}

void setBlok(byte address, bool state){
  Serial.print("Blok ");
  Serial.print(address);
  if(state){
    Serial.println(" bezet");
  }
  else{
    Serial.println(" vrij");
  }
}

Dit werkt prima. Open ik Serial Monitor en type ik W1[enter] krijg ik netjes terug "Wissel 49 recht". Dat het 49 is ipv één komt omdat de Serial Monitor altijd alles stuurt in ASCII, ook de getallen. Het teken '1' heeft de byte waarde 49. Jij stuurt je boodschappen niet met Serial Monitor maar met je programma dus kan jij makkelijk het wel als byte over sturen. Gebruik ik CoolTerm of RealTerm dan kan ik wel netjes [W][1] als twee losse bytes sturen en krijg ik netjes "Wissel 1 recht"

Als je meer code publiceert (zowel de Arduino als de PC) zou ik het er wel netjes in kunnen schrijven. In dit voorbeeld is er bijvoorbeeld geen fout afhandeling ofzo. Iets wat ik in het voorbeeld erna wel (hoewel basic) heb toegevoegd.

En om het netjes te krijgen zou het helpen als je een aantal dingen op een printje zou solderen :) Heb je minder DuPond draadjes nodig enzo.


Timo
Verzonden vanaf mijn desktop met Firefox

smits66

  • Offline Offline
  • Berichten: 543
  • Schaal 1:160, Arduino
Re: Arduino analoge(!) modelbaan sturing
« Reactie #275 Gepost op: 09 January 2016, 21:15:28 »
Hoi volgers,

@Timo

Bedankt voor je input.

Helaas krijg ik deze routine niet werkend, ik zie de gegevens wel op het scherm verschijnen.
Maar een schakel opdracht word er niet gegeven ,althans maar gedeeltelijk, zie voorbeeld code.
Geef ik nu w2 in gaat het ledje branden, deze is hetzelfde als w1 poort 11, ASCII code geeft het wel goed aan.

Ik heb verschillende programmeercode gebruikt maar het lukt mij niet om de juiste ledjes (lees wissels) aan te sturen, het programma stuurt constant dezelfde led (lees wissel) aan.

Ik zal wel wat over het hoofd zien ::)

byte BlokPins[] = {11, 10, 9, 8};//worden voor testen gebruikt voor blok en wissels

#define Recht     0
#define Afbuigen  1
#define Vrij      0
#define Bezet     1
//char MyString;
void setup() {

  for (byte i = 0; i < sizeof(BlokPins); i++) {
    pinMode(BlokPins[i], OUTPUT);
  }

  Serial.begin(115200); //tijd voor 115200?
}

void loop() {
  checkIngekomenSerial();

}

void checkIngekomenSerial() {
  // Ga dan uit dat de serial commando's eruit zien als
  // [commando letter] [adres]
  // Waarbij ieder [] één byte is. Dus geen adressen in ASCII zenden ;)

  //while (Serial.available() >= 2) {
  if (Serial.available() >= 2) {

    //char MyString = Serial.read();

    //if(MyString == 'W1') {
    // setWissel(MyString, Recht);
    // }
    // if(MyString == 'w1'){
    //    setWissel(MyString, Afbuigen);
    // }
    //}
    switch (Serial.read()) {
      //switch (MyString) {


      //schakel een wissel recht
      case 'W':
        //case 'W1':

        setWissel(Serial.read(), Recht);
        //setWissel(MyString, Recht);

        break;

      //schakel een wissel afbuigend
      case 'w':
        //case 'w1':
        setWissel(Serial.read(), Afbuigen);
        //setWissel(MyString, Afbuigen);

        break;

      //Maak blok vrij
      case 'b':
        setBlok(Serial.read(), Vrij);

        break;

      case 'B':
        setBlok(Serial.read(), Bezet);

        break;
    }
  }
}


void setWissel(byte address, bool state) {

  //char MyString = Serial.read();
  //for(byte i = 0; i< sizeof(BlokPins); i++){ // ik gebruik BlokPins ook voor de wissels om makkelijk te testen.
 

  Serial.print("Wissel ");
  Serial.print(address);
  if (state) {
    Serial.println(" Afbuigen");

    digitalWrite(Serial.read(), state);
    //digitalWrite(MyString, state);
    //digitalWrite(address,state);// Deze werkt niet
  }
  else {
    Serial.println(" Rechtdoor");

    digitalWrite(Serial.read(), state);
    //digitalWrite(MyString, state);
    //digitalWrite(address,state);// Deze werkt niet
  }
}
//}

void setBlok(byte address, bool state) {

  Serial.print("Blok ");
  Serial.print(address);
  if (state) {
    Serial.println(" bezet");
  }
  else {
    Serial.println(" vrij");
  }
}
 

ik had de programmeercode expres tussen
Citaat
;D
gezet, het was alweer een tijd geleden dat jij dit geschreven had, wisten we waar het over ging. ;D

Ik heb de programmeercode van het AAMS programma voor de at Mega 2650 op PastBin gezet.
http://pastebin.com/3grW2GGb

Let op! Deze code is alleen geschikt voor de at Mega 2650

Als alle componenten goed werken soldeer ik het op een printplaatje.

De led's worden aangestuurd door een ULN2803A driver ic. (kan ik evt ook seinen kopen met gloeilampjes)

Mvg Paul  ;D


« Laatst bewerkt op: 10 January 2016, 16:48:05 door smits66 »
Üdvözlet Paul Smits.


bouw draadje "Laubenstein"

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino analoge(!) modelbaan sturing
« Reactie #276 Gepost op: 11 January 2016, 14:51:36 »
Hoi Paul,

Je probleem zit hem in twee dingen. Allereerst handelt checkSerial() lekker centraal alle seriële data. Maw, dat hoef je in setWissel() niet meer te doen, daar heb je alle info die je nodig hebt, state en het adress.

Zie deze code:
const byte BlokPins[] = {11, 10, 9, 8};//worden voor testen gebruikt voor blok en wissels
const byte WisselPins[][2] = {{13, 14}, {15, 16}}; //wissel pinnen

#define Recht     0
#define Afbuigen  1
#define Vrij      0
#define Bezet     1

void setup() {

  for (byte i = 0; i < sizeof(BlokPins); i++) {
    pinMode(BlokPins[i], OUTPUT);
  }
 
  for(byte i = 0; i < sizeof(WisselPins); i++){
    pinMode(WisselPins[i][Recht], OUTPUT);
    pinMode(WisselPins[i][Afbuigen], OUTPUT);
  }

  Serial.begin(115200); //tijd voor 115200?
}

void loop() {
  checkIngekomenSerial();

}

void checkIngekomenSerial() {
  // Ga dan uit dat de serial commando's eruit zien als
  // [commando letter] [adres]
  // Waarbij ieder [] één byte is. Dus geen adressen in ASCII zenden ;)
 
  if (Serial.available() >= 2) {
    switch (Serial.read()) {

      //schakel een wissel recht
      case 'W':
        //case 'W1':
        setWissel(Serial.read(), Recht);
       
        break;

      //schakel een wissel afbuigend
      case 'w':
        //case 'w1':
        setWissel(Serial.read(), Afbuigen);
       
        break;

      //Maak blok vrij
      case 'b':
        setBlok(Serial.read(), Vrij);

        break;

      case 'B':
        setBlok(Serial.read(), Bezet);

        break;
    }
  }
}


void setWissel(byte address, bool state) {
  /*
  Hier doe je niets meer met serial. Alle gegeven die je nodig hebt zijn al uit serial gehaald
  en als parameter meegegeven aan deze functie.
  */
  //Even compenseren voor ASCII. Werkt alleen voor 1 t/m 9.
  //GEEN oplossing dus. Beter en simpeler om een echte byte te sturen maar dat doet de serial monitor niet
  address -= '1';
 
  Serial.print("Wissel ");
  Serial.print(address);
 
  if (state) {
    Serial.println(" Afbuigen");

    digitalWrite(WisselPins[address][0], state);
  }
  else {
    Serial.println(" Rechtdoor");

    digitalWrite(WisselPins[address][0], state);
  }
}


void setBlok(byte address, bool state) {

  Serial.print("Blok ");
  Serial.print(address);
  if (state) {
    Serial.println(" bezet");
  }
  else {
    Serial.println(" vrij");
  }
}
Dit geeft al een beetje aan hoe je dus de data kunt gebruiken. Hiermee kun je dus met "w1" en "W1" het ledje op pin 13 aan en uit zetten. (En met 2 die op pin 15.)

Maar dan kom je bij probleem twee, een wissel heeft twee uitgangen die een puls moeten krijgen. Niet zoals nu een commando voor aan en een commando voor uit. Je zou domweg een delay() kunnen gebruiken maar hier wil je nu juist vanaf  ;) Je zal dus een methode moeten schrijven om dat te laten gebeuren.

Ook is de manier van serial data ontvangen nog niet heel robuust. oa blijft een los gestuurde byte (misschien stopte je het programma na 1 byte) in het geheugen staan. Hoe dit op te lossen had ik al laten zien.

Hierbij een implementatie van de meer robuuste serial afhandeling en een manier hoe non-blocking (dus zonder delay) de wissels aan te sturen met een ringbuffer. Voordeel van de ringbuffer is dat het daarmee eenvoudig is het zo te maken dat steeds maar één wissel is bekrachtigd. Ook heb je nu maar één timer nodig hiervoor. En doordat steeds maar één wissel, of sterker nog, één spoel tegelijk is aangestuurd kan je ook nooit per ongeluk beide spoelen van één wissel bekrachtigen.

Nadeel is natuurlijk dat de buffer vol kan raken (maar goed, zo kan de serial buffer). In het voorbeeld heb ik een buffer van 8 wissels gemaakt en de schakeltijd op 200ms gezet. Je moet dus meer dan 8 wissels in 200ms aansturen wil de buffer vol raken.

De code is te vinden op PastBin

Nog een kleine toevoeging. Ik doe nu (overigens schakelbaar met de macro DEBUG_SERIAL_MONITOR) het adres compenseren met '1'. Op deze manier kan je het testen in Serial Monitor door gewoon de ASCII string W1 te sturen. Hoewel dit werkt voor testen is dit geen oplossing. Het werkt alleen maar tot wissel 9 omdat in ASCII 10 overgestuurd wordt als twee bytes. Beter is dus om vanuit de software echt een byte te sturen als adres en niet het adres als ASCII.

Overigens nog een opmerking over de Mega code. Maak het jezelf nu eens makkelijk!  ;D ;D ;D ;D ;D Stop met het gebruik van pinnummers in je code. Gebruik een logische naam en gebruik die. Makkelijker te onthouden en daarna ook op één centrale plek aan te passen.

Want het is dat je hier:
      digitalWrite(22, 1); // Blok 1 Bezet
      digitalWrite(23, 0); // Blok 2 Vrij
      digitalWrite(24, 0); // Blok 3 Vrij
      digitalWrite(25, 0); // Blok 4 Vrij
      digitalWrite(26, 0); // Blok 5 Vrij
      digitalWrite(27, 0); // Blok 6 Vrij
      digitalWrite(28, 0); // Blok 7 Vrij
      digitalWrite(29, 1); // Blok 8 Bezet
Commentaar bij hebt gezet maar anders had ik geen flauw idee wat je deed. Terwijl
//Maak juiste blokken bezet, rest vrij
for(byte i = 0; i < sizeof(BlokPins); i++){
  if(i == 0 || i == 7){
    digitalWrite(BlokPins[i], Bezet);
  }
  else{
    digitalWrite(BlokPins[i], Vrij);
  }
}
of met minder code  ;)
//Maak juiste blokken bezet, rest vrij
for(byte i = 0; i < sizeof(BlokPins); i++){
  digitalWrite(BlokPins[i], (i == 0 || i == 7));
}
al duidelijk is met één regel commentaar. En ik vermijd hier om de bloknummers te noemen in het commentaar. Zou ik deze namelijk later wijzigen heb ik makkelijk code en commentaar die iets anders vertellen. Dit terwijl al makkelijk uit de code af te leiden is welke blokken vrij/bezet moeten zijn. Overigens doet deze code niet wat de print naar serial doet vermoeden  ::)

Daarnaast maak je het jezelf ook makkelijker door ditIsEenVariabele te gebruiken en DitIsEenConstanteVariabele (dus beginnende met een hoofdletter) voor const gedefinieerde te reserveren. Zo geeft de naam weg of je het kunt wijzigen of niet. Wat je doet is absoluut niet fout hoor, maar het is gewoon een programmeersteuntje die het (als je het gewend bent) makkelijker maakt.  ;)

Goed, dat was weer een hele lap tekst maar hopelijk maakt het veel duidelijk en heb je er wat aan.


Timo
Verzonden vanaf mijn desktop met Firefox

Te 2/2

  • Offline Offline
  • Berichten: 1004
  • Metrop-Märklin
Re: Arduino analoge(!) modelbaan sturing
« Reactie #277 Gepost op: 11 January 2016, 16:18:35 »
Ik volg dit draadje al een tijdje. Als ik het goed begrijp ben je nu aan je derde arduino hardware poging begonnen, de nano, die voordelen heeft boven de twee eerder geteste boards.

Als analoog rijder (zonder verstand van arduino, maar wel met IT-achtergrond) ben ik aan de andere kant begonnen. Domweg met relais-blokbesturing met een binaire boomstructuur als basisaanpak. Daarbij beschouw ik een trein als een pointer naar een dubbelgelinkte lijst van relais. Iemand raadde me aan om eens naar Arduino te kijken als een mogelijkheid om de hardware niet alleen te laten doen wat moet, maar ook om daar software matig grip op te houden.

Vandaar mijn interesse in dit project. Ik ben nieuwsgierig naar jouw aanpak. Al weet ik nog niet zeker of ik dit zelf ook zo zou willen doen. En ik probeer iets op te steken over de omgang van arduino met relais. Er zijn van die insteekkaartjes met 8 of 16 relais, uno's? Stel je hebt 16 bordjes met 8 relais, hoeveel io-pins ben je dan daaraan kwijt?
Ik begrijp uit de reacties van o.a. Timo dat je zaken veel efficiënter kunt benutten dan 2 pins per relais, dat je soms beter geen relais kunt gebruiken, ... Ik ben benieuwd.
Er moet ook een reden zijn om meerdere relais op een uno te monteren, en daar moet ook profijt uit zijn te slaan. Maar hoe? Ze maken ze, dus zal er wel een handleiding voor zijn.
 
Jan Willem

analoog hybride DC baan (2-rail+3-rail),
CH, peco, piko, roco, k-rail

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino analoge(!) modelbaan sturing
« Reactie #278 Gepost op: 11 January 2016, 16:46:05 »
Hoi Jan Willem,

Die standaard relais bordjes die je kan kopen op eBay hebben gewoon 1 pin per relais nodig. Ik heb ze nog niet gezien met een bi-stabiel relais. Dus 16 bordjes met 8 relais maakt gewoon 8 x 16 = 128 pinnen nodig. Nu zou je IO expention's kunnen gebruiken zoals de PCF8574. (Volgens mij is dat ook die gebruikt wordt in veel 16x4 LCD drivers...) Maarja, aan de andere kant kost zo'n ding net zo veel als een Arduino Pro Mini  ;D En dan krijg je meer dan 8 pinnen erbij. Dus ik zou denk ik zelf eerder voor een mooi modulair systeem gaan met meerdere Pro Mini's in veel gevallen.


Timo
Verzonden vanaf mijn desktop met Firefox

Reinout van Rees

  • Team forummoderators
  • Offline Offline
  • Berichten: 7751
  • Forummoderator
    • Persoonlijke website + weblog
Re: Arduino analoge(!) modelbaan sturing
« Reactie #279 Gepost op: 11 January 2016, 19:28:37 »
Arduino's koppelen: dat ben ik van plan. Ik zit nog met één vraag wat dat betreft: kan je arduino's rechtstreeks koppelen? Dus: digitale pin OUT van de ene rechtstreeks aansluiten op een digitale pin IN van een andere?

Of moet er ter bescherming een weerstand tussen?

De "IN" pin wilde ik in pull-up modus instellen. En op die manier van de ene arduino naar de andere doorgeven of een wissel wel/niet omgezet mag worden, bijvoorbeeld. Of dat het volgens de dag/nacht simulatie donker genoeg is om de straatlantaarns aan te doen.

Reinout
Bouw v/d EifelBurgenBahn (h0, zijlijn in de Eifel)
Eifelgeschiedenis (verhalen en video's over de Eifelburgenbahn)

Timo

  • Team encyclopedie
  • Offline Offline
  • Berichten: 4656
Re: Arduino analoge(!) modelbaan sturing
« Reactie #280 Gepost op: 11 January 2016, 21:15:20 »
Ze kunnen rustig direct aan elkaar, geen probleem. Pullup niet eens nodig maar kan absoluut geen kwaad. Alleen zou ze niet mijlen ver uit elkaar plaatsen (lees, naast elkaar hangen).

Maar ipv gewone IO kan je makkelijker zoals Paul deed/doet de I2C bus pakken. (Again, alleen als ze naast elkaar zitten.) Op deze manier kan je gewoon data over sturen. Ben je wat flexibeler dan de hoog laag status van een pin. En je kan dezelfde twee I2C lijnen gebruiken om met meer dan één Arduino te praten (officieel tot 127). Wil je ze verder uit elkaar hangen zou ik kijken naar iets als RS485 ofzo.


Timo
Verzonden vanaf mijn desktop met Firefox

smits66

  • Offline Offline
  • Berichten: 543
  • Schaal 1:160, Arduino
Re: Arduino analoge(!) modelbaan sturing
« Reactie #281 Gepost op: 11 January 2016, 21:29:15 »
Hoi Volgers,

@Timo

Bedankt voor je input,  en bedankt voor je code op pastbin.
Met zoveel opmerkingen en beschrijvingen achter de code kom ik daar een heel stuk verder mee, mijn Engels is niet zo erg goed (1 jaar Engels op school gehad :P)  top Bedankt (y).

Helaas heb ik de verkeerde code naar pastbin geupload, Dit is de eerste code die ik schrijf om te bepalen op welke poorten ik wissels, seinen, blokken wil zetten, ik vind het makkelijker werken om de poortnummers te gebruiken, ik weet dan voor mijzelf welke blokken, seinen, wissels ik aanstuur.

Werkt mijn gedachten kronkel dan zet ik de nummers om in namen, ik zie door de bomen het bos niet meer door alle tekst,de code word voller en voller met tekst.
voor mij is het makkelijker om in de code zo min mogelijk tekst te gebruiken als ik in de code  digitalWrite (28,1)  zet weet ik meteen wat er gebeurd als ik digitalWrite (Sein1Pin,Bezet) raak ik op een gegeven moment  het overzicht kwijt  ( Dyslexie ,leesblind) vandaar.

Als ik de code "digitalWrite (28,1) enz."  op die manier op het forum zet snappen de mensen  de code niet , ik zet het dan om meer leesbare code, soms gaat dat fout ::).

Dat is ook de reden dat ik mijn eigen benamingen gebruik voor het benoemen van constanten/variabelen enz, op die manier hou ik het overzicht van de code als ik er mee bezig ben.

Hopelijk is het je duidelijk, waarom de code niet volgens de "regels"  van het programmeren is geschreven, voor mij is het makkelijker om de code te schrijven en ontwikkelen in poortnummers zodat de code leesbaar blijft.

Zie dit niet als commentaar maar als uitleg waarom ik zo programmeer, ik vind het geweldig dat je me helpt met programmeercode tips enz.

@ Jan Willem

Het klopt wat Timo schrijft , alleen zou ik geen pro mini's gebruiken deze processor boardjes hebben geen usb aansluiting, je zult een usb-adapter erbij moeten kopen, ik gebruik zelf de Arduino nano (deze is niet veel duurder dan een pro mini), dit boardje heeft iets meer i/o 8 Analog in (pro mini 6)  en 13 digital out/in en heeft standaard een usb aansluiting.

De relais boardjes zijn er in verschillend uitvoeringen als shield met 4 relais , of als 1,2,4,8,16 voudige  uitvoering en daar zijn ook nog verschillende uitvoeringen van "actief hoog" of  "actief laag"  gestuurd, het verschil zit in de schakeltrap met of zonder Optocoupler.

Foto: Relais board zonder Optocoupler.



Foto: Relais board met Optocoupler.




Een andere manier van schakelen doe je met transistoren of vermogens transistoren in plaats van relais.

Foto:  Transistor sturing, voor rgb led strip.



Een andere manier is het gebruik van solid-state relais, heb daar nog geen ervaring mee.

Helaas heb ik daar geen foto van.

Je kunt ook een Optocoupler gebruiken om te schakelen.(Zie foto 4 voudige relais board.)

Ik ben nog bezig met een keerlus schakeling voor mijn baan ,daarvoor ga ik twee bi-polaire relais gebruiken, in dat geval kost dat vier uitgangen van de Arduino en moet het geheel op een shield of losse print gebouwd worden.

Ik hoop dat je aan deze informatie wat hebt.

@Reinout

Je kunt de Arduino's zoals Timo aangeeft koppelen, alleen het nut daarvan ontgaat mij, beter is het om I2C bus of de RS-485 bus te pakken.

Je kunt ook de Rx/Tx van de Arduino gebruiken om met verschillende Arduino's te communiceren Rx Arduino 1 op Tx arduino 2 en Tx Arduino 1 op Rx Arduino 2, in dat geval kun je beter de AT Mega 2650 gebruiken deze heeft vier hardwarematige RX/TX poorten waardoor het makkelijker is om Arduino's te koppelen.

Wat de I2C betreft, kun je zonder problemen 1 a 2 mtr. kabel tussen de units gebruiken UTP kabel dan werk het nog goed, deze informatie heb ik van het internet gehaald via Youtube, daar staat een filmpje van deze oplossing. Ben allen de link naar het filmpje kwijt.

 I2C sturing van twee Arduino's rechts zit de interface voor 6 Arduino's en een I2c Lcd display, wil je meer gebruiken moet je op de SCL, SDA lijn een weerstand van 4700 ohm naar de +5 leggen (bij mij werkte deze waarde goed, op de datasheet staat een weerstand van 10Kohm getekent.

Foto: I2c tussen twee Arduino's



Foto:  Interface zonder weerstanden



Ik hoop dat je wat aan deze informatie hebt.

Mvg Paul  ;D
« Laatst bewerkt op: 11 January 2016, 23:44:38 door smits66 »
Üdvözlet Paul Smits.


bouw draadje "Laubenstein"

Te 2/2

  • Offline Offline
  • Berichten: 1004
  • Metrop-Märklin
Re: Arduino analoge(!) modelbaan sturing
« Reactie #282 Gepost op: 12 January 2016, 15:11:44 »
Ik hoop dat je een versie-beheermethode hebt. Zo niet, dan wordt het bijhouden van alle script versies op termijn een ramp. Ik zou ze minimaal handmatig standaard bovenaan nummeren. In mijn tijd als C-programmeur waren daarvoor allerlei handige open source programma's.

ga ik twee bi-polaire relais gebruiken, in dat geval kost dat vier uitgangen

Dat maakt me duidelijk hoe het werkt. Voor rijden/niet-rijden gebruik je de monostabiele relais, voor wissels bistabiele relais. De monostabiele zitten op prefab kaartjes, de bistabiele niet.
Je signalering (reedcontact) verbruikt ingangen, het signaal gaat naar de arduino, en die stuurt (via script) de relais aan. Dus stel je vervangt het reedcontact door een lichtsluis, dan gaat het signaal (of signalen) van die lichtsluis ook naar de aduino. M.a.w. de arduino vormt een extra tussenlaag binnen de bestaande schakelingen, tussen input en output?

Jan Willem

analoog hybride DC baan (2-rail+3-rail),
CH, peco, piko, roco, k-rail

Reinout van Rees

  • Team forummoderators
  • Offline Offline
  • Berichten: 7751
  • Forummoderator
    • Persoonlijke website + weblog
Re: Arduino analoge(!) modelbaan sturing
« Reactie #283 Gepost op: 12 January 2016, 15:29:55 »
Koppelen van arduino's: communicatie van de arduino van het toekomstige bedieningspaneel met de arduino, 2 meter verderop, die aan het inrijsein vastzit. Default inrijsein-stand is rood, dus er hoeft alleen een draadje "geel" en "groen" naar toe (afgezien van een massa).

Dus om daar nou een rs485 voor te regelen met evenveel draadjes... Leek me niet zo nuttig. IC2 leek me met 2m te ver weg.

Maar zo'n bus lijkt me ergens wel lekker, vooral de rs485 klonk me wel goed in de oren.

Aan de andere kant zitten er bidirectionele zaken in. Bedieningsplaneel/aansturing wil commando's aan de inrijseinen geven. In de buurt van een inrijsein komt een infraroodpoortje dat ik OF met een lange draad direct aan wil sluiten (huidige plan) of via een plaatselijke arduino kan laten beheren. Maar die zou dan weer naar het bedieningspaneel willen sturen. Enz. Ik moet hier nog over brainstormen.

Reinout
Bouw v/d EifelBurgenBahn (h0, zijlijn in de Eifel)
Eifelgeschiedenis (verhalen en video's over de Eifelburgenbahn)

gvandersel

  • HCC!m maar toch Selectrix (RMX)
  • Offline Offline
  • Berichten: 3603
  • Als het maar elektrisch is.
    • Homepage Gerard van der Sel
Re: Arduino analoge(!) modelbaan sturing
« Reactie #284 Gepost op: 12 January 2016, 15:44:40 »
@reinout,

Tijd voor een SX-bus  ;D

Groet,

Gerard van der Sel.

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