RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#201 von DJMetro , 21.10.2017 14:04

Hallo zusammen,
jetzt zum Herbst hin wollte ich mal mit meinem Bahnübergang weiter machen. Ich habe mich entschieden ihn jetzt doch mit Servos zu machen. Welches ist denn die aktuellste Version die mit Weichenadressen funktioniert?

Gesendet von meinem SM-G950F mit Tapatalk


DJMetro  
DJMetro
InterRegio (IR)
Beiträge: 137
Registriert am: 17.05.2008
Ort: DJMetro
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#202 von MicroBahner , 22.10.2017 21:39

Hallo Andi,

Zitat

Ich habe mich entschieden ihn jetzt doch mit Servos zu machen. Welches ist denn die aktuellste Version die mit Weichenadressen funktioniert?

ich denke das müsste die Version von Thomas aus Post #153 sein. Da ich mit meinen Servo-Versuchen nicht zufrieden war, habe ich dann nur noch mit Schrittmotoren gearbeitet.


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#203 von ralfbahn , 23.10.2017 06:31

Hallo Franz-Peter,

kannst Du bitte die Schrittmotorsteuerung hier mal zeigen.
Bitte auch das Skript, denn da scheitere ich immer ... ( Anfänger halt ... )

Gruß Ralf


 
ralfbahn
S-Bahn (S)
Beiträge: 11
Registriert am: 24.05.2015
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#204 von MicroBahner , 23.10.2017 11:37

Hallo Ralf,
suchst Du mit oder ohne DCC-Ansteuerung? Die letzte Version ohne DCC gab's hier. Die Anschlüsse sind identisch zur Servo-Version

natürlich bis auf den Motoranschluß:


Den Sketch stell ich hier auch nochmal direkt rein:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
 
/* Schrankensteuerung V0.4S Stepmotorversion 7.10.2015
* -- Version mit Schrittmotoren und Nachwippen
* Die Schrankensteuerung benötigt die 'MobaTools' - library ab der Version 0.5
*
* V0.4S Version mit Schrittmotoren und Nachwippen. Der Referenzpunkt des Schrittmotors wird über
* eine Segmentscheibe und Lichtschranke realisiert, und muss um Bewegungsbereich der Schranke liegen.
* V0.3: Mit Justierung der Endlagen und Speichern der Werte im EEPROM, vorbereitet für 4 Schrankenbäume.
* Die gesamte Bewegungskontrolle der Schrankenbäume ist in ein eigenes Unterprogramm ausgelagert.
* Dies erleichtert die Umstellung auf einen anderen Antrieb, z.b. mit einem Schrittmotor.
* Die Endlagenjustierung ist ebenfalls in diesem UP enthalten und kann jederzeit während des Betriebes vorgenommen
* werden. Pro Schranke wird ein Taster benötigt. Wird während der Schrankenbewegung der Taster gedrückt und
* gehalten, so läuft die Schranke verlangsamt weiter, bis die Taste losgelassen wird. Das ist dann die neue
* Endlage. Dies funktioniert sowohl beim Öffnen, als auch beim Schliessen der Schranke.
*
* V0.2: Version mit erweiterter Ablaufsteuerung: mit Vorlauf für Glocke und
* Wechselblinker.
*
* Für eine bessere Übersicht und Erweiterbarkeit ist das Programm logisch in einzelen Blöcke aufgeteilt.
* Diese Blöcke sind im loop hintereinander angeordnet, arbeiten aber weitgehend unabhängig. Damit dies
* möglich ist, dürfen innerhalb der Blöcke keine Warteschleifen/Delays werwendet werden, die den
* Programmablauf temporär anhalten.
*
* 1.Block: Einschaltlogik.
* Hier wird bestimmt, ob die Schranke geschlossen oder geöffnet werden soll. Derzeit ist dies einfach ein
* Schaltereingang, der abgefragt wird. Soll die Schranke später automatisch durch die Züge gesteuert werden
* muss dies in diesem Block eingerichtet werden. Ergebnis der Einschaltlogik ist ein Flag 'schrankeSchliessen'
*
* 2. Block Ablaufsteuerung Schrankenlogik
* zentraler Block, der den Ablauf des Schrankenschliessens bzw -öffnens steuert. Der Block agiert abhängig
* von dem Flag 'schrankeSchliessen' und dem momentanen Zustand der Schrankenlogik
* Hier werden auch die Flags gesetzt, mit denen die Glocke (glAktiv) und der Wechselblinker (wbAktiv)
* ein- bzw ausgeschaltet werden.
*
* 3. Block Ansteuerung der Glocke
* abhängig vom Flag 'glAktiv' wird der Impulsausgang für die Glocke ein- bzw ausgeschaltet. Je nach ange-
* schlossenem Audio-Modul muss gegebenenfalls auch darauf geachtet werden, dass der letzte Glockenschlag
* nicht abgeschnitten wird.
*
* 4. Block Wechselblinker
* abhängig vom Flag 'wbAktiv' wird der Wechselblinker ein- bw ausgeschaltet. Beim Einschalten sind kurz beide
* Blinker gleichzeitig an, bevor sie dann abwechselnd blinken.
*
*/
 
#include <MobaTools.h> // Lib für
 
#define SCHRANKENZAHL 2 // Zahl der Schrankenbäume ( derzeit wegen MobaTools-Lib nur 2 erlaubt)
//#define DEBUG ; // Wenn dieser Wert gesetzt ist, werden Debug ausgaben auf dem ser. Monitor ausgegeben
 
// gegebenenfalls anzupassende Werte (weitere Werte können im Abschnitt 'Portzuordnungen und Konstante' angepasst werden)
#define WINKEL_ZU1 20 // Initiale Winkellage für die Endpositionen. Die Werte können über die Justierung
#define WINKEL_AUF1 -20 // angepasst werden. Die Drehrichung kann durch Vertauschen der Werte für ZU / AUF
#define WINKEL_ZU2 20 // umgedreht werden. Dies ist über die Justierung NICHT anpassbar.
#define WINKEL_AUF2 -20
 
#define GLOCKE_ZYK 1000 // Glockenzyklus und Impulslänge muss an das angeschlossene Soundmodul
#define GLOCKE_PULS 200 // angepasst werden.
 
////////////////////////////////////////////////////////////////////////
//////////////// Portzuordnungen und Konstante /////////////////////////
// 1. Einschaltlogik --------------------------------------------------
const byte schrankeZuP = 7; // Pin HIGH bedeutet Schranke schliessen
 
// 2. Ablaufsteuerung --------------------------------------------------
const byte StepPort[SCHRANKENZAHL] = {SPI_1,SPI_2}; // Step-Motore über SPI-Schieberegister angeschlossen
const byte refLsP[SCHRANKENZAHL] = {A3,A2}; // Anschluß Lichtschranke für Referenzpunkt des Schrittmotors
#define BEREICH_ZU HIGH // Schrittmotor befindet sich im Bereich der geschlossenen Schranke
#define BEREICH_AUF LOW // Schrittmotor befindet sich im Bereich der offenen Schranke
#define RICHTUNG_ZU 1 // Drehrichtung des Motors beim Schliessen der Schranke
#define RICHTUNG_AUF -1 // Drehrichtung des Motors beim Schliessen der Schranke
 
// Definitionen für das Nachwippen
#define WIPPBEREICH 5
byte wippIx[SCHRANKENZAHL]; // Index in die Tabelle für die Nachwippbewegungen
int wippPos[] = {-20,0,-10,0,-5,0}; // Wipppunkte in 1/10 °, gerechnet von Endpunkt
byte wippSpeed[] = {12,0,6,0,3,0}; // Tempo an den Wippunkten. 0 = keine Änderung
const byte wippPnts = sizeof(wippPos)/sizeof(int); // Zahl der Wipppunkte
 
const int steps360 = 4096; // Schritte für eine Umdrehung
const byte schrTempo[SCHRANKENZAHL] = { 20,21 };
const int schrVerzZU[SCHRANKENZAHL] = { 10, 500 }; // Verzögerung für die Schrankenbewegung (ms)
// damit laufen die Schranken nicht exakt gleichzeitig los.
// bei 4 Schrankenbäumen kann dies genutzt werden, um die in Auto-Fahrtrichtung
// hinteren Schranken später schliessen zu lassen
const int vorlaufZu = 6000; // Vorlaufzeit: Glocke und Wechselblinker aktiv, Schranke noch ruhend
const int nachlaufZu = 2000; // Nachlaufzeit: Schranke zu, Glocke nochaktiv
const byte Justage1P = 2;
const byte Justage2P = 3;
 
// 3. Glocke -------------------------------------------------------------
const byte glockeP = 4; // Impulsausgang zur Ansteuerung einer Glocke
const int glZykl = GLOCKE_ZYK; // Glockenrythmus
const int glImp = GLOCKE_PULS; // Impulslänge am Glockenausgang
 
// 4. Wechselblinker ----------------------------------------------------
const byte led1P = 6; // Ausgänge für den Wechselblinker ( Ports müssen PWM-fähig sein )
const byte led2P = 5;
const int wbZykl = 1100; // Zykluszeit des Wechselblinkers
const int wbSoft = 300; // Auf/Abblendzeit der Lampen
 
// sonst. ----------------------------------------------------------------
 
////////////////////// globale Variable //////////////////////////////////////
// 1. Einschaltlogik ----------------------------------------------------
bool schrankeSchliessen; // Wird derzeit nur durch einen einfachen Schalter gesteuert
 
// 2. Ablaufsteuerung ---------------------------------------------------
// EEPROM Aufteilung
// Das EEProm enthält die Endpositionen der Servos und den momentanen Zustand des Bü
// ( offen oder geschlossen ) für den nächsten Programmstart.
// Das Schlüsselwort EEMEM definiert die Variablen als Werte im EEPROM
#define EE_ISVALID 0x55
byte eeValid EEMEM ; // hex55 wenn EEprom gültige Daten enthält (Erstbeschreibung)
byte eeZustand EEMEM ; // aktueller Bue Zustand ( nur OFFEN und GESCHLOSSEN )
word eePosZu[SCHRANKENZAHL] EEMEM ;
word eePosAuf[SCHRANKENZAHL] EEMEM ;
 
// Variable im RAM
int positionZu[SCHRANKENZAHL] = {WINKEL_ZU1, WINKEL_ZU2}; // Servopostionen, über Justiervorgang einstellbar
int positionAuf[SCHRANKENZAHL] = {WINKEL_AUF1, WINKEL_AUF2}; // Servopostionen, über Justiervorgang einstellbar
byte justageAktiv[SCHRANKENZAHL];
Stepper4 Schranke[SCHRANKENZAHL] = { steps360,steps360 }; // Für die Schrankenmotore
EggTimer SchrankeT[SCHRANKENZAHL]; // Schrankenspezifische Zeiten
// Aufrufparameter für das Unterprogramm 'Schrankenbewegung':
#define SB_INIT 0 // Servoansteuerung initiieren
#define SB_START_AUF 1 // Schranke öffnen starten
#define SB_START_ZU 2 // Schranke schliessen starten
#define SB_ENDE 3 // Bewegung überwachen und Ende erkennen. Ggfs. Endlagen justieren
 
