Rotary encoder for Ham radio

Ok, My next issue.
I have my radio scanning channels, but can't manually control the selection as of yet.
I have a rotary encoder with a pushbutton.
I want to use the button to switch between manual and scan.
then use the encoder to select channels.

#include <Rotary.h>
Rotary r = Rotary(A0, A1);


#include <LiquidCrystal.h>
const int rs = 7, en = 8, d4 = 3, d5 = 4, d6 = 5, d7 = 6;  //set up lcd pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


int sig = 12;  //squelch input
int clk = 9;   //pll programming pins
int dat = 10;  //pll programming pins
int ena = 11;  //pll programming pins
//int led = 13;
int sum = 1;   //scan channel
int encoder = 0;   //rotary encoder status

void setup() {
  pinMode(sig, INPUT_PULLUP);
  pinMode(clk, OUTPUT);
  pinMode(dat, OUTPUT);
  pinMode(ena, OUTPUT);
  //pinMode(led, OUTPUT);
  digitalWrite(clk, LOW);
  digitalWrite(dat, LOW);
  digitalWrite(ena, LOW);
  //Serial.begin(9600);
}

void loop() {
  lcd.clear();
  //lcd.print("    ");

  switch (sum) {      //which channels to scan
    case 1:
      five110();
      //lcd.print("   ");
      lcd.print("145.110Mhz");
      break;
    case 2:
      five170();
      // lcd.print("   ");
      lcd.print("145.170Mhz");
      break;
    case 3:
      five210();
      // lcd.print("   ");
      lcd.print("145.210Mhz");
      break;
    case 4:
      five230();
      //lcd.print("   ");
      lcd.print("145.230Mhz");
      break;


    default:
      seven015();
      lcd.print("147.015Mhz");
      // if nothing else matches, do the default
      // default is optional
      break;
  }

  enabl();                    // go to Enable pulse

}

// zero:  load 0 bit
void z() {
  digitalWrite(dat, LOW);    // Load 0 on dat
  digitalWrite(clk, HIGH);   // bring clock HIGH
  digitalWrite(clk, LOW);    // Then back low
}
// one:  load 1 bit
void o() {
  digitalWrite(dat, HIGH);   // Load 1 on DAT
  digitalWrite(clk, HIGH);   // Bring pin CLOCK high
  digitalWrite(clk, LOW);    // Then back low
}
void enabl() {
  digitalWrite(ena, HIGH);   // Bring Enable high
  digitalWrite(ena, LOW);    // Then back low
  delay(100);
  while (digitalRead(12) == 1) ; //during signal detected, wait.
  ++sum;                      //increment scan
  if (sum > 46)               //reset channel to 1
  {
    sum = 1;
  }
  delay (100);
}



// programmed channels
void five110() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  z();         // 128
  o();         // 64
  o();         // 32
  o();         // 16

  o();         // 8
  z();         // 4
  o();         // 2
  o();         // 1
}

void five170() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  o();         // 128
  z();         // 64
  z();         // 32
  z();         // 16

  z();         // 8
  o();         // 4
  o();         // 2
  o();         // 1
}

void five210() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  o();         // 128
  z();         // 64
  z();         // 32
  z();         // 16

  o();         // 8
  o();         // 4
  o();         // 2
  o();         // 1
}

void five230() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  o();         // 128
  z();         // 64
  z();         // 32
  o();         // 16

  z();         // 8
  z();         // 4
  o();         // 2
  o();         // 1
}



void seven015() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  o();         // 256

  o();         // 128
  o();         // 64
  o();         // 32
  o();         // 16

  o();         // 8
  z();         // 4
  z();         // 2
  z();         // 1
}

Make a flag, say, mode. Execute the manual or scan code depending on the state of the mode flag. Toggle the state of the mode flag with a momentary push button state change. Use the state change detection method and ( see also) to detect change of state of the switch.

Here is an example:

// by C Goulding aka groundFungus

const byte  buttonPin = 2;    // the pin to which the pushbutton is attached
const byte ledPin = 13;       // the pin to which the LED is attached

bool buttonState = 0;         // current state of the button
bool lastButtonState = 0;     // previous state of the button

