Reading DC Motor Encoder for 3 Motors

I am using the following motor encoder attached to this motor. I need to count the revolutions of this motor to determine when to stop it. The problem I have is that I need to do this for 3 motors at the same time. The motor has a 63:1 gear ratio and the encoder counts 20 pulses per revolution.

I’m concerned that counting the pulses for all 3 motors on both channels will be too much for the processor. The processor I’m using is an nRF52840 from Adafruit. Should I be concerned?

Just to confirm my calculation, at full speed there could be (63*20) * (220/60) * 3 = 13,608 pulses per second (or is that halved with a RISING edge). Thank you!

The encoder is actually 5 pulses per revolution, the 20 comes from counting both rising and falling edge of both channels. If 63 counts per rev is enough and the motor is only turning one direction, you would only need to connect one channel to an interrupt pin. If you need to know direction, (forward / reverse), you would need a second pin for the other channel, but it would not have to be an interrupt pin. Here’s a simple program for reading a 16 PPR encoder with a Nano (Atmega328, AVR), I’m not familiar with nRF52840.

unsigned long start;
const byte ain1Pin = 3,
           ain2Pin = 11,
           encoderPinA = 2, // external interrupt pin
           encoderPinB = 4;
const uint16_t end = 1000; // 1 second update time
           
int pwmVal;
volatile long pulse;           
int pps,       // pulses per second
    oldpps,
    ppr = 700, // pulses per revolution
    rpm; 

void setup()
{
  Serial.begin(9600); // set serial monitor line ending to Newline
  attachInterrupt(0, readEncoder, FALLING);
  pinMode(ain1Pin,OUTPUT);
  pinMode(ain2Pin,OUTPUT);
  pinMode(encoderPinA,INPUT_PULLUP);
  pinMode(encoderPinB,INPUT_PULLUP);    
}

void loop()
{
  if(Serial.available() > 0) // get motor speed from serial monitor, 0 to 255
  {
     pwmVal = Serial.parseInt(); // input PWM value 
     if(Serial.read() == '\n'){} // skips 1 second delay
     Serial.println(pwmVal);
     if(pwmVal == 0)
     {
       analogWrite(ain1Pin,255); // brake motor
       analogWrite(ain2Pin,255); //  ''     ''
     }
     else if(pwmVal < 0)
     {
       analogWrite(ain2Pin,0); // forward direction
       analogWrite(ain1Pin,abs(pwmVal));
     }
     else
     {
       analogWrite(ain1Pin,0); // reverse
       analogWrite(ain2Pin,pwmVal);
     }
  }
  if(millis() - start > end)
  {
     start += end;
     noInterrupts();
     pps = pulse - oldpps;
     oldpps = pulse;
     interrupts();
     rpm = abs(pps * 600L / ppr);
     if(pps != 0)
     {
       Serial.print(pulse); Serial.print("\t" );
       Serial.print(rpm / 10); Serial.print(".");
       Serial.print(rpm % 10);
       Serial.print("\t" ); Serial.println(abs(pwmVal));
     } 
  }
}
void readEncoder() // ISR
{
  bitRead(PIND,4) ? --pulse : ++pulse; // rotation direction
}  


Thank you!

So I got my encoder code working, and I’m seeing around 460 pulses per second for one channel. I need to count the rotations of 3 motors running at the same time, so could be 1,380 pulses per second.

The rotation count doesn’t have to be exactly precise, but close. Is that going to be too much for the Arduino (in my case the nRF52840) to handle? Will I still have cycles to do other “stuff” while running these motors? And if it’s too much, what are other alternatives to counting rotations? Ideally, an encoder on the output shaft after the gears would be better, but it seems all encoders are on the shaft before gearing.

I was reading there are some chip counters that could work. If that’s the case, are there any examples of using one of those available?

Just to let anyone else know, I ended up using hardware timers built into the nRF52840 to count the pulses and another hardware timer to read all 3 registers every 125ms. I couldn’t figure out how to move this process to external hardware. I am curious how others deal with so many interrupts (or counting pulses from multiple devices at the same time).

Nix that… I don’t have enough hardware timers on the nRF. You need 1 timer to read and the other to count for EACH encoder. The nRF only has 4 timer instances available. Does anyone have a suggestion?

I’d investigate Paul Stoffregens ‘Encoder’ in the IDE library manager. It’s interrupt driven and so may work for you.

Thanks. I decided to move away from DC motors with encoders to a stepper motor. Will work out better I think for my requirements.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.