Page 1 sur 1

Pour un PN: galère avec les servos et le mp3

MessagePublié: Sam 01 Sep 2018, 10:44
par bruno51
Bonjour à tous,
j'ai débuté la fabrication d'un ensemble arduino composé d'une carte et d'un lecteur mp3 pour piloter un passage à niveau.
Mon problème se situe dans l'écriture du programme.
J'ai pour l'instant, deux programmes qui fonctionnent très bien indépendamment:
- Le premier active le clignotement d'une led et la lecture d'un fichier MP3 de sonnerie ->OK
- Le second commande 2 servos et le clignotement d'une led ->OK

Je précise que pour des raisons de cablage, la commande est sommaire avec un interrupteur: ON=fermeture PN et OFF=Ouverture barrière.

Ca se complique quand je veux intégrer la lecture du fichier MP3 dans le programme de base (avec les servos et la led). Quelqu'un aurait une idée?

Re: Pour un PN: galère avec les servos et le mp3

MessagePublié: Sam 01 Sep 2018, 10:46
par bruno51
Voici le programme "MP3 et led"

#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>
SoftwareSerial DFPlayerSerial( 11 ,10 ); // RX, TX

// Declaration des types des variables
int pinBouton;
int pinLedRouge;

void setup()
{
// Initialisation des variables et modes
pinBouton = 4; // Déclaration Pin pour bouton -> Pin4
pinMode(pinBouton, INPUT_PULLUP); // Déclaration mode lecture (entrée) pour le bouton sur le Pin4
pinLedRouge = 12; // Déclaration Pin pour led clignotante -> Pin12
pinMode(pinLedRouge, OUTPUT); // Déclaration mode écriture (sortie) pour la led sur le Pin12

// Config liaison série avec le lecteur
Serial.begin( 115200 );
Serial.print( "\n\nDFPlayer_Mini_Mp3\n" );
DFPlayerSerial.begin( 9600 );
mp3_set_serial( DFPlayerSerial );
// Config lecteur
mp3_set_device( 2 ); // Déclaration emplacement son sur lecteur -> 2 pour "Carte SD"
mp3_set_volume( 0 ); // Initailisation du volume -> 0/30
mp3_play (1); // Lancement lecture fichier 0001.mp3
mp3_single_loop (true); // Répétition du fichier de elcture
}

void loop() // DEBUT BOUCLE LOOP

{
boolean etatBouton = digitalRead(pinBouton); // lecture de l'état du bouton et stockage dans etatBouton

if (etatBouton==HIGH) // test si bouton en position OUVERTURE ou FERMETURE
{
digitalWrite(pinLedRouge,LOW); // Extinction Led Rouge
mp3_set_volume( 0 ); // Arret sonnerie -> Volume 0/30
}
else
{
mp3_set_volume( 15 ); // Activation Sonneire -> Volume 15/30
digitalWrite(pinLedRouge, millis() / 500 % 2 ); // Clignotement led rouge
}

} // FIN BOUCLE LOOP


et voici le programme "Servos et led"
#include <Servo.h> // Intégration bibliothèque Servo
Servo monServo1; // Application bibilotèque au servo1
Servo monServo2; // Application bibilotèque au servo2

// REGLAGE DES POSITIONS HAUT/BAS
const int PosBasse1 = 1874; // Position basse de la barrière - mini Servo 1 connecté au pin 2
const int PosHaute1 = 1318; // Position haute de la barrière - mini Servo 1 connecté au pin 2
const int PosBasse2 = 1874; // Position basse de la barrière - mini Servo 2 connecté au pin 3
const int PosHaute2 = 1318; // Position haute de la barrière - mini Servo 2 connecté au pin 3
const int delai = 5; // REGLAGE DE LA VITESSE MOUVEMENT SERVO (introduit un délai entre chaque pas)

// Declaration des types des variables
int pinLedRouge;
int pinBouton;
int vitesse; // Variable représentant le sens positif ou négatif
int Pos1; // Variable représentant la valeur de la consigne du servo 1
int Pos2; // Variable représentant la valeur de la consigne du servo 2



