1

I am making a program to use a rotary encoder instead of a button in the buttoncycler example in the Adafruit NeoPixel library.

I am using the US Digital S1-256-250-IE-B-D. Datasheet can be found here:
https://cdn.usdigital.com/assets/datasheets/S1_datasheet.pdf?k=636466553771569761

#include < RotaryEncoder.h >
void setup() {
}
void loop() {
  static int change =  0;
  static int pos = 0;
  static int oldPos = 0;
  //Read the Encoder's state
  encoder.tick();
  int enc = encoder.getPosition();
  pos = abs(enc) % 2;
  change = oldPos-pos;
  if (change != 0) {

    switch (pos) {
      case 0:
      //do a program that lasts 5 seconds
      break;
      case 1:
      //do a program that lasts 5 seconds
      break;
    }
    oldPos = pos;
    change = 0;
  }
}

I was wondering if there is a way to change the program immediately after turning the rotary encoder, instead of having to wait for the program to complete.

  • Please edit your question to include a Minimal, Complete, and Verifiable example of code, not just snippets. Minimal means you've stripped away irrelevant stuff, just leaving what's needed to show the problem. Complete means all the library names are shown, all the variable declarations, and all the function definitions – so people don't have to waste time guessing what you did or what you meant. Verifiable means it can be compiled and tested, allowing other people to test their theories about the problem – user31481 Nov 19 '17 at 7:26
  • Sorry @AnotherShrubbery but that's not your code. Setup() is missing. i is not defined. – Code Gorilla Nov 23 '17 at 13:39
2

I was wondering if there is a way to change the program immediately after turning the rotary encoder, instead of having to wait for the program to complete.

There is, but it's not completely trivial. The reason it is not trivial is each animation is implemented as a function that takes a while to execute. For doing what you ask, each of these animations should be modified, with a way to exit early if needed.

One approach would be to manage the rotary encoder using an interrupt. I let you investigate how to do that: you probably can find examples on the Web. Once the encoder reading is interrupt-based, you would need to do the following changes in your program:

At global scope, add

volatile bool stop_now = false;

This will be a sort of “flag” intended to inform the currently running animation that it should return ASAP.

Then, inside the interrupt handler, add

stop_now = true;

In loop(), just after if (change != 0) {, add

stop_now = false;

In each animation, replace delay(wait) with:

uint32_t start_time = millis();
while (millis() - start_time < wait) {
    if (stop_now)
        return;
}
0

Your code (if it worked) is right. All you need to do is turn the comments into function calls:

#include <RotaryEncoder.h>

// Define global variables
int pos = 0;
int oldPos = 0;

void setup() {
// Do stuff
}

void loop() {
  //Read the Encoder's state
  encoder.tick();
  pos = encoder.getPosition();
  const int change = (oldPos - abs(pos)) % 2;
  switch (change) 
  {
      case 0:
        programOne();
        break;
      case 1:
        programTwo()
        break;
    }
    oldPos = pos;
  }
}

void programOne()
{
//Do Stuff
}
void programTwo()
{
// Do stuff
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.