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

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);
  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;
  t_old = t_new;

void loop() {
  // Envoi du signal PWM sur la sortie numérique mosfet_sig_port
  analogWrite(mosfet_sig_port, int(rapport_cyclique));
  • 3
    1. Do not Serial.println() in interrupt context. 2. frequence and old_frequence are redundant (they are always the same). 3. What is the rationale for if (res/old_frequence <= 1.5)? Jan 15, 2022 at 13:25
  • the goal of 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. Jan 16, 2022 at 11:02

1 Answer 1


When you use interrupts your PWM can work bad so don't use them both at the time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.