After some investigation, I've decided to use servos to change the alignment of some of the turnouts on my model railroad. I've also decided to use an Arduino to drive the servos. And I know that the Uno is capable of controlling 14 servos but if I want LED indication of the track set at the turnout, it requires at least 3 pins for each servo. That limits things greatly.
Then I discovered the PCA9685 which can drive 16 servos via SDA and SCL. Tom's Train and Things has a sketch showing this. In his sketch, he uses a button and a 3-way LED, which he connects to the Uno. I've modified his sketch to use a toggle switch and I've come up with a circuit in which only 1 pin of the Uno is required for each servo. Which means I can drive 16 servos with just 1 Arduino Uno. This is great. But now comes my challenge.
In Tom's sketch, he uses the pulse to limit the throw of the servo. This means that the servo goes from one side to the other almost instantaneously. That's not very prototypical. I'd like to slow the movement of the servo so that it sweeps from one side to the other, thereby opening or closing the turnout in a more realistic manner.
My programming days are long gone and it was in Basic and Cobol, casually! So the syntax of C++ leaves me confused at times.
Can some here look at my sketch and enlighten me? I'd copy my sketch here but I'm not sure the best way of copying and not loosing the formatting.
Thanks
David
Can some here look at my sketch and enlighten me? I'd copy my sketch here but I'm not sure the best way of copying and not loosing the formatting.
1. Select the code to be posted in the Arduino IDE.
2. Right-click on the selected code and choose "Copy as HTML" from the pop-up menu.
3. Then in the forum editor window choose the source code icon {:} at the top of the editor.
4. Paste the HTML code into the pop-up window and select ok.
5. You can then select "Preview" at the bottom of the post editor to see exactly how the code will appear when posted.
This method preserves both the alignment and the color formatting of the Arduino code.
DroneBot Workshop Robotics Engineer
James
After some investigation, I've decided to use servos to change the alignment of some of the turnouts on my model railroad. I've also decided to use an Arduino to drive the servos. And I know that the Uno is capable of controlling 14 servos but if I want LED indication of the track set at the turnout, it requires at least 3 pins for each servo. That limits things greatly.
Then I discovered the PCA9685 which can drive 16 servos via SDA and SCL. Tom's Train and Things has a sketch showing this. In his sketch, he uses a button and a 3-way LED, which he connects to the Uno. I've modified his sketch to use a toggle switch and I've come up with a circuit in which only 1 pin of the Uno is required for each servo. Which means I can drive 16 servos with just 1 Arduino Uno. This is great. But now comes my challenge.
In Tom's sketch, he uses the pulse to limit the throw of the servo. This means that the servo goes from one side to the other almost instantaneously. That's not very prototypical. I'd like to slow the movement of the servo so that it sweeps from one side to the other, thereby opening or closing the turnout in a more realistic manner.
My programming days are long gone and it was in Basic and Cobol, casually! So the syntax of C++ leaves me confused at times.
Can some here look at my sketch and enlighten me? I'd copy my sketch here but I'm not sure the best way of copying and not loosing the formatting.
Thanks
Hi, I also went with Toms Trains sketch and modified to operate 16 sets of points on my Model Railway build..
John
Thanks for the heads-up. Please excuse the code structure, it's still in development stage. I haven't yet removed the unnecessary lines, merely commented them out. And because of the way the servos have been mounted on the underside of the layout, I think I need to treat each servo independently so that each doesn't travel to far to cause breakages.
Thanks, David
/*************************************************** This sketch can be used to operate any number of turnouts on a Model Railroad. Code blocks can be added to accomodate any number of servos. This sketch uses only two servos for this demonstration. The pushbutton can be replaced with a SPST switch commonly used on a control panel. Three pin Bicolor LED can be used in place of two seperate LEDs in each circuit. 10K Ohm pulldown resistor used on switch 330 Ohm resistor used on LEDs. One per pair of LEDs Created 03/02/2019 by Tom Kvichak https://tomstrainsandthings.com/ Additional Arduino Projects can be found at the above web address Modified by David Orr 12/01/2020 to use SPDT togle switches instead of buttons. One pole goes to cathode of red LED and digital pin on Arduino, the other pole goes to cathode of green LED and digital pin on Arduino. The central pole goes to GND. 5v rail to anode of LEDs via 1k resistor. This way only 1 digital pin is needed for each turnout switch and LED. Movement of the turnouts is via I2C and PCA9685 using 5v, GND, SCL and SDA. ****************************************************/ #include <Wire.h> #include <Adafruit_PWMServoDriver.h> Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(); int switchPin0 = 2; // Can add as many switches as needed - this is the 1st, set up for loop for as many as needed int switchPin1 = 3; // int switchPin2 = 4; // int switchPin3 = 5; // int switchPin4 = 6; // //int ledPin0C = 3; // C designates Closed position of turnout - I don't think I need this //int ledPin0T = 4; // T designates Thrown position of turnout - I don't think I need this int switchState0 = 0; // - this is the 1st, set up for loop for as many as needed int switchState1 = 0; // int switchState2 = 0; // int switchState3 = 0; // int switchState4 = 0; // //int buttonPin1 = 5; - I don't think I need this yet //int ledPin1C = 6; - I don't think I need this //int ledPin1T = 7; - I don't think I need this //int buttonState1 = 0; - I don't think I need this yet void setup() { Serial.begin(9600); Serial.println("PCA9685_MyTurnouts"); pwm.begin(); pwm.setPWMFreq(60); delay(30); // pinMode(ledPin0C, OUTPUT); //pinMode(ledPin0T, OUTPUT); //pinMode(buttonPin0, INPUT); //pinMode(ledPin1C, OUTPUT); //pinMode(ledPin1T, OUTPUT); //pinMode(buttonPin1, INPUT); pinMode(switchPin0, INPUT_PULLUP); // I'll need switchPin0 to 4 for 5 servos or 0 to 15 for 16 servos pinMode(switchPin1, INPUT_PULLUP); pinMode(switchPin2, INPUT_PULLUP); pinMode(switchPin3, INPUT_PULLUP); pinMode(switchPin4, INPUT_PULLUP); } void loop() { /////////// switchState0 = digitalRead(switchPin0); if (switchState0 == HIGH) { //for (int counter=285; counter <=370; counter++) //{ // pwm.setPWM(0, 0, counter); //swing servo left //delay(10); //} pwm.setPWM(0, 0, 370); //swing servo left //digitalWrite(ledPin0T, LOW); //digitalWrite(ledPin0C, HIGH); } else { //for (int counter=370; counter >=285; counter--) //{ //pwm.setPWM(0, 0, counter);//swing servo right //delay(10); //} pwm.setPWM(0, 0, 290); //swing servo right //digitalWrite(ledPin0C, LOW); //digitalWrite(ledPin0T, HIGH); } ///////////////////// switchState1 = digitalRead(switchPin1); if (switchState1 == HIGH) { pwm.setPWM(1, 0, 370); //swing servo left } else { pwm.setPWM(1, 0, 285); //swing servo right } /////////////////////// switchState2 = digitalRead(switchPin2); if (switchState2 == HIGH) { pwm.setPWM(2, 0, 370); //swing servo left } else { pwm.setPWM(2, 0, 285); //swing servo right } /////////////////////// switchState3 = digitalRead(switchPin3); if (switchState3 == HIGH) { pwm.setPWM(3, 0, 370); //swing servo left } else { pwm.setPWM(3, 0, 285); //swing servo right } //////////////////////// switchState4 = digitalRead(switchPin4); if (switchState4 == HIGH) { pwm.setPWM(4, 0, 370); //swing servo left } else { pwm.setPWM(4, 0, 285); //swing servo right } }
David