Generare treno di impulsi

Buongiorno,
sto tornado ad utilizzare arduino per realizzare un progetto che ho nel cassetto da qualche anno : pilotare degli indicatori analogici (tipo cruscotto) in funzione della telemetria di alcuni giochi di auto.
Riesco ad interfacciarmi e comandare il tutto ma non sono molto soddisfatto del risultato.
I motori che utilizzo sono degli stepper motor per strumentazione del tipo : x27_168 (https://www.jukenswisstech.com/JSTFiles/downloads/2011/06/X27_Flyer_v1.3.pdf)
Per pilotarli utilizzo un driver apposito : https://guy.carpenter.id.au/gaugette/resources/vid/2009111391612_VID6606%20manual%20060927.pdf

Il driver si basa su due segnali : uno che indica la direzione di rotazione CW-CCW ed un secondo che è un treno di impulsi, ad ogni impulso corrisponde uno step.

Il mio algoritmo deve :

    1. ricevere N byte di dati dalla seriale
    1. capire il valore di un parametro ex: Velocità e calcolarne il delta rispetto alla Velocità del ciclo precedente
      -3) convertire questo delta nel numero di impulsi da fornire al driver.

Questo funziona correttamente se utilizzo solo uno strumento analogico e qualche led di indicazione.
Nel momento in cui vado ad inserire anche l'indicatore di RPM noto che viene introdotta della latenza tra il salire di giri del gioco e l'attuazione.
Questo è dovuto al modo in cui creo gli impulsi, purtroppo sto utilizzando dei delay non conoscendo un modo più efficiente.
Questo è il codice di controllo di uno degli indicatori, l'altro è identico :

 void Spd_Motor(float spd){
  int new_spd  ;
  static int old_spd;
  int i= 0;

 new_spd = map(spd,0,320,0,270*12);
 //*************AUMENTO NUMERO DI GIRI *******************
if(new_spd > old_spd) //aumento di giri
{
  fastWrite(4, HIGH); //senso orario
  for(i=0; i<(new_spd-old_spd);i++)
  {
    fastWrite(3, HIGH);        // set pin high
    delayMicroseconds(DELAY);
    fastWrite(3, LOW);        // set pin low
    delayMicroseconds(DELAY);
    }
  }
  //**************RIDUCO NUMERO DI GIRI ****************
if(new_spd < old_spd) //diminuisco di giri
{
  fastWrite(4, LOW); //senso antiorario
  for(i=0; i<(old_spd-new_spd);i++)
  {
    fastWrite(3, HIGH);        // set pin high
    delayMicroseconds(DELAY);
    fastWrite(3, LOW);        // set pin low
    delayMicroseconds(DELAY);
    }
  }
old_spd=new_spd;

  
  }

Vorrei chiedervi se conoscete un modo più efficiente o addirittura corretto per generare un numero preciso di impulsi senza incappare in ritardi indesiderati.

Ringrazio anticipatamente chiunque voglia aiutarmi.

L'unica che conosco è utilizzare millis() o visti i tempi stretti micros() in questo modo non hai blocchi del programma dovuto a delay.

Buongiorno,
grazie per la risposta.
Purtroppo questa idea è da scartare perchè devo creare due treni di impulsi e non riesco a gestirli tramite millis().
Ci vorrebbe una sorta di generazione HW dei segnali indipendentemente dal Firmware, una specie di PWM molto veloce e con il conteggio degli impulsi.
Eventualmente gestire in parallelo due uscite digitali tramite una maschera per generare contemporaneamente i due impulsi.

Rebel_88:
Ci vorrebbe una sorta di generazione HW dei segnali indipendentemente dal Firmware, una specie di PWM molto veloce e con il conteggio degli impulsi.

Secondo me basta impostare la logica del programma in modo da portare avanti più compiti in parallelo (macchine a stati). Da seriale leggi un valore, chiamiamolo 'rxval', e in memoria hai un contatore, chiamiamolo 'contval', che deve "inseguire" costantemente 'rxval'. Una macchinetta a stati controlla ad ogni giro di loop se i due valori sono diversi, se lo sono viene scambiata la direzione nel caso in cui serva, viene generato UN solo impulso (niente cicli for), e viene aggiornato 'contval'. Ci mancano dei dettagli, come il valore di 'DELAY'. La latenza massima diventerebbe pari a un solo impulso. Potresti gestire in parallelo tutti gli stepper che servono.

Il tutto se, e solo se, anche il resto del programma è strutturato in modo non bloccante.

Buongiono,
interessante la tua proposta.
Il problema è che da PC ho l'invio di 180 Byte di dati appena pronti, il ciclo è molto rapido si tratta di pochi ms.
Tra un invio e l'altro dovrei generare un centinaio di impulsi per far ruotare correttamente la lancetta dei giri motore contando che un grado equivale a circa 12 impulsi.
Credi sia fattibile?

Claudio_FF:
Ci mancano dei dettagli, come il valore di 'DELAY'.

Rebel_88:
Tra un invio e l'altro dovrei generare un centinaio di impulsi

Se il programma è scritto con logica non bloccante gli impulsi li puoi generare in continuazione anche durante la ricezione.

In pseudo:

if (Serial.available())
{
    ...tante cose...
    if (...ricezione completa...)  { rxval = ....; }
}


se stato == 0:
    se (rxval > contval)
        se (dir == DOWNDIR)
            imposta direzione aumento
            dir = UPDIR
        impulso on
        tempo = micros;
        stato = 1;
    else se (rxval < contval)
        se (dir == UPDIR)
            imposta direzione decremento
            dir = DOWNDIR
        impulso on
        tempo = micros;
        stato = 1;
else se stato == 1:
    se (trascorso DELAY)
        impulso off
        tempo = micros
        stato = 2
else se stato == 2:
    se (trascorso DELAY)
        stato = 0