Rotary encoder: constraints and floats

Hello,
I'm using a rotary encoder with the PJRC encoder library to set a float value. The value is in the range of 0 to 10.0.
First, I've set up the encoder to reduce each count to 0.1 (by default, it counts 4 digits for each step).

void readEncoder(void) {
  setValue = encoder.read() / 4 * 0.1;
  if(setValue < 0) setValue = 0;
  else if(setValue > 10.0) setValue = 10.0;
  if(setValue != oldPosition) {
    oldPosition = setValue;
    lcd.setCursor(6,3);
    lcd.print(setValue);
  }
}

The problem is that now the value won't go down to 0, it's always at least 0.1 from the multiplication, and even though I've used the if statements to limit the value, the encoder still counts the steps, even though the value isn't changed. So somehow I have to make the encoder actually count between those values.

The rest of the code is here:

#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#include <Encoder.h>

LiquidCrystal_I2C lcd(0x3F,20,4);
//modes are: 0 - CURRENT, 1 - POWER, 2 - RESISTANCE
int mode = 0;
double setValue = 0;

//0 - OUPUT DISABLED, 1 - OUTPUT ENABLED
bool output = 0;

float voltage = 0;
float current = 0;

//define peripherals
const int button = 8;
const int relay = 13;
const int encoderButton = 9;
Encoder encoder(2,3);
long oldPosition = -999;

void readEncoder(void) {
  setValue = encoder.read() / 4 * 0.1;
  if(setValue != oldPosition && setValue >= 0 && setValue <= 10.0) {
    oldPosition = setValue;
    lcd.setCursor(6,3);
    lcd.print(setValue);
  }
}

//function to clear the characters of the output field
void clearOutput(void) {
  lcd.setCursor(16,2);
  lcd.print("    ");
}

//function to clear the characters of the mode field
void clearMode(void) {
  lcd.setCursor(6,2);
  lcd.print("          ");
}

void measureVoltage(void) {
  voltage = 0;
  lcd.setCursor(9,0);
  lcd.print(voltage);
}

void measureCurrent(void) {
  current = 0;
  lcd.setCursor(9,1);
  lcd.print(current);
}

void InitializeLCD(void) {
  lcd.init();         
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("VOLTAGE: ");
  lcd.setCursor(9,0);
  lcd.print(voltage);
  lcd.setCursor(14,0);
  lcd.print("V");
  lcd.setCursor(0,1);
  lcd.print("CURRENT: ");
  lcd.setCursor(9,1);
  lcd.print(current);
  lcd.setCursor(14,1);
  lcd.print("A");
  lcd.setCursor(0,2);
  lcd.print("MODE: ");
  lcd.setCursor(0,3);
  lcd.print("SET: ");
}

//control the output relay
void setOutput() {
  clearOutput();
  if(output == 0) {
    lcd.setCursor(17,2);
    lcd.print("OFF");
    digitalWrite(relay, LOW);
  } else if(output == 1) {
    lcd.setCursor(18,2);
    lcd.print("ON");
    digitalWrite(relay, HIGH);
  }  
}

void setOutputMode(void) {
  clearMode();
  if(mode == 0) {
    lcd.setCursor(6,2);
    lcd.print("CURRENT");
    lcd.setCursor(6,3);
    lcd.print(setValue);
    lcd.setCursor(12,3);
    lcd.print("A");
  } else if(mode == 1) {
    lcd.setCursor(6,2);
    lcd.print("POWER");
    lcd.setCursor(6,3);
    lcd.print(setValue);
    lcd.setCursor(12,3);
    lcd.print("W");
  } else if(mode == 2) {
    lcd.setCursor(6,2);
    lcd.print("RESISTANCE");
    lcd.setCursor(6,3);
    lcd.print(setValue);
    lcd.setCursor(12,3);
    lcd.print("R");
  } else lcd.print("ERROR");
}

void checkOutputButton() {
  if(digitalRead(button) == LOW) {
    delay(50);
    output = !output;
    setOutput();
    delay(300);
  }
}

void checkEncoderButton(){
  if(digitalRead(encoderButton) == LOW) {
    delay(50);
    mode++;
    if(mode == 3) mode = 0;
    setOutputMode();
    delay(300);
  }
}

void setup() {
  lcd.clear();
  //initialize peripherals
  pinMode(button, INPUT_PULLUP);
  pinMode(relay, OUTPUT);
  pinMode(encoderButton, INPUT_PULLUP);

  InitializeLCD();
  setOutputMode();
  setOutput();
}

void loop() {
  //measureVoltage();
  //measureCurrent();
  checkOutputButton();
  checkEncoderButton();
  readEncoder();
}

you could add an offset

I discovered that the encoder library has a write function and I can use it to set the minimum and maximum values. However,

  • the value goes to 10.0 and overflows, goes back to 0.2
  • the value still never goes back to 0.0, and it jumps from 0.1 to -0.1