void setup()
{
monServo1.attach(2); // Attachement du Servo1 au Pin2
monServo2.attach(3); // Attachement du Servo2 au Pin3
Pos1 = PosHaute1; // Initialisation du Servo1 en position haute
Pos2 = PosHaute2; // Initialisation du Servo2 en position haute
vitesse = 1;
// Initialisation des variables et modes
pinBouton = 4; // Déclaration Pin pour bouton -> Pin4
pinMode(pinBouton, INPUT_PULLUP); // Déclaration mode lecture (entrée) pour le bouton sur le Pin4
pinLedRouge = 12; // Déclaration Pin pour led clignotante -> Pin12
pinMode(pinLedRouge, OUTPUT); // Déclaration mode écriture (sortie) pour la led sur le Pin12

}

void loop()
{
boolean etatBouton = digitalRead(pinBouton); // lecture de la position du bouton et stockage dans etatBouton

if (etatBouton==HIGH and Pos1 >= PosHaute1) {
monServo1.writeMicroseconds(Pos1);
Pos1 = Pos1 - vitesse; // Calcul du nouvel angle pour Servo1
}

if (etatBouton==LOW and Pos1 <= PosBasse1) {
monServo1.writeMicroseconds(Pos1);
Pos1 = Pos1 + vitesse; // Calcul du nouvel angle pour Servo1
}

if (etatBouton==HIGH and Pos2 >= PosHaute2) {
monServo2.writeMicroseconds(Pos1);
Pos2 = Pos2 - vitesse; // Calcul du nouvel angle pour Servo2
}

if (etatBouton==LOW and Pos2 <= PosBasse2) {
monServo2.writeMicroseconds(Pos1);
Pos2 = Pos2 + vitesse; // Calcul du nouvel angle pour Servo2
}

delay (delai);

// Clignotement Led Rouge si Interrupteur en position basse ou si position servo non haute
if (etatBouton=LOW or Pos1>PosHaute1){
digitalWrite(pinLedRouge, millis() / 500 % 2 ); // Clignotement Led Rouge
}
else {
digitalWrite(pinLedRouge,LOW); // Extinction Led Rouge
}


} // Fin de boucle Loop

Re: Pour un PN: galère avec les servos et le mp3

MessagePublié: Jeu 06 Sep 2018, 21:06
par Barbadidoua
Bonsoir Bruno,

Voici ce que je suis en train de faire pour mon club (AMFBC73)
- Arduino Nano
- DFplayer Mini
- 4 servo moteurs
- LCD 2*16 I2C (optionnel)


Code: Tout sélectionner
/* =====================================================
* PN AMFBC Oscillant
* - 4 1/2 barrieres
* - Cloche
* - Feux clignotants
*
* librairie SlowMotionServo
* http://www.locoduino.org/spip.php?article159
*
* ouverture avec rebond, fermeture sans rebond
* Clignotement 4 secondes avant fermeture
* Ouverture immediate, arret clignotement
   ==================================================== */

#include <Servo.h>
#include <SlowMotionServo.h>
#include <Bounce2.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,20,2); // set the LCD address to 0x27 for a 16 chars and 2 line display
#include <SoftwareSerial.h>
#include <DFPlayer_Mini_Mp3.h>

SMSLinear monServo;
SMSSmoothBounce myS0;
SMSSmoothBounce myS1;
SMSSmoothBounce myS2;
SMSSmoothBounce myS3;

#define ledPin  13
#define RetardFermeture 4

float         servoTarget = 1.0;
bool          Move=false;
const long    interval = 1000;
unsigned long previousMillis = 0;
int           ledState = LOW;
int           cpt;

// ========================================================
// Gestion de la communication PC via USB
String inputString = "";        // Chaine permettant de recevoir les informations du PC via USB
boolean stringComplete = false; // Drapeau indiquant que la chaine recue est complete (finit par CR)

// ========================================================
// Gestion du son
int Volume=30;                  // Sound volume
// ========================================================
SoftwareSerial DFPlayerSerial( 8, 7 );  // RX, TX vers DF_Player
#define BusyPin 6                       // DF-Player playing
#define Servo1Pin 2                     // Servo 1
#define Servo2Pin 3                     // Servo 2
#define Servo3Pin 4                     // Servo 3
#define Servo4Pin 5                     // Servo 4

