Toggle Switch instead of On-OFF Button for Servo Driver?

I have PCA9685 Servo Button control aimed at Model railway point/turnout control wiring diagram and code.

But I would like to use the 3 pin toggle switch instead of the button as the diagram shows.
How can I wire one toggle switch each servo and do I need to edit the following code?

/* PCA9685ServoButtonsV3
  31/12/23
  Built on the foundations of PCA9685ServoButtonsV2
  This time the relay code has been added.

    

    This example uses 2 servos, one on Pin 0, the other on pin 12
    Relays are on pins 12 and 13

    adding more buttons/servos is just a matter of extending the code.

   Code is written as a state machine without delay() so that other code (without delay()
   can be added if needed.

   PCA9685 board
   2 servos
   4 buttons
   4 x 4.5k OHM resistors for Pull Down on buttons
   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 with 4.7K pull down resistors
  pins 12-13 relays

*/

#include "Wire.h"
#include "Adafruit_PWMServoDriver.h"
//PCA 9685 settings
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// you can also call it with a different address you want
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x41);
// you can also call it with a different address and I2C interface
//Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver(0x40, Wire);

#define USMIN  600 // This is the rounded 'minimum' microsecond length based on the minimum pulse of 150
#define USMAX  2400 // 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
//end pca9685 settings

//position in the following array is the values you would get from the PCA9685 Servo setter project
//see https://www.digitaltown.co.uk/projectPCA9685ServoSetter.php
# define numButtons 4 //number of buttons controlling servos
int servoVariables[numButtons][5] = { //2 lines per servo (2 buttons)
  {8,0,45,12,0}, //pin 8, servo 0, position,relay,off
  {9,0,179,12,1}, //pin 9, servo 0, position,relay,on
  {10,12,33,13,0}, //pin 10,servo 12, position,relay,off
  {11,12,168,13,1} //pin 11, servo 12, position,relay,on
};
//System variables
unsigned long currentMillis; //will stire the current time in from millis()
unsigned long buttonTimer;//stores the next value in millis for debounce
int buttonDebounce = 200;//smaller vale makes buttons more sensitive, easier to get double press

//Servo movement function
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 > 179) {
    pos = 179;
  }
  if (pos < 0) {
    pos = 0;
  }
  sendPos = USMIN + ((USMAX - USMIN) / 180 * pos);
  if (servo > -1 && servo < 16) { //only try to move valid servo addresses
    pwm.writeMicroseconds(servo, sendPos);
  }
}

//deals with button presses
//This works but would become very complicated and hard to read with 16 servos
void buttonState() {
  int q;
  if (currentMillis - buttonTimer >= buttonDebounce) { //are buttons debounced
    buttonTimer = currentMillis;//reset debounce timer
    for(q=0;q < numButtons;q++){
      if(digitalRead(servoVariables[q][0]) > 0){
        setServoPos(servoVariables[q][1], servoVariables[q][2]);//move the servo
        digitalWrite(servoVariables[q][3],servoVariables[q][4]);//set the relay to appropriate value
        q=numButtons;//causes system to exit for loop and wait for debounce again    
      }
    }
  }
}



void setup() {
  Serial.begin(9600);
  Serial.println("PCA9685ServoSetterV3");

  pwm.begin();
  pwm.setOscillatorFrequency(27000000);
  pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates

  delay(10);//let the above values take effect

  for(int q=0;q < numButtons;q++){
    pinMode(servoVariables[q][0], INPUT);//set the pins used for buttons in the servoVariables array
    pinMode(servoVariables[q][3], OUTPUT);//set the pins used for relays servoVariables array
  }

}

void loop() {
  currentMillis = millis();//get the current millis since board started for timing
  buttonState();//deals with button presses
}

What functionality do You want from the toggle switch that differs from the button operation?

Each toggle switch will be operation one servo but diagram of the above each servo has been operation 2 button. I would like to convert one toggle switch instead of 2 button for cosmetic also.

grafik

/*
    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 "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  2400 // 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);
  }
}

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);
  }
}
1 Like

Do your SPDT switches have a center OFF position, or are they simply LEFT or RIGHT, no center position?

My SPDT switches are only simply Left and Right switches. So, there is no center position.
Miniature-Toggle-Switch-MTS-102_600x600

Thank you for diagram and code.I will try tuesday night and will be inform.

Finally,I tested your code but I received this errors;

C:\Users\Kaan Burak\AppData\Local\Temp\.arduinoIDE-unsaved202483-18072-1l3yc0c.fvno\sketch_sep3a\sketch_sep3a.ino: In function 'void setServoPos(int, int)':
C:\Users\Kaan Burak\AppData\Local\Temp\.arduinoIDE-unsaved202483-18072-1l3yc0c.fvno\sketch_sep3a\sketch_sep3a.ino:35:9: error: request for member 'writeMicroseconds' in 'pwm', which is of non-class type 'Adafruit_PWMServoDriver()'
     pwm.writeMicroseconds(servo, sendPos);
         ^~~~~~~~~~~~~~~~~
C:\Users\Kaan Burak\AppData\Local\Temp\.arduinoIDE-unsaved202483-18072-1l3yc0c.fvno\sketch_sep3a\sketch_sep3a.ino: In function 'void setup()':
C:\Users\Kaan Burak\AppData\Local\Temp\.arduinoIDE-unsaved202483-18072-1l3yc0c.fvno\sketch_sep3a\sketch_sep3a.ino:40:7: error: request for member 'begin' in 'pwm', which is of non-class type 'Adafruit_PWMServoDriver()'
   pwm.begin();
       ^~~~~
C:\Users\Kaan Burak\AppData\Local\Temp\.arduinoIDE-unsaved202483-18072-1l3yc0c.fvno\sketch_sep3a\sketch_sep3a.ino:41:7: error: request for member 'setOscillatorFrequency' in 'pwm', which is of non-class type 'Adafruit_PWMServoDriver()'
   pwm.setOscillatorFrequency(27000000);
       ^~~~~~~~~~~~~~~~~~~~~~
C:\Users\Kaan Burak\AppData\Local\Temp\.arduinoIDE-unsaved202483-18072-1l3yc0c.fvno\sketch_sep3a\sketch_sep3a.ino:42:7: error: request for member 'setPWMFreq' in 'pwm', which is of non-class type 'Adafruit_PWMServoDriver()'
   pwm.setPWMFreq(SERVO_FREQ);  // Analog servos run at ~50 Hz updates
       ^~~~~~~~~~

exit status 1

Compilation error: request for member 'writeMicroseconds' in 'pwm', which is of non-class type 'Adafruit_PWMServoDriver()'

Change the instantiation of the pwm object from

Adafruit_PWMServoDriver pwm();

to

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
1 Like

It's working now but the issue is that the toggle switch works only when Arduino is connected via USB.
The toggle switch not working when 5V connected the pca9685 servo driver.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.