Code:
// Define *********************************************************************************************************************
#define CONTROL0 6 // 5 //MUX control pin 0 (S3 is connected to Arduino pin 2)
#define CONTROL1 5 //4
#define CONTROL2 4 //3
#define CONTROL3 3 //2
/* --> das Shield wurde um einen Pin nach oben verschoben, um den Pin 2 fuer die Interrupt der Taster zu
* verwenden !!
*
* !! ALT !! -> Interrupt mit Taster sind nicht empfohlen, wegen Prellen
* -> meine Schaltungs-/Softwareversuche haben das bestaetigt...
*/
#define MUX0 14 //^= Analog 0
#define MUX1 15 //^= Analog 1
#define MUX2 16 //^= Analog 2
// Variablen / Konstanten *****************************************************************************************************
// 1. konstante Vorgaben
const int PIN_TMR_INI_OK = 1; //Kontroll-LED für erfolgreiche Timer-Initialisierung
const int PIN_TMR_INI_NOK = 13; //Kontroll-LED für fehlgeschlagene Timer-Initialisierung -> wenn ocr1a < ocr1b ist !!
const int PIN_TAKT_SRV = 7; //Takteingang ( SH_CP )
const int PIN_SPEICHER_SRV = 8; //Speicher-Sendung ( ST_CP )
const int PIN_DATEN_SRV = 9; //Pin für den Binär-Wert ( DS )
const int PIN_TAKT_LED = 10; //Takteingang ( SH_CP )
const int PIN_SPEICHER_LED = 11; //Speicher-Sendung ( ST_CP )
const int PIN_DATEN_LED = 12; //Pin für den Binär-Wert ( DS )
const int TICKS_ABZW = 150; //Weiche abzweigend - 0.60 ms = 150 Ticks bei Prescaler 1 : 64
const int TICKS_GERADE = 250; //Weiche gerade - 1.00 ms = 250 Ticks bei Prescaler 1 : 64
const int nSRV_MAX = 18; //max Anzahl an Servos -> es sind max 18 Servos moeglich !
// -> ocr1a > ocr1b ist Pflicht
// -> 4999 / 250 = 19.9 -->> 18 fuer Puffer
// -> NUR wenn max Stell-Signal = 250 ist !!
const int FLAG_LED_GERADE = 0; //Offset um die LED des n-ten Servos fuer gerade Fahrt zu setzen
const int FLAG_LED_ABZW = 1; //Offset um die LED des n-ten Servos fuer abzweigende Fahrt zu setzen
const int IX_SRV_POS = 0; //Index der Positionen im Array
const int IX_RTG_LED = 1; //Index der LED-Flags im Array
// 2. variable Werte
int srv = -1; //der aktuelle Servo als Zähler - für OCR1A
int srvPositionen[ nSRV_MAX ][ 2 ]; //Array für die Servo-Positionen und den Pin fuer die Richtungs LED
int tasterStatus[ nSRV_MAX ]; //Logische Schaltung zur Erfassung der Taster-Status-Wechsel
int ocr1b; //variabler Wert für das, je Servo verschiedene, Steuersignal
int srvByte = 0; //1 Byte = 8 Bit, also ein Paket von 8 Servos
int srvZaehler = 0; //Zaehler zur Ermittlung in welchem Byte = Register sich der aktuelle Servo befindet
int ledByte = 0; //1 Byte = 8 Bit, also ein Paket von 4 Servos, da 1 Servo = 2 LED
int ledZaehler = 0; //Zaehler zur Ermittlung in welchem Byte = Register sich die LEDs befinden
int nShiftRegisterSrv; //Anzahl der vorhandenen/noetigen Register fuer die Servos
int nShiftRegisterLEDs; //Anzahl der vorhandenen/noetigen Register fuer die Richtungs-LEDs
// 3. Berechnete Werte
int ocr1a = 4999 / nSRV_MAX; //Intervall für OCR1A um für jeden Servo ein 20 ms Intervall zu erhalten ( 1 : 64 )
// Setup **********************************************************************************************************************
void setup ( ) {
// Serial Monitor
// Serial.begin ( 115200 );
// MUX Pins setzen
pinMode(CONTROL0, OUTPUT);
pinMode(CONTROL1, OUTPUT);
pinMode(CONTROL2, OUTPUT);
pinMode(CONTROL3, OUTPUT);
pinMode( MUX0, INPUT); //Multiplexer 0 zu input setzen - empfaengt die Taster-Eingaben
pinMode( MUX1, INPUT); //Multiplexer 1 zu input setzen - empfaengt die Taster-Eingaben
pinMode( MUX2, INPUT); //Multiplexer 2 unbenutzt
// Ausgaenge festlegen
pinMode ( PIN_TAKT_SRV, OUTPUT );
pinMode ( PIN_SPEICHER_SRV, OUTPUT );
pinMode ( PIN_DATEN_SRV, OUTPUT );
pinMode ( PIN_TAKT_LED, OUTPUT );
pinMode ( PIN_SPEICHER_LED, OUTPUT );
pinMode ( PIN_DATEN_LED, OUTPUT );
pinMode ( PIN_TMR_INI_OK, OUTPUT );
pinMode ( PIN_TMR_INI_NOK, OUTPUT );
//Es muss zwingend ocr1a > ocr1b sein! -> fuer ocr1b muss das laengste Servo-Signal angenommen werden (nServMax x laen. SrvSig)
if ( ocr1a < TICKS_GERADE ) {
digitalWrite ( PIN_TMR_INI_NOK, HIGH );
}
else {
// nShiftRegisterSrv bestimmen und Ueberlauf abfangen
nShiftRegisterSrv = nSRV_MAX / 8 + 1; //Register je aktueller Servo Nr., bzw. Anzahl Register bei nServMax
if ( nShiftRegisterSrv * 8 == nSRV_MAX ) //Korrektur bei einer Oktave ( 16 / 8 + 1 = 3, es sind aber nur 2 Byte ! )
nShiftRegisterSrv--;
// nShiftRegisterLEDs bestimmen und Ueberlauf abfangen
nShiftRegisterLEDs = ( nSRV_MAX ) / 4 + 1; //Teiler = 4 da es pro Servo 2 LEDs gibt (gerade Fahrt && abzweigende Fahrt)
if ( nShiftRegisterLEDs * 4 == nSRV_MAX ) //Korrektur bei einer Oktave ( 16 / 4 + 1 = 5, es sind aber nur 4 Byte ! )
nShiftRegisterLEDs--;
// Definiere Timer
cli ( ); //Interrupts abschalten
// Interrupt - Timer 1
TCCR1A = 0; //reset Register A
TCCR1B = 0; //reset Register B
TCNT1 = 0; //Zaehler nullen
OCR1A = ocr1a; //setze Intervall A
TCCR1B |= ( 1 << CS11 ) | ( 1 << CS10 ); //Prescaler Timer 1 auf 1 : 64 einstellen
TCCR1B |= ( 1 << WGM12 ); //Timer auf CTC mode stellen
TIMSK1 |= ( 1 << OCIE1A ); //Timer 1 aktivieren
sei ( ); //Interrupts einschalten
digitalWrite ( PIN_TMR_INI_OK, HIGH );
// Alle Positionen initialisieren
for ( int serv = 0; serv < nSRV_MAX; serv++ ) {
srvPositionen[ serv ][ IX_SRV_POS ] = TICKS_ABZW;
srvPositionen[ serv ][ IX_RTG_LED ] = FLAG_LED_ABZW;
tasterStatus[ serv ] = 0;
}
}
// Register der Servos loeschen
digitalWrite ( PIN_SPEICHER_SRV, LOW );
for ( int shift = nShiftRegisterSrv; shift >= 0; shift-- )
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
digitalWrite ( PIN_SPEICHER_SRV, HIGH );
// Register der LEDS setzen
setLEDs();
}
// // ************************************************************************************************************************
// ISR TIMER 1 COMP A *********************************************************************************************************
ISR ( TIMER1_COMPA_vect ) {
const int muxMax = 16; //max Anzahl Pins je MUX-Register (Anzahl, NICHT hoechste Pin-Nr !!)
const int mux0 = 14; //Pin des 1. MUX-Registers
int offsetMUXRegister; //Offset um das aktuelle MUX-Register aus dem aktuellen Servo zu errechnen
int muxReg; //MUX-Register des Servo-Tasters
int muxPin; //Pin des akt. Servos je MUX-Regisert
// Auf naechsten Servo zeigen
srv++;
if ( srv > nSRV_MAX - 1 ) { //Ueberlauf abfangen
srv = 0;
srvZaehler = 0;
srvByte = 0;
}
// Den n-ten Servo dem richtigen Register zuordnen
int servRegister = srv / 8 + 1;
// Dem n-ten Servo ueber das entsprechende Register das Steuersignal senden
digitalWrite ( PIN_SPEICHER_SRV, LOW );
for ( int shiftToRegister = nShiftRegisterSrv; shiftToRegister > 0; shiftToRegister-- ) {
if ( shiftToRegister == servRegister ) {
// sende an Shift-Register
// -> der Binaer-Wert ist 2^( srv - srvByte * 8 )
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 1 << ( srv - ( srvByte * 8 ) ) );
// Taster des aktuellen Servos auf Veraenderung pruefen
offsetMUXRegister = srv / 16;
muxReg = mux0 + offsetMUXRegister;
muxPin = srv - offsetMUXRegister * muxMax;
digitalWrite ( CONTROL0, ( muxPin & 15 ) >> 3 );
digitalWrite ( CONTROL1, ( muxPin & 7 ) >> 2 );
digitalWrite ( CONTROL2, ( muxPin & 3 ) >> 1 );
digitalWrite ( CONTROL3, ( muxPin & 1 ) );
if ( digitalRead ( muxReg ) && digitalRead ( muxReg ) != tasterStatus[ srv ] ) {
if ( srvPositionen[ srv ][ IX_SRV_POS ] == TICKS_ABZW ) {
srvPositionen[ srv ][ IX_SRV_POS ] = TICKS_GERADE;
srvPositionen[ srv ][ IX_RTG_LED ] = FLAG_LED_GERADE;
}
else {
srvPositionen[ srv ][ IX_SRV_POS ] = TICKS_ABZW;
srvPositionen[ srv ][ IX_RTG_LED ] = FLAG_LED_ABZW;
}
// bei Tastendruck die LEDs neu schalten
setLEDs();
}
tasterStatus[ srv ] = digitalRead ( muxReg );
}
else {
// sende an Shift-Register
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
}
}
digitalWrite ( PIN_SPEICHER_SRV, HIGH );
// Das Byte des naechsten Servos ermitteln
srvZaehler++;
if ( srvZaehler == 8 ) {
srvZaehler = 0;
srvByte++;
}
ocr1b = srvPositionen[ srv ][ IX_SRV_POS ]; //Länge des Steuersignals aus dem Array lesen
OCR1B = ocr1b; //Timer B setzen
TIFR1 |= ( 1 << OCF1B ); // ??? Klappt immer wenn das gesetzt wird
TIMSK1 |= ( 1 << OCIE1B ); //Timer B aktivieren
}
// // ************************************************************************************************************************
// ISR TIMER 1 COMP B *********************************************************************************************************
ISR ( TIMER1_COMPB_vect ) {
TIMSK1 &= ~ ( 1 << OCIE1B ); //CompB Match interrupt disabled
digitalWrite ( PIN_SPEICHER_SRV, LOW );
for ( int shift = nShiftRegisterSrv; shift >= 0; shift-- ) //das Steuersignal abschalten --> Shift-Ausgang = OFF
shiftOut ( PIN_DATEN_SRV, PIN_TAKT_SRV, MSBFIRST, 0 );
digitalWrite ( PIN_SPEICHER_SRV, HIGH );
}
// // ************************************************************************************************************************
// setLEDs ********************************************************************************************************************
void setLEDs() {
//Reset
shiftOut ( PIN_DATEN_LED, PIN_TAKT_LED, MSBFIRST, 0 );
//Senden der 0/1 Zustaende der LEDs an die Register
// -> festes setzen aller LEDs um Flackern zu verhindern
digitalWrite ( PIN_SPEICHER_LED, LOW );
for ( int srvLEDs = nSRV_MAX; srvLEDs >= 0; srvLEDs-- ) {
if ( srvPositionen [ srvLEDs ][ IX_RTG_LED ] == FLAG_LED_GERADE ) {
digitalWrite ( PIN_TAKT_LED, HIGH ); //"abzweigendes" Bit auf 0 setzen
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt wieder abschalten
digitalWrite ( PIN_DATEN_LED, HIGH ); //"gerades" Bit auf 1 setzen
digitalWrite ( PIN_TAKT_LED, HIGH ); //"gerades" Bit uebertragen
digitalWrite ( PIN_DATEN_LED, LOW ); //Daten abschalten
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt abschalten
}
else {
digitalWrite ( PIN_DATEN_LED, HIGH ); //"abzweigendes" Bit auf 1 setzen
digitalWrite ( PIN_TAKT_LED, HIGH ); //"abzweigendes" Bit uebertragen
digitalWrite ( PIN_DATEN_LED, LOW ); //Daten abschalten
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt abschalten
digitalWrite ( PIN_TAKT_LED, HIGH ); //"gerades" Bit auf 0 setzen
digitalWrite ( PIN_TAKT_LED, LOW ); //Takt abschalten
}
}
Serial.println();
digitalWrite ( PIN_SPEICHER_LED, HIGH );
}
// // ************************************************************************************************************************
// loop ***********************************************************************************************************************
void loop ( ) { }
// // ************************************************************************************************************************
Lesezeichen