Help on Tachometer/encoder code

So i’m working on a project for my dad that requires calculating the RPM of a printing press unwind shaft with a particle photon and displays the data as RPM on a google sheets. Problem is, when the sheet retrieves the data, it gets some absurd number like -2013265920 and I have no idea what’s going on. My code includes a rotary encoder as well. I’m pretty much just starting out with electronics and writing in cpp, so I’m not really sure what I’m doing wrong. Could I get some help with this code please? Thanks a million to anyone who helps!

A good starting point for getting help here is to show your “unruly” code then we might be able to give you hints how to tame it.

At first glance it looks like an unsigned vs. signed int problem.

Sorry I kept reminding myself to paste the code in as I was writing! Here you go:

 int val; 
 int encoder0PinA = 3;
 int encoder0PinB = 4;
 int encoder0Pos = 0;
 int encoder0PinALast = LOW;
 int n = LOW;
int hallsensor =  2;
int SensorState = 0;
int count = 0;
float T, rpmcount, Ts, rpm;
char resultstr[64];
 void setup() { 
   pinMode (encoder0PinA,INPUT);
   pinMode (encoder0PinB,INPUT);
   pinMode(hallsensor,INPUT); //sensor input
   Serial.begin (9600);
   Particle.variable("result", resultstr, STRING);
 } 

 void loop() { 
     
 SensorState = digitalRead(hallsensor);
  if (SensorState >= 1023); //T=duration
 Ts = SensorState/1000.00;
 rpmcount = 1/Ts; //F=frequency
 rpm = (rpmcount / 60);
   n = digitalRead(encoder0PinA);
   if ((encoder0PinALast == LOW) && (n == HIGH)) {
     if (digitalRead(encoder0PinB) == LOW) {
       encoder0Pos--;
     } else {
       encoder0Pos++;
     }
   } 
   encoder0PinALast = n;
   sprintf(resultstr, "{\"encoder0Pos\":%d,\"rpm\":%d,\"rpmcount\":%d,\}", encoder0Pos, rpm, rpmcount);
 }

digitalRead() returns 0 or 1, so your if(SensorState >= 1023) will never be true.
You also have a semicolon (;) terminating the conditional block, rendering that condition useless anyway :wink:
Ts can be zero, so you need to check against zero-div exceptions in rpmcount = 1/Ts;
You are loosing precission when doing your calculations in this order, rather do it this way

  Ts = rpmcount = rpm = 0;
  if (SensorState) {
    Ts = SensorState / 1000.0;
    rpmcount = 1000.0 / SensorState; //F=frequency
    rpm = 60000.0 / SensorState;
  }

But I don’t quite see how these calculations would give you the desired result as the hall sensor will only trigger but not give you speed or timing values.
I’d do the whole counting thing via interrupts as loop() has unpredictable timing behaviour, especially when dealing with WiFi troubles.
Especially in high speed applications you can use digitalReadFast() instead of digitalRead().

BTW: I guess the 1023 in your code come from an Arduino sketch, but analogRead() on Particle devices return values of up to 4095.

Notice that you have a semicolon at the end of your if statement. This short circuits the code you probably intended to have as part of the if clause. This is a common problem and is usually solved by using braces everywhere.

This is good coding style:

if (SensorState >= 1023)
{
   Ts = SensorState / 1000.0;
}

Muskie

Most Hall Effect sensors are digital. There are analog ones though, like the DRV5053 series. See if it’s really analog. Otherwise I’d go with interrupts to catch all the pulses if it’s over like 100 RPM.

1 Like