Pagina 1 di 2

Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 9 mar 2021, 9:33
da cencia01
Salve a tutti, in casa mi sono trovato un quadrature encoder su DC motor, e volevo trasformarlo in un haptic (rotella con scatti gestiti da PWM di Arduino UNO).
Ricordo di averlo fatto più di 20 anni fa con un tabella di questo tipo:

Codice: Seleziona tutto
int pwmSin[] = {0, 0, 1, 4, 10, 17, 20, 26, 37, 45, 50,
                64, 70, 78, 94, 110, 127, 144, 160, 176, 191,
                195, 204, 210, 217, 228, 237, 244, 250, 253, 254,
                255, 250, 244, 237, 228, 217, 210, 204, 195, 191,
                176, 160, 150, 144, 127, 110, 94, 78, 70, 64,
                50, 45, 37, 26, 20, 17, 10, 4, 1, 0, 0
               };




dove pwmSin sono i valori che vado ad inserire qui:

Codice: Seleziona tutto

analogWrite(pin, pwmSin[]);





e con un contatore che legge gli stati del quadrature encoder:
Codice: Seleziona tutto


void contaImpulsi ()
{
  aState = digitalRead(2);
  if (aState != aLastState)
  {
    if (digitalRead(6) != aState)
    {
      counter++;
      stato = 0;
    }
    else
    {
      counter--;
      stato = 1;
    }

  }




A questo punto però non so più come muovermi.
Gli scatti li sento ma solo per una piccola parte di valori. La ruota codificata sull'encoder è di 900cpr e gli scatti riesco a sentirli soltanto per i primi conteggi.

Per caso avreste delle dritte (funzioni o quant'altro) su come procedere?

Grazie in ogni caso

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 9 mar 2021, 11:01
da EcoTan
Girando attorno all'argomento, riporto un frammento di codice in C che elabora direttamente i due segnali digitali, superiore e inferiore, provenienti da ciascun encoder, e ne conta i passi:

//incrementa il numero dei passi:
if ((essv==1 && essp==0 && esiv==0)||(esiv==0 && esip==1 && essv==0)) pas++;
if ((essv==0 && essp==1 && esiv==1)||(esiv==1 && esip==0 && essv==1)) pas++;
if ((esiv==1 && esip==0 && essv==0)||(essv==0 && essp==1 && esiv==0)) pas--;
if ((esiv==0 && esip==1 && essv==1)||(essv==1 && essp==0 && esiv==1)) pas--;
if ((edsv==1 && edsp==0 && ediv==0)||(ediv==0 && edip==1 && edsv==0)) pad++;
if ((edsv==0 && edsp==1 && ediv==1)||(ediv==1 && edip==0 && edsv==1)) pad++;
if ((ediv==1 && edip==0 && edsv==0)||(edsv==0 && edsp==1 && ediv==0)) pad--;
if ((ediv==0 && edip==1 && edsv==1)||(edsv==1 && edsp==0 && ediv==1)) pad--;
essp = essv; esip = esiv; //memorizza stato digital input
edsp = edsv; edip = ediv;

essv=encoder sinistro superiore valore validato attuale
essp=encoder sinistro superiore valore precedente
esiv=encoder sinistro inferiore valore validato attuale
esip=encoder sinistro inferiore valore precedente
pas=passi compiuti dall'encoder sinistro
analogamente per il destro d.

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 9 mar 2021, 12:36
da cencia01
EcoTan ha scritto:Girando attorno all'argomento, riporto un frammento di codice in C che elabora direttamente i due segnali digitali, superiore e inferiore, provenienti da ciascun encoder, e ne conta i passi:

//incrementa il numero dei passi:
if ((essv==1 && essp==0 && esiv==0)||(esiv==0 && esip==1 && essv==0)) pas++;
if ((essv==0 && essp==1 && esiv==1)||(esiv==1 && esip==0 && essv==1)) pas++;
if ((esiv==1 && esip==0 && essv==0)||(essv==0 && essp==1 && esiv==0)) pas--;
if ((esiv==0 && esip==1 && essv==1)||(essv==1 && essp==0 && esiv==1)) pas--;
if ((edsv==1 && edsp==0 && ediv==0)||(ediv==0 && edip==1 && edsv==0)) pad++;
if ((edsv==0 && edsp==1 && ediv==1)||(ediv==1 && edip==0 && edsv==1)) pad++;
if ((ediv==1 && edip==0 && edsv==0)||(edsv==0 && edsp==1 && ediv==0)) pad--;
if ((ediv==0 && edip==1 && edsv==1)||(edsv==1 && edsp==0 && ediv==1)) pad--;
essp = essv; esip = esiv; //memorizza stato digital input
edsp = edsv; edip = ediv;

essv=encoder sinistro superiore valore validato attuale
essp=encoder sinistro superiore valore precedente
esiv=encoder sinistro inferiore valore validato attuale
esip=encoder sinistro inferiore valore precedente
pas=passi compiuti dall'encoder sinistro
analogamente per il destro d.


ma questa procedura non coincide con la mia
void contaImpulsi ()
?

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 9 mar 2021, 14:37
da EcoTan
Non mi è chiaro quando venga scritta la variabile aLastState e quando venga utilizzata la variabile stato.
Non so se le procedure coincidano in tutte le condizioni, vedi cambiamenti di verso, certo quella è più semplice e l'altra comunque sembra funzionare. Inoltre si attiva al cambiamento di qualsiasi dei due input.

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 9 mar 2021, 19:10
da cencia01
benissimo, la procedura sembra molto più robusta della contaImpulsi.

una volta che conto e misuro la posizione dell'albero come posso creare quell'effetto haptico di scatti nella rotazione del motore... :?:

So che devo utilizzare un array del tipo del primo post, ma mi sono bloccato sul come usarlo e implementarlo

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 9 mar 2021, 20:34
da EcoTan
Non conosco il problema. Se il motore è dotato di riduttore lascerei perdere perché l'attrito sarebbe tale da coprire l'effetto. Poi deciderei se il motore deve essere pilotato in ambedue i versi di rotazione, direi di sì, quindi farei qualche prova in proposito. Il programma sarà un po' complicato ma alla fine dovrà pur girare, in qualche modo farà ricorso al resto di una divisione per ottenere l'indice dell'array.

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 11 mar 2021, 12:29
da cencia01
Non ha riduttore.

L'effeto Haptic è quello delle manopole delle Mercedez o BMW che pilotano i settaggi e le selezioni dei computer di bordo.
il mio intento è di creare scanalature con il mio motore DC (vedi allegato).

A dire il vero ho fatto qualcosa, ma ci sono ancora dei punti critici a cui sto lavorando e non vanno.

unsigned long duration;
float f;
int counter=0;
int t;
int aState;
int aLastState;
int pos;
boolean stato;
int epos;
int pwmSin[] = {144,160,176,191,204,217,228,237,244,250,253,254,255,
250,244,237,228,217,204,191,176,160,144,
127,110,94,78,64,50,37,20,4,1,
0,1,4,17,26,37,50,64,78,94,110,127
};

void setup() {
TCCR1B = TCCR1B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 9 and 10
TCCR2B = TCCR2B & 0b11111000 | 0x01; // set PWM frequency @ 31250 Hz for Pins 11 and 3 (3 not used)
ICR1 = 255 ; // 8 bit resolution
pinMode(2,INPUT);
pinMode(6,INPUT);
pinMode(12, OUTPUT);
pinMode(9, OUTPUT);
Serial.begin(9600);

attachInterrupt(digitalPinToInterrupt(2),contaImpulsi,CHANGE);

aLastState=digitalRead(2);
}
void freq ()
{
duration=pulseIn(2, HIGH);
f=1/(duration*2);
Serial.print("Freq: ");
Serial.println(duration);
}

void contaImpulsi()
{
aState=digitalRead(2);
if (aState!=aLastState)
{
if (digitalRead(6)!=aState)
{
count++;
if (counter)stato=0;

}
else
{
count--;
stato=1;

}
}
aLastState=aState;
//t = millis();
}

void CW()
{
digitalWrite(12, LOW); // Impostazione della direzione “avanti” del motore collegato al canale A
digitalWrite(9, LOW); // Disattivazione del brake del motore per il canale A
analogWrite(3, pwmSin[epos]); // Massima velocità del motore

}

void CCW()
{
digitalWrite(12, HIGH); // Impostazione della direzione “avanti” del motore collegato al canale A
digitalWrite(9, LOW); // Disattivazione del brake del motore per il canale A
analogWrite(3, pwmSin[epos]); // Massima velocità del motore

}
void move()
{
if (stato==1)
{
digitalWrite(12, HIGH); // Impostazione della direzione “avanti” del motore collegato al canale A
digitalWrite(9, LOW); // Disattivazione del brake del motore per il canale A
analogWrite(3, pwmSin[epos]); // Massima velocità del motore
}
if (stato==0)
{
digitalWrite(12, LOW); // Impostazione della direzione “avanti” del motore collegato al canale A
digitalWrite(9, LOW); // Disattivazione del brake del motore per il canale A
analogWrite(3, pwmSin[epos]); // Massima velocità del motore
}
if (stato==2)
{
digitalWrite(12, LOW); // Impostazione della direzione “avanti” del motore collegato al canale A
digitalWrite(9, LOW); // Disattivazione del brake del motore per il canale A
analogWrite(3, 0); // Massima velocità del motore
}
}

void nomove()
{
if (pos<0 || pos>360)
{
digitalWrite(9, HIGH);
pos=180;
}
delay(20);
digitalWrite(9, LOW);

}

void loop()
{
pos=map(counter,-900,900,0,360);
//pos=pos%4;
epos=pos%45;
//nomove();
//freq();
//CW();
//CCW();


//move();
Serial.print("pos: ");
Serial.print(pos);
Serial.print(",");
Serial.print("epos: ");
Serial.print(epos);
Serial.print(",");
Serial.print("PWM: ");
Serial.print(pwmSin[epos]);
Serial.print(",");
Serial.print("stato: ");
Serial.println(stato);
}

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 12 mar 2021, 9:21
da EcoTan
Certe volte, mettere dei commenti molto minuziosi e veridici aiuta a scovare gli errori di logica.
Mi chiedo se un motore a corrente continua possa avere una coppia abbastanza uniforme, sempre che io abbia capito che cosa stai facendo.

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 18 mar 2021, 19:33
da cencia01
mi puoi dare delle dritte su come bloccare un motore DC in una posizione fissa a piacere?

motore DC con Encoder

Re: Haptic con Quadrature Encoder su DC motor

MessaggioInviato: 18 mar 2021, 19:59
da EcoTan
Secondo me è come fare stare l'elefante con un piede solo sullo sgabello, un buon domatore ci riesce ma non su uno sgabello da bar. Poi ci sarà da tarare i parametri del solito PID ma la cosa mi pare impostata male in partenza.
P.S. se proprio volessi inventare qualcosa metterei la manopola su un potenziometro e collegherei il motore tramite una frizione, rinunziando all'andamento sinusoidale della spinta.