Hi everyone, thanks for giving me some advice. I'm designing a hat with movable surfaces like feathers that will go up and down... the hardware is made up of a 3S 2500mah 11.1V lipo battery connected to a ZK4XK converter, Arduino Pro Mini, PCA9685 which moves around ten SG90 servomotors which only move 90 degrees max on purpose. I would like to be able to move the servo from the rest position or arm perpendicular to the body of the servo, to the UP position, arm parallel to the servo, via BT commands using an HC05 connected to the Arduino Pro Mini.
Deep search helped me compile a sketch that doesn't seem to work because the servos go to rest position as soon as I power up the circuit (I only powered 3 of them to test), the app communicates via BT but the servos don't respond to the commands given. Here is the sketch and some photos of the connections. What did I do wrong?
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// Configurazione PCA9685
Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver();
// Configurazione Bluetooth
#include <SoftwareSerial.h>
SoftwareSerial BT(3, 2); // RX, TX (puoi cambiare i pin se necessario)
// Numero di servomotori
const int NUM_SERVOS = 15;
// Posizioni dei servo (in gradi)
const int POS_RIposo = 0; // Piume giù (perpendicolare al corpo)
const int POS_SU = 90; // Piume su (parallelo al corpo)
// Velocità di movimento (ms tra i passi)
const int VELOCITA = 15;
// Mappatura dei servo sul PCA9685 (da 0 a 15)
const int servoPins[NUM_SERVOS] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
// Variabile per lo stato corrente
int currentPos[NUM_SERVOS];
void setup() {
// Inizializzazione seriale per debug
Serial.begin(9600);
Serial.println("Cappello Robotico - Inizializzazione");
// Inizializzazione Bluetooth
BT.begin(9600);
// Inizializzazione PCA9685
pwm.begin();
pwm.setPWMFreq(60); // Frequenza PWM per servomotori (60Hz)
// Imposta tutti i servo a POS_RIposo all'avvio
for (int i = 0; i < NUM_SERVOS; i++) {
setServoAngle(i, POS_RIposo);
currentPos[i] = POS_RIposo;
}
Serial.println("Pronto per i comandi (R=riposo, S=su)");
}
void loop() {
// Controllo Bluetooth
if (BT.available()) {
char comando = BT.read();
processCommand(comando);
}
// Controllo Seriale (per debug)
if (Serial.available()) {
char comando = Serial.read();
processCommand(comando);
}
}
void processCommand(char comando) {
switch (comando) {
case 'R':
case 'r':
Serial.println("Comando: Piume a riposo");
muoviTuttiServo(POS_RIposo);
break;
case 'S':
case 's':
Serial.println("Comando: Piume su");
muoviTuttiServo(POS_SU);
break;
default:
Serial.print("Comando non riconosciuto: ");
Serial.println(comando);
break;
}
}
void muoviTuttiServo(int targetPos) {
// Muove tutti i servo alla posizione target in modo sincronizzato
bool inMovimento;
do {
inMovimento = false;
for (int i = 0; i < NUM_SERVOS; i++) {
if (currentPos[i] != targetPos) {
inMovimento = true;
if (currentPos[i] < targetPos) {
currentPos[i]++;
} else {
currentPos[i]--;
}
setServoAngle(i, currentPos[i]);
}
}
if (inMovimento) {
delay(VELOCITA);
}
} while (inMovimento);
}
void setServoAngle(int servoNum, int angle) {
// Converte l'angolo in impulso PWM per SG90
// SG90 tipicamente usa ~500ms per 0° e ~2500ms per 180°
// PCA9685 ha una risoluzione di 4096 per 20ms (50Hz)
angle = constrain(angle, 0, 180);
int pulse = map(angle, 0, 180, 150, 600); // Valori empirici per SG90
pwm.setPWM(servoPins[servoNum], 0, pulse);
}



to conclude there is power to everything, bt communicates and responds, the servos only move the first time in the sense that they go into the rest position if the arm is moved as a first installation.



