Trying to better understand code

I recently used some code from a YouTube video to work with a rotary encoder. There are a few lines that I don't fully understand. I've tried looking it up but have not found answers. The code works perfectly as is, I just want to really know what going on with these lines so that I can better implement them in my future code. Always trying to learn more. Not just knowledge, but understanding.

type or paste code here

Serial.print(virtualPosition > lastCount ? "Up: " : "Down: ");

This seems to be working like an "if" statement within the parentheses. So, in this case, if virtualPosition is greater than lastPosition, it prints "Up", otherwise, it prints "Down". Is that correct? If so, where can I learn more about this topic. I normally would have just used "if else" and had two separate prints. this is MUCH cleaner.

The next line is this:

virtualPosition = min(100, max(0, virtualPosition));

Makes it so vitualPosition dose not exceed 100 or go below 0. But it seems backwards to me.

Here's the whole code:

const int pinA = 3;
const int pinB = 4;
const int pinSW = 8;
int lastCount = 50;
volatile int virtualPosition = 50;

void encoderISR() {
  static unsigned long lastInterruptTime = 0;
  unsigned long interruptTime = millis();
  if (interruptTime - lastInterruptTime > 20) {
    if (digitalRead(pinB) == HIGH) {
      virtualPosition ++;
    }
    else {
      virtualPosition --;
    }
    virtualPosition = min(100, max(0, virtualPosition));
    lastInterruptTime = interruptTime;
  }
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  pinMode(pinA, INPUT);
  pinMode(pinB, INPUT);
  pinMode(pinSW, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(pinA), encoderISR, LOW);
  delay(2000);
  Serial.println("Start");

}

void loop() {
  // put your main code here, to run repeatedly:
  if ((!digitalRead(pinSW))) {
    virtualPosition = 50;
    while (!digitalRead(pinSW))
      delay(10);
    Serial.println("Reset");
  }
  if (virtualPosition != lastCount) {
    Serial.print(virtualPosition > lastCount ? "Up: " : "Down: ");
    Serial.println (virtualPosition);
    lastCount = virtualPosition;
  }
}

First time posting on this forum so if I did something wrong, let me know. Thanks for any help you can give me!

  1. C/C++ ternary operator
  2. The min/max construction is correct. Think it through!
2 Likes
Serial.print(virtualPosition > lastCount ? "Up: " : "Down: ");

When you see the ternary operator (?), say in plain language:

If "virtualPosition" is greater than "lastCount" then Serial.print "Up:" else Serial.print "Down:"

A shorter way to say it is:

(condition) ? (if true): (if false)

Read aloud: "Condition, if true, if false"

=====

virtualPosition = min(100, max(0, virtualPosition));

Read aloud:
"virtualPosition will take the minium (smaller) value of "100" or "max(x)" and "x" will be the maximum (larger) value of "0" or "virtualPosition"

Unabridged code might look like this:

if (virtualPosition > 0)
  virtualPosition = virtualPosition; // do not change virtualPosition
else
  virtualPosition = 0; // change virtualPosition to 0
if (virtualPosition < 100)
  virtualPosition = virtualPosition; // do not change virtualPosition
else
  virtualPosition = 100; // change virtualPosition to 100

Another way to write this is:

if (virtualPosition <=0)
  virtulPosition = 0;
if (virtualPosition >= 100)
  virtualPosition = 100;

You can recognize this as keeping a value within the boundaries (0) to (100) inclusive.

Thank you for you detailed response. It's all very clear now. I had 2 more lines I'm confused about if you have the time:

  if ((!digitalRead(pinSW))) {
    virtualPosition = 50;
    while (!digitalRead(pinSW))
    delay(10);
    Serial.println("Reset");

this line:

 if ((!digitalRead(pinSW))) {

I read this as "not digitalRead (pinSW)" . I don't understand what it's doing.

and this one

    while (!digitalRead(pinSW))

The "while" doesn't have curly brackets? Does "while" not need them for some reason? Or is this a different use entirely from a normal while loop?

The NOT "!" means this is looking for a boolean 0 (LOW, FALSE). If it were looking for a 1/HIGH/TRUE, it would be written:

(digitalRead(pinSW)); // without the "!"

You are testing a "condition"... ("while" is a condition statement, as is "if")... and if you want only one action after the condition, you do not need the braces "{" and "}". Only if you have more than one action after the condition do you need to "embrace" the multiple actions with braces.

Awesome, thanks again!

While this is syntactically correct, it is poor style. It doesn't cost any extra to put those braces and it makes it much clearer without having to stop and focus on that line.

In general you put those braces either way just to make things look nice.

Maybe the person writing this code is having to pay by the character for their keyboard.

1 Like

... and when you want to add another action after the condition... and you do not add the braces, then only the first action depends on the condition, where the added action will occur regardless of the condition.

(condition) // no open brace
  this line happens depending on (condition)
  this line happens always
           // no close brace

as opposed to the good way...

(condition) { // open brace
   this line happens depending on (condition)
   this line happens depending on (condition)
} // close brace
1 Like