EggTimer VorlaufT;
 
// Zustand, in dem sich die Ablaufsteuerung gerade befindet
byte bueZustand; // Aktueller Zustand
byte bueVorZustand; // vorheriger Zustand des Bue ( noch nicht verwendet)
#define OFFEN 0
#define VORLAUF_ZU 1 // Wechselblinker und Glocke, aber noch keine Bewegung
#define SCHRANKE_SCHLIESST 2 // Bewegung Schrankenbaum zu
#define NACHLAUF_ZU 3 // Beide Schrankenbäume in Endpos, Glocke läutet noch.
#define GESCHLOSSEN 4 // Schranke geschlossen
#define SCHRANKE_OEFFNET 6 // Bewegung Schrankenbaum auf
 
// 3. Glocke -------------------------------------------------------------
EggTimer glockeT;
byte glAktiv = false; // Flag ob Glocke aktiv ist
 
// 4. Wechselblinker ------------------------------------------------------
SoftLed Wblinker[2]; // 2 Leds für den Wechselblinker
EggTimer BlinkerT;
byte wbAktiv = false; // Flag ob Wechselblinker aktiv ist
byte ledState = LOW; // Status Wechselblinker
// Zustand Wechselblinker
byte wblZustand = 0;
#define WBL_AUS 0
#define WBL_START 1 // Beim Start sind kurz beide Lampen an
#define WBL_BLINKT 2
 
// sonst. -----------------------------------------------------------------
// für debugging
#ifdef DEBUG
#define DB_PRINT( ... ) {sprintf( dbgbuf,"Dbg: " __VA_ARGS__ ) ; Serial.println( dbgbuf );}
byte debug;
char dbgbuf[80];
#else
#define DB_PRINT ;
#endif
 
//-------------- Ende der Definitionen -------------------------------------
 
void setup()
{
long waitMax; byte i;
#ifdef DEBUG
Serial.begin(38400); //Debugging
waitMax = millis()+5000;
while( !Serial && millis()<waitMax); // nur bei Arduino-Micro oder Leonardo notwendig
Serial.println( "start of Program" );
#endif
// 1. Einschaltlogik ----------------------------------------------------
pinMode(schrankeZuP, INPUT_PULLUP);
schrankeSchliessen = ( digitalRead( schrankeZuP) == HIGH );

// 2. Ablaufsteuerung ---------------------------------------------------
pinMode(Justage1P, INPUT_PULLUP); //Zur Justage der Endlage Schranke 1
pinMode(Justage2P, INPUT_PULLUP); //dto, Schranke 2
for ( i=0; i<SCHRANKENZAHL; i++ ) {
pinMode( refLsP[i], INPUT );
}
//////////////////////////////////////////////////////
// Testen ob gültige Werte im EEProm. Wenn nicht, Grundinitiierung mit default-Werten
// Initiiert wird auch, wenn während des Programmstarts einer der Justageschalter
// betätigt ist
if ( eeprom_read_byte( &eeValid ) != EE_ISVALID ||
digitalRead( Justage1P) == LOW ||
digitalRead( Justage2P) == LOW ){
// Grundinitiierung
DB_PRINT( "EEProm Initiierung" );
eeprom_write_byte( &eeValid, EE_ISVALID );
eeprom_write_byte( &eeZustand, OFFEN );
for ( i=0; i<SCHRANKENZAHL; i++ ) {
eeprom_write_word( &eePosZu[i], positionZu[i] );
eeprom_write_word( &eePosAuf[i], positionAuf[i] );
}
}
/////////////////////////////////////
// Positionswerte aus EEProm lesen
for ( i=0; i<SCHRANKENZAHL; i++ ) {
positionZu[i] = eeprom_read_word( &eePosZu[i] );
positionAuf[i] = eeprom_read_word( &eePosAuf[i] );
DB_PRINT( "Schr.%d - PosZu=%d PosAuf=%d", i, positionZu[i], positionAuf[i] );
}
 
//////////////////////////////////////
/////// Antriebs-Initiierung ////////////
Schrankenbewegung( SB_INIT );
 
// Anfangsstellung der Schranke setzen
bueZustand = eeprom_read_byte( &eeZustand );
if ( bueZustand == GESCHLOSSEN ) {
Schrankenbewegung( SB_START_ZU );
DB_PRINT( "Init = ZU" );
while ( !Schrankenbewegung( SB_ENDE ) );
wbAktiv = true;
} else {
Schrankenbewegung( SB_START_AUF );
DB_PRINT( "Init = AUF" );
while ( !Schrankenbewegung( SB_ENDE ) );
}
// 3. Glocke -------------------------------------------------------------
pinMode( glockeP, OUTPUT );

// 4. Wechselblinker ------------------------------------------------------
Wblinker[0].attach(led1P); // Portzuordnung für den WEchselblinker
Wblinker[1].attach(led2P);
Wblinker[0].riseTime(wbSoft); // Weiches Auf/Abblenden der Lampen
Wblinker[1].riseTime(wbSoft);

// sonst. -----------------------------------------------------------------

} // End Setup
 

void loop()
{
// 1. Einschaltlogik ----------------------------------------------------
////////////// Eingang zur Steuerung des Bahnübergangs /////////////////
schrankeSchliessen = ( digitalRead( schrankeZuP) == HIGH );

// 2. Ablaufsteuerung ---------------------------------------------------
justageAktiv[0] = ( digitalRead( Justage1P ) == LOW ) ;
justageAktiv[1] = ( digitalRead( Justage2P ) == LOW ) ;

//////////// Ablaufsteuerung des Bue - Haupt-Zustandsautomat ///////////////////
switch ( bueZustand ) {
case OFFEN:
// Schranke ist geöffnet, warten auf Eingang
if ( schrankeSchliessen ) {
// Schranke soll sich schliessen, Glocke und Wechselblinker startet.
wbAktiv = true; // Wechselblinker einschalten
glAktiv = true; // Glocke einschalten. Diesen Befehl auskommentieren wenn die Glocke erst
// mit der Schrankenbewegung starten soll
VorlaufT.setTime( vorlaufZu );
bueZustand = VORLAUF_ZU;
DB_PRINT("Zustandswechsel: %d", bueZustand );
}
break; //----------------------------------------------------------
case VORLAUF_ZU:
// Warten bis die Vorlaufzeit abgelaufen ist, dann die Schrankenbewegung starten
if ( !VorlaufT.running() ) {
// Vorlaufzeit abgelaufen, Schrankenbewegung starten.
// spätestens hier muss auch die Glocke aktiviert werden
glAktiv = true; // wurde sie schon aktivert, machts auch nichts ;-)
wbAktiv = true;
Schrankenbewegung(SB_START_ZU); // Überwachung initiieren
bueZustand = SCHRANKE_SCHLIESST;
}
break; //----------------------------------------------------------
case SCHRANKE_SCHLIESST:
// Schrankenbaum schliesst sich.
if ( ( Schrankenbewegung( SB_ENDE ) ) ) {
// beide Schrankenbäume haben ihre Endposition erreicht
VorlaufT.setTime( nachlaufZu );
bueZustand = NACHLAUF_ZU;
}
break; //----------------------------------------------------------
case NACHLAUF_ZU:
// Schrankenbaum geschlossen, kurzer Nachlauf für Glocke.
if ( !VorlaufT.running() ) {
glAktiv = false;
bueZustand = GESCHLOSSEN;
eeprom_write_byte( &eeZustand, bueZustand );
}
break; //----------------------------------------------------------
case GESCHLOSSEN:
// Schranke ist zu, warten auf Eingang
if ( schrankeSchliessen == false ) {
// Schranke soll sich öffnen, Bewegung einleiten
Schrankenbewegung(SB_START_AUF); // Überwachung initiieren
wbAktiv = false; // Wechselblinker ausschalten
bueZustand = SCHRANKE_OEFFNET;
}
break; //----------------------------------------------------------
case SCHRANKE_OEFFNET:
// Schrankenbaum öffnet sich, warten bis offen
if ( schrankeSchliessen == true ) {
// Notfall: beim Öffnen der Schranke kommt wieder der Befehl Schranke schliessen
bueZustand = VORLAUF_ZU; // Da der Vorlauftimer nicht läuft, schliesst die Schranke sofort

}
if ( Schrankenbewegung( SB_ENDE ) ) {
// beide Schrankenbäume haben ihre Endposition erreicht
bueZustand = OFFEN;
eeprom_write_byte( &eeZustand, bueZustand );
}
break; //----------------------------------------------------------
} ////////////// Ende Zustandsautomat Bahnübergang /////////////////////
 
// 3. Glocke -------------------------------------------------------------
////////////////// Glockenimpuls erzeugen ////////////////////////////////
if ( glAktiv ) {
if ( !glockeT.running() ) {
// Glockentimer abgelaufen, Impuls erzeugen
if ( digitalRead( glockeP ) == HIGH ) {
// Port ist gesetzt, abschalten
digitalWrite( glockeP, LOW );
glockeT.setTime( glZykl - glImp );
} else {
// Port ist aus, einschalten
digitalWrite( glockeP, HIGH );
glockeT.setTime( glImp );
}
}
} else {
// Glocke inaktiv, Ausgang abschalten wenn Timer nicht mehr läuft
if ( !glockeT.running() ) {
// Die Timerabfrage stellt sicher, dass auch der letzte Impuls immer in
// voller Länge ausgegeben wird
digitalWrite( glockeP, LOW );
}
}

// 4. Wechselblinker ------------------------------------------------------
/////////////// Wechselblinker (Zustandsautomat ) //////////////////
switch (wblZustand) {
case WBL_AUS:
// Beide Lampen sind aus, warten auf einschalten
if ( wbAktiv ) {
// Beide Leds einschalten, Timer für gemeinsames Startleuchten
Wblinker[0].on();
Wblinker[1].on();
BlinkerT.setTime( wbSoft/2 );
wblZustand = WBL_START;
}
break;
case WBL_START:
// Startphase: Nach Zeitablauf erste Led wieder aus
if ( !BlinkerT.running() ) {
// Übergang zur normalen Blinkphase
ledState = HIGH;
Wblinker[1].off();
BlinkerT.setTime(wbSoft);
wblZustand = WBL_BLINKT;
}
break;
case WBL_BLINKT:
if ( !BlinkerT.running() ) {
BlinkerT.setTime(wbZykl/2);
if ( ledState == LOW ) {
Wblinker[0].on();
Wblinker[1].off();
ledState = HIGH;
} else {
ledState = LOW;
Wblinker[1].on();
Wblinker[0].off();
}
}
if ( !wbAktiv ) {
// Wechselblinker abschalten
Wblinker[0].off();
Wblinker[1].off();
wblZustand = WBL_AUS;
}
break;

} /////////// Ende switch Wechselblinker ////////////////////////
} // End Loop
 