// ========================================================
// USB console interface.
// cmd syntax :2 digits, first digit is action, second digit is parameter
// cmd syntax: letter + number, letter is cmd as per table below, number is the new value for relevant variable
// ========================================================
#define  Msg_Patience          "Patientez S.V.P."
#define  Msg_Recu_USB           "------ Recu : "

#define  Cmd_Open              "O" // Ouverture
#define  Msg_Open              "Ouverture"
#define  Cmd_Close             "F" // Fermeture
#define  Msg_Close             "Fermeture"
#define  Cmd_Toggle            "T" // Toggle
#define  Msg_Toggle            "Toggle"

#define  Cmd_Play              "A" // Avertisseur sonore
#define  Msg_Play              "Avertisseur sonore"
#define  Cmd_PlayStop          "S" // Stop Avertisseur sonore
#define  Msg_PlayStop          "Stop Avertisseur sonore"

#define  Cmd_List              "L" // List des commandes disponibles
#define  Msg_List              "Liste "
#define  Cmd_Help              "?" // Aide (commandes disponibles)
#define  Msg_Help              "Aide" // pour Aide

#define  Msg_Id                "Id "
#define  Cmd_Id                "W" // Who (identification module)
#define  Msg_Decoder           "AMFBC PN Oscillant"  // PN reseau HO Club 
#define  Msg_Vrs               "V0"

// ========================================================
#define MaxSon 4
typedef struct {
    int           Int_Nr;           // Nr fichier
    int           Int_Volume;       // Volume Angle Mini 15
    String        Str_Nom;          // Nom
} Sons;
Sons gSon[MaxSon];

// ========================================================
// USB Serial event reader
// ========================================================
void serialEvent() {
  while (Serial.available()) {
    // acquire new character:
    char inChar = (char)Serial.read();
    // if it is LF, set flag for so main loop takes message into account:
    if (inChar == '\n') {
      stringComplete = true;
    } else {
    // else add this character to being build message:
      inputString += inChar;
    }
  }
}

// ========================================================
// Display help (list of available commands)
// ========================================================
void Help() {
  Serial.print(Msg_Decoder);Serial.print(" ");Serial.println(Msg_Vrs);
  Serial.print(Cmd_Open);Serial.print(" : "); Serial.println(Msg_Open);
  Serial.print(Cmd_Close);Serial.print(" : "); Serial.println(Msg_Close);
  Serial.print(Cmd_Toggle);Serial.print(" : "); Serial.println(Msg_Toggle);
  Serial.print(Cmd_Play);Serial.print(" : "); Serial.println(Msg_Play);
  Serial.print(Cmd_PlayStop);Serial.print(" : "); Serial.println(Msg_PlayStop);

  Serial.print(Cmd_List);Serial.print(" : "); Serial.println(Msg_List);

  Serial.print(Cmd_Help);Serial.print(" : "); Serial.println(Msg_Help);
  Serial.print(Cmd_Id);Serial.print(" : "); Serial.println(Msg_Id);
  Serial.println();
}