bool mode = false;

void setup()
{
   // initialize the button pin as a input with internal pullup enabled
   pinMode(buttonPin, INPUT_PULLUP);
   // initialize the LED as an output:
   pinMode(ledPin, OUTPUT);
   // initialize serial communication:
   Serial.begin(115200);
   Serial.println("Select mode with push button");
}

void loop()
{
   static unsigned long timer = 0;
   unsigned long interval = 50;  // check switch 20 times per second
   if (millis() - timer >= interval)
   {
      timer = millis();
      // read the pushbutton input pin:
      buttonState = digitalRead(buttonPin);
      // compare the new buttonState to its previous state
      if (buttonState != lastButtonState)
      {
         if (buttonState == LOW)
         {
            // if the current state is LOW then the button
            // went from off to on:
            digitalWrite(ledPin, !digitalRead(ledPin)); // toggle the output
            mode = !mode;
            if (mode == true)
            {
               Serial.println("Manual mode\n");
            }
            else
            {
               Serial.println("Scan mode\n");
            }
         }
      }
      // save the current state as the last state,
      //for next time through the loop
      lastButtonState = buttonState;
   }
}

Thank you,
I have a button input.
although when I have a signal The while loop Seems to be blocking.

Next I need a working rotary encoder
Then a way to manually change channels.
I tried to do this but was not succsessful.

here is your code in my script

#include <Rotary.h>
Rotary r = Rotary(A0, A1);


#include <LiquidCrystal.h>
const int rs = 7, en = 8, d4 = 3, d5 = 4, d6 = 5, d7 = 6;  //set up lcd pins
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);

const byte  buttonPin = A2;    // the pin to which the pushbutton is attached
const byte ledPin = 13;       // the pin to which the LED is attached

bool buttonState = 0;         // current state of the button
bool lastButtonState = 0;     // previous state of the button

bool mode = false;



int sig = 12;  //squelch input
int clk = 9;   //pll programming pins
int dat = 10;  //pll programming pins
int ena = 11;  //pll programming pins
//int led = 13;
int sum = 1;   //scan channel
int encoder = 0;   //rotary encoder status
//char freq;
//int buttonState;             // the current reading from the input pin
//int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers


void setup() {
  pinMode(sig, INPUT_PULLUP);
  pinMode(clk, OUTPUT);
  pinMode(dat, OUTPUT);
  pinMode(ena, OUTPUT);
  //pinMode(led, OUTPUT);
  digitalWrite(clk, LOW);
  digitalWrite(dat, LOW);
  digitalWrite(ena, LOW);
  Serial.begin(9600);
  lcd.begin(16, 2);
  // initialize the button pin as a input with internal pullup enabled
  pinMode(buttonPin, INPUT_PULLUP);
  // initialize the LED as an output:
  pinMode(ledPin, OUTPUT);

}

void loop() {
  static unsigned long timer = 0;
  unsigned long interval = 50;  // check switch 20 times per second
  if (millis() - timer >= interval)
  {
    timer = millis();
    // read the pushbutton input pin:
    buttonState = digitalRead(buttonPin);
    // compare the new buttonState to its previous state
    if (buttonState != lastButtonState)
    {
      if (buttonState == LOW)
      {
        // if the current state is LOW then the button
        // went from off to on:
        digitalWrite(ledPin, !digitalRead(ledPin)); // toggle the output
        mode = !mode;
        if (mode == true)
        {
          lcd.setCursor(0, 1) ;  //print Manual on 2nd line of lcd
          lcd.print("Manual");
        }
        else
        {
          lcd.setCursor(0, 1) ;  //print Scan on 2nd line of lcd
          lcd.print("Scan  ");
        }
      }
    }
    // save the current state as the last state,
    //for next time through the loop
    lastButtonState = buttonState;
  }
  //lcd.clear();
  lcd.setCursor(0, 0) ;

  switch (sum) {      //which channels to scan
    case 1:
      five110();
      lcd.print("145.110Mhz");
      break;
    case 2:
      five170();
      lcd.print("145.170Mhz");
      break;
    case 3:
      five210();
      lcd.print("145.210Mhz");
      break;
    case 4:
      five230();
      lcd.print("145.230Mhz");
      break;


   default:
      five230();
      lcd.print("145.230Mhz");
      // if nothing else matches, do the default
      // default is optional
      break;
      
  }

  enabl();                    // go to Enable pulse

}

