Help creating a simple counter.

Hi all,

I’m trying to create a simple count counter, or so i thought it would be.

I have an encoder, which has 2 digital sensors, with each sensor connecting to a different digital pin, lets say pins 11 & 12 for the purpose of this discussion.

So lets say for the purposes of this example, each time a sensor is coverer it returns a value of 1 and when it’s uncovered it returns a value of 0

As far as i can see the encoder only has 3 transitions of state.

State 1
(SensorA=1 - SensorB=0)

State 2
(SensorA=1 - SensorB=1)

State 3
(SensorA=0 - SensorB=1)

I thought thatit would be simple to create a counter with a simple IF statement, but it’s not proving that easy.

i thought something like this would work, but it doesn’t

if (SensorA == 1 & SensorB == 0){i++;}
if (SensorA == 0 & SensorB == 1){i--}

I’ve tried resetting the sensors before and after and still no joy. I’ve attached my code below.

#include <avr/io.h>
#include <avr/interrupt.h>

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#include <Wire.h>
#include <inttypes.h>

// quadrature encoder

#include <QuadratureEncoder.h>

#define encLtA 10
#define encLtB 0
#define encRtA 13
#define encRtB 0

QuadratureEncoder encoder = QuadratureEncoder(encLtA, encLtB, encRtA, encRtB);

int32_t encLt, encRt;
int i=0;

void setup() 
{ 
  encoder.init();
  Serial.begin(9600);
  lcd.begin(20, 4);
  
  
}


void loop()
{
  int  enc_count;
  int  tot_count = 0;
  int  enc_lt, enc_rt, enc;
  
 
  if (encLt == 1 & encRt == 1)
 { encLt == 0;
   encRt == 0;}
 
 if (encLt == 1 & encRt == 0){i++;} 
 if (encLt == 0 & encRt == 1){i--;} 

   /* reset encoder */  
  enc_lt = 0;
  enc_rt = 0;
  encLt = 0;
  encRt = 0;
 
    enc = encoder.readLt();
    enc_lt += abs(enc);                  // read a single step encoder
    encLt += enc_lt;
    enc = encoder.readRt();
    enc_rt += abs(enc);                  // read a single step encoder
    encRt += enc_rt;
    tot_count += enc_lt;
    tot_count += enc_rt;
     tot_count += abs(enc);

lcd.setCursor(0,0);
  lcd.print(tot_count, DEC);
  lcd.print(" ");
  lcd.print(enc_count, DEC);
  lcd.print(" ");
  lcd.print(encLt, DEC);
  lcd.print(" ");
  lcd.print(encRt, DEC);
  lcd.print("    ");
  lcd.print(i);
delay (50);
}

Rich.

What is it you are trying to count?

Are you getting good readings from the encoder? In other words, are the encLt and encRt values what you expect them to be? Are they returning the number of steps that the encoder was moved?

i thought something like this would work, but it doesn't

Code:

if (SensorA == 1 & SensorB == 0){i++;} if (SensorA == 0 & SensorB == 1){i--}

It doesn't work because you are only taking the current values of the sensors. You need to increment or decrement only on the transition not the level. Therefore you need to remember the previous state and only call this when the previous state has changed.

Hi all,

Yes every time the spoke of the wheel passes either sensorA or Sensorb Arduino see this value. I know the sensor is working as i'm seeing values being returned.

Mike i cobbled my code together from lots of different sourced on the internet, and i'm fairly new to this whole Arduino side of things.

Can you suggest how I would count the transitions ?

Rich.

Can you suggest how I would count the transitions

Just count when you see the value change from high to low or vice versa. If the pin has the same value as last time you looked at it (you'll have to store the state in a variable), don't increment the count.

Awol,

isn't that what my IF statement was supposed to be doing, e.g. if sensorA changes from 0 to 1 and SensorB remains static then add to the counter, and vice versa for decramenting the counter.

Can anyone give me an example as i'm struggling to fully understand.

For starters, I would change all of the '&' operators to '&&' operators. They are two different operators. It may be that they don't make a difference in this case, and I'm too lazy to figure out if they do or not, but there are definitely cases where they give different results.

Regards,

-Mike

Hi mfm9,

the double poerators made no difference.

Can nobody give a bit of example code. I've been trying to crack this for weeks and it's driving me nuts.

int oldSensorA = LOW;
int oldSensorB = LOW;
int stateChanges = 0;

void loop()
{
   int newSensorA = abs(encoder.readLt());
   int newSensorB = abs(encoder.readtRt());

   if(oldSensorA != newSensorA || oldSensorB != newSensorB)
   {
      // Sensor A's state changed or Sensor B's state changed
      stateChanges++;
   }

   oldSensorA = newSensorA;
   oldSensorB = newSensorB;
}

If you need to know whether it was A or B that changed, you can compare A's old and new state, inside the if block, as well as comparing B's old and new state.

Hi Paul,

Thanks for the code, but it doesn't seem to work, it just results in a runaway value for stateChanges.

if((oldSensorA != newSensorA) || (oldSensorB != newSensorB))

Might work better.

If not, add serial.print’s to print old and new sensor values.

I give up, looks like i'm going to have to find some other type of sensor as i just cant get a stable counter too work.

I'm just amazed that it's not as simple as it should be, wheel moves in one direction counter incraments value, wheel moves in opposite direction counter decraments value.

I think your encoder might have 4 unique states, and 8 possible transitions...

SensorA = 0, SensorB = 0 SensorA = 1, SensorB = 0 SensorA = 0, SensorB = 1 SensorA = 1, SensorB = 1

The encoder can move clockwise or counterclockwise out of each state.

In that case try this (pseudo)code...

byte myState = 0, prevState = 0;

loop () {
  SensorA = digitalread(pin_A);
  SensorB = digitalread(pin_B);
  myState = SensorA | SensorB >> 1;  // binary 2-bit representation of the encoder flags

  switch (myState) {  // encoder flags progress through values 0, 1, 3, 2 for a forward direction
      case 0:
            if (prevState == 2) i++;
            else if (prevState == 1) i--;
            break;
      case 1:
            if (prevState == 0) i++;
            else if (prevState == 3) i--;
            break;
      case 3:
            if (prevState == 1) i++;
            else if (prevState == 2) i--;
            break;
      case 2:
            if (prevState == 3) i++;
            else if (prevState == 0) i--;
            break;
  }
  prevState = myState;
}

[Edited: replaced "else" clauses with "else if" so that iterations where the prevState == myState are swallowed without changing i]

Hi Mitch,

in your code how would you go about telling arduino what SesnorA and SesnorB are.

could you show me how you would define pin_A and pin_B as well as SensorA and SesnorB

I defined pinA & pinB as show below, but not sure how to define SensorA or SensorB as Arduino keeps giving me an error saying

"In function 'void loop()': error: 'SensorA' was not declared in this scope"

#define pin_A 10
#define pin_B 13

Hi all,

finally cracked this with the following code and the PololuWheelEncoder library.

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#include <PololuWheelEncoders.h>

PololuWheelEncoders encoder;

char val1, val2;
char s;

void setup() {
lcd.begin(20, 4);
  pinMode(13,OUTPUT);
  digitalWrite(13,LOW);

//initialize encoder for pins 10,13  
  encoder.init(10,13,255,255);
}

long t1,t2;

void loop() {

  llegirPos();
  delay(100);
}

//capture encoder counts.
void llegirPos() {

  lcd.setCursor(0,0);
  lcd.print( encoder.getCountsM1(), DEC );
  lcd.print ("    ");
  
}

Rich.