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.

asked Nov 19, 2017 at 2:39
2
  • 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 Commented Nov 19, 2017 at 7:26
  • Sorry @AnotherShrubbery but that's not your code. Setup() is missing. i is not defined. Commented Nov 23, 2017 at 13:39

2 Answers 2

1

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;
}
answered Nov 23, 2017 at 14:46
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
}
answered Nov 23, 2017 at 13:43

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.