byte Schrankenbewegung( byte mode ) {
// Bewegungsvorgang der Schranken überwachen, gegebenenfalls auch die Endlage
// justieren. Das Unterprogramm wird im Loop währende der Bewegung zyklisch aufgerufen
// Der Funktionswert ist 'true', wenn die Bewegung aller Schranken abgeschlossen ist,
// sonst immer 'false'
// mode:SB_INIT Grundinitiierung
// SB_START_ZU Schliessen der Schranken einleiten
// SB_START_AUF Öffnen der Schranken einleiten
// SB_ENDE Bewegung überwachen, meldet 'true' wenn alle Bewegungen abgeschlossen
// sind
// -------------------------------------------------------------------------
//
static enum { WAIT, NORMAL, JUSTAGE_AKTIV, JUSTAGE_ENDE, WIPPEN, FIND_REF } ssZustand[SCHRANKENZAHL] ;
static int startPos[SCHRANKENZAHL] ; // Position der Schranke zu Bewegungsbeginn
static byte gotRef[SCHRANKENZAHL] ; // Flag ob Referenzpunkt bekannt ist
static enum { AUF,ZU } richtung;

byte bewegung=0, sn, refLS;
int tmp;
for( sn=0; sn<SCHRANKENZAHL; sn++ ) {
// für alle Schranken durchlaufen
switch ( mode ) {
case SB_INIT: // Initiierung der Schranken
DB_PRINT("SB_INIT(%d)",sn);
Schranke[sn].attach(StepPort[sn] ); // Schrittmotore an SPI_x
Schranke[sn].setSpeed( schrTempo[sn] );
gotRef[sn]=false;
bewegung = 1;
break; //---------------------------------------------
case SB_START_ZU: // Schliessen der Schranken einleiten
DB_PRINT("SB_START_ZU(%d)",sn);
richtung =ZU;
Schranke[sn].setSpeed( schrTempo[sn]);
SchrankeT[sn].setTime( schrVerzZU[sn] ); //Wartezeit bis Schrankenbewegung
DB_PRINT( "Start Wartezeit %d mit %d ms", sn, schrVerzZU[sn] );
ssZustand[sn] = WAIT;
bewegung = 1;
break; //---------------------------------------------
case SB_START_AUF: // Öffnen der Schranken einleiten
richtung = AUF;
Schranke[sn].setSpeed( schrTempo[sn]);
if ( digitalRead( refLsP[sn] ) == BEREICH_ZU ) {
// Bewegung AUF nur starten, wenn sich die Schranke im Bereich ZU befindet
// Zur Sicherheit dreht der Motor max 1/3 Umdrehung. In diesem Bereich muss er die
// Referenzpunkt LS erreichen, wo auf den endgültigen Endpunkt umgeschaltet wird
Schranke[sn].doSteps( RICHTUNG_AUF * steps360/2);
DB_PRINT( "doSteps(%d):%d R=%d S=%d",sn, RICHTUNG_AUF * steps360/2 , RICHTUNG_AUF, steps360);
ssZustand[sn] = FIND_REF;
DB_PRINT("SB_START_AUF(%d)->FIND_REF",sn);
} else if ( gotRef[sn] ) {
// steht noch im Bereich 'AUF', könnte Notumkehr sein. Da ref bekannt ist, direkt
// auf Position Auf
Schranke[sn].write(positionAuf[sn]);
ssZustand[sn] = NORMAL;
DB_PRINT("SB_START_AUF(%d)->NORMAL(write)",sn);
} else {
// nichts tun
ssZustand[sn] = JUSTAGE_ENDE; // keine Aktion
DB_PRINT("SB_START_AUF(%d)->JUSTAGE_ENDE(nichts)",sn);
}
startPos[sn] = Schranke[sn].read();
DB_PRINT( "Schranke %d, Position: %d, Richtung= %d", sn, startPos[sn], richtung );
bewegung = 1;
break; //---------------------------------------------
case SB_ENDE: // Bewegung überwachen, auf Ende prüfen
// Schrankenbewegung
switch ( ssZustand[sn] ) {
case WAIT: // Verzögerungszeit bis zum Schrankenstart abwarten
// Wird nur beim Schliessen der Schranke durchlaufen
if ( SchrankeT[sn].running() == false ) {
// Zeit abgelaufen, Bewegung starten
//Schranke[sn].write( positionZu[sn]);
if ( digitalRead( refLsP[sn]) == BEREICH_AUF ) {
// Bewegung ZU nur starten, wenn sich die Schranke im Bereich AUF befindet
// Zur Sicherheit dreht der Motor max 1/3 Umdrehung. In diesem Bereich muss er die
// Referenzpunkt LS erreichen, wo auf den endgültigen Endpunkt umgeschaltet wird
Schranke[sn].doSteps( RICHTUNG_ZU * steps360/2);
DB_PRINT( "doSteps(%d):%d", sn, RICHTUNG_ZU * steps360/2 );
ssZustand[sn] = FIND_REF;
DB_PRINT("WAIT(%d)->FIND_REF",sn);
} else if ( gotRef[sn] ) {
// steht noch im Bereich 'ZU', könnte Notumkehr sein. Da ref bekannt ist, direkt
// auf Position Zu
Schranke[sn].write(positionZu[sn]);
DB_PRINT("WAIT(%d)->NORMAL(write)",sn);
ssZustand[sn] = NORMAL;
} else {
// nichts tun
DB_PRINT("WAIT(%d)->JUSTAGE_ENDE(nichts)",sn);
ssZustand[sn] = JUSTAGE_ENDE; // keine Aktion
}
startPos[sn] = Schranke[sn].read();
DB_PRINT( "Schranke %d, Position: %d, Richtung= %d", sn, startPos[sn], richtung );
}
bewegung = 1;
break; //......................................
case FIND_REF: // Bewegungsablauf bis zur LS überwachen. An der LS wird der Refpunkt gesetzt und die
bewegung += Schranke[sn].moving();
// Eigentliche Endposition angesteuert.
refLS = digitalRead( refLsP[sn] );
//if ( sn == 0 ) DB_PRINT( "refLS=%d", refLS );
if ( richtung == ZU && refLS == BEREICH_ZU ) {
//Lichtschranke beim Schliessen erreicht)
Schranke[sn].setZero();
gotRef[sn] = true;
if ( justageAktiv[sn] ) {
// Justagetaster gedrückt
Schranke[sn].setSpeed( schrTempo[sn] / 2);
DB_PRINT( "FIND_REF(%d)->JUSTAGE(zu)",sn );
ssZustand[sn] = JUSTAGE_AKTIV;
} else {
Schranke[sn].write( positionZu[sn]);
DB_PRINT( "FIND_REF(%d)->NORMAL(zu)",sn );
ssZustand[sn] = NORMAL;
}
}
if ( richtung == AUF && refLS != BEREICH_ZU ) {
//Lichtschranke beim Öffnen erreicht)
Schranke[sn].setZero();
gotRef[sn] = true;
if ( justageAktiv[sn] ) {
// Justagetaster gedrückt
Schranke[sn].setSpeed( schrTempo[sn] / 2);
DB_PRINT( "FIND_REF(%d)->JUSTAGE(auf)",sn );
ssZustand[sn] = JUSTAGE_AKTIV;
} else {
Schranke[sn].write( positionAuf[sn]);
DB_PRINT( "FIND_REF(%d)->NORMAL(auf)",sn );
ssZustand[sn] = NORMAL;
}
}
break;
case NORMAL:
tmp = Schranke[sn].moving();
bewegung += tmp;
if (tmp < WIPPBEREICH ) {
DB_PRINT( "NORMAL(%d) -> WIPPEN", sn );
ssZustand[sn] = WIPPEN;
wippIx[sn] = 0; // Zähler für die Wippbewegungen
}
break; // .....................................
case WIPPEN:
tmp = Schranke[sn].moving();
bewegung += tmp;
if ( tmp == 0 ) {
// keine Bewegung mehr aber noch Wippen ?
if ( wippIx[sn] < wippPnts ) {
// nächsten Wipppunkt anfahren
tmp = 10* ((richtung == AUF) ? positionAuf[sn] : positionZu[sn]); // in 1/10° umrechnen
tmp = (tmp>0) ? tmp + wippPos[wippIx[sn]] : tmp - wippPos[wippIx[sn]];
if ( wippSpeed[wippIx[sn]] ) Schranke[sn].setSpeed( wippSpeed[wippIx[sn]]);
Schranke[sn].write( tmp, 10 );
//DB_PRINT( "Wip.write( %d , 10 )", tmp );
wippIx[sn]++;
bewegung +=1; // Es ist noch nicht zu Ende!
}
}
break; //......................................
case JUSTAGE_AKTIV:
bewegung += 1; // keine Endemeldung während der Justage
if ( !justageAktiv[sn] ) {
// Justageschalter wurde wieder losgelassen. Momentane Servo-Position
// als neuen Endpunkt speichern und Servo anhalten
tmp = Schranke[sn].read();
DB_PRINT( "Schranke %d, Justage ende, Pos = %d", sn, tmp );
Schranke[sn].write( tmp );
if ( richtung == ZU ) {
positionZu[sn] = tmp;
eeprom_write_word( &eePosZu[sn], tmp );
} else {
positionAuf[sn] = tmp;
eeprom_write_word( &eePosAuf[sn], tmp );
}
ssZustand[sn] = JUSTAGE_ENDE;
}
break; //......................................
case JUSTAGE_ENDE:
bewegung += Schranke[sn].moving();

break; //......................................
} // ..... Ende switch 'Schrankenzustand' ......

break; //---------------------------------------------
default:
// falscher Programmaufruf, keine Reaktion
;
} // --- Ende Switch 'mode' --------
} // ........Ende forschleife der Schranken........
 
if ( bewegung == 0 ) DB_PRINT( "Endpositionen erreicht");
return ( bewegung == 0 );
}

 

 
 



Die letzte Version als DCC-Funktionsdekoder hatte ich hier vorgestellt. Wenn ich mich recht erinnere, hat sich seitdem aber eine Änderung bei der nmradcc-Lib ergeben, weshalb man den Sketch etwas anpassen müsste.


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#205 von ralfbahn , 23.10.2017 14:19

Hallo Franz-Peter,

