Limit byte values with Encoder

And you think having done something similar proofes that a different code does not work?

O. M. G.

You are asking for the almost sophisticated way of coding without beeing able to manage coding limiting encoder-values. And without having an idea what variables exactly are.

You seem not to even understand what arrays are.
Arrays are a special kind of variables.
If you would like to put variables into an array this would require pointers to the RAM-locations where these variables values are stored at.
Dealing with pointers is another level. And maybe I am wrong but I got the impression that you should learn more basic things before entering this real advanced stuff.

If you would post a description of what functionality you want to have that goes quite beyond what you have posted so far

Then good suggestions can be made.

As a side-note. User gcjr - most of the time offers - highly sophisticated code with pretty short names which requires either a big amount of knowledge I am not exaggerating or hundreds of jours to learn.

He is a retired professional software-developper that collected knowledge over decades by professional coding. He is able to explain simple things but starts at a pretty high level. Which is - in most cases - way above the head of the thread-openers.

Here is a simple example on how using some good libraries could help make your life and code easier

the code does not do much yet but it sets things up nicely

  • the rotary encoder is managed and the call to testEncoder() will see if the encoder's value has changed. The underlying encoder function actually reads the encoder's value and checks against bounds and will force the encoder to stay within those bounds. This is where you can take action accordingly, in this sample code I just print the new encoder value.
  • the button is managed and a call to testSwitch() will see if the button has been pressed and you can take action there accordingly. Here I just print "PRESSED".
  • I did not know what to do with the 2 LEDs you had, so I got them blinking alternatively in a non blocking way to show the code was alive (remove the blink() function to get rid of that).

Now you can "just" add your menu management code into this. You might benefit from studying state machines to handle the modes, here is a small introduction to the topic: Yet another Finite State Machine introduction

hope this helps, happy end of 2024.


click to see the code
/*

  ============================================
  code is placed under the MIT license
  Copyright (c) 2024 J-M-L
  For the Arduino Forum : https://forum.arduino.cc/u/j-m-l

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
  ===============================================


  PIN
   0  NC                        (Rx)
   1  NC                        (Tx)
   2  CLK                       encodeur
   3  DT                        encodeur
   4  SW                        bouton de l'encodeur
   5  200Ω --- Led Anode        Green led on breadboard
   6  200Ω --- Led Anode        Green led on breadboard
   7
   8
   9
  10
  11
  12
  13
  A0
  A1
  A2
  A3
  A4 LCD SDA                commande du LCD
  A5 LCD SCL                commande du LCD

*/

#include <Wire.h>
#include <hd44780.h>                        // main hd44780 header
#include <hd44780ioClass/hd44780_I2Cexp.h>  // i2c expander i/o class header
#include <Encoder.h>                        // https://www.pjrc.com/teensy/td_libs_Encoder.html
#include <Toggle.h>                         // https://www.arduinolibraries.info/libraries/toggle$0

const uint8_t nbCols = 20;
const uint8_t nbRows = 4;

const byte encoderCLKPin = 2;
const byte encoderDTPin  = 3;
const byte encoderSWPin  = 4;
const byte ledPin1 = 5;
const byte ledPin2 = 6;

hd44780_I2Cexp lcd;
Encoder encoder(encoderDTPin, encoderCLKPin);
Toggle encoderSwitch;

long encoderValue;
const long encoderMinValue = -10;
const long encoderMaxValue = +10;


void blink() {
  static unsigned long chrono = 0;
  static bool flipflop = true;
  unsigned long now = millis();
  if (now - chrono >= 500) {
    chrono = now;
    digitalWrite(ledPin1, flipflop ? HIGH : LOW);
    digitalWrite(ledPin2, flipflop ? LOW : HIGH);
    flipflop = !flipflop;
  }
}

void encoderSetValue(long newValue) {
  // as encoders can have multiple ticks, we need to take into account possibles ticks that have been engaged
  long ticks = encoder.read() & 0b11;
  encoder.write(newValue << 2 + ticks);
}

bool encoderChanged() {
  long newPosition = encoder.read() >> 2; // divide by 4 as the rotary sends 4 ticks per click
  if (newPosition < encoderMinValue) {
    newPosition = encoderMinValue;
    encoderSetValue(encoderMinValue);
  } else if (newPosition > encoderMaxValue) {
    newPosition = encoderMaxValue;
    encoderSetValue(encoderMaxValue);
  }

  if (newPosition != encoderValue) {
    encoderValue = newPosition;
    return true;
  }
  return false;
}

void testSwitch() {
  encoderSwitch.poll();
  if (encoderSwitch.onPress()) {
    Serial.println("PRESSED");
  }
}

void testEncoder() {
  if (encoderChanged()) Serial.println(encoderValue);
}