// ========================================================
// Line, Column, Message
// ========================================================
void lcm1602(int l, int c, String msg)
{
  lcd.setCursor(c,l);
//  lcd.print(msg);
  for (int i=0;i<msg.length();i++) {
    lcd.print(msg.substring(i,i+1));
  }   


// ========================================================
// Play a track
// ========================================================
void Track_Play(int Int_Track) {
    Serial.print("Play ");
    Serial.print(gSon[Int_Track].Int_Nr);
    Serial.print(" ");
    Serial.print(gSon[Int_Track].Str_Nom);
    Serial.print(" ");
    mp3_set_volume(0);
    mp3_play(gSon[Int_Track].Int_Nr);
    mp3_set_volume(gSon[Int_Track].Int_Volume);
    while (digitalRead(BusyPin) == LOW ) {
      //Serial.print(".");
    };
    Serial.println("Done");
}

// ========================================================
void setup()
{
  lcd.init();                      // initialize the lcd NOT IN LIB
  lcd.backlight();                 // Retro eclairage
  lcm1602(0,0,Msg_Decoder);        // +Msg_Vrs
  lcm1602(0,0,"               ");

  Serial.begin(115200);
  Serial.println("Test librairie SlowMotionServo");
  pinMode(ledPin, OUTPUT);

  //myS0.setMin(1015);
  //myS0.setMax(1180);
  myS0.setMinMax(700,2000);      // 544 à 2400
  myS0.setMinToMaxSpeed(7.0);
  myS0.setMaxToMinSpeed(3);
  //myS0.setSpeed(5);
  myS0.setReverted(false);
  myS0.setInitialPosition(1.0);
  myS0.setPin(Servo1Pin);

  myS1.setMinMax(700,2000);      // 544 à 2400
  myS1.setMinToMaxSpeed(7.0);
  myS1.setMaxToMinSpeed(3);
  myS1.setReverted(true);
  myS1.setInitialPosition(1.0);
  myS1.setPin(Servo2Pin);

  myS2.setMinMax(700,2000);      // 544 à 2400
  myS2.setMinToMaxSpeed(7.0);
  myS2.setMaxToMinSpeed(3);
  myS2.setReverted(false);
  myS2.setInitialPosition(1.0);
  myS2.setPin(Servo3Pin);

  myS3.setMinMax(700,2000);      // 544 à 2400
  myS3.setMinToMaxSpeed(7.0);
  myS3.setMaxToMinSpeed(3);
  myS3.setReverted(true);
  myS3.setInitialPosition(1.0);
  myS3.setPin(Servo4Pin);

  pinMode(BusyPin, INPUT);
  DFPlayerSerial.begin(9600);
  mp3_set_serial(DFPlayerSerial);
  mp3_set_device(2);                      // Carte SD
  mp3_set_volume(Volume);                 // 0-30

  gSon[0].Int_Nr=1;                       // Nr
  gSon[0].Int_Volume=30;                  // Volume
  gSon[0].Str_Nom="PN";                   // Nom

  Help();
}

// ========================================================
void loop()
{
  SlowMotionServo::update(); /* actualisation de la position */

  // USB received data management:
  if (stringComplete) {
    inputString.toUpperCase();
    Serial.print(Msg_Recu_USB);
    Serial.println(inputString);
    String c = inputString.substring(0,1);
    int V=inputString.substring(1).toInt();
    if (c==Cmd_Help) {               // ...................... Help (Aide)
      Help();
    } else if (c==Cmd_Close) {       // ...................... Fermeture
      Serial.println(Msg_Close);
      lcm1602(0,0,"Fermeture      ");
      cpt=0;
      servoTarget = 0;
    } else if (c==Cmd_Open) {        // ...................... Ouverture
      cpt=0;
      Serial.println(Msg_Open);
      lcm1602(0,0,"Ouverture      ");
      servoTarget = 1.0;
    } else if (c==Cmd_Toggle) {      // ...................... Toggle
      if (servoTarget!=1.0) {
        cpt=0;
        Serial.println(Msg_Open);
        lcm1602(0,0,"Ouverture      ");
        servoTarget = 1.0;
      } else {
        Serial.println(Msg_Close);
        lcm1602(0,0,"Fermeture      ");
        cpt=0;
        servoTarget = 0;
      }     
    } else if (c==Cmd_Play) {        // ...................... Sonnerie
      Serial.println(Msg_Play);
      Track_Play(1);
    } else if (c==Cmd_PlayStop) {    // ...................... Sonnerie Stop
      Serial.println(Msg_PlayStop);
      mp3_stop();
    } else if (c==Cmd_Id) {          // ...................... Who ?
      Serial.print(Msg_Decoder);
      Serial.print(" ");
      Serial.println(Msg_Vrs);
    } else Serial.println("unknown message");
    inputString = "";
    stringComplete = false;
  }

  // Gestion du temps apres la demande
  unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
   
    if (myS0.isStopped()) {
      if (cpt == RetardFermeture && servoTarget!=1.0) {             // Fermeture apres 4 secondes
        myS0.goTo(servoTarget);
      } else if (cpt==0 && servoTarget==1.0) {        // Ouverture immediate
        myS0.goTo(servoTarget);
      }
    }

    if (myS1.isStopped()) {
      if (cpt == RetardFermeture && servoTarget!=1.0) {             // Fermeture apres 4 secondes
        myS1.goTo(servoTarget);
      } else if (cpt==0 && servoTarget==1.0) {        // Ouverture immediate
        myS1.goTo(servoTarget);
      }
    }

    if (myS2.isStopped()) {
      if (cpt == RetardFermeture && servoTarget!=1.0) {             // Fermeture apres 4 secondes
        myS2.goTo(servoTarget);
      } else if (cpt==0 && servoTarget==1.0) {        // Ouverture immediate
        myS2.goTo(servoTarget);
      }
    }

    if (myS3.isStopped()) {
      if (cpt == RetardFermeture && servoTarget!=1.0) {             // Fermeture apres 4 secondes
        myS3.goTo(servoTarget);
      } else if (cpt==0 && servoTarget==1.0) {        // Ouverture immediate
        myS3.goTo(servoTarget);
      }
    }

    // Clignottement des la demande de fermetuer. Arret à l'ouverture
    if (ledState == LOW && servoTarget!=1.0) {
      cpt = cpt+1;
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
}


En espérant avoir ouvert quelques portes ...

Amicalement,
Xavier

Re: Pour un PN: galère avec les servos et le mp3

MessagePublié: Ven 07 Sep 2018, 08:01
par bruno51
Bonjour Xavier et merci pour le partage de ton programme!!

C'est un programme qui fonctionne et que tu as pu tester en réel avec tes servos ou tu en es au stade de l'écriture?

Je vais éplucher ça et chercher des pistes de solution. A première lecture, j'ai quelques questions:
- quel est le déclencheur de la commande? c'est une entrée arduino (interrupteur, ILS)?
- quand tu utilise "BusyPin", tu cables la broche "Busy" de ton lecteur MP3 sur le Pin6? et pourquoi exploites tu cette info?

Depuis mon post, j'ai fouillé internet et je pense avoir découvert le problème: la bibilotèque "Servo.h" et la bibliothèque "DFPlayer_Mini_Mp3.h" semblent incompatibles à cause de l'utilisation simultanée de la liaison série. Je vais essayer avec une autre bibliothèque pour servos.
Pourtant je vois que tu as utilisé ces 2 bibliothèques + SlowmotionSErvo.h

Re: Pour un PN: galère avec les servos et le mp3

MessagePublié: Ven 07 Sep 2018, 17:37
par Barbadidoua
Bonjour Bruno

Le programme fonctionne en test avec DFPlayer, 2 servos, et la ledpin 13 de l'arduino.
Les Pin A0-A1, libres seront utilisées par la suite en entrée sur des détection par consommation de courant opto-couplées, un par voie pour un PN a 2 voies:
- Fermeture si au moins une des voies est occupée.
- Ouverture si les deux voies sont libres.

Pour les tests, j'utilise l'IDE Arduino (115200 bauds + CR et LF) pour envoyer des commandes via USB depuis mon PC. Les commandes sont sur 1 caractère. La liste des commandes s'affiche au démarrage.
Elles sont définies comme suit :
#define Cmd_Open "O" // Ouverture
#define Cmd_Close "F" // Fermeture
#define Cmd_Toggle "T" // Toggle
D'ailleurs les #define sont utilisés pour le paramétrage en général.

J'utilise la bibliothéque "SoftwareSerial" pour dialoguer avec DFPlayer. Je peux ainsi utiliser l'USB pour dialoguer avec l'IDE (pratique pour le debug!)

La structure du programme est celle que j'adopte pour la plupart de mes projets.
Je bannie autant que faire se peut les "delay" (qui bloquent tout le reste) au profit d'une gestion du temps dans la boucle loop, comme le "BlinkWithoutDelay" des exemples Arduino: L'utilisation de la bibliothèque "SlowMotionServo" simplifie grandement la gestion des servomoteurs, et permet en plus de simuler le rebond des barrières.

La Pin Busy est à 1 temps que le fichier MP3 est joué, ce qui n'empêche pas de le stopper si nécessaire. Ainsi, je pourrai boucler sur le fichier si ce dernier ne dure pas assez longtemps.

Le Lcd est pour la mise au point et sera retiré par la suite.

J'utilise cet exemple pour former d'autres personnes à Arduino au sein du club où je sévis.

Amicalement,

Xavier