vielen Dank für die schnelle Reaktion.
Ich suche mit DCC-Ansteuerung und wenn ich das Skript V0.6 30.11.2015 versuche zu kompelieren bekomme ich enen Fehler.
Sicher habe ich da etwas falsch gemacht, aber das bekomme ich noch raus.
Funktioniert das Skript V0.6 30.11.2015 auch mit Schrittmotoren? Denn in Skript-Kopf steht » /* Schrankensteuerung mit Servo und DCC-Ansteuerung V0.6 30.11.2015 « !

Vielen Dank für Deine Mühen ...

Gruß Ralf


 
ralfbahn
S-Bahn (S)
Beiträge: 11
Registriert am: 24.05.2015
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#206 von MicroBahner , 23.10.2017 16:22

Hallo Ralf,
das ist der Sketch von Thomas, und er hat ihn für Servos und Weichenadressen (Zubehördecoder) angepasst. Den kannst Du nicht mit Schrittmotoren verwenden.

Die letzte Version mit Schrittmotor und DCC-Ansteuerung war diese. Die arbeitet aber als Funktionsdecoder, wird also mit einer Lokadresse angesprochen.

Was bekommst Du denn für eine Fehlermeldung?


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#207 von ralfbahn , 24.10.2017 06:43

Hallo Franz-Peter,

noch mal vielen Dank für die schnelle Antwort.
Ich bekomme zum Beispiel folgende Fehlermeldung:
( jetzt wollte ich hier eine Bilddatei mit dem Namen fehler.jpg anhängen und bekomme die Meldung : ungültige Dateierweiterung ops: )

... ino:206:36: warning: large integer implicitly truncated to unsigned type [-Woverflow]
DCC.setCV( 1, DCC_ADDR );

^
Jedenfals muss ich wohl doch erstmal etwas "kleiner" anfangen und dabei noch viel Lernen ...
Aber die Verwendung von Arduino und dessen Programmierung interessiert mich sehr und ich bleib dran ...

Gruß Ralf


 
ralfbahn
S-Bahn (S)
Beiträge: 11
Registriert am: 24.05.2015
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#208 von MicroBahner , 24.10.2017 22:01

Hallo Ralf,

Zitat

jetzt wollte ich hier eine Bilddatei mit dem Namen fehler.jpg anhängen und bekomme die Meldung : ungültige Dateierweiterung ops: )

Wie man Bilder im Forum einfügt, steht hier.

Zitat

. ino:206:36: warning: large integer implicitly truncated to unsigned type [-Woverflow]
DCC.setCV( 1, DCC_ADDR );

Das ist erstmal 'nur' eine Warnung, und sollte das Compilieren nicht verhindern. Bei welchem Sketch tritt es denn auf?


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#209 von ralfbahn , 25.10.2017 07:07

Hallo Franz-Peter,

danke für den Hinweis bezüglich der Bilder ...
Es wäre trotzdem schön, wenn angezeigt wird, welchen Typ bzw. welches Format von Bildern hochgeladen werden dürfen ...
als nur die Meldung: ungültige Dateierweiterung
Andere haben auch Bilder mit der Dateierweiterung .png im Post, nur bei mir will er das 21kB Bild nicht .... aber lassen wir das.

Ja, das Skript wurde trotz der Warnung kompiliert.
Das ist dieses Skript : » /* Schrankensteuerung V0.5DCC Stepmotorversion 23.10.2015 «.
Da ich englischen nicht kann, aber der Google Übersetzer hat mir so viel verraten, dass es dabei um ein Type Problem handelt und es wurde etwas abgeschnitten?!? Ich vermute mal, dass eine Type Umwandlung automatisch vorgenommen wurde und zwar vom Type » Integer « hin zur Vorzeichenlose Ganzen Zahl.
Deute ich das so richtig? Also von ± 32767 ( Integer 2 Byte ) zu 65536 ( Ganzzahl 2 Byte ), nur ohne Vorzeichen Bit.

Da ich ja vorher das falsch Skript verwendet habe, für Servos ...
Spielt der dabei auftretende Fehler eigentlich keine Rolle mehr, aber rein interesse halber ...
Was sagt mir diese Fehlermeldung:

Arduino: 1.6.10 (Windows 7), Board: "Arduino Pro or Pro Mini, ATmega328 (5V, 16 MHz)"

D:DownloadBahnSchrankeSchranke_ServoSchranke_Servo.ino: In function 'void notifyDccAccState(uint16_t, uint16_t, uint8_t, uint8_t)':

Schranke_Servo:578: error: 'class NmraDcc' has no member named 'getAddr'

if (Addr == DCC.getAddr()) {

^ ( steht unter dem getAddr ! )

exit status 1
'class NmraDcc' has no member named 'getAddr'

Kannst Du mir bitte das kurz erklären.
Vielen Dank für deine Mühen ...

Gruß Ralf


 
ralfbahn
S-Bahn (S)
Beiträge: 11
Registriert am: 24.05.2015
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#210 von rmayergfx , 25.10.2017 13:44

Zitat

Hallo Franz-Peter,

danke für den Hinweis bezüglich der Bilder ...
Es wäre trotzdem schön, wenn angezeigt wird, welchen Typ bzw. welches Format von Bildern hochgeladen werden dürfen ...
als nur die Meldung: ungültige Dateierweiterung
Andere haben auch Bilder mit der Dateierweiterung .png im Post, nur bei mir will er das 21kB Bild nicht .... aber lassen wir das....



Hallo Ralf,

wie in den FAQ schon deutlich geschrieben, werden hier keinerlei Bilder im Forum hochgeladen. Die PNG oben im Thread wurde über abload.de verlinkt.

Zitat
Da der Attachment-Container für das gesamte Forum und alle User begrenzt ist (inkl. Anhänge in PNs) und wir uns nicht den rechtlichen Problemen als Bilder-Hoster selber stellen wollen, ist es unerwünscht, dass Bilder als Attachment im Forum eingefügt werden. Die gängigen Bild-Formate werden daher aktiv blockiert.

Bitte nutzt daher zum Einstellen von Bildern entweder Euren eigenen Webspace und verlinkt die Bilder von dort aus oder nutzt einen freien Bilderdienst.

Beachtet ferner, dass nur Bilder mit einer maximalen Breite von 1024 Pixeln eingestellt werden!


Also in Ruhe die Anleitung zum Einstellen der Bilder durcharbeiten und dementsprechend verfahren, dann klappts auch mit den Bildern. Zum Testen gibt es einen eigenen Testbereich hier im Forum.

mfg

Ralf


Der Computer soll die Arbeit des Menschen erleichtern und nicht umgekehrt!
Neue Kupplungen für Faller OHU Selbstentladewagen: viewtopic.php?f=27&t=82863
Kein Support per PN !


 
rmayergfx
ICE-Sprinter
Beiträge: 5.391
Registriert am: 07.07.2008
Gleise C-K-Flex-M-Gleis
Spurweite H0, Z, 1
Steuerung MS2, 6021, 60213
Stromart AC, Digital, Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#211 von MicroBahner , 25.10.2017 21:59

Hallo Ralf,
zum Bildereinstellen hat dir dein Namensvetter ja schon alles geschrieben.

Zitat

Da ich englischen nicht kann, aber der Google Übersetzer hat mir so viel verraten, dass es dabei um ein Type Problem handelt und es wurde etwas abgeschnitten?!? Ich vermute mal, dass eine Type Umwandlung automatisch vorgenommen wurde und zwar vom Type » Integer « hin zur Vorzeichenlose Ganzen Zahl.
Deute ich das so richtig? Also von ± 32767 ( Integer 2 Byte ) zu 65536 ( Ganzzahl 2 Byte ), nur ohne Vorzeichen Bit.

Ja, ein wenig Englischkenntnisse sind beim Programmieren schon sehr hilfreich - aber Du hast das mit googles Hilfe ja gut hinbekommen. Du deutest das richtig. Ist wie so oft bei Warnungen - es kann ein Problem bedeuten, muss es aber nicht. Solange der Ausgangswert positiv ist, passiert bei der Umwandlung auch nichts fehlerhaftes.

Zitat

exit status 1
'class NmraDcc' has no member named 'getAddr'

Da vermute ich, dass Du eine recht alte Version der NmraDcc Lib einsetzt. Da fehlte die hier angesprochene Methode 'getAddr' noch, und deshalb gibt es eine Fehlermeldung, wenn man versucht sie aufzurufen. Installier dir mal die aktuelle nmradcc-Lib. Das geht direkt mit dem Bibliotheksverwalter dier IDE. Oben im Suchfenster 'nmradcc' eingeben, und dann die neueste Version installieren.


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#212 von ralfbahn , 26.10.2017 15:03

Hallo Ralf,

das mit den Bilder werden ich auch noch lernen ... vielen Dank

Hallo Franz-Peter,

ja es hat an der falschen LIB Version gelegen. Ich habe sie jetzt aktualisiert und schon funktioniert es.

Vielen Dank für den hilfreichen Tip
Wenn die Umsetzung funktioniert hat, werde ich mal ein Bild bzw. Video einstellen ...

Gruß Ralf


 
ralfbahn
S-Bahn (S)
Beiträge: 11
Registriert am: 24.05.2015
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#213 von DJMetro , 29.10.2017 15:24

Hi,
kann mir nochmal jemand bei der DCC Schranke V0.6 behilflich sein? Ich bekomme sie nicht ans laufen. Sie reagiert auf kein DCC Signal

hier nochmal der Code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
 
/* Schrankensteuerung mit Servo und DCC-Ansteuerung V0.6 30.11.2015
* Die Schrankensteuerung benötigt die 'MobaTools' - library ab der Version 0.6
* und die NmraDcc Lib (Standard-Version ohne Timer 0 Modifikation)
*
* V0.6: Kleine Korrekturen und Verbesserungen:
* - Beim Beschreiben der CVs mit den Default-Werten werden nun für jeden der beiden Servos die passenden Werte geschrieben
* - bei der Justage den Befehl readMicroseconds() durch read() ersetzt
* - bei notifyDccAccState einen DB_PRINT Befehl eingefügt, der den Inhalt der vier CVs im Debug-Mode ausgibt
*
* V0.5: Speicherung der Position ZU und Position AUF in CVs
* Der Zustand (offen/geschlossen) in CV 46
* Die Position ZU in CV 47 + 48
* Die Position AUF in CV 49 + 50
* Lok-Adresse für POM-Programmierung eines Zubehördecoders in CV 44 und 45
*
* V0.4: Umstellung von Ansteuerung auf Tastendruck auf DCC-Ansteuerung. Der Schranke wird eine DCC-Zubehör-
* Adresse (Weichendecoder) zuordnet, 'gerade' oder 'grün' schließen die Schranke, 'abzweig' oder 'rot' öffnen sie
* Die Justierung erfolgt zunächst weiterhin über die beiden separaten Taster
*
* V0.3: Mit Justierung der Endlagen und Speichern der Werte im EEPROM, vorbereitet für 4 Schrankenbäume.
* Die gesamte Bewegungskontrolle der Schrankenbäume ist in ein eigenes Unterprogramm ausgelagert.
* Dies erleichtert die Umstellung auf einen anderen Antrieb, z.b. mit einem Schrittmotor.
* Die Endlagenjustierung ist ebenfalls in diesem UP enthalten und kann jederzeit während des Betriebes vorgenommen
* werden. Pro Schranke wird ein Taster benötigt. Wird während der Schrankenbewegung der Taster gedrückt und
* gehalten, so läuft die Schranke verlangsamt weiter, bis die Taste losgelassen wird. Das ist dann die neue
* Endlage. Dies funktioniert sowohl beim Öffnen, als auch beim Schliessen der Schranke.
*
* V0.2: Version mit erweiterter Ablaufsteuerung: mit Vorlauf für Glocke und
* Wechselblinker.
*
* Für eine bessere Übersicht und Erweiterbarkeit ist das Programm logisch in einzelen Blöcke aufgeteilt.
* Diese Blöcke sind im loop hintereinander angeordnet, arbeiten aber weitgehend unabhängig. Damit dies
* möglich ist, dürfen innerhalb der Blöcke keine Warteschleifen/Delays werwendet werden, die den
* Programmablauf temporär anhalten.
*
* 1.Block: Einschaltlogik.
* Hier wird bestimmt, ob die Schranke geschlossen oder geöffnet werden soll, über eine DCC-Zubehör-Adresse
* Ergebnis der Einschaltlogik ist ein Flag 'schrankeSchliessen'
*
* 2. Block Ablaufsteuerung Schrankenlogik
* zentraler Block, der den Ablauf des Schrankenschliessens bzw -öffnens steuert. Der Block agiert abhängig
* von dem Flag 'schrankeSchliessen' und dem momentanen Zustand der Schrankenlogik
* Hier werden auch die Flags gesetzt, mit denen die Glocke (glAktiv) und der Wechselblinker (wbAktiv)
* ein- bzw ausgeschaltet werden.
*
* 3. Block Ansteuerung der Glocke
* abhängig vom Flag 'glAktiv' wird der Impulsausgang für die Glocke ein- bzw ausgeschaltet. Je nach ange-
* schlossenem Audio-Modul muss gegebenenfalls auch darauf geachtet werden, dass der letzte Glockenschlag
* nicht abgeschnitten wird.
*
* 4. Block Wechselblinker
* abhängig vom Flag 'wbAktiv' wird der Wechselblinker ein- bw ausgeschaltet. Beim Einschalten sind kurz beide
* Blinker gleichzeitig an, bevor sie dann abwechselnd blinken.
*
* Verwendete Anschlüsse:
* Pin2: DCC-Eingang
* Pin4: ACK-Ausgang
* Pin3 + Pin11: LED-Ausgänge
* Pin5 + Pin6: Servo-Ausgänge
* Pin9 + Pin10: Tastereingänge zum Justieren der Servos
* Pin7: Ausgang für die Ansteuerung der Glocke
*
*
*/
#include <MobaTools.h>
#include <NmraDcc.h>
 
