-1

I created a program that measures the pulses set out by the encoder (part of the dc motor with encoder inbuilt), and uses the ppr value (pulses per rotation) to calculate the rotations per minute (rpm)

However, the serial monitor continuously shows 0 for the variable "pulsecount", that maintains the total pulses sent. enter image description here

code:

float ppr=512.0;
int encpin=3;
volatile long pulsecount=0;
float revs;
float rps;
float rpm;
unsigned long time;


void setup()
{
  pinMode(encpin,INPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //when pulse is detected
                                           //interrupt triggered,
                                           //function callled  
}
void function(){
  pulsecount+=1;
}

void loop()
{
 revs= pulsecount/ppr ;
 time=millis()/1000;
 rps=revs/time ;
 rpm=revs*60;
 Serial.println(pulsecount);
}
2
  • Why are you defining function() inbetween setup() and loop()? If it compiles it might be OK, but I have never seen that... Try to print every value to Serial Monitor and maybe you can see the variable which causes this behavior. Apr 28 at 17:44
  • 2
    What happens if you use INPUT_PULLUP rather than INPUT?
    – timemage
    Apr 28 at 17:57
2

You code counts pulses just fine when tested here.

Fan/motor tachometer outputs and encoders frequently are set to switch your signal contact to ground, either with a transistor or mechanically. When the ground contact is not being made, the signal connection is floating and not reliably HIGH. So, you need a pullup resistor on the pin, just like you do for a typical push button switch configured to switch to ground.

My comment on the question:

What happens if you use INPUT_PULLUP rather than INPUT?

was referring to doing this in your code:

pinMode(encpin, INPUT_PULLUP);

At higher frequencies, higher RPM, you may need to use an external resistor to get a lower resistance value than the 20k-50k of the internal pullup resistor that INPUT_PULLUP enables.

It is best to turn off interrupts when you retrieve your volatile pulse counter variable so that there's no tearing of the value where the ISR interrupts your code mid-read and updates the latter half of the value.

e.g.:

// Note I've switched your pulsecount variable
//  to unsigned long for this example.
unsigned long get_pulsecount() {
  noInterrupts();
  const auto r = pulsecount;
  interrupts();
  return r;
}

Note you can probably avoid float usage altogether, and should if you can.

0

It is hard to find the error in these TinkerCad examples, because I do not know where to find the datasheet of the components used there and I am never sure, what am I debugging, the program or Tinkercad?

Anyhow, the encoder simulated there needs to be connected with a pull-up resistor. Arduino has a built-in pullup and you can activate via the pinmode() function:

void setup()
{
  pinMode(encpin,INPUT_PULLUP); //  before here was pinMode(encpin,INPUT); 
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(encpin),function,RISING); //when pulse is detected
                                           //interrupt triggered,
                                           //function callled  
}

But notice: your types are all over the place and I expect that you get some bugs due to this. Avoid to divide float and int variables without converting, especially this can cause trouble, because you might divide by 0:

 time=millis()/1000;
 rps=revs/time ;

Also it is a long shot to have basic doubts regarding encoders and arduino, just because some code does not work. Many people are using encoders all the time and countless libraries of encoders have been published for arduino.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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