I have a code for only one servo and buttons.I need to add several servo and button to the code but doesn't work what I'm doing.
So How can I add multiple pin following line?
int Pin_Servo = 3;
int Pin_Taster = 12;
In german Taster is Button.
Original code ;
// Einbinden der Servo-Bibliothek
#include <Servo.h>
// Definition der Variablen
// für den Servo
int Weiche_Gerade = 60; // Endlage des Servos wenn Weiche auf Gerade
int Weiche_Mitte = 90; // Mittellage
int Weiche_Abzweig = 120; // Endlage des Servos wenn Weiche auf Abzweig
int Weiche_soll = Weiche_Mitte; // Speichervariable für die aktuelle Lage
int Stellzeit_Servo_Weiche = 30; // Stellgeschwindigkeit Weiche
int Pin_Servo = 3; // Servo an PIN 3
// für den Taster
int Pin_Taster = 12; // Taster an PIN 4
unsigned long entprellzeit = 20; // Zeitintervall der Tasterabfrage
unsigned long tasterzeit = 0; // Speichervariable für die Zeit
int taster_gedrueckt = 0; // Speichervariable für den Tasterzustand
// Anlegen eines Servo-Objektes
Servo servo;
void setup()
{
// Initialisieren der Weiche auf Grundstellung
servo.attach(Pin_Servo); // Aktivierung ServoPin
servo.write(Weiche_Mitte); // Servo fährt in Mittelstellung
delay(500); // Warten das der Servo die Stellung erreicht hat
// Servo fährt in Stellgeschwindigkeit in die Grundlage (in der Regel Gerade
while (Weiche_Gerade < Weiche_soll)
{
Weiche_soll--;
servo.write(Weiche_soll);
delay(Stellzeit_Servo_Weiche);
if (Weiche_soll == Weiche_Gerade)
{
servo.detach(); // Deaktivierung Servo
}
}
}
void loop()
{
// Definition des PINS
pinMode(Pin_Taster, INPUT);
// Entprellen des Tasters
if (digitalRead(Pin_Taster) == HIGH)
{
tasterzeit = millis(); // Speichern der aktuellen Zeit
taster_gedrueckt = 1;
}
// Abfrage der Weichenlage, Servo fährt dann in die jeweils Andere
if ((millis() - tasterzeit > entprellzeit) && taster_gedrueckt == 1 && Weiche_soll == Weiche_Abzweig)
{
while (Weiche_Gerade < Weiche_soll)
{
servo.attach(Pin_Servo);
Weiche_soll--;
servo.write(Weiche_soll);
delay(Stellzeit_Servo_Weiche);
if (Weiche_soll == Weiche_Gerade)
{
servo.detach(); // Deaktivierung Servo
taster_gedrueckt = 0;
}
}
}
if ((millis() - tasterzeit > entprellzeit) && taster_gedrueckt == 1 && Weiche_soll == Weiche_Gerade)
{
while (Weiche_Abzweig > Weiche_soll)
{
servo.attach(Pin_Servo);
Weiche_soll++;
servo.write(Weiche_soll);
delay(Stellzeit_Servo_Weiche);
if (Weiche_soll == Weiche_Abzweig) // Abfrage ob Endlage erreicht
{
servo.detach(); // Deaktivierung Servo
taster_gedrueckt = 0; // Zurückstellen des Tasterstatus
}
}
}
}
Although I'm language limited, it doesn't appear that you tried more than one button or servo in the code you posted, so we can't see what's going wrong. If that's the case, please post the nonworking code, and we can further advise.
To switch multiple turnouts, you could use the MobaTools library. It provides classes for moving servos slowly and to debounce buttons. A dokumentation in english and german is provided.
Arrays are the way to go with multiple turnouts.
Ok, then I misunderstood you. You need a servo and a relais for each turnout. And the relais should switch when the servo is in the middle of its movement to avoid shortcircuits at the switch blade? Or are the switch blades firmly connected to the stock rail and only the frog is insulated and has to be switched? In the latter it doesn't matter when the relais switches.
I need a servo and a relais for each turnout. And the relais should switch when the servo is in the middle of its movement to avoid shortcircuits at the switch blade.
Actually, I have working code from @kolaha multiple switches with relay and uses pca9685 servo driver.In fact I can't add the MobaTools for slow speed. Here is the working code. This code just need a slow-speed servo.
/*
This example uses 2 servos, one on Pin 0, the other on pin 12 of AdaFruit PCA9685 module
Relays are on pins 12 and 13
1 PCA9685 board
2 servos
2 3-pole switches
2 relay modules
SDA/SCL connections for PCA9685
Arduino UNO: A4 (SDA), A5 (SCL)
Arduino Mega 2560: 20 (SDA), 21 (SCL)
ESP32: 21(SDA), 22 (SCL)
pins 8 - 11 for buttons/switches
pins 12-13 relays
*/
#include "Wire.h"
#include <MobaTools.h>
#include "Adafruit_PWMServoDriver.h"
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); // called this way, it uses the default address 0x40
#define USMIN 600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
#define USMAX 1800 // This is the rounded 'maximum' microsecond length based on the maximum pulse of 600
#define SERVO_FREQ 50 // Analog servos run at ~50 Hz updates
void setServoPos(int servo, int pos) {
//This first bit of code makes sure we are not trying to set the servo outside of limits
int sendPos;
if (pos > 180) pos = 180 ;
if (pos < 0) pos = 0;
sendPos = map(pos, 0, 180, USMIN, USMAX);
if (servo > -1 && servo < 16) { //only try to move valid servo addresses
pwm.writeMicroseconds(servo, sendPos);
delay (500);
}
}
void setup() {
pwm.begin();
pwm.setOscillatorFrequency(27000000);
pwm.setPWMFreq(SERVO_FREQ); // Analog servos run at ~50 Hz updates
pinMode(8, INPUT_PULLUP);
pinMode(9, INPUT_PULLUP);
pinMode(10, INPUT_PULLUP);
pinMode(11, INPUT_PULLUP);
pinMode(12, OUTPUT);
pinMode(13, OUTPUT);
Serial.begin(9600);
Serial.print("PCA9685ServoSetterV3");
Serial.end();
}
void loop() {
static bool StateFirst = false;
static bool StateSecond = false;
if (StateFirst) { //code variant 1
if (!digitalRead(8)) {
StateFirst = false;
setServoPos(0, 180);
digitalWrite(12, HIGH);
}
} else {
if (!digitalRead(9)) {
StateFirst = true;
setServoPos(0, 0);
digitalWrite(12, LOW);
}
}
if (!digitalRead(10) && StateSecond) { //code variant 2
StateSecond = false;
setServoPos(12, 180);
digitalWrite(13, HIGH);
} else if (!digitalRead(11) && !StateSecond) {
StateSecond = true;
setServoPos(12, 0);
digitalWrite(13, LOW);
}
}
I'm not quite shure to understand your post. Do you want to use the PCA?
If not, this may be a solution ( it will be a servo example for model railroaders in the next release of MobaTools ):
/* MobaTools - Model railroad example for servos
Switching two turnouts with servos and a relais for frog polarisation.
The relais is switched in the middle of the path whe switching the turnout.
It uses a FSM for each turnout.
The example can easily expanded for more turnouts
*/
#include <MobaTools.h>
// Pin definitions, change to your needs
constexpr byte servoPin[] = { 2, 3 };
constexpr byte nbrTurnouts = sizeof(servoPin); // Number of turnouts
constexpr byte relPin[nbrTurnouts] = {4, 5};
constexpr byte switchPin[nbrTurnouts] = {A0, A1}; // The switches must be connected between pin and Gnd
// Open switch is the straight position of the turnout
// you can set the servo positions for STRAIGHT and DEVIATE individually for each turnout:
constexpr byte straightPos[nbrTurnouts] = { 30, 120 }; // Servo position in the straight position of the turnout.
constexpr byte deviatePos[nbrTurnouts] = { 120, 30 }; // Servo position in the deviating position of the turnout
constexpr uint16_t servoSpeed = 2000; // 2 sec to move from 0 to 180 deg
//FSM states:
enum fsmStates : byte { STRAIGHT, MOVE2DEV, DEVIATE, MOVE2STRAIGHT };
fsmStates turnoutState[nbrTurnouts];
MoToServo myServo[nbrTurnouts]; // create servo objects
void setup() {
Serial.begin(115200);
// initialize all objects
Serial.print("Initializing all turnouts ...");
for ( byte toIx = 0; toIx < nbrTurnouts; toIx++ ) {
pinMode( relPin[toIx], OUTPUT );
pinMode( switchPin[toIx], INPUT_PULLUP);
myServo[toIx].attach( servoPin[toIx], true ); // with auto switch off the pulses
myServo[toIx].setSpeedTime( servoSpeed );
// Set initial servo position and relais according to the switches
// If switches are not changed since last shut down, this should be the actual servo position
if ( digitalRead( switchPin[toIx] ) ) {
// switch is open -> 'strait' position
myServo[toIx].write( straightPos[toIx] );
digitalWrite( relPin[toIx], LOW );
turnoutState[toIx] = STRAIGHT;
} else {
// switch is closed -> 'deviate' position
myServo[toIx].write( deviatePos[toIx] );
digitalWrite( relPin[toIx], HIGH );
turnoutState[toIx] = DEVIATE;
}
}
Serial.println("finished");
}
void loop() {
for ( byte toIx = 0; toIx < nbrTurnouts; toIx++ ) {
// turnout-FSM
switch ( turnoutState[toIx] ) {
case STRAIGHT: /////// Turnout is in the STRAIGHT position. wait until switch is changed
if ( !digitalRead(switchPin[toIx] ) ) {
// switch now in deviate position -> change servo position
myServo[toIx].write( deviatePos[toIx] );
turnoutState[toIx] = MOVE2DEV;
Serial.print(toIx); Serial.print(" - moving to DEV position...");
}
break;
case MOVE2DEV: /////// Turnout is moving to deviate position
// set relais when servo reaches middle position
if ( myServo[toIx].moving() < 50 ) {
// Servo has reached middle position -> switch relais
digitalWrite( relPin[toIx], HIGH );
}
if ( !myServo[toIx].moving() ) {
// Servo has reached end position -> next FSM state
turnoutState[toIx] = DEVIATE;
Serial.println("finished");
}
break;
case DEVIATE: /////// Turnout is in DEVIATE position
if ( digitalRead(switchPin[toIx] ) ) {
// switch now is in straight position -> change servo position
myServo[toIx].write( straightPos[toIx] );
turnoutState[toIx] = MOVE2STRAIGHT;
Serial.print(toIx); Serial.print(" - moving to STRAIGHT position...");
}
break;
case MOVE2STRAIGHT: /////// Turnout is moving to straight position
// set relais when servo reaches middle position
if ( myServo[toIx].moving() < 50 ) {
// Servo has reached middle position -> switch relais
digitalWrite( relPin[toIx], LOW );
}
if ( !myServo[toIx].moving() ) {
// Servo has reached end position -> next FSM state
turnoutState[toIx] = STRAIGHT;
Serial.println("finished");
}
break;
}
}
}