/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
S e r v o W i s s e l S t e l l e r
Testprogramma voor het omzetten van een modelspoorwissel m.b.v.
een modelbouw servo.
Te testen:
- 2 losse drukknoppen voor recht en afbuigend
- 2 optocoupler ingangen; funtioneel als schakelaar, bedoeld
voor besturing vanuit HCC!m-systeem of Dinamo OC32
- 1 van de optocouplers moet later ook DCC kunnen verwerken
Er wordt gebruik gemaakt van 2 servo's
Ten behoeve van hartstukpolarisatie zijn er per servo 2 relais
Werking per wissel:
- na een wisselcommando valt eerst het aangetrokken relais af
- daarna loopt het wissel om (servo)
- dan komt het andere relais op
Bij opstarten gebeurt er niets. Het hartstuk van het wissel heeft
geen spanning en de servo staat in een ongedefinieerde stand.
De gebruikte Arduino is een Pro Mini, 5V met ATmega328.
Gebruikte libraries en voorbeelden:
- code uit het Debounce-voorbeeld bestand van Arduino.cc
http://www.arduino.cc/en/Tutorial/Debounce
- Servo library uit Arduino - omgeving
- adServo van Timo Engelgeer
Created: 30-04-2015
By: Cees Baarda
Modified:
By:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// - - - - - L i b r a r i e s i n g e b r u i k :
#include <Servo.h> // hiermee besturen we de servo's
// - - - - - C o n s t a n t e n :
// De pinnummers en vaste waarden een naam geven
// - - - - - voor wissel 1
const int optoIn_1 = 3; // voor externe aansturing met 0 of 1
const int servo_1 = 9;
// - - - - - t.b.v puntstukpolarisatie
const int relaisR_1 = 7;
const int relaisG_1 = 8;
// - - - - - t.b.v. bediening met knoppen
const int knopR_1 = 6; // input; toets wissel recht leggen
const int knopG_1 = 5; // input; toets wissel gebogen leggen
// - - - - - voor wissel 2
const int optoIn_2 = 2; // voor externe aansturing met 0 of 1
const int servo_2 = 10; // output; Servo 2
// - - - - - t.b.v puntstukpolarisatie
const int relaisR_2 = 11; // output; t.b.v. relais bij recht gelegd wisssel
const int relaisG_2 = 12; // output; t.b.v. relais bij gebogen gelegd wisssel
// - - - - - t.b.v. bediening met knoppen
const int knopR_2 = A2; // input; toets wissel recht leggen
const int knopG_2 = A0; // input; toets wissel gebogen leggen
// - - - - - beide wissels met DCC, nog niet in gebruik
// const int DCC_in = 2; // input; de DCC-railspanning gaat hier aan
const int LED = A1; // LED op de print
// - - - - - nog niet in gebruik, zijn bedoeld voor extra print aan 8 polige
// connector
// const int LEDarduino = 13; // LED op de arduino
// const int LEDextern_1 = A2; // evt. extra LED op externe print (pin 4)
// const int LEDextern_2 = A3; // evt. extra LED op externe print (pin 5)
// const int externKnop_1 = A2; // evt. extra knop op externe print (pin 4)
// const int externKnop_1 = A3; // evt. extra knop op externe print (pin 5)
const long servoWacht = 500;
// - - - - - G l o b a l e V a r i a b e l e n :
//
Servo wisselServo1; // 2 objecten van het type Servo
Servo wisselServo2;
// - - - - - voor wissel 1
int relaisR1StateRecht = LOW; // de huidige staat van de output pin
int relaisG1StateGebogen = LOW; // *
int knopG_1State; // de huidige waarde van de input pin
int lastknopG_1State = LOW; // de vorige waarde van de input pin
int knopR_1State; // de huidige waarde van de input pin
int lastknopR_1State = LOW; // de vorige waarde van de input pin
int optoIn1State = HIGH; // de huidige waarde van de input pin
int lastoptoIn1State = HIGH; // de vorige waarde van de input pin
// - - - - - voor wissel 2
int relaisR2StateRecht = LOW; // de huidige waarde van de output pin
int relaisG2StateGebogen = LOW; // *
int knopG_2State; // de huidige waarde van de input pin
int lastknopG_2State = LOW; // de vorige waarde van de input pin
int knopR_2State; // de huidige waarde van de input pin
int lastknopR_2State = LOW; // de vorige waarde van de input pin
int optoIn2State = HIGH; // de huidige waarde van de input pin
int lastoptoIn2State = HIGH; // de vorige waarde van de input pin
// de volgende variabelen zijn 'long', omdat de tijd gemeten in milliseconden
// snel de max waarde van een 'int' zal overschrijden.
// - - - - - voor wissel 1
long lastDebounceTimeRecht_1 = 0; // het laatste tijdstip waarop de ingang is veranderd
long lastDebounceTimeGebogen_1 = 0; // *
long lastDebounceTimeoptoIn_1 = 0; // *
// - - - - - voor wissel 2
long lastDebounceTimeRecht_2 = 0; // het laatste tijdstip waarop de ingang is veranderd
long lastDebounceTimeGebogen_2 = 0; // *
long lastDebounceTimeoptoIn_2 = 0; // *
const long debounceDelay = 50; // de debounce tijd; hoger maken als de uitgang knippert
// - - - - - setup, 1 x doorlopen
//
void setup()
{
// - - - - - setup input en output
// - - - - - voor wissel 1
pinMode(knopG_1, INPUT_PULLUP);
pinMode(relaisR_1, OUTPUT);
pinMode(knopR_1, INPUT_PULLUP);
pinMode(relaisG_1, OUTPUT);
pinMode(optoIn_1, INPUT);
// - - - - - voor wissel 2
pinMode(knopG_2, INPUT_PULLUP);
pinMode(relaisR_2, OUTPUT);
pinMode(knopR_2, INPUT_PULLUP);
pinMode(relaisG_2, OUTPUT);
pinMode(optoIn_2, INPUT);
// - - - - - LED's
pinMode(LED, OUTPUT);
// - - - - - zet relais uit
// - - - - - voor wissel 1
digitalWrite(relaisR_1, relaisR2StateRecht);
digitalWrite(relaisG_1, relaisG2StateGebogen);
// - - - - - voor wissel 2
digitalWrite(relaisR_2, relaisR2StateRecht);
digitalWrite(relaisG_2, relaisG2StateGebogen);
// - - - - - testen van werking (moet later weg?)
digitalWrite(LED, HIGH);
}
// - - - - - eindeloos doorgaan
void loop()
{
// - - - - - lokale variabelen voor inlezen 'knoppen'
// - - - - - voor wissel 2
int readingKnopG2;
int readingKnopR2;
int readingOptoIn2;
int readingKnopG1;
int readingKnopR1;
int readingOptoIn1;
// - - - - - lees de knoppen in
readingKnopG2 = digitalRead(knopG_2);
readingKnopR2 = digitalRead(knopR_2);
readingOptoIn2 = digitalRead(optoIn_2);
readingKnopG1 = digitalRead(knopG_1);
readingKnopR1 = digitalRead(knopR_1);
readingOptoIn1 = digitalRead(optoIn_1);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (readingKnopG1 != lastknopG_1State)
{
lastDebounceTimeRecht_1 = millis(); // reset the debouncing timer
}
if (readingKnopR1 != lastknopR_1State)
{
lastDebounceTimeGebogen_1 = millis(); // reset the debouncing timer
}
if (readingOptoIn1 != lastoptoIn1State)
{
lastDebounceTimeoptoIn_1 = millis(); // reset the debouncing timer
}
if (readingKnopG2 != lastknopG_2State)
{
lastDebounceTimeRecht_2 = millis(); // reset the debouncing timer
}
if (readingKnopR2 != lastknopR_2State)
{
lastDebounceTimeGebogen_2 = millis(); // reset the debouncing timer
}
if (readingOptoIn2 != lastoptoIn2State)
{
lastDebounceTimeoptoIn_2 = millis(); // reset the debouncing timer
}
// - - - - - zet wissel 1 gebogen met knop
if ((millis() - lastDebounceTimeGebogen_1) > debounceDelay)
{
// whatever the readingKnopG2 is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (readingKnopG1 != knopG_1State)
{
knopG_1State = readingKnopG1;
if (knopG_1State == LOW)
{
wisselServo1.attach(servo_1,1000,2500); // zet servo aan
digitalWrite(relaisG_1, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_1, LOW); // relais valt af, hartstuk stroomloos
wisselServo1.write(1832); // zet servo om
delay(servoWacht); // wacht op omlopen wissel
digitalWrite(relaisR_1, HIGH); // andere relais op, hartstuk krijgt juiste spanning
//digitalWrite(LED, LOW); // LED gaat uit (kan na testen weg)
wisselServo1.detach(); // zet servo uit, o.a. jitter voorkomen
}
}
}
// - - - - - zet wissel 1 recht met knop
if ((millis() - lastDebounceTimeRecht_1) > debounceDelay)
{
// whatever the readingKnopR1 is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (readingKnopR1 != knopR_1State) {
knopR_1State = readingKnopR1;
// only toggle the LED if the new button state is HIGH
if (knopR_1State == LOW)
{
wisselServo1.attach(servo_1,1000,2500); // zet servo aan
digitalWrite(relaisR_1, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisG_1, LOW); // relais valt af, hartstuk stroomloos
wisselServo1.write(1260); // zet servo om
delay(servoWacht); // wacht op omlopen wissel
digitalWrite(relaisG_1, HIGH); // andere relais op, hartstuk krijgt juiste spanning
//digitalWrite(LED, HIGH); // LED gaat aan (kan na testen weg)
wisselServo1.detach(); // zet servo uit, o.a. jitter voorkomen
}
}
}
// - - - - - zet wissel 1 om met schakelaar
if ((millis() - lastDebounceTimeoptoIn_1) > debounceDelay)
{
// if the button state has changed:
if (readingOptoIn1 != optoIn1State)
{
optoIn1State = readingOptoIn1;
wisselServo1.attach(servo_1,1000,2500); // zet servo aan
// only toggle the LED if the new button state is HIGH
if (optoIn1State == LOW)
{
digitalWrite(relaisG_1, LOW); // zie commentaar bij
digitalWrite(relaisR_1, LOW); //
wisselServo1.write(1832); // zet wissel 1 gebogen met knop
delay(servoWacht);
digitalWrite(relaisR_1, HIGH);
digitalWrite(LED, HIGH);
}
else
{
digitalWrite(relaisR_1, LOW); // zie commentaar bij
digitalWrite(relaisG_1, LOW); //
wisselServo1.write(1260); // zet wissel 1 recht met knop
delay(servoWacht);
digitalWrite(relaisG_1, HIGH);
digitalWrite(LED, LOW);
}
wisselServo1.detach(); // zet servo uit
}
}
// - - - - - zet wissel 2 gebogen met knop
if ((millis() - lastDebounceTimeGebogen_2) > debounceDelay)
{
// whatever the readingKnopG2 is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (readingKnopG2 != knopG_2State)
{
knopG_2State = readingKnopG2;
// only toggle the LED if the new button state is HIGH
if (knopG_2State == LOW)
{
wisselServo2.attach(servo_2,1000,2500); // zie commentaar bij
digitalWrite(relaisG_2, LOW); // zet wissel 1 gebogen met knop
digitalWrite(relaisR_2, LOW);
wisselServo2.write(1161);
delay(servoWacht);
digitalWrite(relaisR_2, HIGH);
digitalWrite(LED, LOW);
wisselServo2.detach();
}
}
}
// - - - - - zet wissel 2 recht met knop
if ((millis() - lastDebounceTimeRecht_2) > debounceDelay)
{
// whatever the readingKnopR2 is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (readingKnopR2 != knopR_2State) {
knopR_2State = readingKnopR2;
if (knopR_2State == LOW)
{
wisselServo2.attach(servo_2,1000,2500); // zie commentaar bij
digitalWrite(relaisR_2, LOW); // zet wissel 1 gebogen met knop
digitalWrite(relaisG_2, LOW);
wisselServo2.write(1760);
delay(servoWacht);
digitalWrite(relaisG_2, HIGH);
digitalWrite(LED, HIGH);
wisselServo2.detach();
}
}
}
// - - - - - zet wissel 2 om met schakelaar
if ((millis() - lastDebounceTimeoptoIn_2) > debounceDelay)
{
// if the button state has changed:
if (readingOptoIn2 != optoIn2State)
{
optoIn2State = readingOptoIn2;
wisselServo1.attach(servo_2,1000,2500);
// only toggle the LED if the new button state is HIGH
if (optoIn2State == LOW)
{
digitalWrite(relaisG_2, LOW); // zie commentaar bij
digitalWrite(relaisR_2, LOW);
wisselServo1.write(1161); // zet wissel 1 recht met knop
delay(servoWacht);
digitalWrite(relaisR_2, HIGH);
digitalWrite(LED, HIGH);
}
else
{
digitalWrite(relaisR_2, LOW); // zie commentaar bij
digitalWrite(relaisG_2, LOW);
wisselServo1.write(1790); // zet wissel 1 gebogen met knop
delay(servoWacht);
digitalWrite(relaisG_2, HIGH);
digitalWrite(LED, LOW);
}
wisselServo1.detach();
}
}
// save the readings. Next time through the loop,
// it'll be the last_XXX_state:
lastknopG_1State = readingKnopG1;
lastknopR_1State = readingKnopR1;
lastoptoIn1State = readingOptoIn1;
lastknopG_2State = readingKnopG2;
lastknopR_2State = readingKnopR2;
lastoptoIn2State = readingOptoIn2;
}
Voor mijn eerste toepassing voldoende, echter alles (ook de servostanden) hard ingecodeerd. Zelfs gebruik gemaakt van "delay()" in de mainloop. Niet zo'n elegante oplossing. Verder mis je ook nog snelheid instellen. define NrRelais sizeof(relaisMap)
.
.
.
const byte relaisMap[] = {7, 8, 12, 11}; // Pins van de relais (2 per servo) CB
.
.
. in setup()
// Maak de pinnen voor de relais OUTPUT - CB
for(byte i = 0; i < NrRelais; i++)
{
pinMode(relaisMap[i], OUTPUT);
}
.
.
. in loop()
servoControl.gotoEndPos(i / 2, 0); //go to position A
digitalWrite(relaisMap[i / 2], LOW); // laat beide relais afvallen
digitalWrite(relaisMap[i / 2 + 1], LOW); // CB
numButtons += 1;
.
.
servoControl.gotoEndPos(i / 2, 1); //go to position B
digitalWrite(relaisMap[i / 2], LOW); // laat beide relais afvallen
digitalWrite(relaisMap[i / 2 + 1], LOW); // CB
numButtons += 1;
.
.
. aan het eind van loop()
// zet juiste relais weer aan
if (servoControl.isAtEndPos(0, 0)) {digitalWrite(relaisMap[0], HIGH);}
if (servoControl.isAtEndPos(0, 1)) {digitalWrite(relaisMap[1], HIGH);}
if (servoControl.isAtEndPos(1, 0)) {digitalWrite(relaisMap[2], HIGH);}
if (servoControl.isAtEndPos(1, 1)) {digitalWrite(relaisMap[3], HIGH);}
Hiermee een poosje gespeeld op mijn testplankje en daar ben ik bijna tevreden mee. De volgende wens is wisselaansturing door de 2 optocouplers naast de 4 drukknoppen. Dan kun je ook met een simpele schakelaar de wisselstand zetten. Daar ga ik binnenkort aan werken. Nog een vraag voor de modelspoorders:Bij voorontkoppelen: vóór het eerste verdelende wissel. Hierbij mag de koppeling niet meer vastklikken bij het verder duwen van het rangeerdeel. Als dat teveel problemen geeft, dan aan het begin van de opstelsporen.
Ik rijd N en wil gaan voorontkoppelen bij het uitrangeren op de Inglenook. Waar zouden jullie een ontkoppelvoorziening maken? Op ieder van de 3 opstelsporen aan het begin of slechts 1 voor het eerste verdelende wissel.
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
S e r v o W i s s e l S t e l l e r
Testprogramma voor het omzetten van twee modelspoorwissels m.b.v.
een modelbouw servo.
Te testen:
- 4 losse drukknoppen voor recht en afbuigend
- 2 optocoupler ingangen; funtioneel als schakelaar, bedoeld
voor besturing vanuit HCC!m-systeem of Dinamo OC32
- 1 van de optocouplers moet later ook DCC kunnen verwerken
Er wordt gebruik gemaakt van 2 servo's
Ten behoeve van hartstukpolarisatie zijn er per servo 2 relais
Werking per wissel:
- na een wisselcommando vallen eerst beide relais af
- daarna loopt het wissel om (servo)
- dan komt het juiste relais op
Bij opstarten gebeurt er niets. Het hartstuk van het wissel heeft
geen spanning en de servo staat in een ongedefinieerde stand.
De gebruikte Arduino is een Pro Mini, 5V met ATmega328.
Gebruikte libraries en voorbeelden:
- code uit het Debounce-voorbeeld bestand van Arduino.cc
http://www.arduino.cc/en/Tutorial/Debounce
- ServoExtend library van Timo Engelgeer
- ServoControl library van Timo Engelgeer
Created: 30-04-2015
By: Cees Baarda
Eerste opzet met gebruikmaking van de library Servo uit de Arduino-
omgeving.
Modified: 15-07-2015
By: Cees Baarda
Aangepast aan gebruik met de libraries van Timo Engelgeer
De servo's starten nu op in de middenstand, ongeacht de stand van schakelaars.
De relais blijven afgevallen tot het eerste wisselstel commando. Nadeel:
Je moet het wissel 2 keer stellen als je het wissel in de stand van de
schakelaar wilt hebben.
Je kunt de drukknoppen en schakelaars door elkaar gebruiken.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - L i b r a r i e s i n g e b r u i k :
#include <ServoExtend.h>
#include <ServoControl.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - C o n s t a n t e n :
// De pinnummers en vaste waarden een naam geven
// - - - - - voor wissel 1
const int optoIn_1 = 3; // voor externe aansturing met 0 of 1
const int servo_1 = 9;
const int servo1_endPosR = 10; // voorlopig hard coderen, later uit EEPROM
const int servo1_endPosG = 1002; // voorlopig hard coderen, later uit EEPROM
// - - - - - t.b.v puntstukpolarisatie
const int relaisR_1 = 7;
const int relaisG_1 = 8;
// - - - - - t.b.v. bediening met knoppen
const int knopR_1 = 6; // input; toets wissel recht leggen
const int knopG_1 = 5; // input; toets wissel gebogen leggen
// - - - - - voor wissel 2
const int optoIn_2 = 2; // voor externe aansturing met 0 of 1
const int servo_2 = 10; // output; Servo 2
const int servo2_endPosR = 10; // voorlopig hard coderen, later uit EEPROM
const int servo2_endPosG = 1002; // voorlopig hard coderen, later uit EEPROM
// - - - - - t.b.v puntstukpolarisatie
const int relaisR_2 = 11; // output; t.b.v. relais bij recht gelegd wisssel
const int relaisG_2 = 12; // output; t.b.v. relais bij gebogen gelegd wisssel
// - - - - - t.b.v. bediening met knoppen
const int knopR_2 = A2; // input; toets wissel recht leggen
const int knopG_2 = A0; // input; toets wissel gebogen leggen
// - - - - - beide wissels met DCC, nog niet in gebruik
// const int DCC_in = 2; // input; de DCC-railspanning gaat hier aan
const int servoSnelheid = 30;
const int servoStepInterval = 1;
const int LED = A1; // LED op de print
// - - - - - nog niet in gebruik, voor servo instelmodus
// encoder: common moet aan GND, andere aan pin 5 en 6
// const int pgmEncA = 6;
// const int pgmAncB = 5;
// const int pgmOK = A0; // kan losse knop of knop van de encoder zijn
// - - - - - nog niet in gebruik, zijn bedoeld voor extra print aan 8 polige
// connector
// const int LEDarduino = 13; // LED op de arduino
// const int LEDextern_1 = A2; // evt. extra LED op externe print (pin 4)
// const int LEDextern_2 = A3; // evt. extra LED op externe print (pin 5)
// const int externKnop_1 = A2; // evt. extra knop op externe print (pin 4)
// const int externKnop_1 = A3; // evt. extra knop op externe print (pin 5)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - G l o b a l e V a r i a b e l e n :
//
ServoControl wisselServos; // 1 object van het type ServoControl
// - - - - - voor wissel 1
int knopG_1State; // de huidige waarde van de input pin
int lastknopG_1State = LOW; // de vorige waarde van de input pin
int knopR_1State; // de huidige waarde van de input pin
int lastknopR_1State = LOW; // de vorige waarde van de input pin
// door de huidige PIN-waarde in te lezen wordt het wissel niet direct gesteld in een
// stand na opstarten
int optoIn1State = digitalRead(optoIn_1); // de huidige waarde van de input pin
int lastoptoIn1State = digitalRead(optoIn_1); // de vorige waarde van de input pin
// - - - - - voor wissel 2
int knopG_2State; // de huidige waarde van de input pin
int lastknopG_2State = LOW; // de vorige waarde van de input pin
int knopR_2State; // de huidige waarde van de input pin
int lastknopR_2State = LOW; // de vorige waarde van de input pin
// door de huidige PIN-waarde in te lezen wordt het wissel niet direct gesteld in een
// stand na opstarten
int optoIn2State = digitalRead(optoIn_2); // de huidige waarde van de input pin
int lastoptoIn2State = digitalRead(optoIn_2); // de vorige waarde van de input pin
// de volgende variabelen zijn 'long', omdat de tijd gemeten in milliseconden
// snel de max waarde van een 'int' zal overschrijden.
// - - - - - voor wissel 1
long lastDebounceTimeRecht_1 = 0; // het laatste tijdstip waarop de ingang is veranderd
long lastDebounceTimeGebogen_1 = 0; // *
long lastDebounceTimeoptoIn_1 = 0; // *
// - - - - - voor wissel 2
long lastDebounceTimeRecht_2 = 0; // het laatste tijdstip waarop de ingang is veranderd
long lastDebounceTimeGebogen_2 = 0; // *
long lastDebounceTimeoptoIn_2 = 0; // *
const long debounceDelay = 50; // de debounce tijd; hoger maken als de uitgang knippert
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - prototypes
//
void servoInstellen();
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - setup, 1 x doorlopen
//
void setup()
{
// - - - - - setup input en output
// - - - - - voor wissel 1
pinMode(knopG_1, INPUT_PULLUP);
pinMode(relaisR_1, OUTPUT);
pinMode(knopR_1, INPUT_PULLUP);
pinMode(relaisG_1, OUTPUT);
pinMode(optoIn_1, INPUT);
// - - - - - voor wissel 2
pinMode(knopG_2, INPUT_PULLUP);
pinMode(relaisR_2, OUTPUT);
pinMode(knopR_2, INPUT_PULLUP);
pinMode(relaisG_2, OUTPUT);
pinMode(optoIn_2, INPUT);
// - - - - - LED's
pinMode(LED, OUTPUT);
// - - - - - zet relais uit
// - - - - - voor wissel 1
digitalWrite(relaisR_1, LOW);
digitalWrite(relaisG_1, LOW);
// - - - - - voor wissel 2
digitalWrite(relaisR_2, LOW);
digitalWrite(relaisG_2, LOW);
// - - - - - initialiseer de servo's
// voor wissel 1
wisselServos.setEndPos(0, 0, servo1_endPosR);
wisselServos.setEndPos(0, 1, servo1_endPosG);
wisselServos.setSpeed(0, servoSnelheid, servoStepInterval);
wisselServos.init(0, servo_1);
// voor wissel 2
wisselServos.setEndPos(1, 0, servo2_endPosR);
wisselServos.setEndPos(1, 1, servo2_endPosG);
wisselServos.setSpeed(1, servoSnelheid, servoStepInterval);
wisselServos.init(1, servo_2);
// zet beide servo's in de middenstand
wisselServos.gotoPos(0,511);
wisselServos.gotoPos(1,511);
wisselServos.update();
// - - - - - testen van werking (moet later weg?)
// digitalWrite(LED, HIGH);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - eindeloos doorgaan
void loop()
{
// - - - - - lokale variabelen voor inlezen 'knoppen'
// - - - - - voor wissel 2
int readingKnopG2;
int readingKnopR2;
int readingOptoIn2;
// - - - - - voor wissel 1
int readingKnopG1;
int readingKnopR1;
int readingOptoIn1;
// - - - - - lees de knoppen in
readingKnopG2 = digitalRead(knopG_2);
readingKnopR2 = digitalRead(knopR_2);
readingOptoIn2 = digitalRead(optoIn_2);
readingKnopG1 = digitalRead(knopG_1);
readingKnopR1 = digitalRead(knopR_1);
readingOptoIn1 = digitalRead(optoIn_1);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (readingKnopG1 != lastknopG_1State)
{
lastDebounceTimeRecht_1 = millis(); // reset the debouncing timer
}
if (readingKnopR1 != lastknopR_1State)
{
lastDebounceTimeGebogen_1 = millis(); // reset the debouncing timer
}
if (readingOptoIn1 != lastoptoIn1State)
{
lastDebounceTimeoptoIn_1 = millis(); // reset the debouncing timer
}
if (readingKnopG2 != lastknopG_2State)
{
lastDebounceTimeRecht_2 = millis(); // reset the debouncing timer
}
if (readingKnopR2 != lastknopR_2State)
{
lastDebounceTimeGebogen_2 = millis(); // reset the debouncing timer
}
if (readingOptoIn2 != lastoptoIn2State)
{
lastDebounceTimeoptoIn_2 = millis(); // reset the debouncing timer
}
// - - - - - zet wissel 1 gebogen met knop
if ((millis() - lastDebounceTimeGebogen_1) > debounceDelay)
{
// if the button state has changed:
if (readingKnopG1 != knopG_1State)
{
knopG_1State = readingKnopG1;
if (knopG_1State == LOW)
{
digitalWrite(relaisG_1, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_1, LOW); // relais valt af, hartstuk stroomloos
wisselServos.gotoEndPos(0,0); // zet servo om
}
}
}
// - - - - - zet wissel 1 recht met knop
if ((millis() - lastDebounceTimeRecht_1) > debounceDelay)
{
// if the button state has changed:
if (readingKnopR1 != knopR_1State) {
knopR_1State = readingKnopR1;
// only toggle the LED if the new button state is HIGH
if (knopR_1State == LOW)
{
digitalWrite(relaisG_1, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_1, LOW); // relais valt af, hartstuk stroomloos
wisselServos.gotoEndPos(0,1); // zet servo om
}
}
}
/* - - - - - zet wissel 1 om met schakelaar--*/
if ((millis() - lastDebounceTimeoptoIn_1) > debounceDelay)
{
// if the button state has changed:
if (readingOptoIn1 != optoIn1State)
{
optoIn1State = readingOptoIn1;
// - - - - - Eerst het hartstuk stroomloos maken
digitalWrite(relaisG_1, LOW); // relais valt af
digitalWrite(relaisR_1, LOW); // relais valt af
// - - - - - stuur servo alleen aan als die nog naar een nieuwe eindpositie moet
if (optoIn1State == LOW)
{
if (!wisselServos.isAtEndPos(0,1)) wisselServos.gotoEndPos(0,1);
}
else
{
if (!wisselServos.isAtEndPos(0,0)) wisselServos.gotoEndPos(0,0);
}
}
}
// - - - - - zet wissel 2 gebogen met knop
if ((millis() - lastDebounceTimeGebogen_2) > debounceDelay)
{
// if the button state has changed:
if (readingKnopG2 != knopG_2State)
{
knopG_2State = readingKnopG2;
// only toggle the LED if the new button state is HIGH
if (knopG_2State == LOW)
{
digitalWrite(relaisG_2, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_2, LOW); // relais valt af, hartstuk stroomloos
wisselServos.gotoEndPos(1,0); // zet servo om
}
}
}
// - - - - - zet wissel 2 recht met knop
if ((millis() - lastDebounceTimeRecht_2) > debounceDelay)
{
// whatever the readingKnopR2 is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (readingKnopR2 != knopR_2State) {
knopR_2State = readingKnopR2;
if (knopR_2State == LOW)
{
digitalWrite(relaisG_2, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_2, LOW); // relais valt af, hartstuk stroomloos
wisselServos.gotoEndPos(1,1); // zet servo om
}
}
}
/* - - - - - zet wissel 2 om met schakelaar*/
if ((millis() - lastDebounceTimeoptoIn_2) > debounceDelay)
{
// if the button state has changed:
if (readingOptoIn2 != optoIn2State)
{
optoIn2State = readingOptoIn2;
digitalWrite(relaisG_2, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_2, LOW); // relais valt af, hartstuk stroomloos
// only toggle the LED if the new button state is HIGH
if (optoIn2State == LOW)
{
if (!wisselServos.isAtEndPos(1,1)) wisselServos.gotoEndPos(1,1); // zet servo om
}
else
{
if (!wisselServos.isAtEndPos(1,0)) wisselServos.gotoEndPos(1,0); // zet servo om
}
}
}
wisselServos.update();
// zet juiste relais weer aan
if (!wisselServos.isMoving(0)) // zorg eerst dat het servo stil staat, dan relais aan
{
if (wisselServos.isAtEndPos(0, 0)) {digitalWrite(relaisR_1, HIGH);}
if (wisselServos.isAtEndPos(0, 1)) {digitalWrite(relaisG_1, HIGH);}
}
if (!wisselServos.isMoving(1)) // zorg eerst dat het servo stil staat, dan relais aan
{
if (wisselServos.isAtEndPos(1, 0)) {digitalWrite(relaisR_2, HIGH);}
if (wisselServos.isAtEndPos(1, 1)) {digitalWrite(relaisG_2, HIGH);}
}
// save the readings. Next time through the loop,
// it'll be the last_XXX_state:
lastknopG_1State = readingKnopG1;
lastknopR_1State = readingKnopR1;
lastoptoIn1State = readingOptoIn1;
lastknopG_2State = readingKnopG2;
lastknopR_2State = readingKnopR2;
lastoptoIn2State = readingOptoIn2;
}
Een update:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - Servo instelmodus
void servoInstellen()
{
}
Verder gebruik ik principieel waar mogelijk Nederlandse benamingen voor variabelen en dergelijke, om te voorkomen dat ik een "keyword" van IDE of library gebruik.Zoveel keyword heeft de IDE niet hoor ;) En die van een library gebruiken is ook niet zo erg omdat het vaak dan toch om een object gaat. Niet dat Nederlandse variabele niet mogen maar de reden ervoor (afgezien van dat Nederlands de moedertaal is) zijn niet echt geldig.
Debounce van de knoppen gaat zonder library.Het lijkt bijna wel of je dit met trots zegt ::) ;D Maar waarom niet gewoon een library pakken? Deze zijn juist bedacht om jou veel werk uit handen te namen en bijvoorbeeld de Bounce2 library zou je code een heeeeeeel stuk makkelijker maken. Een stuk als
// - - - - - zet wissel 1 gebogen met knop
if ((millis() - lastDebounceTimeGebogen_1) > debounceDelay)
{
// if the button state has changed:
if (readingKnopG1 != knopG_1State)
{
knopG_1State = readingKnopG1;
if (knopG_1State == LOW)
{
digitalWrite(relaisG_1, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_1, LOW); // relais valt af, hartstuk stroomloos
wisselServos.gotoEndPos(0,0); // zet servo om
}
}
}
Is dan te herschrijven tot:knopGebogen1.update();
if(knopGebogen1.fell()){
digitalWrite(relaisG_1, LOW); // relais valt af, hartstuk stroomloos
digitalWrite(relaisR_1, LOW); // relais valt af, hartstuk stroomloos
wisselServos.gotoEndPos(0,0); // zet servo om
}
Ik zie alleen ook hier weer veel "dubbel werk" omdat je bijvoorbeeld alles voor wissel 1 en wissel 2 los uit schrijft.helemaal gelijk, echter ik ben niet voornemens om de firmware uit te breiden voor meer dan die 2 wissels. En dan heb ik de keus 1 x kopiëren en plakken met wat wijzigingen of extra code toevoegen.
Citaat van: Cees Baarda op 24 augustus 2015, 12:21:37Ik heb het geschreven als constatering en om aan te geven, dat er hiervoor geen library hoeft te worden bijgevoegd. Ik heb denk ik wel bewezen libraries te gebruiken. Zeker als het gaat om het uitvinden van een wiel, zoals met je eigen libraries, zal ik er dankbaar gebruik van maken. Ik ben overigens nog niet zo ver dat ik me wil wagen aan array's om e.e.a. te vereenvoudigen. Mijn ervaring is dat dan je eigen code cryptischer wordt, waardoor zeker ik de weg dreig kwijt te raken. Ik verwacht op een later moment je tips ter harte te nemen en alsnog de code anders op te bouwen. Plezierig gevolg wordt dan natuurlijk de vereenvoudiging richting meer te bedienen wissels.
Debounce van de knoppen gaat zonder library.
Het lijkt bijna wel of je dit met trots zegt
if(this->servoInfo[i].relaisAvailable)
{
//laat relais afvallen
}
//time to detach
else if(this->servoInfo[i].speed.intervalCount == 1)
{
this->servoInfo[i].speed.intervalCount--;
this->servoList[i].detach();
if(this->servoInfo.relaisAvailable)
{
// laat het juiste relais opkomen
}
}
En dan heb ik de keus 1 x kopiëren en plakken met wat wijzigingen of extra code toevoegen.3x, want eigenlijk doe je voor zowel rechtdoor als afbuigen al hetzelfde. En dan is het echt al de moeite waard om het anders te doen.
Ik heb het geschreven als constatering en om aan te geven, dat er hiervoor geen library hoeft te worden bijgevoegd. Ik heb denk ik wel bewezen libraries te gebruiken.Dat heb je zeker! Maar doelde er meer op de de Bounce library zo makkelijk en simpel is dat ik eigenlijk vind dat hij een standaard Arduino library zou moeten zijn. Gebruik ervan maakt de code ook zoveel leesbaarder.
Ik ben overigens nog niet zo ver dat ik me wil wagen aan array's om e.e.a. te vereenvoudigen. Mijn ervaring is dat dan je eigen code cryptischer wordt, waardoor zeker ik de weg dreig kwijt te raken.Nouwja, cryptischer. Ipv een hele rij variabele zoals knop1, knop2, knop 3 te definiëren doe je gewoon knop[3] en gebruik je het als knop[0], knop[1] en knop[2]. Lastiger is het eigenlijk niet...
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
S e r v o W i s s e l S t e l l e r
Testprogramma voor het omzetten van twee modelspoorwissels m.b.v.
een modelbouw servo.
Te testen:
- 4 losse drukknoppen voor recht en afbuigend
- 2 optocoupler ingangen; funtioneel als schakelaar, bedoeld
voor besturing vanuit HCC!m-systeem of Dinamo OC32
- 1 van de optocouplers moet later ook DCC kunnen verwerken
Er wordt gebruik gemaakt van 2 servo's
Ten behoeve van hartstukpolarisatie zijn er per servo 2 relais
Werking per wissel:
- na een wisselcommando vallen eerst beide relais af
- daarna loopt het wissel om (servo)
- dan komt het juiste relais op
Bij opstarten gebeurt er niets. Het hartstuk van het wissel heeft
geen spanning en de servo staat in een ongedefinieerde stand.
De gebruikte Arduino is een Pro Mini, 5V met ATmega328.
Gebruikte libraries en voorbeelden:
- code uit het Debounce-voorbeeld bestand van Arduino.cc
http://www.arduino.cc/en/Tutorial/Debounce
- ServoExtend library van Timo Engelgeer
- ServoControl library van Timo Engelgeer
Created: 30-04-2015
By: Cees Baarda
Eerste opzet met gebruikmaking van de library Servo uit de Arduino-
omgeving.
Modified: 15-07-2015
By: Cees Baarda
Aangepast aan gebruik met de libraries van Timo Engelgeer
De servo's starten nu op in de middenstand, ongeacht de stand van schakelaars.
De relais blijven afgevallen tot het eerste wisselstel commando. Nadeel:
Je moet het wissel 2 keer stellen als je het wissel in de stand van de
schakelaar wilt hebben.
Je kunt de drukknoppen en schakelaars door elkaar gebruiken.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - L i b r a r i e s i n g e b r u i k :
#include <ServoExtend.h>
#include <ServoControl.h>
#include <Bounce2.h>
//#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#define R 0
#define G 1
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - C o n s t a n t e n :
// De pinnummers en vaste waarden een naam geven
#define AANTAL_POS 2 //Aantal posities per wissel
// - - - - - voor wissels
const byte OptoPin[] = {3, 2}; //Pin van de opto's in
const byte ServoPin[] = {9, 10};//Pin van de servo's
//eindposities sevo's {R, G} (ServoEndPos[wiselnummer][R of G])
const byte ServoEndPos[][AANTAL_POS] = {{10, 1002}, //wissel 1
{10, 1002}};//wissel 2
// output; t.b.v. relais bij recht gelegd wisssel {R, G} (RelaisPin[wiselnummer][R of G])
const byte RelaisPin[][AANTAL_POS] = {{7, 8}, //wissel 1
{11, 12}}; //wissel 2
// inputs t.b.v. bediening met knoppen {R, G} (KnopPin[wiselnummer][R of G])
const byte KnopPin[][AANTAL_POS] = {{6, 5},
{A2, A0}};
#define AANTAL_SERVOS sizeof(ServoPin)
#define AantalOptos sizeof(OptoPin)
// - - - - - beide wissels met DCC, nog niet in gebruik
// const int DCC_in = 2; // input; de DCC-railspanning gaat hier aan
const int ServoSnelheid = 30;
const int ServoStepInterval = 1;
const int LedPin = A1; // LED op de print
// - - - - - nog niet in gebruik, voor servo instelmodus
// encoder: common moet aan GND, andere aan pin 5 en 6
// const int pgmEncA = 6;
// const int pgmAncB = 5;
// const int pgmOK = A0; // kan losse knop of knop van de encoder zijn
// - - - - - nog niet in gebruik, zijn bedoeld voor extra print aan 8 polige
// connector
// const int LEDarduino = 13; // LED op de arduino
// const int LEDextern_1 = A2; // evt. extra LED op externe print (pin 4)
// const int LEDextern_2 = A3; // evt. extra LED op externe print (pin 5)
// const int externKnop_1 = A2; // evt. extra knop op externe print (pin 4)
// const int externKnop_1 = A3; // evt. extra knop op externe print (pin 5)
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - G l o b a l e V a r i a b e l e n :
//
ServoControl wisselServos; // 1 object van het type ServoControl
// - - - - - Inputs
Bounce knop[AANTAL_SERVOS][2]; //Voor alle knoppen (knop[wisselnummer][R of G])
Bounce opto[AantalOptos]; //Voor alle opto's (opto[wisselnummer])
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - prototypes
//
void servoInstellen();
void stelWissel(byte, byte);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - setup, 1 x doorlopen
//
void setup()
{
//Doe alles voor elke servo
for(byte servoNr = 0; servoNr < AANTAL_SERVOS; servoNr++){ //Ga alle wissels langs
//Setup voor alle knoppen
for(byte posNr = 0; posNr < AANTAL_POS; posNr++){ //Ga R en G langs
pinMode(KnopPin[servoNr][posNr], INPUT_PULLUP); //Zet alle knoppen als input met pullup
knop[servoNr][posNr].attach(KnopPin[servoNr][posNr]); //Koppel aan Bounce object
}
//Setup alle opto's
pinMode(OptoPin[servoNr], INPUT_PULLUP); //Zet alle opto's als input met pullup
opto[servoNr].attach(OptoPin[servoNr]); //Koppel aan Bounce object
//Setup voor alle relais
for(byte posNr = 0; posNr < AANTAL_POS; posNr++){
pinMode(RelaisPin[servoNr][posNr], OUTPUT);
digitalWrite(RelaisPin[servoNr][posNr], LOW);
}
//Setup voor alle servo's
for(byte posNr = 0; posNr < AANTAL_POS; posNr++){
wisselServos.setEndPos(servoNr, posNr, ServoEndPos[servoNr][posNr]); //Stel beide/alle eindposities in
}
wisselServos.setSpeed(servoNr, ServoSnelheid, ServoStepInterval); //stel snelheid in
wisselServos.init(servoNr, ServoPin[servoNr]); //Koppel aan pin enzo
wisselServos.gotoPos(servoNr, 511); //Ga naar middenstand
}
wisselServos.update();
// - - - - - testen van werking (moet later weg?)
// digitalWrite(LedPin, HIGH);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - eindeloos doorgaan
void loop()
{
//loop alle wissels langs
for(byte servoNr = 0; servoNr < AANTAL_SERVOS; servoNr++){
//----De knoppen
//Loop posities langs
for(byte posNr = 0; posNr < AANTAL_POS; posNr++){
knop[servoNr][posNr].update(); //Update de knop
if(knop[servoNr][posNr].fell()){ //Knop is ingedrukt (gevallen) sidns vorige keer
stelWissel(servoNr, posNr); //Zet wissel in bijbehorende stand
}
}
//----De opto's
opto[servoNr].update(); //update de opto
if(opto[servoNr].rose()){
stelWissel(servoNr, R); //R-positie als hoog geworden
}
else if(opto[servoNr].fell()){ //G-positie als laag geworden
stelWissel(servoNr, G);
}
//----De relais
//Klaar met bewegen
if(!wisselServos.isMoving(servoNr)){
//Vind de eindstand waar hij is
for(byte posNr = 0; posNr < AANTAL_POS; posNr++){
if(wisselServos.isAtEndPos(servoNr, posNr)){
//En zet juiste relais aan
digitalWrite(RelaisPin[servoNr][posNr], HIGH);
}
}
}
}
wisselServos.update(); //update alle servo's
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// - - - - - Servo instelmodus
void servoInstellen()
{
}
void stelWissel(byte wisselNr, byte pos){
//laat relais afvallen
for(byte j = 0; j < AANTAL_POS; j++){
digitalWrite(RelaisPin[wisselNr][j], LOW); // relais valt af, hartstuk stroomloos
}
wisselServos.gotoEndPos(wisselNr, pos); // zet servo om
}
void loop()
{
// - - - - - zet wissel 1 en 2 om met knoppen
for (byte i = 0; i < NrButtons; i++)
{
buttons[i].update();
if (buttons[i].fell())
{
wisselServos.gotoEndPos(i / 2,i % 2); // zet servo om
}
}
// - - - - - zet wissel 1 en 2 om met schakelaars
for (byte j = 0; j < NrSwitches; j++)
{
switches[j].update();
{
if (switches[j].fell()) {wisselServos.gotoEndPos(j,0);}
if (switches[j].rose()) wisselServos.gotoEndPos(j,1);
}
}
wisselServos.update();
}
Enige wat ik alleen nog denk als ik de print nu zie:Dat had ik al op een eerdere versie uitgeprobeerd (zie afb.). De rotary's, die ik besteld heb, zouden ruim moeten passen.
- De rotary lijkt me nogal dicht op de Arduino te zitten. Misschien kan deze meer naar de buitenkant?
- Weet niet wat je wilt instellen met de potmeter, maar als je het vaak wilt aanpassen is misschien versie met as makkelijk?Die is een beetje extra. Voor het testen is deze goed. Ik heb altijd wel een trimschroevendraaier klaar liggen. Als ik er een met een knop zou inzetten, kies ik waarschijnlijk voor een paneelpotmeter. Die moet dan toch met draadjes aangesloten worden.
- Misschien dc jack naar links laten uitkomen zodat het niet in de weg zit met eventuele heat link?Ik had in eerste instantie de jack naar links wijzen. Later bedacht ik toch de DC_DC convertors te gaan gebruiken. Er zijn een aantal van een groter model (http://nl.aliexpress.com/item/1pcs-LM2596-LM2596S-DC-DC-3-40V-adjustable-step-down-power-Supply-module-NEW-High-Quality/1116954291.html) onderweg.
- Ik denk dat ik 78xx zie? Je zou kunnen overwegen deze te vervangen door DC-DC converters. Maar goed, met kleine modules zoals deze past het zelfs met dezelfde voetprint ;D
De rotary's, die ik besteld heb, zouden ruim moeten passen.Dat ze passen had ik ook niet anders verwacht ;D Maar dat rotary aan de buitenkant iets toegankelijker zit.
- Ik zou voor de LM311, de potmeter en Vcc out (bij de I2C) de Vcc van de Arduino gebruiken. Op die manier is de 7805/5V DC-DC alleen voor de servo en hou je alle storing gevoelige dingen op een nette losse voeding.Kan ik het mee eens zijn, echter aan de i2c aansluiting komt mogelijk een LCD-display te hangen. Die lijkt me wat veel stroom trekken voor de 100 mA die de regulator op de APM kan leveren. En als je meer slaves er aan hangt, zonder eigen voeding en dat gaat vast gebeuren tijdens het testen, is dat ook niet zo bevorderlijk voor die regelaar.
- De ledjes zou je kunnen voeden vanaf de 5V, scheelt vermogenIk heb die samen met de relais op 12v gezet om de 5 V te ontzien. Zeker als je 2 regelaars achter elkaar zet leek me dat handiger. Voorts met de DC-DC-converters zullen ze beide apart uit de ingang gevoed gaan worden. Overigens: het scheelt geen vermogen, het wordt alleen op een andere plek verstookt.
De rotary's hebben een vrij lange as en naar de rand brengen vond ik te lastig.Als je er zo mee kunt werken dan (y) Was maar iets wat in mijn hoofd op kwam.
Kan ik het mee eens zijn, echter aan de i2c aansluiting komt mogelijk een LCD-display te hangen. Die lijkt me wat veel stroom trekken voor de 100 mA die de regulator op de APM kan leveren.Als je inderdaad denkt dat het zal voorkomen dan inderdaad aan losse regulator hangen. Maar het blijft staan voor de LM311 en de potmeter. Hou je de noise van de servo lekker weg bij de analoge readings.
R16 blijft, omdat ik de drukknop nog wil verhuizen naar een andere pin (RXI). De reset is door de opzet van deze print goed bereikbaar op de APM.Deze snap ik even niet. Reset is toch reset? Wat heeft dat te doen met de RXI/pin1?
R2 blijft onder het motto "baat het niet, het schaadt ook niet.Dat is wel een beetje een kul reden... ;) Als je helemaal niets meer aan de print gaat doen snap ik het. Dan kan je hem met solderen gewoon weg laten. Maar als je toch nog gaat aanpassen kan je nutteloze componenten best weglaten toch?
D3 en D4 blijven, want dicht bij de relais en dus geen tegen EMK door een dun spoortje naar de ULN. Hier ben ik in het verleden wel eens tegen aan gelopen.Okay, prima reden.
Ik heb die samen met de relais op 12v gezet om de 5 V te ontzien. Zeker als je 2 regelaars achter elkaar zet leek me dat handiger. Voorts met de DC-DC-converters zullen ze beide apart uit de ingang gevoed gaan worden. Overigens: het scheelt geen vermogen, het wordt alleen op een andere plek verstookt.Ik ging hierbij uit van DCDC, dan scheelt het wel vermogen. Lineair is het inderdaad om het even. ;D
Deze snap ik even niet. Reset is toch reset? Wat heeft dat te doen met de RXI/pin1?Daar was mijn tekst duidelijk te kort. Ik miste nog een extra toets om in program-modus te kunnen gaan. Dat is die druktoets inmiddels geworden. R16 kan dan ook wel weg. Wat je verderop zegt over de resettoets is helemaal waar.
Als je inderdaad denkt dat het zal voorkomen dan inderdaad aan losse regulator hangen. Maar het blijft staan voor de LM311 en de potmeter. Hou je de noise van de servo lekker weg bij de analoge readings.Daar heb je een punt, moet ik nog maar even over nadenken (y). Zou ik weleens kunnen gaan aanpassen.
ik ben niet snel over de rooie te krijgen :D.Gelukkig! ;D Maar zet het er meestal toch even bij op het forum. Voor je het weet vatten mensen het anders negatief op terwijl ik alleen mijn gedachten over de print heb laten gaan.
Daar was mijn tekst duidelijk te kort. Ik miste nog een extra toets om in program-modus te kunnen gaan. Dat is die druktoets inmiddels geworden. R16 kan dan ook wel weg. Wat je verderop zegt over de resettoets is helemaal waar.Ahhhh, dat verklaard! (y)
Daar heb je een punt, moet ik nog maar even over nadenken (y). Zou ik weleens kunnen gaan aanpassen.Zou anders zonde zijn als je readings schommelen door de servo.
Over R2 hebben we al eens eerder gediscussieerd. Ik heb intussen gevonden waar ik die "wijsheid" vandaan heb. Hans Kufer [knip] Je zou dan zelfs de datastroom naar de micro kunnen stopzetten, door Enable laag te trekken. Of je in deze toepassing daar wat aan hebt??Ah, dat was ik al weer vergeten. ::) Maar hard aan Vcc of via een pull up kan inderdaad geen kwaad. Maar volgens de truth tabel en het test circuit van de datasheet mag deze dus weggelaten worden. Was dus vooral bedoelt als opmerking dat je dus een onderdeel kon besparen. Niet dat een weerstand veel kost, meer voor de ruimte en ontwerp/montage tijd.
Er stond nog wel een aardige tip: als je D1 vervangt door een LED heb je wat indicatie van de DCC activiteit.Dat kan inderdaad makkelijk. (y) Maar bedenk wel dat het best een fel ledje kan worden ;D Op een DCC signaal van 20V heb je namelijk +-12mA door het ledje, aardige schijnwerper bij moderne ledjes (waar 1mA al prima is voor een indicatie led).
De maximale (beginwaarde van de) stroom door de flyback diode is net zo groot als de voorwaartse stroom. De maximale inverse spanning is de spoelspanning die over het relais staat op het ogenblik dat het relais afvalt.
Ook al moet ik wel zeggen dat ik er nooit tegenaan gelopen ben. Zeker omdat het vermogen van de tegen EMK stukken lager is dan normale relais stroom. En de stroom is miniem vergeleken met de normale stroom. Het probleem zit hem alleen in het voltage.
Timo
DCC_out_inv gaat nergens heen. Was meer een geheugensteun. De library CmdrArduino gebruikt die pin om een geïnverteerd DCC-signaal op te zetten. Dat gebruik ik niet, maar de pin wordt natuurlijk wel aangestuurd.Ah, kijk. Maar als je niet wil dat dit signaal naar buiten komt kan je dit natuurlijk aanpassen. Misschien is het inderdaad niet zo makkelijk in de library zelf (of moet je die echt aanpassen) maar een mooie manier van valsspelen is pin A7 opgeven. Als eerste heb je deze niet en als tweede is deze puur analoog. Elke poging tot digitaal aansturen gaat gewoon verloren zonder error ;D
Die header voor de 2803 is bedoeld voor input aan de APM. Het zijn alle digitale poorten.Ah, kijk. Je zou eventueel ook nog een header op de uitgang kunnen doen, ben je helemaal multifunctioneel. Iig makkelijker dan een losse 2 pin header per led.
#include <DCCPacket.h>
#include <DCCPacketQueue.h>
#include <DCCPacketScheduler.h>
#include <Bounce2.h>
#include <EEPROM.h>
Bijna bovenaan kun je van 4 loks korte adressen invoeren./* * * * * *
* 4 lok-adressen invoeren. Deze zijn te kiezen m.b.v. een bcd-schakelaar of 2 jumpers.
* De adressen mogen alleen korte adressen zijn (1..127)
*/
const byte lok1 = 99;
const byte lok2 = 3;
const byte lok3 = 3;
const byte lok4 = 25;
/* Einde lokadressen invoeren */
byte lok[] = {lok4, lok3, lok2, lok1};
byte lokAdres;
byte lokIndex;
Rest van variabelen aanmaken.DCCPacketScheduler dps;
char speed_byte, old_speed = 0, snelheid = 1;
byte prev_state = 0;
byte F0 = 0;
/* * * * * *
* Drukknoppen voor de besturing;
* DK_xxx = de gebruikte Arduino pin */
const byte DK_Vooruit = 3; // Drukknop vooruit
const byte DK_Achteruit = 4; // Drukknop achteruit
const byte DK_Stop = 5; // Drukknop stop
const byte Knoppenlijst[] = {DK_Vooruit, DK_Achteruit, DK_Stop};
// * Geef de posities in het array een naam
const byte Vooruit = 0;
const byte Achteruit = 1;
const byte Stop = 2;
#define Aantal_Knoppen sizeof(Knoppenlijst)
// * * * * Einde Drukknoppen voor de besturing
const byte Speed_Potm = A0; // Instelling max. snelheid
Bounce Knoppen[Aantal_Knoppen] = Bounce();
const byte Arduino_LED = 13;
void setup()
{
Serial.begin(115200); // voor debug, we gebruiken Pinnen 0 en 1 niet voor iets anders
dps.setup(); //start de DCC packet schedular
pinMode(Arduino_LED, OUTPUT);
digitalWrite(Arduino_LED, LOW);
/* * * * * * *
* setup knoppen voor debounce
*/
for (byte i = 0; i < Aantal_Knoppen; i++) Knoppen[i].attach(Knoppenlijst[i], INPUT_PULLUP);
// * * * * Einde setup knoppen
Er zijn 2 input pins, die bepalen met welk lokadres gereden gaat worden. /* * * * * * *
* Kies huidige locomotief
* Aan de pinnen A1 en A2 komen voor dit programma 2 jumpers naar massa.
* Zonder jumpers krijgt lokIndex de waarde 3. De jumpers verlagen de waarde met resp. 1 en 2.
* Dus beide jumpers geplaatst geeft lokIndex de waarde 3 - 1 - 2 = 0.
*
* Als het programma eenmaal loopt kun je niet meer van DCC-adres wisselen.
* Hiermee voorkom je eventuele 'missers' op bijv. een tentoonstelling.
*/
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
lokIndex = digitalRead(A1); // index wordt 0 of 1
lokIndex = lokIndex + 2 * digitalRead(A2); // index krijgt er 0 of 2 bij
lokAdres = lok[lokIndex];
// * * * * Einde kies locomotief
Ik heb er voor gekozen alleen bij het opstarten in programmeermodus te gaan.
if (digitalRead(DK_Vooruit) == 0) // werd de knop ingedrukt gehouden
{
stel_snelheid_in(); // stel dan de max. snelheid in
}
speed_byte = EEPROM.read(lokIndex);
snelheid = 1;
Serial.println(speed_byte, DEC);
// if (speed_byte == 0 or speed_byte > 127) stel_snelheid_in();
}
void loop()
{
/* * * * * * *
* Knoppen afhandelen
* Als 1 van de knoppen gedrukt wordt, gaat de trein rijden met de ingestelde snelheid of
* wordt er gestopt.
* Er zijn 3 knoppen: Vooruit - Stop - Achteruit */
for (byte i = 0; i < Aantal_Knoppen; i++)
{
Knoppen[i].update();
}
if (Knoppen[Stop].fell())
{
if (snelheid > 0) snelheid = 1;
if (snelheid < 0) snelheid = -1;
}
if (Knoppen[Vooruit].fell())
{
if (snelheid < -1) snelheid = -1; else snelheid = speed_byte;
}
if (Knoppen[Achteruit].fell())
{
if (snelheid > 1) snelheid = 1; else snelheid = -speed_byte;
}
/* Einde knoppen afhandelen */
Serial.print("Ingestelde snelheid: "); // debug
Serial.println(snelheid, DEC); // debug
dps.setSpeed128(lokAdres,DCC_SHORT_ADDRESS,snelheid); // zet de gekozen snelhied klaar
dps.update(); // en voer uit naar DCC-booster
}
void stel_snelheid_in()
{
Knoppen[Stop].update();
while (!Knoppen[Stop].fell())
{
digitalWrite(Arduino_LED, HIGH);
int analoge_waarde = analogRead(0);
speed_byte = (analoge_waarde >> 2)-127 ; // deel door vier en breng naar -126 tot 126 reeks
if(speed_byte == 0)
{
if(old_speed > 0) speed_byte = 1;
else speed_byte = -1;
}
old_speed = speed_byte;
dps.setSpeed128(lokAdres,DCC_SHORT_ADDRESS,speed_byte);
dps.update();
Knoppen[Stop].update();
}
if (speed_byte < 0) speed_byte = -speed_byte;
EEPROM.write(lokIndex, speed_byte);
delay(500); // wacht tot zeker is dat EEPROM beschreven werd
digitalWrite(Arduino_LED, LOW);
}
if (snelheid < -1) snelheid = -1; else snelheid = speed_byte;
Van die regel gaan mijn rugharen een beetje overeind staan ;D Voor de leesbaarheid, regels eindigen na de ;. Omdat het een simpel statement is zou je er wel een one line'er van kunnen maken maar dan als:(snelheid < -1 ? snelheid = -1: snelheid = speed_byte);
Maar meestal gaat mijn voorkeur toch gewoon uit naar voluit omdat het vaak duidelijker is en makkelijker uit te breiden.if (snelheid < -1)
snelheid = 1;
else
snelheid = speed_byte;
Dus als hij achteruit rijdt en je druk op vooruit wel de richting omdraaien maar niet rijden. const byte lok1 = 99;
const byte lok2 = 3;
const byte lok3 = 3;
const byte lok4 = 25;
/* Einde lokadressen invoeren */
byte lok[] = {lok4, lok3, lok2, lok1};
Waarom niet gelijk de array vullen? Dan heb je geen overhead aan variabele en bespaar je jezelf typewerk. Nu ben je gewoon werk dubbel aan het doen, altijd zonde ;D pinMode(locAdresPinnen[0], INPUT_PULLUP);
pinMode(locAdresPinnen[1], INPUT_PULLUP);
byte lokIndex = digitalRead(locAdresPinnen[0]); // index wordt 0 of 1
lokIndex += 2 * digitalRead(locAdresPinnen[1]); // index krijgt er 0 of 2 bij
lokAdres = lok[lokIndex];
Gelijk ze een naam gegeven, naamloos is nooit echt duidelijk ;) Of meer schaalbaar (mocht je uit willen breiden):byte locIndex = 0;
for(byte i = 0; i < sizeof(locAdresPinnen); i++){
locIndex <<= 1;
pinMode(locAdresPinnen[i], INPUT_PULLUP);
locIndex |= !!digitalRead(locAdresPinnen[i]);
}
Edit Ik zie dat je de index gebruikt voor eeprom. Ik zou dan alleen de index opslaan en adres weg doen en dan adres altijd ophalen uit de lijst. Zo heb je niet twee variabele die eigenlijk beide naar het adres moeten wijzen maar per ongeluk toch verschillend zouden kunnen zijn.char speed_byte, old_speed = 0, snelheid = 1;
Zoals je zelf ook gemerkt hebt is char niet echt het handigste type om hier te gebruiken. Dit omdat char door veel functies afgehandeld wordt als een ASCII karakter. Ik zou het vervangen door int8_t. Is ook gewoon signed 8-bit maar wordt niet gelijk gezien als karakter.void stel_snelheid_in()
{
Paar opmerkingen over die functie. if(speed_byte == 0){
speed_byte = 1; //richting maakt niet uit, 0 wil je toch niet en nu heb je één extra stapje voor "0 vooruit"
}
Ook heeft old_speed geen enkel recht om global te zijn ;Dspeed_byte = (analoge_waarde >> 2)-127 ;
Besef dat je dit ook ongewenst -127 als snelheid kan geven. if (speed_byte < 0) speed_byte = -speed_byte;
EEPROM.write(lokIndex, speed_byte);
delay(500); // wacht tot zeker is dat EEPROM beschreven werd
Nergens voor nodig ;) Komt gewoon in EEPROM. Je had ook abs() kunnen gebruiken.//Hier de locadressen invullen
byte locAdressen[] = {60, //Adres 1
45, //Adres 2
67, //Adres 3
32}; //Adres 4
E.e.a. levert wel meer tikwerk op, maar maakt het hopelijk ook veel duidelijker voor iemand, die veel minder programmeert dan wij.Niet alleen voor iemand die minder programmeert. Maar zeker ook voor future you. Als je een project een jaar in de kast heb laten liggen (af of niet ::) ) is het altijd een stuk makkelijker wat aanpassen als de code duidelijk, gestructureerd en becommentarieerd is.
Wat betreft duidelijke plekken, de extra namen zou ik nu juist als verwarrend zien. En waarom zou dat in omgekeerde volgorde moeten? Wat is er mis met iets alsWaarom had ik gekozen voor losse declaraties:Code: [Selecteer]//Hier de locadressen invullen
byte locAdressen[] = {60, //Adres 1
45, //Adres 2
67, //Adres 3
32}; //Adres 4
huidigeLok = digitalRead(lokKeuzePin1); // index wordt 0 of 1
huidigeLok = huidigeLok + 2 * digitalRead(lokKeuzePin2); // index krijgt er 0 of 2 bij
lokAdres = 3 - lokAdressen[huidigeLok]; // keer de telling om
Maar door de keuze van aparte constanten voor de lokAdressen kon ik dat al oplossen in de array declaratie.Code: [Selecteer]if (snelheid < -1) snelheid = -1; else snelheid = speed_byte;
Van die regel gaan mijn rugharen een beetje overeind staan ;D Voor de leesbaarheid, regels eindigen na de ;. Omdat het een simpel statement is zou je er wel een one line'er van kunnen maken maar dan als:Code: [Selecteer](snelheid < -1 ? snelheid = -1: snelheid = speed_byte);
Maar meestal gaat mijn voorkeur toch gewoon uit naar voluit omdat het vaak duidelijker is en makkelijker uit te breiden.
Overigens, wil je daar niet van richting veranderen als je op de andere richting drukt? Dus:Code: [Selecteer]if (snelheid < -1)
snelheid = 1;
else
snelheid = speed_byte;
(snelheid < -1 ? snelheid = -1: snelheid = speed_byte);
snelheid = (snelheid < -1) ? -1 : speed_byte;
Zou ik je toch een paar tips mogen geven? Zie het vooral dus niet als negatief iets maar puur als hulp! (y)
//Hier de locadressen invullen
byte locAdressen[] = {60, //Adres 1
45, //Adres 2
67, //Adres 3
32}; //Adres 4
const byte LokKeuzePinnen[] = {A1, A2, A3, A4};
byte locIndex;
void kiesLoc(){
locIndex = 0;
for(byte 1 = 0; i < sizeof(LokKeuzePinnen); i++){
pinMode(LokKeuzePinnen[i], INPUT_PULLUP);
//schuif eens op
locIndex <<= 1;
//Inverse lezen om het omdraaien van de loc adressen ongedaan te maken.
locIndex |= !digitalRead(LokKeuzePinnen[i]);
}
}
inline byte locAdres(){
//Als er een te hoge geselecteerd wordt geef gewoon de 1e.
if(locIndex >= sizeof(locAdressen)){
return locAdressen[0];
}
return locAdressen[locIndex];
}
Let wel op dat hierdoor locKeuzePinnen[0] MSB is van de index. Wil je dat niet dan locIndex |= !digitalRead(LokKeuzePinnen[sizeof(LokKeuzePinnen) -1 - i]);
Om de array andersom te gebruiken./* * * * * * O n d e r s t a a n d e c o d e a l l e e n * * * *
* * * * * * a a n p a s s e n a l s j e v e r t r o u w d * * * *
* * * * * * b e n t m e t C-p r o g r a m m e r e n e n * * *
* * * * * * A R D U I N O * * * *
*/
En ergens bovenaan komt ook nog iets te staan dat iedereen vrij is te doen met dit stukje code wat men wil. -Maar ik vind het dan wel altijd fijn om een paar wegen te kennen zodat je de voor en nadelen van een route vooraf kunt vaststellen 8)somser leiden meer wegen naar Rome, waarbij de kortste of beste niet altijd te prefereren valt.
@Cees, gek dat de RJ12 van Walter gespiegeld is, zie het nu ook ja. Nummers zouden moet blijven kloppen aangezien de connector nu op zijn kop werkt. Er is overigens geen enkele reden een boven en onder de print versie te maken. Gewoon een versie (voor boven de print). Wil je hem aan de andere kant van plaats je hem gewoon op de achterkant van de PCB en klaar.Zo heb ik dat nu gedaan en dat werkt voor LocoNet. Als je echter de connector ook anders wilt gebruiken, waarbij de 6 aders verschillend zijn, dan heb je wel 2 versies nodig.
Ook al heb ik zelf een hekel aan Java ;D :-XDat was nou net de reden om geen velden en menu's te maken. Slider had ook leuk geweest, maar de implementatie was me te ingewikkeld.
Misschien nog iets toevoegen om van servo/stand te wisselen?
Processing geeft je dan de mogelijkheid een deel van de teksten daarheen te verhuizen, zodat je meer ruimte overhoudt voor leukere dingen.Dat is dan ook meer "zoals het hoort". Altijd al zonde gevonden om bergen karakters op te slaan op een kleine uC.
void setup()
{
...
...
if (digitalRead(progKnop) == 0)
{
....
....
digitalWrite(LED, HIGH);
servoInstellen();
}
void servoInstellen()
{
String tekst = "";
for (byte servoNummer = 0; servoNummer < NrServos; servoNummer++)
{
// local variables
boolean done = false;
boolean wiggel = false;
// stuur commando naar processing (evt. terminal)
tekst = "SS " + String(servoNummer + 1, HEX) + String(" ");
Serial.println(tekst);
Serial.flush();
// zet servo in de middenstand
wisselServos.gotoPos(servoNummer,servoMid);
wisselServos.update();
while (!done)
{
while (Serial.available() > 0)
{
// De te ontvangen string bevat altijd: "CCCCC xxx yyy zzz" en wordt afgesloten met \n
// de delen worden gescheiden door een spatie
// CCCCC maximaal 10 karakters, hier gebruiken we er 2
// xxx een int (10 .. 1012) voor een eindstand rood van de servo
// yyy een int (10 .. 1012) voor een eindstand groen van de servo
// zzz een int () voor de servosnelheid
// De commando's kunnen zijn:
// "SK" = skip deze servo
// "SA" = save de meegestuurde waarden
// en save de ingestelde snelheid
// "SR" = set servo in de stand xxx
// "SG" = set servo in de stand yyy
// "SW" = set wiggelen servo aan
// "SD" = servo speed down
// "SU" = servo speed up
String commando = "";
char comm[10];
int aantal;
aantal = Serial.readBytesUntil(' ', comm, 10);
int standGroen, standRood, val3;
for (int i = 0; i < aantal; i++)
{
commando = commando + String(comm[i]);
}
// look for the 3 next valid integers in the incoming serial stream:
standGroen = Serial.parseInt();
standRood = Serial.parseInt();
val3 = Serial.parseInt(); // reserved, not used in this sketch
// wacht op newline, dan zijn we aan het eind van een zin
if (Serial.read() == '\n')
{
commando.toUpperCase();
if (commando == "SG")
{
wisselServos.gotoPos(servoNummer, standGroen);
}
if (commando == "SR")
{
wisselServos.gotoPos(servoNummer, standRood);
}
if (commando == "SK")
{
done = true;
}
if (commando == "SA")
{
wisselServos.setEndPos(servoNummer, 0, standGroen);
wisselServos.setEndPos(servoNummer, 1, standRood);
//bewaar ze in EEPROM
EEPROM.write(EEServoDirs + (servoNummer*2), (standGroen / 4));
EEPROM.write(EEServoDirs + (servoNummer*2) + 1, (standRood / 4));
servoSpeed_t servoSpeed = wisselServos.getSpeed(servoNummer);
EEPROM.write(EEServoSpeedStep + servoNummer, servoSpeed.step);
EEPROM.write(EEServoSpeedInterval + servoNummer, servoSpeed.interval);
done = true;
}
if (commando == "SW")
{
wisselServos.gotoEndPos(servoNummer,0);
wiggel = true;
}
if (commando == "SD")
{
wisselServos.speedDown(servoNummer);
}
if (commando == "SU")
{
wisselServos.speedUp(servoNummer);
}
} // end if (Serial.read()
} // end while (Serial.available(
if (wiggel == true)
{
wiggelServo(servoNummer);
}
wisselServos.update();
} // end while (!done)
} // end for-loop 1
// We're done setting up. Let processing now.
tekst = "XX " + String(255, HEX) + String(" ");
Serial.println(tekst);
Serial.flush();
digitalWrite(LED,LOW);
} //end servoInstellen()
void wiggelServo(int i)
{
if(!wisselServos.isActive(i)) //only change endPos after detached to wait @ endPos
{
if(wisselServos.isAtEndPos(i, 0))
{
wisselServos.gotoEndPos(i, 1);
}
else if(wisselServos.isAtEndPos(i, 1))
{
wisselServos.gotoEndPos(i, 0);
}
}
}
Hoe ik dat anders/eenvoudiger kan doen ben ik niet uitgekomen.Aangezien de knop indrukken en dan Prcessing starten met je andere hand misschien wat lastiger is zou je ook kunnen gaan voor Processing starten, dan knopje indrukken en even de reset knop indrukken. Voorwaarde is dan wel dat je PRocessing sketch niet in de stress schiet als deze niet gelijk contact heeft ;D
tekst = "SS " + String(servoNummer + 1, HEX) + String(" ");
Vraagt bijvoorbeeld nu belachelijk veel geheugen doordat je werkt met drie String objecten!// wacht op newline, dan zijn we aan het eind van een zin
if (Serial.read() == '\n')
Lijkt me niet zo handig. Wat als deze nooit komt? Of als het een ander character is? Wil je dan echt alles weggooien? void servoInstellen(){
for (byte servoNummer = 0; servoNummer < NrServos; servoNummer++){
bool done = false;
bool wiggel = false;
Serial.print(F("SS"));
Serial.print(servoNummer + 1, HEX);
Serial.println(" "); //<--- deze kan deze ik wel weg, de '\n' lijkt me genoeg?
// zet servo in de middenstand
wisselServos.gotoPos(servoNummer,servoMid);
wisselServos.update();
while(!done){
//wachten op serial
while(Serial.available())
{
// De te ontvangen string bevat altijd: "CCCCC xxx yyy zzz" en wordt afgesloten met \n
// de delen worden gescheiden door een spatie
// CCCCC maximaal 10 karakters, hier gebruiken we er 2
// xxx een int (10 .. 1012) voor een eindstand rood van de servo
// yyy een int (10 .. 1012) voor een eindstand groen van de servo
// zzz een int () voor de servosnelheid
// De commando's kunnen zijn:
// "SK" = skip deze servo
// "SA" = save de meegestuurde waarden
// en save de ingestelde snelheid
// "SR" = set servo in de stand xxx
// "SG" = set servo in de stand yyy
// "SW" = set wiggelen servo aan
// "SD" = servo speed down
// "SU" = servo speed up
char command[11]; //een plaats extra voor een '\n'
byte aantalBytes = Serial.readBytesUntil('', command, 10);
command[aantalBytes] = '\n'; //altijd eindigen met een '\n'
int standGroen = Serial.parseInt();
int standRood = Serial.parseInt();
int servoSpeed = Serial.parseInt();
toUpper(command);
//laten staan omdat je het nu eenmaal stuurt
if (Serial.read() == '\n')
{
if (!strcmp(command, F("SG")))
{
wisselServos.gotoPos(servoNummer, standGroen);
}
//else if, want als het SG was kunnen we gewoon stoppen met zoeken
else if (!strcmp(command, F("SR")))
{
wisselServos.gotoPos(servoNummer, standRood);
}
else if (!strcmp(command, F("SK")))
{
done = true;
}
else if (!strcmp(command, F("SA")))
{
wisselServos.setEndPos(servoNummer, 0, standGroen);
wisselServos.setEndPos(servoNummer, 1, standRood);
//bewaar ze in EEPROM
EEPROM.write(EEServoDirs + (servoNummer*2), (standGroen / 4));
EEPROM.write(EEServoDirs + (servoNummer*2) + 1, (standRood / 4));
servoSpeed_t servoSpeed = wisselServos.getSpeed(servoNummer);
EEPROM.write(EEServoSpeedStep + servoNummer, servoSpeed.step);
EEPROM.write(EEServoSpeedInterval + servoNummer, servoSpeed.interval);
done = true;
}
else if (!strcmp(command, F("SW")))
{
wisselServos.gotoEndPos(servoNummer,0);
wiggel = true;
}
else if (!strcmp(command, F("SD")))
{
wisselServos.speedDown(servoNummer);
}
else if (!strcmp(command, F("SU")))
{
wisselServos.speedUp(servoNummer);
}
} // end if (Serial.read()
} // end while (Serial.available(
if (wiggel == true)
{
wiggelServo(servoNummer);
}
wisselServos.update();
} // end while (!done)
} // end for-loop 1
// We're done setting up. Let processing know.
Serial.println(F("XX FF"));
digitalWrite(LED,LOW);
} //end servoInstellen()
//Hele string naar uppercase
void toUpper(&in){
for(unsigned int i = 0; i < strlen(in); i++){
in[i] = toupper(in[i]);
}
}