#define DCC_DECODER_VERSION_ID 5 // Versions-ID zur Speicherung in CV 7
#define DCC_ADDR 1 // Zubehör-Adresse, Weichendecoder
#define CV_DCC_POM_PROG 44 // CV 44 beinhaltet LSB der Digitaladresse, unter der der Decoder auf dem Hauptgleis programmiert werden kann (POM)
#define DEBUG ; // Wenn dieser Wert gesetzt ist, werden Debug ausgaben auf dem ser. Monitor ausgegeben
 
#define SCHRANKENZAHL 2 // Zahl der Schrankenbäume
 
// gegebenenfalls anzupassende Werte (weitere Werte können im Abschnitt 'Portzuordnungen und Konstante' angepasst werden)
#define PULS_ZU1 50 // Initiale Winkel für die Endpositionen. Die Werte können über die Justierung
#define PULS_AUF1 100 // angepasst werden. Die Drehrichung kann durch Vertauschen der Werte für ZU / AUF
#define PULS_ZU2 50 // umgedreht werden. Dies ist über die Justierung NICHT anpassbar.
#define PULS_AUF2 100
 
#define GLOCKE_ZYK 1000 // Glockenzyklus und Impulslänge muss an das angeschlossene Soundmodul
#define GLOCKE_PULS 200 // angepasst werden.
 
////////////////////////////////////////////////////////////////////////
//////////////// Portzuordnungen und Konstante /////////////////////////
// 1. Einschaltlogik --------------------------------------------------
const byte DccInputP = 2; // IRQ-Pin 2 des Arduino
const byte DccAckPin = 4; // Ausgang für das ACK
 
// 2. Ablaufsteuerung --------------------------------------------------
const byte ServoPort[SCHRANKENZAHL] = { 5, 6 };
const byte schrTempo[SCHRANKENZAHL] = { 5, 4 };
const int schrVerzZU[SCHRANKENZAHL] = { 10, 500 }; // Verzögerung für die Schrankenbewegung (ms)
// damit laufen die Schranken nicht exakt gleichzeitig los.
// bei 4 Schrankenbäumen kann dies genutzt werden, um die in Auto-Fahrtrichtung
// hinteren Schranken später schliessen zu lassen
const int vorlaufZu = 6000; // Vorlaufzeit: Glocke und Wechselblinker aktiv, Schranke noch ruhend
const int nachlaufZu = 2000; // Nachlaufzeit: Schranke zu, Glocke nochaktiv
const byte Justage1P = 9; // Taster zum Justieren von Servo1
const byte Justage2P = 10; // Taster zum Justieren von Servo2
 
// 3. Glocke -------------------------------------------------------------
const byte glockeP = 7; // Impulsausgang zur Ansteuerung einer Glocke
const int glZykl = GLOCKE_ZYK; // Glockenrythmus
const int glImp = GLOCKE_PULS; // Impulslänge am Glockenausgang
 
// 4. Wechselblinker ----------------------------------------------------
const byte led1P = 3; // Ausgänge für den Wechselblinker ( Ports müssen PWM-fähig sein )
const byte led2P = 11;
const int wbZykl = 1100; // Zykluszeit des Wechselblinkers
const int wbSoft = 300; // Auf/Abblendzeit der Lampen
 
// sonst. ----------------------------------------------------------------
 
////////////////////// globale Variable //////////////////////////////////////
// 1. Einschaltlogik ----------------------------------------------------
bool schrankeSchliessen; // Wird über DCC Zubehördecoder angesteuert
 
NmraDcc DCC;
DCC_MSG Packet ;
 
// 2. Ablaufsteuerung ---------------------------------------------------
 
// Aufteilung der CV-Variablen (Standardadressen werden in der NmraDcc.h definiert)
// CV-Adresse für die Speicherung des BÜ-Zustandes
const word CvBueZustand = 46; // CV 46, Werte: 50 = offen, 54 = geschlossen
 
// CV-Adressen für die Speicherung der Endlagen (Winkel des Servos)
const word CvPosZu = 47; // CV 47, Werte zwischen 0 und 180, 255 gilt als ungültig (leeres EEPROM)
const word CvPosAuf = CvPosZu + (SCHRANKENZAHL);
 
static uint8_t FactoryDefaultCVIndex;
 
// Variable im RAM
int positionZu[SCHRANKENZAHL] = {PULS_ZU1, PULS_ZU2}; // Servopostionen, über Justiervorgang einstellbar
int positionAuf[SCHRANKENZAHL] = {PULS_AUF1, PULS_AUF2}; // Servopostionen, über Justiervorgang einstellbar
byte justageAktiv[SCHRANKENZAHL];
Servo8 Schranke[SCHRANKENZAHL]; // Für die Schrankenservos
EggTimer SchrankeT[SCHRANKENZAHL]; // Schrankenspezifische Zeiten
EggTimer VorlaufT;
 
// Aufrufparameter für das Unterprogramm 'Schrankenbewegung':
#define SB_INIT 0 // Servoansteuerung initiieren
#define SB_START_AUF 1 // Schranke öffnen starten
#define SB_START_ZU 2 // Schranke schliessen starten
#define SB_ENDE 3 // Bewegung überwachen und Ende erkennen. Ggfs. Endlagen justieren
 
// Zustand, in dem sich die Ablaufsteuerung gerade befindet
byte bueZustand; // Aktueller Zustand
byte bueVorZustand; // vorheriger Zustand des Bue ( noch nicht verwendet)
#define OFFEN 50
#define VORLAUF_ZU 51 // Wechselblinker und Glocke, aber noch keine Bewegung
#define SCHRANKE_SCHLIESST 52 // Bewegung Schrankenbaum zu
#define NACHLAUF_ZU 53 // Beide Schrankenbäume in Endpos, Glocke läutet noch.
#define GESCHLOSSEN 54 // Schranke geschlossen
#define SCHRANKE_OEFFNET 56 // Bewegung Schrankenbaum auf
 
// CV Speicher Struktur
struct CVPair
{
uint16_t CV;
uint8_t Value;
};
 
// CV Default-Werte
CVPair FactoryDefaultCVs [] =
{
{CV_ACCESSORY_DECODER_ADDRESS_LSB, DCC_ADDR},
{CV_ACCESSORY_DECODER_ADDRESS_MSB, 0},
{CV_VERSION_ID, DCC_DECODER_VERSION_ID},
{CV_MANUFACTURER_ID, MAN_ID_DIY},
{CV_29_CONFIG, 192},
{CV_DCC_POM_PROG, DCC_ADDR},
{CV_DCC_POM_PROG + 1, 0 },
{CvBueZustand, OFFEN},
{CvPosZu, PULS_ZU1},
{CvPosZu + 1, PULS_ZU2},
{CvPosAuf, PULS_AUF1},
{CvPosAuf + 1, PULS_AUF2},
};
 
// 3. Glocke -------------------------------------------------------------
EggTimer glockeT;
byte glAktiv = false; // Flag ob Glocke aktiv ist
 
// 4. Wechselblinker ------------------------------------------------------
SoftLed Wblinker[2]; // 2 Leds für den Wechselblinker
EggTimer BlinkerT;
byte wbAktiv = false; // Flag ob Wechselblinker aktiv ist
byte ledState = LOW; // Status Wechselblinker
// Zustand Wechselblinker
byte wblZustand = 0;
#define WBL_AUS 0
#define WBL_START 1 // Beim Start sind kurz beide Lampen an
#define WBL_BLINKT 2
 
