Help with encoder based position display

Hi folks.

I am working on a imo more advanced yet simple arduino project.lol

The sort rundown is, i am using a rotary encoder to measure the position of a large mechanical display dial, and having a scaled value displayed on a 64x32 led matrix display, along with some other simple values (a current reading and a max reading) The display is stage 2 of this project.

First thing first. At this moment i am using a arduino nano and a omron E6B2-CWZ6C rotary encoder with 600p/rev

I found some sample code on the forum, and after a bit of tweaking and removing unwanted code, i have a working very basic program that actually reads the encoder. And prints it out via serial.
It is so far extremely accurate and doesnt loose any pulses. I also checked the signals via my oscilloscope, and the (digitalwrite, HIGH) pullups were important to implement for proper signal conditioning.

The encoder doesnt turn more then 4-6RPM at most, so its signal speed shouldn't swamp the nano

The encoder has a outputA, outputB, and outputZ (output z is condsidered a home position signal, and i dont need to use it)

I have outputA hooked up to dgital pin 2
I have outputB hooked up to digital pin 7

i had the output A hooked up to digital pin 6 before (with obvious changes in the code), but couldn't get it to read. Is there something special about pin 2 capabilities.

I want to keep the encoder on pins 6&7 because if im not mistaken the 64x32 lcd display uses the IDC communication protocol which will use up a few select digital pins?

Anyways, long story short. I also have a momentary push button on digital pin 9, and pulls the pin low when activated. I want to use this push button to reset the current encoder reading to 0.

Issue is with the way i have the code, it only resets the encoder value to 0 while the PB is held, and once released it will default back to its original value.

idelay i can add 2 PB. one to reset the current encoder reading value (kinda like a calibration reset when the dial is reading 0), and the other PB to reset the max value reading (preferably this would be for the scaled final value outputed to the LED display)

I have attached the modified code below.

Any help would be greatly appreciated.

Hopefully i can get this whole setup to work with a Nano, if not i have a few megas that i can use for this project.

#define ClockPin 2 // Must be pin 2 or 3
#define DataPin 7 // can be any other pin
#define ResetPB 9 // Reset counter Push Button
  
volatile long EncoderCounter = 0;


void onPin2CHANGECallBackFunction(uint32_t Time, uint32_t PinsChanged, uint32_t Pins){
    static uint32_t lTime; // Saved Last Time of Last Pulse
    uint32_t cTime; // Current Time
    cTime = micros(); // Store the time for RPM Calculations
    int32_t dTime; // Delt in time

// Encoder Code
    bool DataPinVal = digitalRead(DataPin);
// We know pin 2 just went high to trigger the interrupt
// depending on direction the data pin will either be high or low
    EncoderCounter -= (DataPinVal) ? 1 : -1; // Should we step up or down? (neg for cw + rotation)
// End Encoder Code

}

void setup() {
  Serial.begin(9600); //115200
  // put your setup code here, to run once:
  pinMode(ClockPin, INPUT);  
   digitalWrite(ClockPin, HIGH);
  pinMode(DataPin, INPUT);
  digitalWrite(DataPin, HIGH);
  attachInterrupt(0,onPin2CHANGECallBackFunction,RISING);

  pinMode(ResetPB, INPUT);
  digitalWrite(ResetPB, HIGH);
}

void loop() {
  long Counter;
  //float Speed;
  noInterrupts ();
// Because when the interrupt occurs the EncoderCounter and SpeedInRPM could be interrupted while they
// are being used we need to say hold for a split second while we copy these values down. This doesn't keep the
// interrupt from occurring it just slightly delays it while we maneuver values.
// if we don't do this we could be interrupted in the middle of copying a value and the result get a corrupted value.
  Counter = EncoderCounter;

if (digitalRead(ResetPB) == LOW)
  {
      Counter = 0;
  }
  
  interrupts ();

  

    {
    Serial.print(Counter );
    Serial.print("   Pulse");

    Serial.println();
    //SpeedInRPM = 0; // if no pulses occure in the next 100 miliseconds then we must assume that the motor has stopped
  }
}

the base code came from this thread Rotary encoder using interrupts - Programming Questions - Arduino Forum

Now i know folks might say that the nano cannot drive the 64x32 matrix, but ive seen some examples where it supposedly does work?. I would like to stick with the nano because it will keep the footprint of this experiment small.

EDIT looks like the 64x32 crashes the nano, so ill have to use the mega regardless.. None the less i think the inital code above should stay the same.

Post a data sheet for your display. Without knowing the exact display that you have it is difficult to help you. Post a schematic of how it is wired to the Nano.

Is there something special about pin 2 capabilities.

Pin 2 is one of the 2 external interrupts on a Nano. Pin 3 is the other. No other pins will work as external interrupts, they must be set up as pin change interrupts and act quite differently from the external interrupts.

the 64x32 lcd display uses the IDC communication

Maybe you mean I2C. That interface uses pins A4 and A5 pins only (plus Vcc and ground). IDC is short for Insulation Displacement Connector which makes little sense in the context.

looks like the 64x32 crashes the nano,

I have a 128x160 color graphic LCD connected to a standalone Mega328 and it works fine so maybe it is not the display.

Counter = EncoderCounter;

if (digitalRead(ResetPB) == LOW)
  {
      Counter = 0; 
  }

You set Counter to zero and the next time through loop set Counter to equal EncoderCounter. If you want to reset (zero) the count, set EncoderCounter to zero with the reset button.

 pinMode(DataPin, INPUT);
  digitalWrite(DataPin, HIGH);

That enables the internal pullup on the pin. A more readable way to do it is with:

pinMode(DataPin, INPUT_PULLUP);

Thanks for the tips, I will try those few changes to the code for my encoder setup.

After I posed the topic, I decided to start playing with the display. After refreshing myself with the display info (ordered it a few months ago, and just unboxed it now). It looks like I might have no choice but to use the mega board.

Heres a link to the type of displays I ordered.

and along with the adafruit wiki I used this also to get me going, 64x32_RGB_LED_Matrix_-_4mm_pitch_SKU_DFR0460-DFRobot

About 20 mins in I got the display working, and am able to write text to it.. So im on a roll now.

I guess I have no choice but to transfer my encoder setup from the nano to the mega, and populate a breakout board for it. Honestly I think it would be a better choice in the long run seeing that I will be adding extra sensors and such, and the nano would be running out of space.

I will try the PB reset modification and update with the outcome.

Thanks :slight_smile:

groundFungus:

Counter = EncoderCounter;

if (digitalRead(ResetPB) == LOW)
  {
      Counter = 0;
  }



You set Counter to zero and the next time through loop set Counter to equal EncoderCounter. If you want to reset (zero) the count, set EncoderCounter to zero with the reset button.

Such a simple overlook, and yes it works great!

Ok is there a way i can store the max + value, and reset that with a 2nd push button?

I will try and see what i can find as well. Im not by any means fully knowledged with arduino, but the past few months i have been diving head first into some fun little projects.

EDIT..

I got my max value reading to work using the following reference.