Need help with encoder

Hello!
I use encoder without Z output as wind direction sensor.
I have 400 counts per revolution from encoder.

When i start code - i use simple reset after push button to zero setting.

But i have trouble - if encoder rotates clockwise - everything ok - output going up, if encoder rotates counter clockwise - output going down and crossing zero...

So how i can convert encoder values from -2,147,483,648 to 2,147,483,647 (long type) to 0 359 out.

Sorry my bad English.

I'm sure someone more knowledgeable will be along shortly. Until then I would:

  1. Not worry about counting +- 2 billion something.

  2. If encoder gives up pulse and current count is 359, reset count to zero.

  3. If encoder gives down pulse and current count is -359 reset count to zero.

Sorta like the odometer on a car.

Module by 360.

Val %= 360;

Degrees = count * 0.9, then what @dougp said. Or:

if(count > 399)
 count = 0;
else if (count < 0)
 count = 399;
degrees = count * 0.9

EDIT: Changed degrees to count.

dougp:
2. If encoder gives up pulse and current count is 359 399, reset count to zero.

  1. If encoder gives down pulse and current count is -359 -399 reset count to zero.

Oops! :blush:

Delta_G:
Module by 360.

Val %= 360;

Will that work when transitioning from positive to negative numbers?

No it will not. And it's actually wrong, I misread the OP. He needs to scale by 400 and then 360. that post should probably be ignored.

Delta_G:
No it will not. And it's actually wrong, I misread the OP. He needs to scale by 400 and then 360. that post should probably be ignored.

Right. No need for float here.

The encoder has 400 steps but can count 2 or 4 times that or at 4 transitions per step = 1600 counts per revolution so for incredible detail try this code:

#define DataPin 3
#define ClockPin 2
volatile int Ctr;
volatile byte Flag;
void E1() {
  if (digitalRead(DataPin))( digitalRead(ClockPin)) ? Ctr ++ : Ctr --;
  else ( digitalRead(ClockPin)) ? Ctr -- : Ctr ++;
  Ctr = Ctr % 1600; // only use a number from 0 to 1599 the % returns the remainder after dividing by 1600
  Flag = true;
}
void E2() {
  if (digitalRead(ClockPin))( digitalRead(DataPin)) ? Ctr -- : Ctr ++;
  else ( digitalRead(DataPin)) ?  Ctr ++ : Ctr --;
  Ctr = Ctr % 1600; // only use a number from 0 to 1599 the % returns the remainder after dividing by 1600
  Flag = true;
}
void EncodetInterruptSetup() {

  attachInterrupt(digitalPinToInterrupt(DataPin), E1 , CHANGE);
  attachInterrupt(digitalPinToInterrupt(ClockPin), E2, CHANGE);
}

void setup() {
  Serial.begin(115200);
  EncodetInterruptSetup();
}

void loop() {
  int C;
  float Deg;

  if (Flag) {
    cli ();         // clear interrupts flag
    C = Ctr;
    sei ();
    Deg = ((float)C) * 0.225;
    Flag = false;
    Serial.println(Deg, 4);
  }
}

This should limit the count to 1 revolution worth or 1600 counts * 0.225 degrees per count = 360°
Then convert it to degrees as a floating point number

Z
I am assuming this is the encoder you are using:


Sorry if I'm wrong I am using this for several projects

Thanks All.

So this is my ugly code:

#include <Encoder.h>


Encoder myEnc(2, 3);


void setup() {
  Serial.begin(9600);
  Serial.println("Basic Encoder Test:");
}

int newPosition;
int oldPosition  = -999;
int degres=0;
float outval=0;



void loop() {
   newPosition = myEnc.read();
  if (newPosition != oldPosition) {
    oldPosition = newPosition;
  //  Serial.print("Encoder value=");
  //  Serial.print(newPosition);
      
  }
  
 if (newPosition == 400) 
 {
  myEnc.write(0);
 }
 if (newPosition <= -400) 
 {
  myEnc.write(0);
 }
  
   
degres=abs(newPosition);

degres=map(degres,0,400,0,360);

if (degres>=180) 
{
  degres=360-degres;
}


    Serial.print("  Degres value=");
    Serial.println(degres); 
  
}