// sonst. -----------------------------------------------------------------
// für debugging
#ifdef DEBUG
#define DB_PRINT( ... ) sprintf( dbgbuf,"Dbg: " __VA_ARGS__ ) ; Serial.println( dbgbuf )
byte debug;
char dbgbuf[80];
#else
#define DB_PRINT ;
#endif
 
//###################### Ende der Definitionen ##############################
//###########################################################################
 
void setup()
{
byte i;
#ifdef DEBUG
Serial.begin(38400); //Debugging
Serial.println( "start of Program" );
#endif
// 1. Einschaltlogik ----------------------------------------------------
DCC.pin(digitalPinToInterrupt(DccInputP), DccInputP, 1); // Dcc-Signal mit Pullup
DCC.init( MAN_ID_DIY, DCC_DECODER_VERSION_ID,
FLAGS_OUTPUT_ADDRESS_MODE | FLAGS_DCC_ACCESSORY_DECODER,
CV_DCC_POM_PROG ); // Zubehördecoder, 11bit-Adresse
 
/////////////////////////////////////
// DCC-Adresse setzen
if ( DCC.getCV( 1 ) == 255 ) { // wenn keine gültige Adresse gespeichert ist
DCC.setCV( 1, DCC_ADDR % 256 );
DCC.setCV( 9, DCC_ADDR / 256 );
}
if ( DCC.getCV( CV_DCC_POM_PROG ) == 255 ) { // wenn keine gültige Adresse gespeichert ist
DCC.setCV( CV_DCC_POM_PROG, DCC_ADDR );
DCC.setCV( CV_DCC_POM_PROG + 1, 0 );
}
 
#ifdef DEBUG
// CV-Werte ausgeben
DB_PRINT( "CV1:%d, CV9:%d, CV29:%d, CV7=%d, CV8=%d", DCC.getCV(1), DCC.getCV(9), DCC.getCV(29), DCC.getCV(7), DCC.getCV(8) );
#endif
 
pinMode(DccAckPin, OUTPUT);
digitalWrite( DccAckPin, LOW ); // Der ACK Pin wird auf LOW gesetzt,damit ein definierter Zustand vorhanden ist
 
// 2. Ablaufsteuerung ---------------------------------------------------
pinMode(Justage1P, INPUT_PULLUP); // Zur Justage der Endlage Schranke 1
pinMode(Justage2P, INPUT_PULLUP); // dto, Schranke 2
 
////////////////////// Grundinitiierung ////////////////////////////
// Testen ob gültige Werte in den CVs abgelegt sind. Wenn nicht, Grundinitiierung mit default-Werten
// Initiiert wird auch, wenn während des Programmstarts einer der Justageschalter betätigt ist
if ( DCC.getCV( CvPosZu ) == 255 ||
digitalRead( Justage1P) == LOW ||
digitalRead( Justage2P) == LOW ) {
// Grundinitiierung
DB_PRINT( "CV Initiierung" );
// Endlagen auf Default-Werte setzen
DCC.setCV( CvPosZu, PULS_ZU1 );
DCC.setCV( CvPosAuf, PULS_AUF1 );
DCC.setCV( CvPosZu + 1, PULS_ZU2 );
DCC.setCV( CvPosAuf + 1, PULS_AUF2 );
DCC.setCV(CvBueZustand, OFFEN);
}
 
/////////////////////////////////////
// Positionswerte aus CV lesen
for ( i = 0; i < SCHRANKENZAHL; i++ ) {
positionZu[i] = DCC.getCV( CvPosZu + i );
positionAuf[i] = DCC.getCV( CvPosAuf + i );
DB_PRINT( "Setup // Schr.%d - PosZu=%d PosAuf=%d", i, positionZu[i], positionAuf[i] );
DB_PRINT( "Zustand: %d", DCC.getCV( CvBueZustand ));
}
 
#ifdef DEBUG
// CV-Werte ausgeben
DB_PRINT( "CV1:%d, CV29:%d, CV7:%d, CV8:%d", DCC.getCV(1), DCC.getCV(29), DCC.getCV(7), DCC.getCV(8) );
#endif
 
/////////////////////////////////////////
/////// Antriebs-Initiierung ////////////
Schrankenbewegung( SB_INIT );
 
// Anfangsstellung der Schranke setzen
bueZustand = DCC.getCV( CvBueZustand );
if ( bueZustand == GESCHLOSSEN ) {
Schrankenbewegung( SB_START_ZU );
while ( !Schrankenbewegung( SB_ENDE ) );
wbAktiv = true;
} else {
Schrankenbewegung( SB_START_AUF );
while ( !Schrankenbewegung( SB_ENDE ) );
}
// 3. Glocke -------------------------------------------------------------
pinMode( glockeP, OUTPUT );
 
// 4. Wechselblinker ------------------------------------------------------
Wblinker[0].attach(led1P); // Portzuordnung für den WEchselblinker
Wblinker[1].attach(led2P);
Wblinker[0].riseTime(wbSoft); // Weiches Auf/Abblenden der Lampen
Wblinker[1].riseTime(wbSoft);
 
// sonst. -----------------------------------------------------------------
 
} // End Setup
//############################### ENDE SETUP ##################################
//#############################################################################
 
void loop()
{
// 1. Einschaltlogik ----------------------------------------------------
////////////// Eingang zur Steuerung des Bahnübergangs /////////////////
DCC.process();
// schrankeSchliessen wird in notifyDccFunc gesetzt
 
// 2. Ablaufsteuerung ---------------------------------------------------
justageAktiv[0] = ( digitalRead( Justage1P ) == LOW ) ;
justageAktiv[1] = ( digitalRead( Justage2P ) == LOW ) ;
 
//////////// Ablaufsteuerung des Bue - Haupt-Zustandsautomat ///////////////////
switch ( bueZustand ) {
case OFFEN:
// Schranke ist geöffnet, warten auf Eingang
if ( schrankeSchliessen ) {
// Schranke soll sich schliessen, Glocke und Wechselblinker startet.
wbAktiv = true; // Wechselblinker einschalten
glAktiv = true; // Glocke einschalten. Diesen Befehl auskommentieren wenn die Glocke erst
// mit der Schrankenbewegung starten soll
VorlaufT.setTime( vorlaufZu );
bueZustand = VORLAUF_ZU;
DB_PRINT("Zustandswechsel: %d", bueZustand );
}
break; //----------------------------------------------------------
case VORLAUF_ZU:
// Warten bis die Vorlaufzeit abgelaufen ist, dann die Schrankenbewegung starten
if ( !VorlaufT.running() ) {
// Vorlaufzeit abgelaufen, Schrankenbewegung starten.
// spätestens hier muss auch die Glocke aktiviert werden
glAktiv = true; // wurde sie schon aktivert, machts auch nichts ;-)
wbAktiv = true;
Schrankenbewegung(SB_START_ZU); // Überwachung initiieren
bueZustand = SCHRANKE_SCHLIESST;
}
break; //----------------------------------------------------------
case SCHRANKE_SCHLIESST:
// Schrankenbaum schliesst sich.
if ( ( Schrankenbewegung( SB_ENDE ) ) ) {
// beide Schrankenbäume haben ihre Endposition erreicht
VorlaufT.setTime( nachlaufZu );
bueZustand = NACHLAUF_ZU;
}
break; //----------------------------------------------------------
case NACHLAUF_ZU:
// Schrankenbaum geschlossen, kurzer Nachlauf für Glocke.
if ( !VorlaufT.running() ) {
glAktiv = false;
bueZustand = GESCHLOSSEN;
DCC.setCV( CvBueZustand, bueZustand );
}
break; //----------------------------------------------------------
case GESCHLOSSEN:
// Schranke ist zu, warten auf Eingang
if ( schrankeSchliessen == false ) {
// Schranke soll sich öffnen, Bewegung einleiten
Schrankenbewegung(SB_START_AUF); // Überwachung initiieren
wbAktiv = false; // Wechselblinker ausschalten
bueZustand = SCHRANKE_OEFFNET;
}
break; //----------------------------------------------------------
case SCHRANKE_OEFFNET:
// Schrankenbaum öffnet sich, warten bis offen
if ( schrankeSchliessen == true ) {
// Notfall: beim Öffnen der Schranke kommt wieder der Befehl Schranke schliessen
bueZustand = VORLAUF_ZU; // Da der Vorlauftimer nicht läuft, schliesst die Schranke sofort
 
}
if ( Schrankenbewegung( SB_ENDE ) ) {
// beide Schrankenbäume haben ihre Endposition erreicht
bueZustand = OFFEN;
DCC.setCV( CvBueZustand, bueZustand );
}
break; //----------------------------------------------------------
} ////////////// Ende Zustandsautomat Bahnübergang /////////////////////
 
// 3. Glocke -------------------------------------------------------------
////////////////// Glockenimpuls erzeugen ////////////////////////////////
if ( glAktiv ) {
if ( !glockeT.running() ) {
// Glockentimer abgelaufen, Impuls erzeugen
if ( digitalRead( glockeP ) == HIGH ) {
// Port ist gesetzt, abschalten
digitalWrite( glockeP, LOW );
glockeT.setTime( glZykl - glImp );
} else {
// Port ist aus, einschalten
digitalWrite( glockeP, HIGH );
glockeT.setTime( glImp );
}
}
} else {
// Glocke inaktiv, Ausgang abschalten wenn Timer nicht mehr läuft
if ( !glockeT.running() ) {
// Die Timerabfrage stellt sicher, dass auch der letzte Impuls immer in
// voller Länge ausgegeben wird
digitalWrite( glockeP, LOW );
}
}
 
// 4. Wechselblinker ------------------------------------------------------
/////////////// Wechselblinker (Zustandsautomat ) //////////////////
switch (wblZustand) {
case WBL_AUS:
// Beide Lampen sind aus, warten auf einschalten
if ( wbAktiv ) {
// Beide Leds einschalten, Timer für gemeinsames Startleuchten
Wblinker[0].on();
Wblinker[1].on();
BlinkerT.setTime( wbSoft / 2 );
wblZustand = WBL_START;
}
break;
case WBL_START:
// Startphase: Nach Zeitablauf erste Led wieder aus
if ( !BlinkerT.running() ) {
// Übergang zur normalen Blinkphase
ledState = HIGH;
Wblinker[1].off();
BlinkerT.setTime(wbSoft);
wblZustand = WBL_BLINKT;
}
break;
case WBL_BLINKT:
if ( !BlinkerT.running() ) {
BlinkerT.setTime(wbZykl / 2);
if ( ledState == LOW ) {
Wblinker[0].on();
Wblinker[1].off();
ledState = HIGH;
} else {
ledState = LOW;
Wblinker[1].on();
Wblinker[0].off();
}
}
if ( !wbAktiv ) {
// Wechselblinker abschalten
Wblinker[0].off();
Wblinker[1].off();
wblZustand = WBL_AUS;
}
break;
 
} /////////// Ende switch Wechselblinker ////////////////////////
 
/* Prüfen, ob die default CV-Werte benötigt werden */
if ( FactoryDefaultCVIndex && DCC.isSetCVReady())
{
FactoryDefaultCVIndex--; // Zunächst verringern, da es zu Beginn die Größe des Arrays ist
DCC.setCV( FactoryDefaultCVs[FactoryDefaultCVIndex].CV,
FactoryDefaultCVs[FactoryDefaultCVIndex].Value);
}
} // End Loop
//#################### ENDE LOOP ##################################################
//#################################################################################
 
