Création compte tour avec TB6612FNG et x27168

Bonjour à tous
Le programme fonctionne bien, il est stable, tout fonctionne, mais par contre je n'arrive pas a accélérer la réponse de l'aiguille, elle est beaucoup trop lente pour simuler un compte tour.
J'ai bien essayer de faire sauter des pas pour aller plus vite, mais là l'aiguille fait n'importe quoi...
Auriez vous une idée ?

#include <Arduino.h>

// --- constantes ---
const int AIN1 = 8;
const int AIN2 = 9;
const int BIN1 = 10;
const int BIN2 = 11;
const int SIGNAL_PIN = A0;
const int POT_PIN = A1;

const int STEP_DELAY = 2;       // délai standard pour fluidité
const int STEPS_INIT = 700;
const int LEFT_OFFSET = 50;
const int SIGNAL_THRESHOLD = 5;
const int DEADZONE = 3;
const int MAX_SIGNAL = 400;
const int GAIN = 9;
const int INPUT_OFFSET = 61;

// --- moyenne ---
#define NUM_SAMPLES 1
int samples[NUM_SAMPLES];
int sampleIndex = 0;

// séquence pas à pas
int steps[4][4] = {
  {1, 0, 1, 0},
  {0, 1, 1, 0},
  {0, 1, 0, 1},
  {1, 0, 0, 1}
};

int stepIndex = 0;
int currentPos = LEFT_OFFSET;
int cycleMax = STEPS_INIT;
bool initDone = false;

// --- fonctions ---
void stepMotor(int step) {
  digitalWrite(AIN1, steps[step][0]);
  digitalWrite(AIN2, steps[step][1]);
  digitalWrite(BIN1, steps[step][2]);
  digitalWrite(BIN2, steps[step][3]);
}

void setup() {
  pinMode(AIN1, OUTPUT);
  pinMode(AIN2, OUTPUT);
  pinMode(BIN1, OUTPUT);
  pinMode(BIN2, OUTPUT);
  Serial.begin(115200);

  // init buffer
  for (int i = 0; i < NUM_SAMPLES; i++) samples[i] = 0;

  // --- phase init aiguille (aller-retour complet) ---
  int potVal = analogRead(POT_PIN);
  cycleMax = map(potVal, 0, 1023, LEFT_OFFSET + 50, STEPS_INIT);

  // aller à droite
  for (int i = LEFT_OFFSET; i < cycleMax; i++) {
    stepIndex = (stepIndex + 1) % 4;
    stepMotor(stepIndex);
    delay(STEP_DELAY);
  }
  // retour gauche
  for (int i = cycleMax; i > LEFT_OFFSET; i--) {
    stepIndex = (stepIndex + 3) % 4;
    stepMotor(stepIndex);
    delay(STEP_DELAY);
  }

  currentPos = LEFT_OFFSET;
  initDone = true;

  // couper bobines
  digitalWrite(AIN1, LOW);
  digitalWrite(AIN2, LOW);
  digitalWrite(BIN1, LOW);
  digitalWrite(BIN2, LOW);
}

void loop() {
  if (!initDone) return;

  // lire et stocker l’échantillon
  samples[sampleIndex] = analogRead(SIGNAL_PIN);
  sampleIndex = (sampleIndex + 1) % NUM_SAMPLES;

  // calcul moyenne
  long sum = 0;
  for (int i = 0; i < NUM_SAMPLES; i++) sum += samples[i];
  int avgSigVal = sum / NUM_SAMPLES;

  int correctedVal = avgSigVal - INPUT_OFFSET;
  if (correctedVal < 0) correctedVal = 0;

  // recalcul cycleMax si signal très faible
  if (correctedVal < SIGNAL_THRESHOLD) {
    int potVal = analogRead(POT_PIN);
    cycleMax = map(potVal, 0, 1023, LEFT_OFFSET + 50, STEPS_INIT);
  }

  // calcul target
  int target;
  if (correctedVal < SIGNAL_THRESHOLD) {
    target = LEFT_OFFSET;
  } else {
    long calc = (long)correctedVal * (long)GAIN * (long)(cycleMax - LEFT_OFFSET);
    target = LEFT_OFFSET + (calc / MAX_SIGNAL);
    target = constrain(target, LEFT_OFFSET, cycleMax);
  }

  // déplacement vers target
  if (abs(currentPos - target) > DEADZONE) {
    if (currentPos < target) {
      stepIndex = (stepIndex + 1) % 4;
      stepMotor(stepIndex);
      currentPos++;
    } else {
      stepIndex = (stepIndex + 3) % 4;
      stepMotor(stepIndex);
      currentPos--;
    }
  }

  // debug série
  static unsigned long lastPrint = 0;
  if (millis() - lastPrint > 200) {
    lastPrint = millis();
    Serial.print("avg="); Serial.print(avgSigVal);
    Serial.print("  Target="); Serial.print(target);
    Serial.print("  Pos="); Serial.println(currentPos);
  }

  delay(10);
}

