Doel:€250.00
Donaties:€50.00

Per saldo:€-200.00

Steun ons nu!

Laatst bijgewerkt
op 03-01-2024

Vacature: secretaris bestuur
Algemeen

De stichting

Recente berichten

Cherteau, fictieve Waals industriedorp door Hans GJ
Vandaag om 16:28:18
Werps Soldeerworkshop door gdh
Vandaag om 16:24:36
nieuw te leggen sporen passend maken door onmogelijkhier
Vandaag om 16:08:15
Marklin Telexkoppelingen blijven hangen door Klaas Zondervan
Vandaag om 15:51:59
Zoekfunctie ? door VAM65
Vandaag om 15:22:08
Onlangs gespot - gefotografeerd, de foto's door Keska
Vandaag om 14:48:26
Geluid NS Mat'46 vs NS Mat'54 door Peter Kleton
Vandaag om 14:27:30
De (3d) knutsels van Ronald. door MaraNCS
Vandaag om 14:25:44
FFA koelwagen door Duoblock
Vandaag om 14:19:55
Bentheimer Eisenbahn, gisteren, vandaag en morgen. door Hans Reints
Vandaag om 14:03:01
De IJmuider spoorlijn - korte geschiedenis en plaatjes door sncf231e
Vandaag om 13:45:43
Piko NS 2015 stroomafname probleem door Rick
Vandaag om 13:24:51
Punt- en hartstukken door 1200blauw
Vandaag om 13:12:58
welk jaar ging Marklin OVP voor wagons van blauw naar wit door Bahn-AG
Vandaag om 12:42:50
US diorama in H0 door moonlicht
Vandaag om 12:40:54
Doornvliet door raymond erdtsieck
Vandaag om 12:23:03
U-vorm beperkte ruimte (H0 C-rails) door eitreb
Vandaag om 12:06:06
Leids spoor (voorheen Blauwpoortsbrug) door gdh
Vandaag om 11:55:50
7 april De Karel on tour door NL-modelspoor
Vandaag om 11:51:04
NS Tals wagons (kalktrein) door Arjan6511
Vandaag om 11:41:59
Ombouw/Pimpen Bolle neuzen door bollen neus
Vandaag om 11:19:47
Beekdaelen in H0 door VulcanRaven
Vandaag om 11:00:45
Stroomdetectie bij goederenwagens door henk
Vandaag om 10:32:03
MARDEC, de Multifunctionele ARduino dcc DECoder. door NTeering
Vandaag om 10:23:47
MSV Post B, even voorstellen... door Rsd1000
Vandaag om 10:01:44
30 maart Modelspoorbeurs Houten & HCC Kennisdag door Jelmer
Vandaag om 09:52:49
Mijn eerste H0-modeltreinbaan in aanbouw door DJV
Vandaag om 09:42:59
Bouw van materieel 40 treinstellen door Pauldg
Vandaag om 07:52:09
NS 8400 van Werps door MathynK
Vandaag om 07:05:15
Al mijn goede ideeën... door bask185
28 maart 2024, 23:12:12
  

Auteur Topic: De CanBus komt naar Kranenberg, Arduino's en de CanBus  (gelezen 59932 keer)

meino

  • Offline Offline
  • Berichten: 2089
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #135 Gepost op: 10 mei 2020, 23:01:35 »
Reinout

heb je een linkje naar die video?

Groet Meino
A clean desk is a sign of an empty mind

Kranenberg
De CanBus komt naar Kranenberg

ikbenerevenniet

  • Offline Offline
  • Berichten: 379
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #136 Gepost op: 11 mei 2020, 01:30:52 »
derde toestand: stand onbepaald

Je zegt het zelf al: stand onbepaald, en dat mag je geen toestand noemen. Dat mag bovendien alleen als het object in rust is, en dat is het tijdens de overgang uiteraard niet.

bask185

  • Offline Offline
  • Berichten: 4009
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #137 Gepost op: 11 mei 2020, 08:41:57 »
Bas: je lijkt booleans niet leuk te vinden? Waarom niet?
No offense maar volgens mij heb ik het 2x gezegd... letterlijk  ;D:
Reden 1: Ze nemen 1 hele byte geheugen in beslag. Als je er maar 1 heb in je programma, dan zei het zo. Heb je 8 booleans, dan gooi je dus 7 bytes weg.
Reden 2: Als je een derde state wilt toevoegen, bijvoorbeeld aan een bewegende wissel of aan een sein met 3 standen, en je bent vergeten dat je ooit zo 'dom' was om 'bool' ipv byte te tikken, dan heb je dus pech.

Voor deze reden alleen al, zou je al byte moeten tikken ipv bool. Een byte kan wat een bool kan en meer en een bool kan niet wat een byte kan. Een bool gebruiken ipv een byte is wat ik ook beschrijf als: 'shooting yourself in the foot.'. Je mag ook prima de woorden true en false gebruiken in arduino voor een byte type variabele.