byte Schrankenbewegung( byte mode ) {
// Bewegungsvorgang der Schranken überwachen, gegebenenfalls auch die Endlage
// justieren. Das Unterprogramm wird im Loop während der Bewegung zyklisch aufgerufen
// Der Funktionswert ist 'true', wenn die Bewegung aller Schranken abgeschlossen ist,
// sonst immer 'false'
// mode:SB_INIT Grundinitiierung
// SB_START_ZU Schliessen der Schranken einleiten
// SB_START_AUF Öffnen der Schranken einleiten
// SB_ENDE Bewegung überwachen, meldet 'true' wenn alle Bewegungen abgeschlossen
// sind
// -------------------------------------------------------------------------
//
static enum { WAIT, NORMAL, JUSTAGE_AKTIV, JUSTAGE_ENDE, WIPPEN } ssZustand[SCHRANKENZAHL] ;
static int startPos[SCHRANKENZAHL] ; // Position der Schranke zu Bewegungsbeginn
static enum { AUF, ZU } richtung;
 
byte bewegung = 0, sn;
int tmp;
for ( sn = 0; sn < SCHRANKENZAHL; sn++ ) {
// für alle Schranken durchlaufen
switch ( mode ) {
case SB_INIT: // Initiierung der Schranken
Schranke[sn].attach(ServoPort[sn], 1); //Servos an Pin 5 / 6 mit AutoOff
Schranke[sn].setSpeed( schrTempo[sn] );
bewegung = 1;
break; //---------------------------------------------
case SB_START_ZU: // Schliessen der Schranken einleiten
richtung = ZU;
Schranke[sn].setSpeed( schrTempo[sn]);
SchrankeT[sn].setTime( schrVerzZU[sn] ); //Wartezeit bis Schrankenbewegung
DB_PRINT( "Start Wartezeit %d mit %d ms", sn, schrVerzZU[sn] );
ssZustand[sn] = WAIT;
bewegung = 1;
break; //---------------------------------------------
case SB_START_AUF: // Öffnen der Schranken einleiten
richtung = AUF;
Schranke[sn].setSpeed( schrTempo[sn]);
Schranke[sn].write( DCC.getCV( CvPosAuf + sn ));
ssZustand[sn] = NORMAL;
startPos[sn] = Schranke[sn].read();
DB_PRINT( "Schranke %d, Position: %d, Richtung= %d", sn, startPos[sn], richtung );
bewegung = 1;
break; //---------------------------------------------
case SB_ENDE: // Bewegung überwachen, auf Ende prüfen
// Schrankenbewegung
switch ( ssZustand[sn] ) {
case WAIT: // Verzögerungszeit bis zum Schrankenstart abwarten
// Wird nur beim Schliessen der Schranke durchlaufen
if ( SchrankeT[sn].running() == false ) {
// Zeit abgelaufen, Bewegung starten
Schranke[sn].write( DCC.getCV( CvPosZu + sn ));
ssZustand[sn] = NORMAL;
startPos[sn] = Schranke[sn].read();
DB_PRINT( "Schranke %d, Position: %d, Richtung= %d", sn, startPos[sn], richtung );
ssZustand[sn] = NORMAL;
}
bewegung = 1;
break; //......................................
case NORMAL:
bewegung += Schranke[sn].moving();
if ( justageAktiv[sn] ) {
// Justageschalter betätigt, Speed auf 1, Servobewegung um 10% weitersetzen,
// sodass die neue Endposition auch hinter der alten liegen kann.
Schranke[sn].setSpeed( 1 );
ssZustand[sn] = JUSTAGE_AKTIV;
if ( richtung == ZU ) tmp = (positionZu[sn] * 3 - positionAuf[sn]) / 2;
else tmp = (positionAuf[sn] * 3 - positionZu[sn]) / 2;
DB_PRINT( "Schranke %d, Justage Endpso=%d", sn, tmp );
Schranke[sn].write( tmp );
}
// if ( bewegung < 5 ) ssZustand[SchrNr] = WIPPEN;
break; // .....................................
case WIPPEN:
// to be defined ;-)
break; //......................................
case JUSTAGE_AKTIV:
bewegung += 1; // keine Endemeldung während der Justage
if ( !justageAktiv[sn] ) {
// Justageschalter wurde wieder losgelassen. Momentane Servo-Position
// als neuen Endpunkt speichern und Servo anhalten
tmp = Schranke[sn].read();
DB_PRINT( "Schranke %d, Justage ende, Pos = %d", sn, tmp );
Schranke[sn].write( tmp );
if ( richtung == ZU ) {
positionZu[sn] = tmp;
DCC.setCV( CvPosZu + sn, tmp );
} else {
positionAuf[sn] = tmp;
DCC.setCV( CvPosAuf + sn, tmp );
}
ssZustand[sn] = JUSTAGE_ENDE;
}
break; //......................................
case JUSTAGE_ENDE:
bewegung += Schranke[sn].moving();
 
break; //......................................
} // ..... Ende switch 'Schrankenzustand' ......
 
break; //---------------------------------------------
default:
// falscher Programmaufruf, keine Reaktion
;
} // --- Ende Switch 'mode' --------
} // ........Ende forschleife der Schranken........
 
if ( bewegung == 0 ) DB_PRINT( "Endpositionen erreicht");
return ( bewegung == 0 );
}
 
//###################################################################################
//###################### DCC - Funktionen ###########################################
// Auswertung des Zubehördecoders
void notifyDccAccState( uint16_t Addr, uint16_t BoardAddr, uint8_t OutputAddr, uint8_t State)
{
if (Addr == DCC.getAddr()) {
schrankeSchliessen = ((OutputAddr & 0x1) != 0);
DB_PRINT( " Adresse: %u, Status %x", Addr, schrankeSchliessen );
DB_PRINT( " CV 47: %d, CV 48: %d, CV 49: %d, CV 50: %d", DCC.getCV(47),DCC.getCV(48),DCC.getCV(49),DCC.getCV(50) );
}
}
 
// Diese Funktion wird von der Nmra-Lib aufgerufen, wenn ein DCC ACK gesendet werden muss
// z.B. beim Programmieren des Decoders über die Digitalzentrale
void notifyCVAck(void)
{
digitalWrite( DccAckPin, HIGH );
delay( 6 );
digitalWrite( DccAckPin, LOW );
}
 
// Ein Decoder Reset wird angefordert
void notifyCVResetFactoryDefault()
{
// Setze FactoryDefaultCVIndex ungleich Null und auf die Anzahl der CVs, die zurückgesetzt werden müssen
// damit die Funktion im loop erkennt, dass ein Reset durchzuführen ist
FactoryDefaultCVIndex = sizeof(FactoryDefaultCVs) / sizeof(CVPair);
}
 

 



Andi


DJMetro  
DJMetro
InterRegio (IR)
Beiträge: 137
Registriert am: 17.05.2008
Ort: DJMetro
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#214 von digi_thomas2003 , 29.10.2017 21:16

Hallo Andi,

Zitat

Hi,
kann mir nochmal jemand bei der DCC Schranke V0.6 behilflich sein? Ich bekomme sie nicht ans laufen. Sie reagiert auf kein DCC Signal
...
Andi



mit welcher Zentrale arbeitest Du?
Den Anschluss des Arduinos (Nano?) an das DCC-Signal ist wie in meinem Schaltplan erfolgt?

Freundliche Grüße
Thomas


Thomas
------------------
Anlage H0: U-Form, im kreativen Bau
Fahren: Tams MC
Schalten: IB
Melden: HSI 88
Steuern: TrainController 9.0 Gold
Denken: Brain 4.1


 
digi_thomas2003
InterRegioExpress (IRE)
Beiträge: 305
Registriert am: 03.05.2005
Gleise sind vorhanden
Spurweite H0
Steuerung TrainController
Stromart AC, Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#215 von md95129 , 12.11.2017 21:27

Hallo Hans-Peter,
ich bin gerade ueber diesen Thread gestolpert. Die mit Schrittmotoren gesteuerte Schranke bewegt sich wirklich sehr naturgetreu. Danke auch fuer die vielen Bibliotheken und Programm(Sketch)-beispiele in diesem Thread. Dein Bahnuebergangsprogramm mit "State Machines" ist sehr schoen geschrieben. Ich selbst habe vor vielen Jahrzehnten eine Schiebebuehne mit Schrittmotor gebaut. Damals hatte ich einen geklauten (na, ja zwangsausgemusterten) 8748 zur Verfuegung, der natuerlich in Assembler programmiert werden musste. Als "Entwicklungsumgebung" diente ein Prompt48 - eine riesige und teure Kiste und ein selbstgeschriebener Assembler auf einer PDP11. Die Buehne konnte Stern/Dreieck Anfahren/Bremsen, Spielausgleich, Schalten von Relais und Sperrsignal und damit waren die Moeglichkeiten von Prozessor/Programmierer so ziemlich erschoepft. Trotz Selbstbau von Loks habe ich nie die Elektronik aus dem Auge verloren, z.B. Entwicklung eines speziellen Low-Voltage DCC Decoders "from Scratch". Aber zurueck zu Deinen Arbeiten. Ich ueberlege mir im Augenblick, eine Drehscheibe mit Schrittmotor zu bauen (Mechanik fast fertig). Dank Deiner Bibliotheken sehe ich fuer die Software keine Probleme, eher mit der "Philosophie" einer Drehscheibe. Ich moechte keine Schaltkontakte an den Abgaengen einbauen, sondern den Fahrstrom fuer Buehne/Abgaenge mit Relais schalten. Das 180Grad Drehen von Fahrzeugen soll natuerlich moeglich sein. Die Buehne soll ohne Schleifringe auskommen. Damit entfaellt eine Drehbewegung groesser als z.B. 720Grad. Das Problem ist die eindeutige Erkennung der Homeposition bei einer Gesamtbewegung >360 Grad, um das "Aufwickeln" der Buehnenversorgung zu vermeiden und die richtige Polaritaet fuer die Buehnengleise zu ermitteln. Die letzte Position vor dem Abschalten in einem EEPROM zu speichern halte ich fuer nicht so gut. Hat jemand eine zuendende Idee?
Regards


