Servos + Audio simultanément ?

Bonjour,

Je suis un néophyte d'Arduino et je cherche un moyen de commander simultanément des servomoteurs et de l'audio. J'utilise le PCA9685 d'Adafruit (contrôleur PWM/Servo 16 canaux) et le Catalex Serial MP3 Player V1.0 reliés à une carte Mega 2560 indépendante. Les deux codes fonctionnent individuellement mais une fois combinés, impossible de les faire marcher en même temps. La musique se lance normalement mais les servos démarrent avec un délai de dix minutes (Ce qui correspond, à ce que j'ai pu comprendre, à la ligne "delay(1000000);//the programm will send the play option each 100 seconds to the catalex chip" de la partie audio). Quelqu'un pourrait-il m'indiquer comment corriger ce problème ?

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <SoftwareSerial.h>

Adafruit_PWMServoDriver pwm = Adafruit_PWMServoDriver( 0x40 );

#define SERVOMIN  150 // La longueur d'impulsion 'minimale' (valeur du compteur, max 4096)
#define SERVOMAX  600 // La longueur d'impulsion 'maximale' (valeur du compteur, max 4096)

// Servos Commandés - Numéro de sorties sur le breakout
uint8_t servo1 = 9;
uint8_t servo2 = 10;

#define ARDUINO_RX 5//should connect to TX of the Serial MP3 Player module
#define ARDUINO_TX 6//connect to RX of the module
SoftwareSerial mySerial(5, 6);//init the serial protocol, tell to myserial wich pins are TX and RX

////////////////////////////////////////////////////////////////////////////////////
//all the commands needed in the datasheet(http://geekmatic.in.ua/pdf/Catalex_MP3_board.pdf)
static int8_t Send_buf[8] = {0} ;//The MP3 player undestands orders in a 8 int string
                                 //0X7E FF 06 command 00 00 00 EF;(if command =01 next song order) 
#define NEXT_SONG 0X01 
#define PREV_SONG 0X02 

#define CMD_PLAY_W_INDEX 0X03 //DATA IS REQUIRED (number of song)

#define VOLUME_UP_ONE 0X04
#define VOLUME_DOWN_ONE 0X05
#define CMD_SET_VOLUME 0X06//DATA IS REQUIRED (number of volume from 0 up to 30(0x1E))
#define SET_DAC 0X17
#define CMD_PLAY_WITHVOLUME 0X22 //data is needed  0x7E 06 22 00 xx yy EF;(xx volume)(yy number of song)

#define CMD_SEL_DEV 0X09 //SELECT STORAGE DEVICE, DATA IS REQUIRED
                #define DEV_TF 0X02 //HELLO,IM THE DATA REQUIRED
                
#define SLEEP_MODE_START 0X0A
#define SLEEP_MODE_WAKEUP 0X0B

#define CMD_RESET 0X0C//CHIP RESET
#define CMD_PLAY 0X0D //RESUME PLAYBACK
#define CMD_PAUSE 0X0E //PLAYBACK IS PAUSED

#define CMD_PLAY_WITHFOLDER 0X0F//DATA IS NEEDED, 0x7E 06 0F 00 01 02 EF;(play the song with the directory \01\002xxxxxx.mp3

#define STOP_PLAY 0X16

#define PLAY_FOLDER 0X17// data is needed 0x7E 06 17 00 01 XX EF;(play the 01 folder)(value xx we dont care)

#define SET_CYCLEPLAY 0X19//data is needed 00 start; 01 close

#define SET_DAC 0X17//data is needed 00 start DAC OUTPUT;01 DAC no output
////////////////////////////////////////////////////////////////////////////////////


void setup() {

  Serial.begin(9600);
  Serial.println("Controle des Servo Moteur #1 et #2!");

  pwm.begin();
  
  pwm.setPWMFreq(60);  // Les servo sont mis-à-jour à ~60 Hz
  Serial.println("Fin de setup()");

  mySerial.begin(9600);//Start our Serial coms for THE MP3
delay(500);//Wait chip initialization is complete
   sendCommand(CMD_SEL_DEV, DEV_TF);//select the TF card  
delay(200);//wait for 200ms
}

void loop() {

  sendCommand(CMD_PLAY_WITHVOLUME, 0X0F01);//play the first song with volume 15 class
  delay(1000000);//the programm will send the play option each 100 seconds to the catalex chip


  //--- Controle du Premier Servo (no 1) ---
  Serial.println("Servo #1 à 45 degrés");
  // Transformation de degré (0 à 180) en pulse (SERVOMIN à SERVOMAX)
  int pulseLen = map( 45, 0, 180, SERVOMIN, SERVOMAX );
  pwm.setPWM(servo1, 0, pulseLen);
  
  delay(1000);
  
  //--- Controle du Deuxieme Servo (no 2) ---
  Serial.println("Servo #2 à 30 degrés");
  pulseLen = map( 30, 0, 180, SERVOMIN, SERVOMAX );
  pwm.setPWM(servo2, 0, pulseLen);
  
  delay(1000);
  
  //--- Controle du Premier Servo (no 1) ---
  Serial.println("Servo #1 à 120 degrés");
  // Transformation de degré (0 à 180) en pulse (SERVOMIN à SERVOMAX)
pulseLen = map( 120, 0, 180, SERVOMIN, SERVOMAX );
  pwm.setPWM(servo1, 0, pulseLen);
  
  delay(1000);

  //--- Controle du Deuxieme Servo (no 2) ---
  Serial.println("Servo #2 à 150 degrés");
  pulseLen = map( 150, 0, 180, SERVOMIN, SERVOMAX );
  pwm.setPWM(servo2, 0, pulseLen);
  
  delay(1000);
  
  //--- Les deux servo à 0 ---
  Serial.println("Servo #1 et #2 à 150 degrés");
  pulseLen = map( 0, 0, 180, SERVOMIN, SERVOMAX );
  pwm.setPWM(servo1, 0, pulseLen);
  pwm.setPWM(servo2, 0, pulseLen);
  
  delay(3000); 
}


void sendCommand(int8_t command, int16_t dat)
{
 delay(20);
 Send_buf[0] = 0x7e; //starting byte
 Send_buf[1] = 0xff; //version
 Send_buf[2] = 0x06; //the number of bytes of the command without starting byte and ending byte
 Send_buf[3] = command; //
 Send_buf[4] = 0x00;//0x00 = no feedback, 0x01 = feedback
 Send_buf[5] = (int8_t)(dat >> 8);//datah
 Send_buf[6] = (int8_t)(dat); //datal
 Send_buf[7] = 0xef; //ending byte
 for(uint8_t i=0; i<8; i++)//
 {
   mySerial.write(Send_buf[i]) ;//send bit to serial mp3
   Serial.print(Send_buf[i],HEX);//send bit to serial monitor in pc
 }
 Serial.println();
}

Merci d'avance

en enlevant le delay(1000000); :slight_smile:

(cf les tutos sur la gestion du temps avec millis())

Il est clair que tu vas devoir supprimer ce délai.

Ensuite, à la fin du morceau de musique, tout dépend de ce que tu veux faire. Rejouer le même morceau ou un autre ?

Il existe une librairie : GitHub - MajicDesigns/MD_YX5300: Library for Serial MP3 Player based on YX5300 IC (Catalex Module)

Soit tu l'utilises, soit tu t'en inspires pour créer une commande genre getStatus qui te permettra de savoir si le morceau est terminé.

Merci pour vos réponses,

Si je supprime le delay(1000000); les servos démarrent effectivement tout de suite mais la musique reste bloquée sur les premières secondes qui se rejouent en boucle. J'ai regardé le tuto sur millis() mais j'ai du mal à comprendre comment l'utiliser dans ce contexte.

Je n'ai besoin que d'un seul morceau.
J'ai testé la librairie mais elle ne marche pas (Pas de musique) et je ne m'y connais malheureusement pas assez pour savoir comment créer une commande comme getStatus.

Le problème est que cette ligne :

sendCommand(CMD_PLAY_WITHVOLUME, 0X0F01);

est exécutée à chaque entrée dans la fonction loop, en boucle.
A la fin de la loop, elle est appelée à nouveau, d'où ton problème. Les temps cumulés des delay() = 7s.
Il faut que tu mémorises le fait qu'un morceau est en cours d'écoute :

static bool playing;

if (!playing) {
  sendCommand(CMD_PLAY_WITHVOLUME, 0X0F01);
  playing = true;
}

Ensuite il faudra bien remettre cette variable playing à zéro.
Et tu vas être obligé de consulter l'état du player pour savoir quand le morceau est terminé.

Cette librairie a l'air bien foutue.
Il y a un exemple qui utilise les mêmes pins RX TX que dans ton code.

Tu devrais insister.
Il faut toujours profiter du travail des autres ...

Merci beaucoup, je comprends déjà mieux, le code marche parfaitement.
Je vais retester la librairie, par contre est-il possible d'augmenter le volume de la musique ?

Avec 15 tu es déjà au maximum.

1W ce n'est pas grand chose.
Adopter un haut-parleur à plus haut rendement ou un ampli.
Tout dépend de ce que tu veux obtenir comme puissance.

Oui, c'est bien ce que je pensais , je vais changer le haut parleur et installer un amplificateur audio le " LM386"
que j'ai commandé pour moins d'1 euro . Encore merci hbachetti pour ton aide précieuse .

Un LM386 risque d'être un peu léger (< 1W), c'est à dire pas mieux que le lecteur MP3.

Il faut savoir que pour avoir l'impression de doubler la puissance à l'oreille il faut multiplier par 10 la puissance efficace.

Ce n'est pas avec 5V que tu obtiendras de la puissance.

Il existe des solutions à découpage bien plus intéressantes.

TPA3118

VCC = 4.5V à 26V

TDA8932

VCC = 10V à 36V

En alimentant un TDA8932 bridgé (mono) en 12V tu obtiendras 15W.

Il te faut par contre une alimentation en conséquence : 12V 20W à découpage bien sûr.

Et un potentiomètre de volume ! entre 10K et 47K

Laisse le volume logiciel du lecteur MP3 à fond et règle avec le potentiomètre. Tu obtiendras un bien meilleur résultat.

En effet, le LM386 est un peu faible , je vais donc essayer le TPA318 ou le TDA8932...
Merci pour tous les conseils .