// zero:  load 0 bit
void z() {
  digitalWrite(dat, LOW);    // Load 0 on dat
  digitalWrite(clk, HIGH);   // bring clock HIGH
  digitalWrite(clk, LOW);    // Then back low
}
// one:  load 1 bit
void o() {
  digitalWrite(dat, HIGH);   // Load 1 on DAT
  digitalWrite(clk, HIGH);   // Bring pin CLOCK high
  digitalWrite(clk, LOW);    // Then back low
}
void enabl() {
  digitalWrite(ena, HIGH);   // Bring Enable high
  digitalWrite(ena, LOW);    // Then back low
  delay(100);
  while (digitalRead(12) == 1) ; //during signal detected, wait.
  ++sum;                      //increment scan
  if (sum > 4)               //reset channel to 1
  {
    sum = 1;
  }
  delay (100);
}



// programmed channels
void five110() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  z();         // 128
  o();         // 64
  o();         // 32
  o();         // 16

  o();         // 8
  z();         // 4
  o();         // 2
  o();         // 1
}

void five170() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  o();         // 128
  z();         // 64
  z();         // 32
  z();         // 16

  z();         // 8
  o();         // 4
  o();         // 2
  o();         // 1
}

void five210() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  o();         // 128
  z();         // 64
  z();         // 32
  z();         // 16

  o();         // 8
  o();         // 4
  o();         // 2
  o();         // 1
}

void five230() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  z();         // 256

  o();         // 128
  z();         // 64
  z();         // 32
  o();         // 16

  z();         // 8
  z();         // 4
  o();         // 2
  o();         // 1
}



void seven015() {
  z();         // 8192
  z();         // 4096

  o();         // 2048
  o();         // 1024
  z();         // 512
  o();         // 256

  o();         // 128
  o();         // 64
  o();         // 32
  o();         // 16

  o();         // 8
  z();         // 4
  z();         // 2
  z();         // 1
}

Have You verified the reading of the encoder? Used example code or written the test code Yourself?

Banging all things together and the look for errors is the worst way to build up code.

What works and what doesn't work?

1 Like

Hello
Who is the manufacturer of the amateur radio?
Have a nice day and enjoy coding in C++.

I recommend using the NewEncoder-library.

With the NewEncoder-library you can setup the encoder to behave like this
if turned clockwise increment a value until max-value. If max-value is reached more rotating clockwise does not count up more.
The value stays on max

if turned counterclockwise deccrement a value until min-value. If min-value is reached more rotating counterclockwise does not count down more.
The value stays on min.

For buttons I recommend the MoBaTools. The MobaTools offer

shortPress( buttonNbr ); True if button ‘buttonNbr’ was pressed short. 
This event is set when the button is released after a short press 
and reset after the call of  this method or if it is pressed again. 

myButtons.longPress( buttonNbr );
True if button ‘buttonNbr’ was pressed long. 
This event is set when the time for a long press has elapsed after pressing 
and holding the key and is reset after calling this method or when 
the key is pressed again. 

myButtons.pressed( buttonNbr );
True if button ‘buttonNbr’ was pressed. 
This event is set when the button was pressed and reset after the call of  this method or if it is released. 


uint8_t myButtons.released( buttonNbr );
>0 if button ‘buttonNbr’ was released. This event is set when the button was released and 
reset after the call of  this method or if it is pressed again. 
The value returned is the duration of the press in debTime (debounce time) units. The 
maximum value is 255, even if the key was pressed longer.


myButtons.clicked(  buttonNbr );
Returns whether the button was single or double clicked. The return value is:
NOCLICK (=0) if nothing has been clicked.
SINGLECLICK (=1) when a single click is detected.
DOUBLECLICK (=2) when a double click is detected.

NewEncoder must be installed as a ZIP-library

The MoBaTools can be installed with the library manager

best regards Stefan

The boards I am using is from a kenwood tm-2550