Henner,
ex-Donkey Doktor der EDH Lumber
Schamlose Selbstbeweihräucherung: Eigenbauten eines alten Neulings.
US Waldbahnen/Echtdampf-Eigenbau


 
md95129
EuroCity (EC)
Beiträge: 1.079
Registriert am: 15.01.2017
Ort: Berlin
Gleise IIm Echtdampf,H0m
Steuerung DCC Eigenbau
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#216 von DJMetro , 21.02.2018 14:48

Hi Leute, wo finde ich denn den Eggtimer der teilweise benutzt wird?

Andi


DJMetro  
DJMetro
InterRegio (IR)
Beiträge: 137
Registriert am: 17.05.2008
Ort: DJMetro
Spurweite H0
Stromart Digital


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#217 von B-B , 21.02.2018 15:36

Hai Andi,

er befindet sich in den Mobatools

https://stummiforum.de/viewtopic.php?f=21&t=127899

Dort auf Mobatols Zip klicken.

LG
Bernd


 
B-B
InterRegio (IR)
Beiträge: 172
Registriert am: 28.10.2009


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#218 von hpe , 23.01.2019 17:57

Hallo,
bin Neuling in Bezug auf Arduino, analoge Anlage
Ich möchte den Sketch BueSteuerung_V0.3 verwenden, weil Servo Endlagen langsam anfährt, Endlagenjustage genial und WBL integriert ist
habe mit Arduino 1.8.8 und Mobatools 1.0.2 den Sketch auf meinen Arduino UNO geladen (EggTimer bei include auskommentiert),bis dahin alles ok

1.nach Start fahren beide Servos in Richtung 1 zur Posi 1800 (PULS_AUF1 1800) (Serieller Monitor, Debug aktiviert)
2.nach dem ersten Betätigen des Tasters(7) fahren beide Servos in Richtung 0 zur Posi 1200 (PULS_ZU1 1200) scheinbar noch ok
3.und sofort nach Wartezeit von 10,500,500,500ms
4.fährt Servo 0 in Richtung 1 auf Posi 1237 und Servo 1 in Richtung 1 auf Posi 1280

nach jedem weiteren Betätigen des Tasters wiederholt sich die Positionierung entsprechend Zeilen 2.-4., gleiche Positionen
oder anders gesagt, Schranke bewegt sich nach einem Tasterdruck ein Stück hoch und sofort wieder runter
Justageschalter funktionieren- Servo fährt auf Position, aber justierte Endlagen werden beim nächsten Tastendruck ignoriert, wie oben
Wechselblinker startet mit Programm und endet nicht !!!
Hardware:
Taster über PullUp Widerstände 10kOhm nach plus
separate Stromversorgung Servos über regelbares Labornetzteil 5V
Stromversorgung Uno über 9V Batterie
sonst entsprechend Schaltung

mit ArduinoDroid habe ich auch probiert:
dort sofort Compiler Fehler
u.a. byte eeValid EEMEM fehlendes ";" wird moniert, setzen bringt auch nichts
eeprom_read_byte( &eevalid ).... undeclared identifier eeprom_read_byte
Schrankenbewegung ( SB_Start_Auf ); undeclared identifier Schrankenbewegung

habe auch schon ältere Versionen von MOBATools Ardunio IDE versucht, BueSteuerung_V0.3 ist ja von 2015, aber nichts geht

nun merke ich, dass ich Anfänger bin
vielleicht kann mir jemand helfen


hpe  
hpe
Beiträge: 4
Registriert am: 13.01.2019


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#219 von MicroBahner , 23.01.2019 18:15

Hallo hpe,

Zitat

2.nach dem ersten Betätigen des Tasters(7) fahren beide Servos in Richtung 0 zur Posi 1200 (PULS_ZU1 1200) scheinbar noch ok

Der Schalter für 'Schranke zu' an Pin 7 ist kein Taster. Das ist als Schalter gedacht, der solange geschlossen ist, wie die Schranke geschlossen ist. Wird der Schalter wieder geöffnet, öffnet auch die Schranke. Vielleicht ist das ja schon dein ganzes Problem.
Edit: hab' gerade nochmal genauer geschaut - es ist umgekehrt. Ein HIGH an Pin 7 schließt die Schranke. Und mit Pullups und Schalter nach Gnd bedeutet dass einen offenen Schalter.

Natürlich kann Du das auch ändern, so dass das als Tastfunktion arbeitet ( Schranke offen und tasten -> Schranke geht zu, Schranke zu und Tasten-> Schranke geht auf ). Dazu musst Du den Sketch aber natürlich ändern.


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#220 von hpe , 24.01.2019 22:52

Hallo Franz-Peter,
besten Dank für die schnelle Antwort.
Sorry, hatte Taster und Schalter verwechselt. Nach Deiner Antwort Sketch wieder getestet. Funktionierte sofort.
Nachdem ich ausgiebig justiert habe, blinkte mein UNO wild und Sketch funktionierte nicht mehr. Kann es sein, dass Positionen im EEprom nicht überschrieben werden und dadurch EEprom voll geschrieben wird? Nach Löschen des EEproms war alles wieder ok.
Das Ändern des Sketches von Schalter auf Taster bekomme ich nicht hin, habe auch keinen Plan, wo ich da anfangen soll.
Ich werde versuchen, das Tastersignal in Dauersignal umzuwandeln (Relais oder Flipflop).
Das Signal soll über Reflexlichtschranke (Schließen Schranke) und Nicht_Besetztmeldung (Öffnen Schranke) erzeugt werden. Muss ich mir noch genau überlegen.

Also nochmals vielen herzlichen Dank und viele Grüße
hpe


hpe  
hpe
Beiträge: 4
Registriert am: 13.01.2019


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#221 von MicroBahner , 25.01.2019 09:54

Hallo hpe,
wenn Du von Schalter auf Tastereingänge umstellen willst, müsstest du hier ansetzen:

1
2
3
4
5
 
    // 1. Einschaltlogik ----------------------------------------------------
////////////// Eingang zur Steuerung des Bahnübergangs /////////////////
schrankeSchliessen = ( digitalRead( schrankeZuP) == HIGH );

 
 

Ds 'schrankeSchliessen' ist der interne Zustand, nach dem sich alles richtet. Am einfachsten ist es, wenn Du 2 Eingänge hast ( so wie ich das deiner Beschreibung entnehme ). Das könnte dann etwas so aussehen:

1
2
3
4
5
 
    // 1. Einschaltlogik ----------------------------------------------------
////////////// Eingang zur Steuerung des Bahnübergangs /////////////////
if ( digitalRead( schrankeZuP) == LOW ) schrankeSchliessen = true;
else if ( digitalRead( schrankeAufP ) == LOW ) schrankeSchliessen = false;
 
 

Natürlich musst Du beide Eingänge vorher definieren und initiieren. Ob auf LOW oder HIGH abgefragt werden muss, hängt von den Eingangssignalen ab. Wichtig wäre in diesem einfachen Fall auch noch, dass nicht beide gleichzeitig aktiv sind.

Zitat

Nachdem ich ausgiebig justiert habe, blinkte mein UNO wild und Sketch funktionierte nicht mehr. Kann es sein, dass Positionen im EEprom nicht überschrieben werden und dadurch EEprom voll geschrieben wird? Nach Löschen des EEproms war alles wieder ok.

Das ist seltsam. Vollgeschrieben werden kann das EEPROM nicht, es wird immer an der selben Stelle geschrieben, und die alten Daten werden überschrieben. Eine EEPROM Zelle hält 100000 Schreibzyklen aus. Das sollte man nur mit Justierung kaum erreichen.


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#222 von hpe , 26.02.2019 23:52

Hallo Franz-Peter,
der Bü ist wirklich Klasse
ich habe den Code in Bezug auf die Glocke so geändert, dass ich während der Soundausgabe ständig 5V habe. Das Soundmodul mit MP3 Speicherkarte habe ich über Transistor angeschlossen. So können meine Enkel immer mal eine andere Glocke anhören.
Den Warnblinker habe ich so geändert, dass er, bis die Schranke vollständig geöffnet ist, blinkt.
Am Problem Schalter / Taster arbeite ich noch.
Viele Grüße
Hans-Peter


hpe  
hpe
Beiträge: 4
Registriert am: 13.01.2019


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#223 von andreakarina , 25.08.2019 17:18

Hallo.
Habe die Datei installiert auf dem Arduino mit der neusten Moobatools
Nach der Überprüfung durch das Arduino Sketch kommt die Fehlermeldung:
Eggtimer.H no such file or Directory.
Wo bekomme ich diesen Scetch .
Blockiere ich diesen Sketch im Programm kann ich es Hochladen.
Die LED blinken nur die Servos laufen nicht
Mfg


andreakarina  
andreakarina
RegionalExpress (RE)
Beiträge: 63
Registriert am: 29.03.2015
Spurweite H0


RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#224 von Railcar ( gelöscht ) , 25.08.2019 18:07

Hallo Andrea? Karina?,

1
 
Habe die Datei installiert auf dem Arduino mit der neusten Moobatools
 



Vielleicht veräts du einmal welche Datei du installiert hast , den Sketch?, die MobaTools?
Du meinst den Sketch in die Arduino IDE geladen und die MobaTools mit dem Library Manager??
Bischen mehr Info könnte nicht schaden?

Ulrich


Railcar

RE: Arduino: Schrankensteuerung - DCC-Ansteuerung für Betrieb und Justage

#225 von MicroBahner , 25.08.2019 21:37

Zitat

Eggtimer.H no such file or Directory.

Ist es der hier besprochene Sketch? Der ist ja schon etwas älter. Die Eggtimer.h gibt es nicht mehr, das ist in die MobaTools integriert. Die entsprechende Zeile im Sketch kann einfach gelöscht werden. Auch die Hinweise auf die erlaubten Servo-Pins sind nicht mehr aktuell - da sind jetzt alle ( nicht anderweitig benutzten ) Pins erlaubt.
Die Servos sollten schon laufen. Ist die Verdrahtung ok? Ein bisschen mehr Info wäre in der Tat von Nutzen.


viele Grüße
Franz-Peter
Ein 'elektromechanisches' Stellwerk
Der (ehemalige) 'Eisberg'


 
MicroBahner
Metropolitan (MET)
Beiträge: 2.833
Registriert am: 28.11.2012
Ort: Mittelfranken
Gleise Tillig Elite
Steuerung Eigenbau
Stromart Analog


   

CAN-Stellpult oder analoges Stellpult mit LEDs für Weichen
Viessmann 5552 Umschaltrelais gehen ständig kaputt

  • Ähnliche Themen
    Antworten
    Zugriffe
    Letzter Beitrag
Xobor Einfach ein eigenes Forum erstellen
Datenschutz