Ik had in Processing trouwens nog eens een 3e probleem met een bool. Om mijn layout op te slaan, gebruik ik een .txt bestand. Er was een bepaald rail item en die had ook een bool.
Reden 3: Bij het opslaan werd de state van die bool opgeslagen met de woorden 'true' en 'false'. Ik had net mijn code ingericht om uit dat txt bestandje getallen uit te lezen en geen woorden. Ik verwachtte een '0' en een '1' maar kreeg dus iets anders. En ook deze ellende loste ik op door bool te vervangen door byte.

Dus daarom Reinout, gebruik ik nooit meer bools. Ze voegen helemaal niks toe behalve potentiele bugs.

Ik gebruik dus standaard bit fields voor precies dit.
struct {
    unsigned int seinStand: 2; // 2 bits
    unsigned int wisselStand : 2; // 2 bits
    unsigned int terugmelder : 1; // 1 bit
} status;  // gebruikt 1 byte aan geheugen

// gebruik:
#define STRAIGHT 0
#define CURVED 1
#define MOVING 2 // of UNDEFINED of TRANSITIONING of net wat je wilt
// nog een 4e stand voor een drieweg wissel is ook nog mogelijk.

status.wisselStand = MOVING ;

if( status.terugmelder ) {
// etc

Dit is ook 1 van de redenen waarom ik classes en objecten probeer te vermijden waar mogelijk. Als je 20 objecten maak in SW die allemaal 1 enkel bitje nodig hebben. Dan heb je dus minimaal 20 bytes nodig. En volgens mij kan je met de OO structuur geen bitfields toepassen die objecten samen kunnen delen.

Die atmega328 heeft slechts 2kb. Meestal volstaat dit en dan maakt het niet zoveel uit. Immers "unused space is wasted space", maar soms dan kom je er toch aan.

@Erik
Stand onbepaald is nog steeds een bestaande fysieke toestand. Wanneer puntje bij paaltje bij komt, mag een trein niet rijden over een bewegende wissel. Voor hetzelfde zit de wissel vast door een stukje ballast. Dan heb je dus wel degelijk de noodzaak om deze stand op te slaan in je software.

En @Reinout als je derde wissel state in een bool probeert te stoppen, nou dan kan je je ontspoorde trein gaan opruimen  ;D ;D ;D

Mvg,

Bas




Train-Science.com
Train-Science github
It ain't rocket science ;-)

ikbenerevenniet

  • Offline Offline
  • Berichten: 379
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #138 Gepost op: 12 mei 2020, 01:03:46 »
Ik weet niet waar te beginnen... Kan eigenlijk alleen maar zeggen: als het jou goed bevalt is dat prima, maar ga het asjeblieft niet aanprijzen als "the way to go".

bask185

  • Offline Offline
  • Berichten: 4009
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #139 Gepost op: 12 mei 2020, 08:13:06 »
Prima. Beter dat we de discussie staken, want hier gaan we niet uitkomen blijkbaar. Denk dat Meino er ook niet meer vrolijk van wordt :-[
(sorry Meino)

Mvg,

Bas
Train-Science.com
Train-Science github
It ain't rocket science ;-)

Reinout van Rees

  • Team forummoderators
  • Offline Offline
  • Berichten: 7361
  • Forummoderator
    • Persoonlijke website + weblog
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #140 Gepost op: 12 mei 2020, 14:56:09 »
Meino: deze video (link gaat naar 6:14) bijvoorbeeld. Het zat net iets anders dan ik me herinnerde: tijdens het omleggen knippert de "doel"-led. Maar goed.

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

meino

  • Offline Offline
  • Berichten: 2089
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #141 Gepost op: 12 mei 2020, 17:19:07 »
@Reinout, bedankt voor het linkje,.

@Erik en @Bas
Ik heb maar niet gereageerd, want het werd een welles/nietes gebeuren en dat is zinloos.
Om met Rudyard Kipling te spreken  "East is east and west is west, and never the twain shall meet".

Maar Bas laat ik je niet weerhouden om je mening te plaatsen.

Groet Meino
A clean desk is a sign of an empty mind

Kranenberg
De CanBus komt naar Kranenberg

meino

  • Offline Offline
  • Berichten: 2089
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #142 Gepost op: 20 december 2021, 22:07:05 »
Ik zie dat het al ruim 1,5jaar geleden is dat ik hier iets publiceerde. Toch is er best wel het een en ander gebeurd. Sommige zaken zijn wel eens terloops ter sprake geweest in mijn Kranenberg draadje. Dus laten we dit draadje maar weer eens oprakelen.
Om te beginnen met een systeem waarmee ik mijn eerste ervaring met Arduino's kreeg, n.l. een Arduino voor de aansturing van een draaischijf, de Draaischijf Controller. Ik realiseerde me vandaag, dat ik het regelmatig over de draaischijf gehad heb in andere draadjes, maar dat er nooit een complete beschrijving geweest is. Dus bij deze.

De draaischijf in kwestie.


Het begon een aantal jaren geleden toen ik in de eerste fases van de bouw van Kranenberg was. Er moest een klein locdepot met een draaischijf komen. Vanwege de kosten besloten om zelfs iets te bouwen. In eerste instantie op basis van een heel goedkope Dapol kit, maar dat werd niets, dus eens gekeken naar de Peco LK55. Maar die wilde ik wel laten werken. Op het RMWeb vond ik het volgende artikeltje Automatisering Peco LK55 met een Arduino, dat leek me wel wat, ik kende de Arduino niet, maar C en C++ hadden weinig geheimen, dus spul besteld, NEMA17 400step motor, Adafruit motorshield, etc. en aan de gang gegaan.
Omdat de Adafruit nogal een irritante pieptoon genereerde bij microstepping is die uiteindelijk vervangen door een TMC2130 Silentstepstick.

Goed, een paar uitgangspunten.
  • De posities van de aansluitrails moesten puur op basis van het aantal stapjes gevonden kunnen worden, dus geen optische of mechanische positie bepaling en vergrendeling. Dit is ook het uitgangspunt van het artikeltje op RMWeb.
  • Aansturing van de draaischijf gebeurd d.m.v. DCC commando's.

Om puur met het tellen van stapjes de brug te kunnen positioneren, moet het systeem een nulpunt kennen. Een stappenmotor heeft één nadeel, n.l. als hij spanningsloos is, kan hij vrij bewegen. Dus na het inschakelen van het systeem is het in principe niet bekend waar de brug precies gepositioneerd is. Daar dient dus de Hallsensor en magneet voor. Hiermee kan de draaischijf gekalibreerd worden zodat er een exacte locatie van een nulpunt bepaald wordt tijdens het opstarten, en de posities van iedere rail aansluiting vast ligt.

De koppeling van de railaansluiting met DCC accessory commando's is simpel, iedere railaansluiting heeft zijn eigen DCC adres, waarbij het commando "--" (rechtdoor) voor de ene kant van de brug geldt en het commando "/" (afbuigend) voor de andere kant geldt.

Zie dit schema


Groet Meino


A clean desk is a sign of an empty mind

Kranenberg
De CanBus komt naar Kranenberg

meino

  • Offline Offline
  • Berichten: 2089
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #143 Gepost op: 21 december 2021, 00:27:07 »
Ok we gaan even verder.
Het hart van het systeem is één klasse, Turntable, die alle nitty gritty details van het aansturen van de draaischijf verbergt achter een paar simpele methoden.
Ik heb deze klasse in een Arduino bibliotheek gezet, welke twee bestanden bevat, KB_Turntable.h en KB_Turntable.cpp. Helaas laat het forum maximaal 20k tekens toe, dus lukt het me niet om de source hier op te nemen. Mocht iemand daar belangstelling voor hebben stuur me een PB.

Maar voor het gebruik zijn eigenlijk alleen de publieke methoden van de klasse van belang, dat is niet erg uitgebreid, dus die zal ik hier even bespreken.

De publieke methoden:
  public:
    //
    //  Turntable constructor
    //
    Turntable(int anHallSensorPin, int aBounceSize, AccelStepper *aStepper, long aFullRotation);
 
    //
    //  Set a new turntable position and start the movement
    //  to the new position.
    //
    void gotoTTPosition(long newTTPosition);

    //
    //  Keep the turntable moving if necessary
    //
    void heartBeat();

    //
    //  This method performs a calibration operation for the turntable. During this operation it
    //  executes a full turn counter clockwise looking for the hall sensor. When found, it will
    //  skip past the sensor and do a turn clockwise until the sensor is again found.
    //  Based on the four points (2 points counter clockwise and 2 points clockwise) where the sensor
    //  tripped, the 0 position of the TT is calculated and the TT will go to its last known position.
    //  This whole process is blocking, during the execution of this method no other DCC commands are honored.
    //
    void calibrate();
   
    //
    //  This method performs a calibration operation for the turntable. During this operation it
    //  executes a full turn counter clockwise looking for the hall sensor. When found, it will
    //  skip past the sensor and do a turn clockwise until the sensor is again found.
    //  Based on the four points (2 points counter clockwise and 2 points clockwise) where the sensor
    //  tripped, the 0 position of the TT is calculated and the TT will go to the specified new position.
    //  This whole process is blocking, during the execution of this method no other DCC commands are honored.
    //
    void calibrate(long newTTPosition);

Wat doen deze methoden?

Turntable(int anHallSensorPin, int aBounceSize, AccelStepper *aStepper, long aFullRotation)

      Dit is de constructor. De volgende parameters moeten meegegeven worden;
  • int anHallSensorPin   Dit is de pin waar de Hall sensor aan verbonden is
  • int aBounceSize        De draaischijf kan een bounce hebben, dat betekend dat hij iets verder gaat dan de opgegeven positie om vervolgens terug te veren naar de eind positie. De waarde is het aantal stapjes.
  • AccelStepper *aStepper  Dit is een AccelStepper object die verantwoordelijk is voor de aansturing van de steppermotor driver.
  • long aFullRotation     Om goed te functioneren, moet de Turntable klasse weten uit hoeveel stapjes een volledige rotatie bestaat

void gotoTTPosition(long newTTPosition)

     Deze methode start de beweging van de draaischijf naar de opgegeven positie.

  • long newTTPosition   De positie waar de draaischijf naar toe moet

void heartBeat()

     Het bewegen van de draaischijf gebeurt non-blocking, de aanroep van deze methode zorgt er voor dat, indien nodig, de stappenmotor een stapje verder gaat.

void calibrate()

     Aangezien een stappenmotor vrij kan bewegen als hij spanningsloos is, heeft de draaischijf niet een vast nulpunt. Deze methode gaat op zoek naar de Hallsensor, en wanneer gevonden, wordt op basis daarvan het nulpunt vast gelegd. Na afloop van de calibratie gaat de draaischijf terug naar de laatst ingenomen positie. Deze methode is blocking.

void calibrate(long newTTPosition)
    Zie de beschrijving van calibrate(), met dit verschil dat nu na afloop van de calibratie de draaischijf naar de opgegeven positie zal gaan.

Alle posities worden gespecificeerd in stapjes, modulo aFullRotation

Groet Meino

« Laatst bewerkt op: 21 december 2021, 00:42:36 door meino »
A clean desk is a sign of an empty mind

Kranenberg
De CanBus komt naar Kranenberg

zuylen

  • Offline Offline
  • Berichten: 4454
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #144 Gepost op: 21 december 2021, 10:23:46 »
Mooi systeem! IK heb mijn beide draaischijven van Fleischmann. En dan niet de nieuwste draaischijf met een klein relais ingebouwd. Mijn draaischijven hebben beiden dat relais nog niet. Ik gebruik het systeem dat Dick Koning ooit ontwikkeld heeft. Dat zit in een Arduino Nano gepropt. En die stuurt mijn twee Fleischmann schijven per stap (= spoor en er zijn 48 mogelijke sporen dus stappen) van de draaischijf. Het gevolg is dat de schijf iedere keer steeds even stopt en dan weer doorgaat naar het ingestelde eindpunt.
« Laatst bewerkt op: 21 december 2021, 10:53:46 door zuylen »

meino

  • Offline Offline
  • Berichten: 2089
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #145 Gepost op: 21 december 2021, 16:21:14 »
Goed, we hebben het even gehad over het hart van het systeem, de klasse die de draaischijf aanstuurd. Maar die staat niet alleen, de schets moet er wel voor zorgen dat het zijn werk goed kan doen. Dus gaan we het nu even over de schets hebben.
Een paar opmerkingen;
  • De schets stuurt ook nog twee servo's aan voor het openen en sluiten van deuren in een lokloods.
  • De opdrachten komen binnen via de Canbus. Daarvoor is bij het Canbus object een functie geregistreerd voor de Accessory commando's. Als een dergelijk commando binnen komt zal het Canbus object deze functie aanroepen, die dan vervolgens het ontvangen bericht analiseerd en eventueel afhandeld. Dit deel zal aangepast moeten worden voor andere manieren van aansturen.

We gaan nu even stukje bij beetje door de schets.
#include <Servo.h>
#include <TMC2130Stepper.h>
#include <AccelStepper.h>
#include "CanBus.h"
#include "KB_Eeprom.h"
#include "KB_Turntable.h"
#include "KB_Servo.h"
De bibliotheken die gebruikt worden.

//
//  KB_CB-TurntableController  Turntable control
//
//      Author: Meino de Graaf
//      email: meino@innerside.demon.nl
//
//  This program controls a NEMA-17 bi-polar stepper motor, which turns a Peco LK-55 turntable.
//  The stepper motor has 400 full steps/rotation (0.9 degree per step). The motor is driven
//  by an TMC2130 SilentDrive using micro stepping (32 micro steps/full step).
//
//  Further two micro servos are also controlled by this program. These two servos are responsible for
//  opening or closing of the doors of a two track loco shed.
//
//  The program listens for DCC commands (coming from the Canbus) that activates the different functions
//  (moving to a track or opening/closing of a door).
//  Currently there are 9 tracks defined in the program, each track has it's own DCC address and has two
//  positions for the stepper motor defined. One position defines the 0 degree ('-') position for the
//  control platform and the other one defines the 180 degree ('/') opposite position.
//
//  Due to the fact that an unpowered stepper motor is free to turn (contrary to a micro servo, which stays
//  put due to the friction of it's gears), the position of the stepper motor is unknown after a power-up.
//  Therefore the turntable performs a calibration during the initialisation phase. This calibration is done
//  by locating a Hall sensor using a small magnet attached to the turntable. The location of the Hall sensor
//  defines the zero position from which all track positions are derived.
//
//  Two door servos are defined. Each has it's own DCC address and the open/close position for the servo.
//  If a DCC command for a servo is received, the '-' command activates a door close, while the reception
//  of a '/' command activates the opening of the door. Further the speed of the movement is also part of
//  the servo definition.
//  At this moment all definitions are part of the code and no provision are made to make these remotely
//  configurable.
//
Standaard beschrijving en "disclaimer" tekst.

#define SERVO_DEBUG 0
#define DEBUG 0

//
//  Pins used for the Hall sensor on the Turntable
//
#define HALL_SENSORPIN  5

//
//  Pin definitions for the TMC2130 SilentStepper on the UNO
//
#define EN_PIN    7  // enable (CFG6)
#define DIR_PIN   8  // direction
#define STEP_PIN  6  // step
#define CS_PIN    10  // chip select TMC2130 (Silent stepper driver)

//
//  Pins used by the SPI interface (only for documentation)
//
#define MOSI_PIN 11  //SDI/MOSI (ICSP: 4, Uno: 11, Mega: 51)
#define MISO_PIN 12  //SDO/MISO (ICSP: 1, Uno: 12, Mega: 50)
#define SCK_PIN  13  //CLK/SCK  (ICSP: 3, Uno: 13, Mega: 52)

//
//  Pin for the CanBus
//
#define CB_CS_PIN  9 // Chip select MCP2515 (Canbus)

//
//  The door servo pins
//
#define SERVO_2_PIN 4
#define SERVO_1_PIN 3
Standaard debug en pin definities (Gelieve niet te zeuren over Enums!!)

//
//  The CanBus
//
CanBus *canBus;

//
//  Data that is stored in EEPROM to remember the state of the
//  turnouts. It is handled by a eepromController class
//
EepromController *EepromControl = new EepromController();
Canbus en EepromController objecten. EEpromController is een kleine klasse die ik gebruik om de stand van de draaischijf en locloods deuren in EEProm op te slaan, zodat bij een herstart de handel in de laatste situatie terugkomt.

//
//  The definitions for the geometry of the TT-stepper combination
//
#define MICROSTEPS   32L        // This parameter defines the number of microsteps used for the stepper.
//                                 16 is the minimum you may use (otherwise you have to change the
//                                 ADJUSTMENT define). Settings of 16 & 32 are save to use.
//                                 Higher values (64,128 or 256) are also save to use for controlling the stepper
//                                 however these values create such an interrupt load, that the DCC commands
//                                 will fail while the stepper is moving.
//
#define FULL_STEPS    400L      // A Nema 17/23 motor with steps of 0.9degree per step
#define HALF_STEPS    200L

#define FULL_ROTATION (MICROSTEPS * FULL_STEPS)     //  The nr of steps for a 360degree turn
#define ROTATION180   (MICROSTEPS * HALF_STEPS)     //  The nr of steps needed for 180degree turn

#define BOUNCE        (MICROSTEPS/4)               //  In real life there is always an
//                                                     overshoot and a rebounce

//
// The following defines give a full rotation in aprox. 2 minutes like the prototype
//
#define MAX_SPEED     (2.8*MICROSTEPS) // Avoid speed settings 2.3-2.7 (step time 1400-1700 microsec). All
//                                        with 256 microsteps, because in this speed window a faint whine
//                                        is noticeble, probably caused by interference.
//                                        This is valid when stealthChop is active.
#define ACCELERATION  (MICROSTEPS/1.4)
#define START_SPEED   (MICROSTEPS/1.4)

//
//  Rough Definitions for the Turntable track positions
//
#define TRACK_POSITION1  (376L*MICROSTEPS)  //  DCC address 201
#define TRACK_POSITION2  (350L*MICROSTEPS)  //  DCC address 202
#define TRACK_POSITION3  (293L*MICROSTEPS)  //  DCC address 203
#define TRACK_POSITION4  (281L*MICROSTEPS)  //  DCC address 204
#define TRACK_POSITION5  (269L*MICROSTEPS)  //  DCC address 205
#define TRACK_POSITION6  (257L*MICROSTEPS)  //  DCC address 206
#define TRACK_POSITION7  (245L*MICROSTEPS)  //  DCC address 207
#define TRACK_POSITION8  (233L*MICROSTEPS)  //  DCC address 208
#define TRACK_POSITION9  (215L*MICROSTEPS)  //  DCC address 209

//
//  Structure which defines the coupling between the used Accessory address and turntable
//  position
//
typedef struct
{
  short address;     // Accessory address
  long position0;    // Straight (-) location
  long position180;  // Diverging (/) location, 180 degrees turned.
}
TrackPosition;

const int nrOfTracks = 10;

//
//  A table with all the track positions. Each track position is fine tuned using small amounts
//  of microsteps. All these position have to be derived by Error and trial from the physical Turntable
//
TrackPosition trackPositions[nrOfTracks] = {
  {200, 0, 0},          // Triggers a Calibration action
  {201, TRACK_POSITION1 + 0, TRACK_POSITION1 + ROTATION180 - 4},
  {202, TRACK_POSITION2 + 2, TRACK_POSITION2 + ROTATION180 - 2},
  {203, TRACK_POSITION3 + 0, TRACK_POSITION3 + ROTATION180 + 0},
  {204, TRACK_POSITION4 + 6, TRACK_POSITION4 + ROTATION180 + 6},
  {205, TRACK_POSITION5 + 6, TRACK_POSITION5 + ROTATION180 + 4},
  {206, TRACK_POSITION6 + 0, TRACK_POSITION6 + ROTATION180 - 2},
  {207, TRACK_POSITION7 + 6, TRACK_POSITION7 + ROTATION180 + 0},
  {208, TRACK_POSITION8 + 0, TRACK_POSITION8 + ROTATION180 + 0},
  {209, TRACK_POSITION9 + 4, TRACK_POSITION9 + ROTATION180 + 4}
};
Een aantal defines voor de geometrie van de stepper/draaischijf. Defines voor het gedrag van de AccelStepper die gebruikt word en een tabel met het DCC adres per railpositie en de bijbehorende positie. Een opmerking, er is een extra DCC adres (200) dat hoort niet bij een railpositie maar triggered een kalibratie van de draaischijf.

//
//  Structure which defines the coupling between the used Accessory address and a door servo
//
typedef struct
{
  short address;     // Accessory address
  DoorServo *doorServo;
}
Door;


//
//  Number of door servo's
//
#define NR_OF_DOORS 2

Door doors[NR_OF_DOORS] = {
  { 108, new DoorServo(SERVO_1_PIN, 20, 108, 48)}, // DCC address 108, 20mS between steps, pos 108 open, pos 48 closed
  { 109, new DoorServo(SERVO_2_PIN, 20, 54, 116)}  // DCC address 109, 20mS between steps, pos 54 open, pos 116 closed
};
Ook de servos van de locloods deuren hebben hun eigen tabelletje.

//
// Create an interface to the TMC2130 driver card
//
TMC2130Stepper driver = TMC2130Stepper(EN_PIN, DIR_PIN, STEP_PIN, CS_PIN);

//
// Two methods used by the AccelStepper object for driving the stepper.
// This is done by using the defined STEP_PIN and the shaft_dir method
// on the TMC2130 interface object
//
void forwardStep()
{
  driver.shaft_dir(1);
  digitalWrite(STEP_PIN, LOW);
  //delayMicroseconds(1);       // Make sure that the pulse is detected
  digitalWrite(STEP_PIN, HIGH);
  //delayMicroseconds(10);
}

void backwardStep()
{
  driver.shaft_dir(0);
  digitalWrite(STEP_PIN, LOW);
  //delayMicroseconds(1);       // Make sure that the pulse is detected
  digitalWrite(STEP_PIN, HIGH);
  //delayMicroseconds(10);
}

//
// Time to wrap the stepper in an AccelStepper object
//
AccelStepper stepper(forwardStep, backwardStep);
We maken nu een interface naar het TMC2130 kaartje. Het aansturen daarvan gebeurd in de twee functies (forwardStep en backwardStep) die gebruikt worden om het AccelStepper object te maken.

//
// Create the Turntable object, give it the pin for the Hall Sensor, the AccellStepper object and
// the nr of steps for doing a full rotation
//
Turntable TT(HALL_SENSORPIN, BOUNCE, &stepper, FULL_ROTATION);
Nu kunnen we eindelijk het Turntable object aanmaken waarme we de draaischijf aansturen.

//
//  A function that executes whenever a DCC_ACC message is received from the Canbus
//  It's purpose is to analyze the received event (Signal or turnout) and
//  update the track position of the TT or update the position of the doors.
//
void dccAccReceiver(unsigned char aMsgLen, DCC_ACC_MSG *msgData)
{
#if (DEBUG)
  Serial.print("[dccAccReceiver] dccId: ");
  Serial.print(msgData->address);
  Serial.print(", dccState: ");
  Serial.println(msgData->direction);
  Serial.flush();
#endif //DEBUG

  unsigned short address = msgData->address;
 
  //
  //  Do we perform a straight(-) or a diverging(/) operation?
  //  For a straight operation enable is true, for a diverging operation
  //  enable is false.
  //
  bool enable = (msgData->direction) ? 0 : 1;

  //
  //  Search for the specified accessory address, when found lookup the
  //  specified position for the straight or diverging operation and start moving
  //  to that target position.
  //
  for (int i = 0; i < nrOfTracks; i++)
  {
    if ( address == trackPositions[i].address )
    {
#if (DEBUG)
      Serial.print("[dccAccReceiver] TT Address: ");
      Serial.print(address, DEC);
#endif //DEBUG
      //
      //  The new position of the TT
      //
      long newTargetPosition = 0;

      if (enable)     // Received a "-" command
      {
#if (DEBUG)
        Serial.print(" (-)");
#endif //DEBUG
        //
        //  Go to the straight position (0 degree)
        //
        newTargetPosition = trackPositions[i].position0;

        EepromControl->setTTposition(i);
        EepromControl->saveData();
      }
      else            // Received a "/" command
      {
#if (DEBUG)
        Serial.print(" (/)");
#endif //DEBUG
        //  Go to the diverging (180 degree) position.
        //
        newTargetPosition = trackPositions[i].position180;

        EepromControl->setTTposition(i+nrOfTracks);
        EepromControl->saveData();
      }

#if (DEBUG)
      Serial.print(" Position: ");
      Serial.println(newTargetPosition, DEC);
      Serial.flush();
#endif //DEBUG

      //
      //  If the choosen position equals 0, then we have to recalibrate
      //
      if (newTargetPosition == 0)
      {
        TT.calibrate();
      }
      else
      {
        //
        //  Not a recalibrate, goto the choosen position
        //
        TT.gotoTTPosition(newTargetPosition);
      }

      return;
    }
  }

  //
  //  If we didn't find an address match with a track location
  //  check if a door servo matches the received address
  //
  for (int i = 0; i < NR_OF_DOORS; i++)
  {
    if ( address == doors[i].address )
    {
#if (DEBUG)
      Serial.print("[dccAccReceiver] Door address: ");
      Serial.print(address, DEC);
#endif //DEBUG
      if (enable)
      {
#if (DEBUG)
        Serial.println(" (-)");
        Serial.flush();
#endif //DEBUG
        //
        //  Go to the closed position
        //
        doors[i].doorServo->closeDoor();

        EepromControl->setDoorPosition(i,DoorClosed);
        EepromControl->saveData();
      }
      else
      {
#if (DEBUG)
        Serial.println(" (/)");
        Serial.flush();
#endif //DEBUG
        //
        //  Go to the open position.
        //
        doors[i].doorServo->openDoor();

        EepromControl->setDoorPosition(i,DoorOpen);
        EepromControl->saveData();
      }

      return;
    }
  }

#if (DEBUG)
  Serial.print("[dccAccReceiver] Unknown address: ");
  Serial.println(address, DEC);
  Serial.flush();
#endif //DEBUG
}
Dit is de functie die we straks gaan registreren bij de Canbus en die daarna aangeroepen gaat worden als er een Accessory commando binnenkomt.

void setup()
{
#if (DEBUG || TT_DEBUG || SERVO_DEBUG || EEPROM_DEBUG)
  //Serial.begin(9600);
  Serial.begin(115200);
  while (!Serial);
  Serial.println("Starting");
#endif //DEBUG || TT_DEBUG || SERVO_DEBUG ||EEPROM_DEBUG

  //
  //  Setup the TMC2130 silent driver
  //
  driver.begin();              // Initiate pins and registeries
  driver.rms_current(900);     // Set stepper current to 900/1100mA. The stepper is rated at 0.9A.
  //                              The command is the same as command TMC2130.setCurrent(900, 0.11, 0.5);
  driver.hold_current(22);     // Hold current 70%
  driver.run_current(31);      // Run current 100%
  driver.hold_delay(1);        // Time between switch from run to hold 1sec
  //
  driver.microsteps(MICROSTEPS);   // Set the nr of microsteps
  //
  driver.interpolate(1);       // Use internally always the maximum nr of microsteps (256). This creates
  //                              the smoothest movement, when not set a small hum of the stepping is
  //                              noticeble
  driver.diag1_steps_skipped(1);
  //
  driver.stealthChop(1);       // Enable extremely quiet stepping

  digitalWrite(EN_PIN, LOW);
  //
  //   Enabling of the TMC2130 driver done
  //
Start van de Setup. We beginnen met het initialiseren van de TMC2130 driver kaart.

#if (DEBUG)
  for (int i = 0; i < nrOfTracks; i++)
  {
    Serial.print(trackPositions[i].address);
    Serial.print(", pos0 ");
    Serial.print(trackPositions[i].position0);
    Serial.print(", pos180 ");
    Serial.println(trackPositions[i].position180);
  }
#endif //DEBUG

  //
  //  Load the EEPROM data for the turnout directions
  //
  EepromControl->loadData();

  byte eePromData = EepromControl->getTTposition();

#if (DEBUG)
  Serial.print("[setup] eePromData: ");
  Serial.println(eePromData);
  Serial.flush();
#endif

  if (eePromData > 2*nrOfTracks)
  {
    eePromData = 1;
  }
 
  //
  //  Get the in EEPROM stored track position, it wil be used when we calibrate the
  //  turntable
  //
  long ttPosition;
  if (eePromData < nrOfTracks)
  {
    ttPosition = trackPositions[eePromData].position0;
  }
  else
  {
    ttPosition = trackPositions[eePromData-nrOfTracks].position180;
  }

  //
  //  Initialize the door servos with the in EEPROM stored position
  //
  for (int i = 0; i < NR_OF_DOORS; i++)
  {
    if (EepromControl->getDoorPosition(i) == DoorOpen)
    {
#if (DEBUG)
      Serial.print("[setup] door: ");
      Serial.print(i);
      Serial.println(" open");
      Serial.flush();
#endif

      //
      //  Go to the open position
      //
      doors[i].doorServo->initDoorOpen();
    }
    else
    {
#if (DEBUG)
      Serial.print("[setup] door: ");
      Serial.print(i);
      Serial.println(" closed");
      Serial.flush();
#endif
      //
      //  Go to the closed position
      //
      doors[i].doorServo->initDoorClosed();
    }
  }
We halen wat gegevens op uit de EEprom, de stand van de deuren zetten we gelijk, maar de positie van de draaischijf bewaren we even voor later.

  //
  //  Set some parameters of the AccelStepper object
  //
  stepper.setMaxSpeed(MAX_SPEED);
  stepper.setAcceleration(ACCELERATION);
  stepper.setSpeed(START_SPEED);

  //
  //  Initialy the 0 position of the stepper motor is not known, so we
  //  have to do a calibration to find the Hall sensor and establish a
  //  known position for the stepper motor.
  //
  TT.calibrate(ttPosition);
Initialiseer het AccelStepper object voor wat betreft, maximum snelheid, acceleratie en start snelheid. Daarna doen we de kalibratie van de draaischijf, zodat het nulpunt weer vastligt. Let op, dit is een blocking operatie, dus de schets zal tijdens het uitvoeren van de kalibratie nergens op reageren.

  //
  //  Create an interface to the CanBus and start the CanBus communication
  //
  canBus = new CanBus(TT_CONTROLLER_ID, nullptr, new Mcp2515(CB_CS_PIN)); // Only a Receiver

  //
  //  Register a callback routine for handling the Accessory(DCC_ACC type) messages
  //
  canBus->setMsgReceiver(DCC_ACC, dccAccReceiver);
  canBus->begin();

#if (DEBUG)
  Serial.println("[setup], Canbus ready");
  Serial.println("[setup] ready");
#endif

}//--(end setup )---
Het is nu tijd om de Canbus zelf te initialiseren, de callback functie te registreren en daarna is de setup klaar.

void loop()
{
  //
  //  Check for Canbus messages
  //
  canBus->heartBeat();
 
  //
  //  Activate the door servos
  //
  for (int i = 0; i < NR_OF_DOORS; i++)
  {
    //
    //  Activate the servo, so it can go to it's next position.
    //
    doors[i].doorServo->heartBeat();
  }

  //
  //  Check for CanBus packets
  //
  canBus->heartBeat();

  //
  //  Keep the turntable running
  //
  TT.heartBeat();
}
De loop functie doet niet zoveel, het enige waar we voor moeten zorgen is dat het Canbus object, de servo objecten en de Turntable object aan de gang blijven, dat doen we door constant hun heartBeat methods aan te roepen.

Hiermee werkt dus de draaischijf. Een klein filmpje van de draaischijf in werking.
<a href="https://www.youtube.com/v/CDENbNU9pK8" target="_blank" class="new_win">https://www.youtube.com/v/CDENbNU9pK8</a>

Groet Meino



« Laatst bewerkt op: 21 december 2021, 16:26:30 door meino »
A clean desk is a sign of an empty mind

Kranenberg
De CanBus komt naar Kranenberg

Reinout van Rees

  • Team forummoderators
  • Offline Offline
  • Berichten: 7361
  • Forummoderator
    • Persoonlijke website + weblog
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #146 Gepost op: 21 december 2021, 22:15:30 »
Die draait netjes en soepel en stil. Mooi gedaan.

Vraagje: dat initiële rondjes draaien om het nulpunt te bepalen, draait 'ie dan sneller? Hoe lang is 'ie daarmee bezig?

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

meino

  • Offline Offline
  • Berichten: 2089
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #147 Gepost op: 21 december 2021, 23:30:00 »
Reinout

Het initiëele rondje draait even snel. Hoe lang duurt het? dat hangt er van af waar de brug van de draaischijf staat.  De brug van de draaischijf heeft een voorkant (waar het bedieningspaneel en het mannetje staat) en een achterkant. De magneet zit aan de achterkant van de brug. De Hallsensor zit tussen spoor 209-- en 201/. Tijdens de kalibratie zal de brug altijd tegen de klok in bewegen. Dus als de achterkant van de brug op spoor 209-- staat (voorkant staat dan op 209/) dan moet hij de grootste afstand afleggen, dat kost ongeveer 150sec. Als de achterkant van de brug op 201/ staat (voorkant staat dan op 201--) dan is de afstand kort en kost het iets meer dan 25sec. Ik heb daar tot nu toe geen problemen mee, want dit gebeurd alleen als ik de baan onder spanning zet (dan worden alle Arduino's in een keer gestart). Daarna nog Koploper starten, en het rijden opstarten. Meestal is dan de draaischijf wel klaar. Maar het is zeker mogelijk om nog het een en ander te optimaliseren.

Groet Meino
« Laatst bewerkt op: 21 december 2021, 23:34:24 door meino »
A clean desk is a sign of an empty mind

Kranenberg
De CanBus komt naar Kranenberg

Reinout van Rees

  • Team forummoderators
  • Offline Offline
  • Berichten: 7361
  • Forummoderator
    • Persoonlijke website + weblog
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #148 Gepost op: 22 december 2021, 20:31:02 »
Duidelijk, bedankt!

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

meino

  • Offline Offline
  • Berichten: 2089
Re: De CanBus komt naar Kranenberg, Arduino's en de CanBus
« Reactie #149 Gepost op: 22 december 2021, 20:54:57 »
Dag Reinout

je hebt me wel even aan het piekeren gezet, dus toch nog even wat vertimmerd. De kalibratie houdt nu rekening met de vermoedelijk laatste positie en gaat nu klokwijs of antiklokwijs afhankelijk van wat de kortste afstand is. Verder verdubbel ik de maxSpeed van de AccelStepper tijdens de kalibratie. Dat halveert de maximale kalibratie tijd tot rond 75-80sec.

Groet Meino
A clean desk is a sign of an empty mind

Kranenberg
De CanBus komt naar Kranenberg