I'm trying to control the speed of a DC current motor with PWM.
I use an arduino UNO to send PWM signal to a mosfet Velleman vma411 to change the average tension of a my motor which is wired to stabilized power supply (about 10V).
In order to get the rotational frequency of my motor, I have a hall effect sensor next to the rotational axis. Each half turn the sensor changes value (either 0 or 5V).
To detect the changes I use attachInterrupt()
to detect the changes.
When the arduino is not sending any PWM signal, the frequency measured is perfectly fine (I verified it using an oscilloscope). BUT when I send PWM signal to my motor, the frequency makes no more sense (about 1 value out of 3 is 10 times higher than the expected one).
To solve this issue I tried three different things :
- putting a capacitor (between 100 microF and 2200 microF) between the arduino and the mosfet sig port,
- using a average value of the last 10 measured frequencies,
- adding a numerical filter,
- using one
ground
pin for the mosfet and a different one for the sensor port,
Nevertheless any of those ideas really worked for me.
I suppose this may be due to some electrical reflection issues? Maybe should I change my mosfet or use a L298N?
Thanks in advance
My code which goal is to measure accurately the rotational frequency while sending a PWM signal to the mosfet:
/*
alimentation du capteur : 4V
mesure précise jusqu'à au moins 10V
*/
//ports
int rotation_port = 3;
int mosfet_sig_port = 11;
int debug_port = 10;
//mesures :
volatile long t_new;
volatile long t_old;
volatile long res;
volatile float frequence;
volatile float old_frequence;
// asser
float rapport_cyclique = 127; //entre 0 et 255
void setup() {
pinMode(rotation_port, INPUT_PULLUP); // pour interrupt
attachInterrupt(digitalPinToInterrupt(rotation_port), capteur_hall_changement, FALLING);
pinMode(debug_port, OUTPUT);
pinMode(mosfet_sig_port, OUTPUT);
Serial.begin(115200);
old_frequence = 100;
}
void capteur_hall_changement() {
t_new = micros();
res = 1.0 / (t_new - t_old) * 1000000;
if (res/old_frequence <= 1.5) {
frequence = res;
old_frequence=frequence;
}
t_old = t_new;
Serial.println(frequence);
}
void loop() {
// Envoi du signal PWM sur la sortie numérique mosfet_sig_port
analogWrite(mosfet_sig_port, int(rapport_cyclique));
}
Serial.println()
in interrupt context. 2.frequence
andold_frequence
are redundant (they are always the same). 3. What is the rationale forif (res/old_frequence <= 1.5)
?if (res/old_frequence <= 1.5)
is to remove the measures that should not appear. I want to measure a frequency of around 100Hz and some measures are giving a 200Hz frequency for no reason, so the goal was to numerically filter them.