Un souci est que vous ne faites avancer le moteur que d’un seul pas par boucle, avec en plus un delay(10) qui ralentit fortement la réponse de l’aiguille.

➜ virez le delay(10) et voyez ce que ça donne. S'il y a encore trop de latence il faudra prévoir

Un autre souci est le delay(STEP_DELAY); utilisé lors des phases de déplacement ralentit aussi la vitesse de l’aiguille. 2ms c'est peut être trop, vous devriez passer en delayMicroseconds() et expérimenter des valeurs qui laisse quand même le temps au driver et à l'aiguille de réagir à la commande. Essayez avec delayMicroseconds(1000); // 1ms voire delayMicroseconds(500); // 0.5ms pour voir si ça fonctionne encore (si on va beaucoup trop bas on risque de provoquer des pertes de pas ou une aiguille instable).

merci pour votre réponse :slight_smile:
J'avais déjà essayé de descendre le STEP_DELAY , 2 c'est le mini, si je descend a 1 ça ne fonctionne plus
Si je supprime le delay ça ne fonctionne plus, je peux le réduire a 1. C'est dejà mieux mais toujours pas assez rapide.

Mais je ne comprends pas pourquoi je n'arrive pas a ne serait ce que doubler les pas.
si je modifie avec cette séquence pour le faire :

if (abs(currentPos - target) > DEADZONE) {
  if (currentPos < target) {
    stepIndex = (stepIndex + 2) % 4;  // avancer de 2 pas
    stepMotor(stepIndex);
    currentPos += 2;
    if (currentPos > target) currentPos = target; // éviter dépassement
  } else {
    stepIndex = (stepIndex - 2 + 4) % 4;  // reculer de 2 pas
    stepMotor(stepIndex);
    currentPos -= 2;
    if (currentPos < target) currentPos = target; // éviter dépassement
  }
}

plus rien ne fonctionne, l'aiguille semple avancer d'un pas et bloque ... :unamused_face:

Non, cette ligne fais sauter un pas et le moteur ne tourne plus. Tu dois toujours dérouler les 4 pas de la séquence et dans le bon ordre pour faire tourner le moteur.
Si tu veux aller plus vite il faut faire 2 pas de la séquence l'un après l'autre (avec un petit delay()) pour laisser au moteur le temps d'avancer.

Si j'ai bien compris, ton moteur fait 600 pas pour parcourir 315°. Donc, il faut dérouler les pas assez vite pour faire bouger l'aiguille. Tous les delay() que tu mets dans ton code ralentissent le mouvement.

Pour accélérer le code, il faut essayer de le simplifier au maximum.
Par exemple, la multiplication sur des long doit prendre du temps et tu pourrais certainement revoir ton algorithme pour réduire les calculs.
Par exemple, tu ajoutes LEFT_OFFSET dans le map lors du calcul de cycleMax et tu le soustrait dans le calcul de calc. Il y a moyen d'éviter ça.

Au lieu de recalculer la somme pour la moyenne à chaque itération tu peux faire

  long sum = 0; // mettre cette variable en global ou la déclarer static

  // lire et stocker l’échantillon
  int sample= analogRead(SIGNAL_PIN);
  sum = sum - samples[sampleIndex] + sample;
  samples[sampleIndex] = sample;
  sampleIndex = (sampleIndex + 1) % NUM_SAMPLES;
  int avgSigVal = sum / NUM_SAMPLES;

Cette solution est plus rapide car elle ne refait pas la somme de tous les échantillons qui sont dans le buffer.
Ceci dit, dans ton cas tu n'as que 2 échantillons donc tu pourrais sans doute faire différemment.

stepIndex = (stepIndex + 2) % 4;  // avancer de 2 pas

"Non, cette ligne fais sauter un pas et le moteur ne tourne plus."

ben, alors pourquoi ça fonctionne quand :

 stepIndex = (stepIndex + 1) % 4;

Là ça fonctionne parce que tu déroules les pas un par un dans l'ordre.

Pour faire tourner un moteur pas-à-pas, il faut suivre la séquence ci-dessous en passant par tous les pas les uns après les autres. On ne peut faire varie la vitesse qu'en jouant sur le rythme auquel on déroule les pas.

Bonjour berfaz

As tu regardé du côté du circuit VID6606, ça pourrai te faciliter le travail.
Il semblerai qu'il soit fait pour les tableaux de bord.

Cordialement
jpbbricole

Salut !
je suis allé voir ça JP, je ne connaissais pas mais il me semble un peu trop complexe pour mon utilisation... en meme temps il prend moins de place... je met ça en post it :slight_smile:

Merci fdufnews , je vais fouiller un peu de ce côté là et je reviens vous dire ou j'en suis :slight_smile: