Hi everyone
Finally, I’ve solved the problem. It was not about the Arduino nano capabilities. It was a timming problem.
The loop is temporized to last exactly 10 msec and that’s what happens in due. But (I don’t know why) in the nano one out of 6 or so loops last 9.something msec. As the duration of the loop is smaller, the number of pulses counted is smaller. When calculating the derivative:
(enc_act-enc_ant)/Ts
I assume Ts=10 msec and so, the velocity is smaller.
It can be solved, using the real duration of the loop, or using micros() instead of millis() to have a more precise timing. This is the result for both due (left) and nano (right). The error is in both cases around 0.16 msec, as expected from the encoder resolution. Blue line is the measured velocity and red line is the error.
Thanks for the useful comments and best regards
PS: Just in case you are interested, find attached the code.
#define pinENC_chA 2
#define pinENC_chB 3
#define PWM1 9
#define PWM2 10
//#define PPV 8960.0 //64*70*2
//#define VMAX 8
#define PPV 3840.0 //64*30*2
#define VMAX 20
int t1 = 0 ;
int t2 = 0 ;
//int T = 10 ; // Periodo de muestreo (milisegundos)
int T = 10000 ; // Periodo de muestreo (microsegundos)
float U ;
int D1=0, D2=0 ;
//double Tm = T/1000.0 ; // Periodo de muestreo segundos
double Tm = T/1000000.0 ; // Periodo de muestreo segundos
double C2D = 360.0/PPV ; // Conversión cuentas a deg
double C2RS = (2*3.14/PPV)/Tm ; // Conversión cuentas a rad/seg
double vel = 0.0 , vel_ant = 0.0 ;
double pos = 0.0 ;
volatile long quad = 2240 ;
long enc_ant = 0 ;
long enc_act = 0 ;
int enc_dif = 0 ;
bool ChA_ant = 0 , ChB_ant = 0 ;
bool ChA_act = 0 , ChB_act = 0 ;
//long mm_ant = 0 , mm_act = 0 ;
void setup() {
Serial.begin(115200) ; // Inicializa comunicación serie
attachInterrupt(digitalPinToInterrupt(pinENC_chA),encoder,CHANGE) ;
attachInterrupt(digitalPinToInterrupt(pinENC_chB),encoder,CHANGE) ;
pinMode(PWM1,OUTPUT) ; pinMode(PWM2,OUTPUT) ;
}
void loop() {
noInterrupts() ; enc_act=quad ; interrupts() ;
enc_dif=enc_act-enc_ant ;
pos=(enc_act)*C2D ; pos=((int)pos % 360)-180.0 ;
vel=(enc_act-enc_ant)*C2RS ;
//mm_act=micros() ;
//Serial.println(mm_act-mm_ant) ;
//vel=vel/(mm_act-mm_ant) ; mm_ant=mm_act ;
enc_ant=enc_act ;
//Serial.print(quad) ; Serial.print("\t") ;
//Serial.print(enc_dif) ; Serial.print("\t") ;
Serial.print(vel) ; Serial.print("\t") ;
Serial.print(vel-vel_ant) ; Serial.print("\n") ;
vel_ant=vel ;
U=5.0 ;
if (U>10) {U=10 ;} ; if (U<-10) {U=-10 ;} ;
if (U>0) {D1=map(abs(U)*25,0,10*25,0,255) ; D2=0 ;}
else {D2=map(abs(U)*25,0,10*25,0,255) ; D1=0 ;}
analogWrite(PWM1,D1) ; analogWrite(PWM2,D2) ;
//t2=millis() ; // Temporización
t2=micros() ; // Temporización
if (t2-t1>T) {
digitalWrite(13,HIGH) ; Serial.println(t2-t1) ;}
else {digitalWrite(13,LOW) ;}
//while (t2-t1<T) {t2=millis() ;} t1=millis() ;
while (t2-t1<T) {t2=micros() ;}
t1=micros() ;
}
void encoder () {
ChA_ant=ChA_act ; ChA_act=digitalRead(pinENC_chA) ;
ChB_ant=ChB_act ; ChB_act=digitalRead(pinENC_chB) ;
if (!ChA_ant && !ChB_ant && ChA_act && !ChB_act) {quad++ ;}
if (!ChA_ant && ChB_ant && !ChA_act && !ChB_act) {quad++ ;}
if (ChA_ant && !ChB_ant && ChA_act && ChB_act) {quad++ ;}
if (ChA_ant && ChB_ant && !ChA_act && ChB_act) {quad++ ;}
if (!ChA_ant && !ChB_ant && !ChA_act && ChB_act) {quad-- ;}
if (!ChA_ant && ChB_ant && ChA_act && ChB_act) {quad-- ;}
if (ChA_ant && !ChB_ant && !ChA_act && !ChB_act) {quad-- ;}
if (ChA_ant && ChB_ant && ChA_act && !ChB_act) {quad-- ;}
}