void setup() {
  pinMode(ledPin1, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  encoderSwitch.begin(encoderSWPin);
  Serial.begin(115200);

  int result = lcd.begin(nbCols, nbRows);
  if (result) {
    Serial.print("LCD initialization failed: ");
    Serial.println(result);
    hd44780::fatalError(result);
  }

  lcd.clear();
  lcd.setCursor(5, 0); //Defining positon to write from first row, first column .
  lcd.print("CHARCUPRO");
  lcd.setCursor(3, 2);
  lcd.print("Version 1.1.1");

  lcd.setCursor(0, 2); //Second row, first column
  lcd.print("");
  delay(1000); 

  lcd.clear(); //clear the whole LCD
  lcd.setCursor(1, 1);
  lcd.print("TEMP"); //text
  //----------------------
  lcd.setCursor(1, 3);
  lcd.print("HUMI"); //text
  //----------------------
  lcd.setCursor(12, 1);
  lcd.print("VENT"); //text
  //----------------------
  lcd.setCursor(12, 3);
  lcd.print("UV"); //text
  //----------------------
  lcd.setCursor(8, 1);
  lcd.print((char)223); //signe de degrees
  //----------------------
  lcd.setCursor(9, 1);
  lcd.print("C"); //signe de degrees
  //----------------------
  lcd.setCursor(9, 3);
  lcd.print("%"); //text
  //----------------------
  lcd.setCursor(17, 1);
  lcd.print("off"); //text
  //----------------------
  lcd.setCursor(17, 3);
  lcd.print("off"); //text

}

void loop() {
  testEncoder();
  testSwitch();
  blink();
}

1 Like

No one get better at playing tennis by playing with beginners.I am learning, yes. I guess that forum is meant to shre for those who want to. Not to compete with who is higher level or not. I am wise enough to navigate trough all your generous shares and do my home work on my side.

I will try to be more precise in my demands instead of posting full codes. Good Idea. Thanks for the hints.

I already did the set up of the encoder with to leds to really know what kind of pluses/detents I got. That said. The knoledge you share will be helpful. Thanks for that!

Okay I will do this in c programming language book. I got to remember the functionning of arrays now. I am watching var per var in the code you sent me and I mannage to figure out each part by changing var names to make it mine Now I will check the beta and gamma stuff... Will get trough it. Thanks for your shares.

Because thoso I understood I put them commented out. The one I kept alive is the one I did not understand. ( *lbl ) that was just for the question post

instead of having individual variables, i imagined that accessing a variable would be by indexing into the array of structs and accessing the .val element.

an enum can be used to assign symbols, TempC to the index values making it easier to use indicies. see pg 39

  enum { TempC, DewPtC, Alpha, Beta, Gamma };
1 Like

OK got it

My comment was because the code you shared would not compile because you were providing more values in the initialisation than you had fieds in the struct.

I see, there is certain variables in my code that were part of different trials but I dit not remove them. The code I posted is definatly too heavy for what it does. With learning suggestions your guys share, I should be able to figure out how to minimize. Thanks again for contribution.

good - have fun for the end of the year

Thanks and for you as well, I will sure get back when solved nice and smooth. good news years eve too!. By the way, I find french words in the code you sent.... just a coincidence? :upside_down_face:

Your words - but I’m French indeed (and there is an active French speaking section if you want)

Got it !! Et bien salut à vous! Je suis québécois et amis de plusieurs français. Je vais aller explorer le cÎté francophone bien sûr!

I slightly changed this code from J-M-L jackson to force the values going back to MinValue when I hit the MaxValue by turning the rotary CW; it works.

but vice versa...

I want the same to happen when I hit the minValue turning the rotary CCW i.e. go to maxValue.

It does not work so I had to set it as it just stops to minValue instead of going to Maxvalue when turning CCW.

What is my mistake?

bool menuChanged(){ //issu de encoderChanged
  long newPosition = encoder.read() >> 1;  //ajustement type encoder
  if (newPosition < encoderMinValue) {
    newPosition = (encoderValue );  //encoderValue au lieu de encoderMinValue ou encoderMaxValue
    encoderSetValue(encoderMinValue);
  } else if (newPosition > encoderMaxValue) {
    newPosition = encoderMinValue;
    encoderSetValue(encoderMinValue);
  }

  if (newPosition != encoderValue) {
    encoderValue = newPosition;
    return true;
  }
  return false;
} 

Try


if (newPosition < encoderMinValue) {
    newPosition = encoderMaxValue;
    encoderSetValue(encoderMaxValue);
  } else if (newPosition > encoderMaxValue) {
    newPosition = encoderMinValue;
    encoderSetValue(encoderMinValue);
  }

I didalready, but it printed on serial monitor when I hit lower than 0 turning CCW:
0
20
0
20
0
20

What does your encoderSetValue() function look like?

As you can see from this question. It is better to always post your most actual and complete sketch.

void encoderSetValue(long newValue) {
  // as encoders can have multiple ticks, we need to take into account possibles ticks that have been engaged
  long ticks = encoder.read() & 0b11;
  encoder.write(newValue << 2 + ticks); // Propably here the trick for Min to Max when CCW
}

bool menuChange(){ //issu de encoderChanged
  long newPosition = encoder.read() >> 1; // divide by 4 as the rotary sends 4 ticks per click(chang/ pour 1)
  if (newPosition < modeMinValue) {
    newPosition = (encoderValue );  //encoderValue au lieu de encoderMinValue ou encoderMaxValue
    encoderSetValue(modeMinValue);
  } else if (newPosition > modeMaxValue) {
    newPosition = modeMinValue;
    encoderSetValue(modeMinValue);
  }

  if (newPosition != encoderValue) {
    encoderValue = newPosition;
    return true;
  }
  return false;
} 

:+1: