Contrôle/commande d'une platine vinyle

Bonjour à vous,

Avant de passer pour un con : je suis totalement débutant sur Arduino. :slight_smile:
J'essaye de réaliser la partie contrôle commande de l'entrainement du plateau d'une platine vinyle. L'entrainement se fera donc par courroie et driver par un moteur DC.
Ayant une formation en domotique et génie climatique, j'aimerais me rapprocher de ce qui fonctionne pas mal en régulation de chaufferie : les PID avec correction d'erreur.
J'ai donc trouver cette librairie qui m'a l'air parfaite et que j'ai donc mis en œuvre dans mon code en pièce jointe.

J'ai donc le matériel suivant :

Le tout câblé comme dans l'image jointe.
Mon moteur DC est alimenté par un transformateur torique 2x15V et 150VA. La régulation de l'alimentation est des plus classique avec pont de diode et condos de filtrage.
J'utilise aussi un petit convertisseur AC/DC pour générer le 5v nécessaire pour les modules complémentaires de l'Arduino.
Bien sûr, comme je suis nul :confused: , je rencontre plusieurs problèmes :

  • Mon petit interrupteur 3 positions est certainement mal câblé car impossible de changer de consigne moteur (fonction "chsRPM()")
  • La mesure de vitesse de rotation du plateau est remise à zéro en permanence, je pense que cela viens de la fonction Interrupt (fonction 'rpm_calc()")
  • La commande du module MOSFET ne décolle pas de zéro alors que la valeur sur la pin PWN est à 255 (fonction "fonc_pil_mot()")

Pouvez-vous m'apporter votre aide sur ces points ?

Merci par avance :slight_smile: .
Vincent,

Proto_plat.ino (6.13 KB)

Je met le code ici, il ne rentrait pas dans le premier post :

#include <PID_v1.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// Déclare l'adressse série de l'afficheur (0x3F) avec 16 char de long et 2 lignes
LiquidCrystal_I2C lcd(0x3F,16,2);

// Déclaration des PIN
const int phot_res=2; //pin de la DO de la photoresistance
const int speed_33=7; //pin du sélecteur vitesse 33 rpm
const int speed_45=8; //pin du sélecteur vitesse 45 rpm
const int com_mot=3; //pin de la commande relais moteur
const int transi_mot=5; // Pin du PWN module transistor pilotage moteur

// Variables du code pour calcul RPM
float cons_rpm=0; // Consigne vitesse en RPM dans le loop 
volatile byte rev_plat; // varibale correspondant aux de révolution du plateau
float rpm_count; // RPM calculé
unsigned long timeold; // compteur de temps entre deux calcul de révolution

// Variables pour PID de consigne moteur
float cons_mot=0;
//Define the aggressive and conservative Tuning Parameters
double aggKp=4, aggKi=0.2, aggKd=1;
double consKp=1, consKi=0.05, consKd=0.25;
//Convertion en double des float de mesure et consigne
double rpm_count_double=0, cons_mot_double=0, cons_rpm_double=0;
// Déclaration du PID
PID motPID(&rpm_count_double, &cons_mot_double, &cons_rpm_double, consKp, consKi, consKd, DIRECT); 

// Varible pour pilotage MOSFET 
float cons_old;

void setup() 
{
  // put your setup code here, to run once:
  pinMode(phot_res, INPUT_PULLUP);
  pinMode(speed_33, INPUT_PULLUP);
  pinMode(speed_45, INPUT_PULLUP);
  pinMode(com_mot, OUTPUT);
  pinMode(transi_mot, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(phot_res), rpm_fun, RISING);
  
  rev_plat = 0; // Initialisation des valeurs
  rpm_count = 0;
  timeold = 0;
  cons_old=0;
  
  motPID.SetMode(AUTOMATIC);
  lcd.init(); // Cette ligne et celles d'en dessous commençant par "lcd." initialisent l'écran
  lcd.backlight();
  lcd.noCursor();

  //Com moniteur série pour débug
  Serial.begin(9600);
}

void loop() 
{
  // put your main code here, to run repeatedly:
  func_affich();// Actu de l'affichange
  cons_rpm=chxRPM(); // Appelle chxRPM qui choisie la consigne RPM
  rpm_count=rpm_calc(); // calcule le RPM et le stock dans rpm_count
  fonc_pil_mot(); //consigne sur transis de pilotage moteur & démarrage moteur (PID)
  debug_moni();
}

float chxRPM() //Sélecteur de vitesse (choix de la consigne de vitesse)
{
  float rpm=0;
  if (digitalRead(speed_45)==HIGH) // à 0=33rpm, à 1=45rpm
  {
    rpm=45;
  }
    else
    {
      if (digitalRead(speed_33)==HIGH) // à 0=33rpm, à 1=45rpm
      {
        rpm=100/3;
      }
    }  
  return rpm;
}

void start_mot(float valeur_rpm) //pilote le relais d'actionnement moteur
{
  if (valeur_rpm!=0) // Pilote le relais, l'allume si une consigne est demandé sur le commutateur 2 positions
  {
    digitalWrite(com_mot, HIGH); 
    if(cons_mot=0)//Si il n'y a aucune donnée de pilotage moteur (état du mosfet au démarrage) ...
    {
      cons_mot=95; // Lance un premier coup le moteur
    }
  }  
  else
  {
    digitalWrite(com_mot, LOW);
  }
}

void rpm_fun()
{
  rev_plat++;
  // Compteur de révolutions plateau
}

float rpm_calc() // Calcul du RPM
{
  float calc_rpm=0; //variable pour la boucle
  if (millis() - timeold >= 1000) //Met à jour le compteur de RPM toutes les secondes 
  { 
    detachInterrupt(0);//empèche les interrupt le temps du calcul
    calc_rpm = rev_plat * 60; // Converti en RPM, à raison de 1 interruption par rotation
    rev_plat = 0; // Remet à zéro le compteur de rév
    timeold = millis(); // met à jour le compteur de temps entre 2 calcul
    attachInterrupt(digitalPinToInterrupt(phot_res), rpm_fun, RISING); //rétabli les interrupt
 }
 return calc_rpm; //renvoie la vitesse en RPM
}

void fonc_pil_mot()
{
  
  //conversion float double
  rpm_count_double=rpm_count*100;
  cons_mot_double=cons_mot*100;
  cons_rpm_double=cons_rpm*100;
  
  //Rappel :
  //
  //PID motPID(&rpm_count_double, &cons_mot_double, &cons_rpm_double, consKp, consKi, consKd, DIRECT); 
  double gap = abs(cons_mot_double-rpm_count_double); //écart entre consigne et mesure (rappel c'est x100)

  if (gap < 20)
  {  //we're close to setpoint, use conservative tuning parameters
    motPID.SetTunings(consKp, consKi, consKd);
  }
  else
  {
     //we're far from setpoint, use aggressive tuning parameters
     motPID.SetTunings(aggKp, aggKi, aggKd);
  }
  motPID.Compute();
  
  //conversion double float
  rpm_count=rpm_count_double/100;
  cons_mot=cons_mot_double/100; 
  cons_rpm=cons_rpm_double/100;

  pil_trans_mot(cons_mot, cons_old);
      
  start_mot(cons_rpm);
  cons_old = cons_mot;
}

void func_affich() // Actu de l'affichange
{
  int err=0;
  err=(cons_rpm/rpm_count)*100;
  lcd.home();
  lcd.print("Cs:");
  lcd.print(cons_rpm); // Affiche la consigne
  lcd.print("|Me:");
  lcd.print(rpm_count); // Affiche la mesure
  lcd.setCursor(0,1);
  lcd.print("Mot:");
  lcd.print(digitalRead(com_mot)); // Donne l'état de la commande moteur
  lcd.setCursor(8,1);
  lcd.print("Err:"); // Affiche l'erreur Cons/mesure (variable err)
  lcd.print(err);
  lcd.setCursor(15,1);
  lcd.print("%");
}

void pil_trans_mot(float consigne, float old_cons)
{
  
  if (consigne<64) // Etalonne la commande transistor sur 64-->255 (6V-->24V, soit les valeurs limites du moteur)
  {
    consigne = 64;
  }
  if (consigne>255)
  {
    consigne = 255;
  }
  
  int a=consigne;
  int b=old_cons;  
  if (consigne <= old_cons) // Détermine si la vitesse cible diminue ou augmente
  {
    for(int x = b; x <= a; x++) // Si elle augmente, augmente la tension progressivement
    {
      analogWrite(transi_mot, x);
      delay(5);
    }
  }
  else
  {
    for(int x = b; x >= a; x--) // diminue progressivement
    {
      analogWrite(transi_mot, x);
      delay(5);
    }
  }
}

//Fonction pour débug moniteur série
void debug_moni()
{
  Serial.print("Etat photores");
  Serial.print(digitalRead(phot_res));
  Serial.print("Mesure rpm");
  Serial.print(rpm_count);
  Serial.print("Consigne RPM (ds loop)");
  Serial.print(cons_rpm);
  Serial.print("Consignes émise transistor pilotage moteur");
  Serial.print(analogRead(transi_mot));
  Serial.print("Dernière consignes stockée");
  Serial.print(cons_mot);
  Serial.print("Commande relai moteur");
  Serial.print(digitalRead(com_mot));
}