I got frustrated and deleted the changes. I forgot what I had done and am now starting over.
I would say I am 2% proficient at coding.

Hello
Many thanks for your relpy.
Did you make some research for remote control on Amatuer Radio sites?
Have a nice day and enjoy coding in C++.

I want to write in my own words what I guess how the codes functionality should be:

You want to have a manual mode where turning the rotary encoder changes the frequency between four frequencies
145.110Mhz
145.170Mhz
145.210Mhz
145.230Mhz

in scan-mode is active
the code shall change between these 4 frequencies automatically
If a signal is detected stay on this channel

the change between manual mode and scan-mode is done by pressing the rotary-encoders push-button-function

I have some additional questions:
In scan-mode:
if a signal is detected - for how long shall the code stay on this frequency
5 seconds, 20 seconds?

if in manual mode:
if you have reached the upper-end or the lower-end of the frequencies
shall turning the rotary-encoder change automatically from
lowest-frequency to highest-frequency
highest-frequency to lowest-frequency ?

or should it stay on lowest-freq / highest-freq and you would have to turn the rotary-encoder into the opposite direction to change frequency?
both is possible to code. just a few different lines of code to create the one or the other logic.

You have written some functions which is very good. You should make some more parts of the code as functions. Each part of the code that does some kind of senseful thing can be its own function.

A while loop has a blocking character. As long as the while-loop is "looping" nothing else can happen. The trick do repeat a certain part of the code and beeing able to check for button-presses at the same time is to move the "looping" to a higher level.

This higher-level is function loop itself.

as a pseudo-code that just shows the principle

void loop() {
   checkForButtonPresses();
   if (manualMode) {
    checkRotaryEncoder();
   }

   if (scanMode) {
     DoScanning();
   }  

function DoScanning() is working in a way that the function is entered and leaved repeatedly and always checking some conditions
if no signal detected move on to next channel

if signal detected stay on this channel for n seconds
which means
set a flag variable "signalDetected" to true and start a timer

if(signalDetected) {

  • check how many seconds have passed by since signal detection
  • if less than n seconds do nothing = stay on the channel
  • if n seconds are reached change to next channel and reset flag to signalDetected = false;

that's the raw picture as pseudo-code.

The code you have posted in this thread is a good base to start on.
For keeping track of changes I have the habit of saving code-versions that do work with a serial-number in the filename and a short hint about the functionality

HAM-Radio-001-just-manual
HAM-Radio-002-Btn-man_scan
HAM-Radio-003-scan-timing
HAM-Radio-004-....
This makes it easy to rollback or to look up how the code looked like in a earlier version

again I want to emphasize:
if the "looping" is done by loop itself you can check for buttonpressed all the time in parallel to scanning

void loop() {
  jump_In_And_Out_A();
  jump_In_And_Out_B();
  jump_In_And_Out_C();
}  

inside each jump_In_And_Out_-function stepping forward to the next step is done by a switch-case-structure like you already use it.

best regards Stefan

Stefan, Thank you for your response.
In scan mode, It should scan channels until a signal is detected on pin 12 (the squelch control) then when signal is dropped hold for 3 seconds to see if the signal comes back, if not then resume scan.
when channel list high or low is reached, recycle to top or bottom of list depending on rotary encoder direction (if high channel is reached, go to first channel) the code I have shown is an abbreviated channel list, I presently have 46 channels.

The code I have is aquired from various sketches found on the internet. I don't fully understand the functions, just that they work. When I try to make my own, I cannot get them to work. So I think I need alot of learning about this matter. The serial transfer to the PLL is rather clunky. so I eventually want to use a more conventional SPI form. But I don't understand that yet.
Another of the future parts of this project is to add a MX365 CTCSS IC for tone decode.
and to integrate that into the channel definition. But that will be later once I get the more basic functions working properly.
Many of the instructions on arduino programming I have a very hard time understanding because I seem to be missing some kind of basic foundation. unless the code is meticulously commented with every aspect explained. I'm lost.
So I apreciate patience from everyone until I get further along on this learning curve. I have no mentor.
Thank you
Michael

Hi Michael,

The basic technique to analyse how code works is to use serial output.
Even for professional programmers it is hard to imagine the values of mutliple variables in their head and what if-conditions evaluate to true or false => what the
code will execute next.

Serial output writes down a trace to follow and to directly read on the screen what values variables have. This makes it much easier to understand what the code is doing.

With the help of other members here in the userforum I wrote two macros that reduce the effort to add serial output. These macros reduce the effort from writing three lines of code to a single line.
For fast running loops that iterate thousands of times per second it doe not make sense to printout 1000 lines to the serial monitor each second. So the second macro called "dbgi" just prints in intervalls that you can define. Hence the "i" at the end.

You can find the two macros and explanation in this thread:

give it a try and add the macros to your actual code. If you have any questions or get a compiler-error just ask here. Add the compiler-messages to the posting as a code-section.

For a functionality like this a state-machine is very suitable.

  • state-machines,
  • non-blocking timing based on function millis(),
  • executing mutliple tasks almost in parallel

are medium advanced coding techniques that need some time to understand.

It will take more than 2 or 3 hours. And the way to learn them is do examine small testcodes and how the testcodes behave through serial output.

Add the following lines of code at the very top of your actual code. Really above anything else. These lines shall start with line 1

// start of macros dbg and dbgi
#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);
// usage: dbg("1:my fixed text",myVariable);
// myVariable can be any variable or expression that is defined in scope

#define dbgi(myFixedText, variableName,timeInterval) \
  do { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  } while (false);
// usage: dbgi("2:my fixed text",myVariable,1000);
// myVariable can be any variable or expression that is defined in scope
// third parameter is the time in milliseconds that must pass by until the next time a 
// Serial.print is executed
// end of macros dbg and dbgi

best regards Stefan

for the very basics about how programming with Arduino-IDE works
Take a look into this tutorial:

Arduino Programming Course

It is easy to understand and has a good mixture between explaining important concepts and example-codes to get you going. So give it a try and report your opinion about this tutorial.

Stefan,
I was experimenting with creating a function.

  enabl();                                             // go to Enable pulse

//Added call

  scan();                                              // scan channels           

}

// zero:  load 0 bit
void z() {
  digitalWrite(dat, LOW);                              // Load 0 on dat
  digitalWrite(clk, HIGH);                             // bring clock HIGH
  digitalWrite(clk, LOW);                              // Then back low
}
// one:  load 1 bit
void o() {
  digitalWrite(dat, HIGH);                             // Load 1 on DAT
  digitalWrite(clk, HIGH);                             // Bring pin CLOCK high
  digitalWrite(clk, LOW);                              // Then back low
}
void enabl() {
  digitalWrite(ena, HIGH);                             // Bring Enable high
  digitalWrite(ena, LOW);                              // Then back low
  delay(200);

//Original location of code

  // while (digitalRead(12) == 1) ;                      //during signal detected, wait.
  //++sum;                                              //increment scan
  //if (sum > 46)                                       //reset channel to 1
  //{
  //sum = 1;
  //}
}

//my attempt at a function

int scan() {
  while (digitalRead(12) == 1) ;                      //during signal detected, wait.
  ++sum;                                              //increment scan
  if (sum > 46)                                       //reset channel to 1
  {
    sum = 1;
  }
  return sum;
}

I have not tested this yet, but it does compile ok.
Now to figure out how to do a manual function.
Michael

What is the exact type of microcontroller you are using?
This important information to make the rotary-enocder work reliably.

The manual mode uses the rotary encoder right?
Can you please post a link to the datasheet of the rotary-encoder a link to where you have bought the encoder or at least a picture of the encoder.

Your function scan has a while loop. This means the code-execution stays inside the while loop as long as the while-condition evaluates to true.
This is blocking. code-execution is "blocked" = stays inside the while-loop.
If you allow yourself to step back from your actual code and try some example-how non-blocking coding works you will walk up the learning curve.

trying to code all things directly into your HAM-Radio-code is like trying to climb up such a rock without training

You will would need supporters that provide you a seat on a long rope = writing the code for you or you yourself need some training and practising technique
the do it yourself.

Fortunately learning to code needs much less "training" and only a little bit physical fitness.
best regards Stefan

Stefan,
I am using a Nano.
Yes, I do feel like I am climbing a mountain with this code.
The encoder is something i scavenged from a Chinese board I had in my junk box.
It does work with the rotary library. I tried it with the sample sketch provided.

My code is very much like a Frankenstein monster, parts of this and that.

Michael

picture please. At least how many pins does the rotary-encoder have?

rotary-encoders work best with interrupts. Though it is not a must.
The library newEncoder does use interrupts and does work very reliable with any kind of encoder.

On an Arduino Nano only the IO-pins 2 and 3 can be used with interrupts

If you have IO-pin 2 and 3 free you should connect the encoder to those two io-pins.
best regards Stefan

The encoder has 5 pins, 2 for the button. 3 for the encoder A,B, Com.
sorry, I do not have a camera. Thank you for the interupt info, That explains why the interupt sample sketch didn't work.

Mike

Stefan,
Here is the closest rotary encoder picture to what I have.
Mike

So here is a demo-code with some comments how the library NewEncoder works.

#include "NewEncoder.h"

const byte EncChA_Pin = 2;
const byte EncChB_Pin = 3;
const int minVal = -20;
const int maxVal =  20;
const int startVal = 0;

// Pins 2 and 3 should work for many processors, including Uno. See README for meaning of constructor arguments.
// Use FULL_PULSE for encoders that produce one complete quadrature pulse per detnet, such as: https://www.adafruit.com/product/377
// Use HALF_PULSE for endoders that produce one complete quadrature pulse for every two detents, such as: https://www.mouser.com/ProductDetail/alps/ec11e15244g1/?qs=YMSFtX0bdJDiV4LBO61anw==&countrycode=US&currencycode=USD

NewEncoder myEncoderObject(EncChA_Pin, EncChB_Pin, minVal, maxVal, startVal, FULL_PULSE);

int16_t currentValue;
int16_t prevEncoderValue;

void setup() {
  // myEncState is a variable of type EncoderState
  // EncoderState is a structured variable that has two "simple" variables
  // .currentValue which is type int16_t
  // (16 bit signed integer valuerange -36767 to 36767)
  // currentValue counts up / down with each pulse created through rotating the encoder
  // and
  // .currentClick which is of type "EncoderClick"
  // the variable type "EncoderClick" can have just 3 values
  // NoClick, DownClick, UpClick where "click" means a "pulse" created through rotating the encoder
  NewEncoder::EncoderState myEncState;

  Serial.begin(115200);
  delay(2000);
  Serial.println("Starting");

  if (!myEncoderObject.begin()) {
    Serial.println("Encoder Failed to Start. Check pin assignments and available interrupts. Aborting.");
    while (1) {
      yield();
    }
  } else {
    // store values of currentValue and EncoderClick into variable myEncState
    myEncoderObject.getState(myEncState);
    Serial.print("Encoder Successfully Started at value = ");
    prevEncoderValue = myEncState.currentValue;
    Serial.println(prevEncoderValue);
  }
}

void loop() {
  NewEncoder::EncoderState myCurrentEncoderState;

  // store actual values into variable myCurrentEncoderState
  if (myEncoderObject.getState(myCurrentEncoderState)) {
    Serial.print("Encoder: ");
    currentValue = myCurrentEncoderState.currentValue;

    // if currentValue has REALLY changed print new currentValue
    if (currentValue != prevEncoderValue) {
      Serial.println(currentValue);
      prevEncoderValue = currentValue;


      // if currentValue stayed the same because the number is at upper/lower limit
      // check if encoder was rotated by using the UpClick / DownClick-values
    } else
      switch (myCurrentEncoderState.currentClick) {
        case NewEncoder::UpClick:
          Serial.println("at upper limit.");
          break;

        case NewEncoder::DownClick:
          Serial.println("at lower limit.");
          break;

        default:
          break;
      }
  }
}

The puprose of this code is to check if the hardware / the wiring is OK
It just prints the counter-value to the serial monitor.
If it is easy for you to change your setup to have just this encoder connected to the Arduino nano you can check if the demo-code is working.

Do you know how to install a ZIP-library from GitHub?
best regards Stefan