working on it ...

## Filters

Sort by

Found 105 snippets matching: rotary

### Rotary Encoder State table

```/* Common 2 pins rotary encoder (ignore push button pin)
Default pin output = (0,0)
Read each pin and combine them into one value
then use it to index the state table to advance to next state
State sequence 00->01->11->10->00 return -1
Next state  0   1   3   2   0
00->10->11->01->00 return +1
0   2   3   1   0
*/
const int ENC_A = 2;
const int ENC_B = 3;

// State table
static uint8_t stb[][4] =
{
//       0 1 2 3
{8,2,1,8}, //0 start here v=0
{0,8,1,3}, //1 0*2(-3-1-0 -1
{0,8,2,4}, //2 0*1(-3-2-0
{8,5,1,3}, //3 0-2*3(-1-0 -1
{8,2,6,4}, //4 0-1*3(-2-0
{7,5,8,3}, //5 0-2-3*1(-0 -1
{9,8,6,4}, //6 0-1-3*2(-0
};
static int encRead( int pa, int pb)
{
int8_t cx = 0; 			// initial state 0
int errCnt = 0;
while (errCnt < 1550)
{

if (v < 4)
{
uint8_t nx = stb[cx][v];

if (nx > 6)
{
if (nx == 8)
errCnt++;
else
return (8 - (int)nx);
}
else
{
cx = nx;
}
}
else
{
cx = 0;
errCnt++;
}
}

return 0;
}

void setup()
{
Serial.begin(9600);

pinMode( ENC_A, INPUT_PULLUP);
pinMode( ENC_B, INPUT_PULLUP);

}

const int MAX_VAL = 64*6 -1;

int lastPos = 0;

void loop() {

unsigned long 	sampleTime = millis();
sampleTime = millis() - sampleTime;

if (rv == 0)
{
delay(50);
}
else
{
lastPos += rv;
if (sampleTime < 20)
sampleTime = 20;
// simulate acceleration
lastPos += rv*int(9000.0/(sampleTime*sampleTime));

if (lastPos < 0) lastPos = 0;
if (lastPos > MAX_VAL) lastPos = MAX_VAL;

Serial.print(lastPos); Serial.print(" "); Serial.println(sampleTime);

}

}

```

### Use rotary encoder with Arduino Micro to increase/decrease a value and show that value on SSD1306 display. Based on https://learn.adafruit.com/pro-trinket-rotary-encoder/example-rotary-encoder-volume-control

Use rotary encoder with Arduino Micro to increase/decrease a value and show that value on SSD1306 display. Based on https://learn.adafruit.com/pro-trinket-rotary-encoder/example-rotary-encoder-volume-control: rotary-encoder.ino
```#include <SPI.h>
#include <Wire.h>

#define OLED_DC         6
#define OLED_CS         7
#define OLED_RESET      8
#define PIN_ENCODER_A   4 //Micro pin 4 - encoder A
#define PIN_ENCODER_B   6
#define PIN_ENCODER_BX  12 //Micro pin 12 - encoder B
#define ARDUINO_PINx    PIND

static uint8_t enc_prev_pos = 0;
static uint8_t enc_flags = 0;
int displayedNumber = 0;
const int ledPin =  13;

void setup()
{
// set pins as input with internal pull-up resistors enabled
pinMode(PIN_ENCODER_A, INPUT);
pinMode(PIN_ENCODER_BX, INPUT);
digitalWrite(PIN_ENCODER_A, HIGH);
digitalWrite(PIN_ENCODER_BX, HIGH);

display.begin(SSD1306_SWITCHCAPVCC);

display.display(); // show splashscreen

//delay(2000);
//display.clearDisplay();

// get an initial reading on the encoder pins
{
enc_prev_pos |= (1 << 0);
}
{
enc_prev_pos |= (1 << 1);
}
}

void loop()
{
int8_t enc_action = 0; // 1 or -1 if moved, sign is direction

// note: for better performance, the code will now use
// direct port access techniques
// http://www.arduino.cc/en/Reference/PortManipulation
uint8_t enc_cur_pos = 0;

// read in the encoder state first
if (bit_is_clear(ARDUINO_PINx, PIN_ENCODER_A))
{
enc_cur_pos |= (1 << 0);
}
if (bit_is_clear(ARDUINO_PINx, PIN_ENCODER_B))
{
enc_cur_pos |= (1 << 1);
}

// if any rotation at all
if (enc_cur_pos != enc_prev_pos)
{
if (enc_prev_pos == 0x00)
{
// this is the first edge
if (enc_cur_pos == 0x01)
{
enc_flags |= (1 << 0);
}
else if (enc_cur_pos == 0x02)
{
enc_flags |= (1 << 1);
}
}

if (enc_cur_pos == 0x03)
{
// this is when the encoder is in the middle of a "step"
enc_flags |= (1 << 4);
}
else if (enc_cur_pos == 0x00)
{
// this is the final edge
if (enc_prev_pos == 0x02)
{
enc_flags |= (1 << 2);
}
else if (enc_prev_pos == 0x01)
{
enc_flags |= (1 << 3);
}

// check the first and last edge
// or maybe one edge is missing, if missing then require the middle state
// this will reject bounces and false movements
if (bit_is_set(enc_flags, 0) && (bit_is_set(enc_flags, 2) || bit_is_set(enc_flags, 4)))
{
enc_action = 1;
}
else if (bit_is_set(enc_flags, 2) && (bit_is_set(enc_flags, 0) || bit_is_set(enc_flags, 4)))
{
enc_action = 1;
}
else if (bit_is_set(enc_flags, 1) && (bit_is_set(enc_flags, 3) || bit_is_set(enc_flags, 4)))
{
enc_action = -1;
}
else if (bit_is_set(enc_flags, 3) && (bit_is_set(enc_flags, 1) || bit_is_set(enc_flags, 4)))
{
enc_action = -1;
}

enc_flags = 0; // reset for next time
}
}

enc_prev_pos = enc_cur_pos;

if (enc_action > 0)
{
draw(++displayedNumber);
digitalWrite(ledPin, HIGH);
}
else if (enc_action < 0)
{
digitalWrite(ledPin, LOW);
draw(--displayedNumber);
}
else {
// do nothing
}
}

void draw(int number) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(0,0);
display.println(number);
display.display();
}

```

### Read incremental rotary encoder (optical) using Arduino Uno

Read incremental rotary encoder (optical) using Arduino Uno: rotary_encoder.ino
```/*
Read optical incremental rotary encoder output.

Serial output gives encoder position (absolute since start of program), and speed in /second separated by a tab.

Seems reasonably repeatable.
*/

// Pin definitions.
#define enc_a  2
#define enc_b  3
#define led 13

volatile int prev = 0;
volatile int current = 0;
volatile int enc_pos = 0;
volatile int enc_pos_prev = 0;
volatile int enc_pos_change = 0;
volatile unsigned long micros_current = 0;
volatile unsigned long micros_prev = 0;
volatile boolean state_a = 0;
volatile boolean state_b = 0;

void setup()
{
pinMode(enc_a, INPUT);
pinMode(enc_b, INPUT);

attachInterrupt(0, interrupt_enc_a, CHANGE);
attachInterrupt(1, interrupt_enc_b, CHANGE);

Serial.begin(115200);
}

void loop()
{
Serial.print(enc_pos);
Serial.print("\t");

// Need to handle overflow in micros_prev (i.e. micros() < micros_prev)
micros_current = micros();
enc_pos_change = enc_pos - enc_pos_prev;
enc_pos_change = abs(enc_pos_change);
Serial.print(enc_pos_change / ((micros_current - micros_prev) / 1e6));

Serial.print("\n");
enc_pos_prev = enc_pos;
micros_prev = micros_current;
delay(100);
}

void interrupt_enc_a()
{

if (!state_a) {
state_b ? enc_pos++: enc_pos--;
}
state_a = !state_a;
}

void interrupt_enc_b()
{
state_b = !state_b;
}

```

### fastled demoreel100 with rotary encoder

fastled demoreel100 with rotary encoder: lampe.ino
```#include "FastLED.h"

FASTLED_USING_NAMESPACE

#define DATA_PIN    10
//#define CLK_PIN   4
#define LED_TYPE    WS2812B
#define COLOR_ORDER GRB
#define NUM_LEDS    6
CRGB leds[NUM_LEDS];

volatile byte BRIGHTNESS = 0;
#define FRAMES_PER_SECOND  120

static int pinA = 2; // Our first hardware interrupt pin is digital pin 2
static int pinB = 3; // Our second hardware interrupt pin is digital pin 3
static int pinC = 4;
volatile long pinCignoreCycles = 0;         // the last time the output pin was sampled
volatile byte aFlag = 0; // let's us know when we're expecting a rising edge on pinA to signal that the encoder has arrived at a detent
volatile byte bFlag = 0; // let's us know when we're expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set)
volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255
volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor)
volatile byte reading = 0; //somewhere to store the direct values we read from our interrupt pins before checking to see if we have moved a whole detent
volatile bool encoderMode = true; // 0 brightness // 1 pattern
// List of patterns to cycle through.  Each is defined as a separate function below.
typedef void (*SimplePatternList[])();
SimplePatternList gPatterns = { rainbow, rainbowWithGlitter, confetti, sinelon, juggle, bpm, white, red,redglitter, green,greenglitter, blue };

uint8_t gCurrentPatternNumber = 0; // Index number of which pattern is current
uint8_t gHue = 0; // rotating "base color" used by many of the patterns

void setup() {
delay(3000); // 3 second delay for recovery

// tell FastLED about the LED strip configuration

// set master brightness control
FastLED.setBrightness(BRIGHTNESS);

pinMode(pinA, INPUT_PULLUP); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
pinMode(pinB, INPUT_PULLUP); // set pinB as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases)
attachInterrupt(0,PinA,RISING); // set an interrupt on PinA, looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below)
attachInterrupt(1,PinB,RISING); // set an interrupt on PinB, looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below)
pinMode(pinC, INPUT_PULLUP);
Serial.begin(115200); // start the serial monitor link
}

void PinA(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; // read all eight pin values then strip away all but pinA and pinB's values
if(reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPos ++; //decrement the encoder's position count
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
}
else if (reading == B00000100) bFlag = 1; //signal that we're expecting pinB to signal the transition to detent from free rotation
sei(); //restart interrupts
}

void PinB(){
cli(); //stop interrupts happening before we read pin values
reading = PIND & 0xC; //read all eight pin values then strip away all but pinA and pinB's values
if (reading == B00001100 && bFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin's rising edge
encoderPos --; //increment the encoder's position count
bFlag = 0; //reset flags for the next turn
aFlag = 0; //reset flags for the next turn
}
else if (reading == B00001000) aFlag = 1; //signal that we're expecting pinA to signal the transition to detent from free rotation
sei(); //restart interrupts
}
byte b; // used to detect if brighness have overflowed
void loop(){

if(oldEncPos != encoderPos) {
if (encoderMode) {
if (oldEncPos > encoderPos) {
b = BRIGHTNESS;
BRIGHTNESS -= 15;
if(BRIGHTNESS > b) {
BRIGHTNESS = 0;
}
} else {
b = BRIGHTNESS;
BRIGHTNESS += 15;
if(BRIGHTNESS < b) {
BRIGHTNESS = 255;
}
}
FastLED.setBrightness(BRIGHTNESS);
}
if (!encoderMode) {
if (oldEncPos > encoderPos) {
prevPattern();
} else {
nextPattern();
}
}

Serial.print("C:");
Serial.print(BRIGHTNESS);
Serial.print(",");
Serial.print(gCurrentPatternNumber);
Serial.println(".");
oldEncPos = encoderPos;
}

if (pinCignoreCycles > 0) {
pinCignoreCycles--;
}

if(pinCignoreCycles == 0) {
pinCignoreCycles = 25;
Serial.println("Btn");
encoderMode = !encoderMode;

}
}

// Call the current pattern function once, updating the 'leds' array
gPatterns[gCurrentPatternNumber]();

// send the 'leds' array out to the actual LED strip
FastLED.show();
// insert a delay to keep the framerate modest
FastLED.delay(1000/FRAMES_PER_SECOND);

EVERY_N_MILLISECONDS( 20 ) { gHue++; } // slowly cycle the "base color" through the rainbow
EVERY_N_SECONDS(30) {
if(BRIGHTNESS > 0) {
BRIGHTNESS--;
Serial.print("A:");
Serial.print(BRIGHTNESS);
Serial.print(",");
Serial.print(gCurrentPatternNumber);
Serial.println(".");
if (BRIGHTNESS == 0) {
encoderMode = true; //fall back to brightness mode
}
FastLED.setBrightness(BRIGHTNESS);
}
}
}

#define ARRAY_SIZE(A) (sizeof(A) / sizeof((A)[0]))

void nextPattern()
{
// add one to the current pattern number, and wrap around at the end
gCurrentPatternNumber = (gCurrentPatternNumber + 1) % ARRAY_SIZE( gPatterns);
}
void prevPattern()
{
gCurrentPatternNumber = (gCurrentPatternNumber - 1);
if (gCurrentPatternNumber > ARRAY_SIZE(gPatterns)) {
gCurrentPatternNumber = ARRAY_SIZE(gPatterns)-1;
}
}

void rainbow()
{
// FastLED's built-in rainbow generator
fill_rainbow( leds, NUM_LEDS, gHue, 7);
}

void rainbowWithGlitter()
{
// built-in FastLED rainbow, plus some random sparkly glitter
rainbow();
}

{
if( random8() < chanceOfGlitter) {
leds[ random16(NUM_LEDS) ] += CRGB::White;
}
}

void confetti()
{
int pos = random16(NUM_LEDS);
leds[pos] += CHSV( gHue + random8(64), 200, 255);
}

void sinelon()
{
// a colored dot sweeping back and forth, with fading trails
int pos = beatsin16(13,0,NUM_LEDS);
leds[pos] += CHSV( gHue, 255, 192);
}

void bpm()
{
// colored stripes pulsing at a defined Beats-Per-Minute (BPM)
uint8_t BeatsPerMinute = 62;
CRGBPalette16 palette = PartyColors_p;
uint8_t beat = beatsin8( BeatsPerMinute, 64, 255);
for( int i = 0; i < NUM_LEDS; i++) { //9948
leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
}
}

void juggle() {
// eight colored dots, weaving in and out of sync with each other
byte dothue = 0;
for( int i = 0; i < 8; i++) {
leds[beatsin16(i+7,0,NUM_LEDS)] |= CHSV(dothue, 200, 255);
dothue += 32;
}
}
void white() {
for(int i=0; i < NUM_LEDS; i++) {
leds[i] = 0xFFFFFF;
}
}
void red() {
for(int i=0; i < NUM_LEDS; i++) {
leds[i] = 0x00FF00;
}
}
void redglitter() {
for(int i=0; i < NUM_LEDS; i++) {
leds[i] = 0x00FF00;
}
}
void green() {
for(int i=0; i < NUM_LEDS; i++) {
leds[i] = 0xFF0000;
}
}
void greenglitter() {
for(int i=0; i < NUM_LEDS; i++) {
leds[i] = 0xFF0000;
}
}
void blue() {
for(int i=0; i < NUM_LEDS; i++) {
leds[i] = 0x0000FF;
}
}

```

### Arduino - Rotary encoder using Neopixel ring indicator

Arduino - Rotary encoder using Neopixel ring indicator: rotary_encoder_and_neopixel_ring.ino
```#include <Adafruit_NeoPixel.h>

* Connect Encoder to Pins encoder0PinA, encoder0PinB, and +5V.
*
* Sketch by max wolf / www.meso.net
* v. 0.1 - very basic functions - mw 20061220
*
*/

#define PIN            9
#define NUMPIXELS      16

int val;
int encoder0PinA = 2;
int encoder0PinB = 3;
int encoder0Pos = 0;
int encoder0PinALast = LOW;
int n = LOW;

void setup() {
pinMode (encoder0PinA,INPUT);
pinMode (encoder0PinB,INPUT);
pinMode (5, OUTPUT);
pinMode (6, OUTPUT);
digitalWrite (5, HIGH);
digitalWrite (6, LOW );
Serial.begin (9600);
pixels.begin(); // This initializes the NeoPixel library.
}

void loop() {
if ((encoder0PinALast == LOW) && (n == HIGH)) {
encoder0Pos--;
} else {
encoder0Pos++;
}
Serial.print (encoder0Pos);
Serial.print ("\n");

for (byte i=0; i<16; i++) {
if (encoder0Pos == 0) {
pixels.setPixelColor(i, pixels.Color(0, 0, 0));
} else if (encoder0Pos > 0) {
uint32_t pixelColor = (encoder0Pos > i)? Wheel((15-i)*16) : 0;
pixels.setPixelColor(i,pixelColor);
} else {
uint32_t pixelColor = (encoder0Pos < -i)? Wheel((i+1)*16) : 0;
pixels.setPixelColor(15-i, pixelColor);
}

}
pixels.show();
}
encoder0PinALast = n;
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return pixels.Color(255 - WheelPos * 3, 0, WheelPos * 3);
}
if(WheelPos < 170) {
WheelPos -= 85;
return pixels.Color(0, WheelPos * 3, 255 - WheelPos * 3);
}
WheelPos -= 170;
return pixels.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}

```

### Code for a Tessel automated rotary welder

Code for a Tessel automated rotary welder: tessel-welder.js
```var tessel = require('tessel');
var led = require('tessel-led');
var _ = require('underscore');

// Setup the Relay module on Port A
var relaylib = require('relay-mono');
var relay = relaylib.use(tessel.port['A']);

// Setup all switches & sensors to the GPIO
var gpio = tessel.port['GPIO'];
var swTurnTable = gpio.pin['G1'];
var btnWeld = gpio.pin['G2'];
var btnHome = gpio.pin['G3'];
var btnJog = gpio.pin['G6'];

// Add/Set 'Active' state for each GPIO object
swTurnTable.pressed = false;
btnWeld.pressed = false;
btnHome.pressed = false;
btnJog.pressed = false;

// Set pulldown switches/sensors (Tessel 'pull' functionality wasn't working when I did this project so I hardwired some physical pulldown resistors inline with my wiring)
//swTurnTable.pull('pulldown');
//btnWeld.pull('pulldown');
//btnHome.pull('pulldown');
//btnJog.pull('pulldown');

// Set all switches & sensors to input
swTurnTable.input();
btnWeld.input();
btnHome.input();
btnJog.input();

// underscore debounce function time
var timeDebounce = 100;

// Wait for the relay module to connect

// Check for btnWeld... then start welding
btnWeld.on('rise', _.debounce(function(time, type) {
console.log('btnWeld was pressed!', type, time);
btnWeld.pressed = true;
weld();
}
}, debounceTime));

// Check for btnHome... then home the turn table w/o welding
btnHome.on('rise', _.debounce(function(time, type) {
console.log('btnHome was pressed!', type, time);
btnHome.pressed = true;
weld();
}
}, timeDebounce));

// Check for btnJog... then jog the turn table w/o welding
btnJog.on('change', _.debounce(function(time, type) {
console.log('btnJog was pressed!', type, time);
btnJog.pressed = true;
jog();
}
if ( !btnJog.read() && btnJog.pressed ) {
console.log('btnJog was released!', type, time);
btnJog.pressed = false;
jog();
}
}, timeDebounce));

});

// When a relay 'latch' state is changed, it emits the 'latch' event
relay.on('latch', function(channel, value) {
if ( channel == 1 ) {
console.log('latch on turn table relay (channel ' + channel + ') switched to', value);
}
if ( channel == 2 ) {
console.log('latch on welder relay (channel ' + channel + ') switched to', value);
}
});

// Function to weld or home the turn table
function weld() {

swTurnTable.on('rise', _.debounce(function(time, type) {

if ( swTurnTable.read() && !swTurnTable.pressed ) {

swTurnTable.pressed = true;

console.log('on ' + type + ': ' + swTurnTable.read());

swTurnTable.once('low', _.debounce(function(time, type) {

led.green.hide();
led.blue.hide();

console.log('once ' + type + ': ' + swTurnTable.read());

if ( btnWeld.pressed || btnHome.pressed ) {
relay.turnOff(1, function(err) {
if (err) console.log('Err turning off turn table relay 1', err);
btnHome.pressed = false;
});
}
if ( btnWeld.pressed ) {
relay.turnOff(2, function(err) {
if (err) console.log('Err turning off welder relay 2', err);
btnWeld.pressed = false;
});
}

swTurnTable.removeAllListeners();
swTurnTable.pressed = false;

}, timeDebounce));

}

}, timeDebounce));

if ( btnWeld.pressed || btnHome.pressed ) {
relay.turnOn(1, function(err) {
if ( err ) {
console.log('Err turning on turn table relay 1', err);
}
else {
if ( btnWeld.pressed ) {
led.green.show();
}
if ( btnHome.pressed ) {
led.blue.show();
}
}
});
}

if ( btnWeld.pressed ) {
relay.turnOn(2, function(err) {
if ( err ) {
console.log('Err turning on welder relay 2', err);
}
});
}

}

// Function to jog the weld turn table while btnJog is pressed
function jog() {
if ( btnJog.pressed ) {
relay.turnOn(1, function(err) {
if (err) console.log("Err turning on relay 1", err);
led.blue.show();
});
}
else {
relay.turnOff(1, function(err) {
if (err) console.log("Err turning off relay 1", err);
led.blue.hide();
});
}
}

```

### Control the frequency in SDR# with a rotary encoder. From the tutorial http://eartoearoak.com/tutorials-and-examples/sdrsharp-physical-controls

Control the frequency in SDR# with a rotary encoder. From the tutorial http://eartoearoak.com/tutorials-and-examples/sdrsharp-physical-controls: SDRSharp Frequency Control.ino
```/*
Basic example demonstrating the how to control SDR# frequency
with SDRSharp Net Remote, an Arduino and rotary encoder.

Requires:
http://eartoearoak.com/software/sdrsharp-net-remote
http://www.pjrc.com/teensy/td_libs_Encoder.html

Connections:
Encoder    Arduino
A          D3
B          D2
C          GND

This program is free software: you can redistribute it and/or modify
the Free Software Foundation, or (at your option)
any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <Encoder.h>

// Initialise the encoder on digital pins 2 & 3
Encoder encoder(2, 3);
long oldPos  = -999;

// Initial frequency
long frequency = 100000000;

void setup() {
Serial.begin(115200);
}

void loop() {
// Get the encoder position
if (newPos != oldPos) {
oldPos = newPos;

// Send the command to change the frequency via the serial port
Serial.print("{\"Command\": \"Set\", \"Method\": \"Frequency\", \"Value\": ");
Serial.print(frequency + (newPos * 1000));
Serial.println("}");
}
}

```

#### external by Maxim Kachurovskiy  420  3  3  0

```// Pin pinA - CLK pin,
// Pin pinB - DT pin
// rotate(int i) - callback receiving -1 or 1

inputA = gpio.provisionDigitalInputPin(pinA, "PinA", PinPullResistance.PULL_UP);
inputB = gpio.provisionDigitalInputPin(pinB, "PinB", PinPullResistance.PULL_UP);
int lastA;

@Override
public synchronized void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent arg0) {
int a = inputA.getState().getValue();
int b = inputB.getState().getValue();
if (lastA != a) {
rotate(b == a ? -1 : 1);
lastA = a;
}
}
});

```

### A simple intervalometer for Arduino. Requires a rotary encoder, a SSD1306 OLED display and a bunch of analog electronics. With display idle sleep.

A simple intervalometer for Arduino. Requires a rotary encoder, a SSD1306 OLED display and a bunch of analog electronics. With display idle sleep.: intervalometer.cpp
```#include <Arduino.h>

#include <SPI.h>  // problems with PlatformIO
#include <U8g2lib.h>
#include <Wire.h>

#include <ClickEncoder.h>
#include <TimerOne.h>

#define SW1 4               // Rotary switch
#define CAMERA_FOCUS   14   // -> optoisolator circuit
#define CAMERA_SHUTTER 13   // -> optoisolator circuit

#define DISPLAY_AUTOSLEEP_MS 15000  // sleep display on idle (after ms)
#define DISPLAY_BLIT_FREQ 100       // redraw display every N ms

// Forward declarations
void takePhoto();
void blitDisplay();
void tick();
void blitActive();
void displaySleep();
void displayWake();

// logic variables
int timelapseInterval = 0;
bool timelapseRunning = false;
bool focus = false;
int shootCount = 0;
bool blit = true;
uint8_t activityToggle = 0;
bool isSleeping = false;

// Library initializations
ClickEncoder *encoder;
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(SCL, SDA, U8X8_PIN_NONE);

Scheduler scheduler;

void timerIsr() {
encoder->service();
}

void setup(void) {
pinMode(SW1, INPUT_PULLUP);
pinMode(CAMERA_FOCUS, OUTPUT);
pinMode(CAMERA_SHUTTER, OUTPUT);

// Encoder in pins 2, 3 (hw int). Switch in 4.
encoder = new ClickEncoder(3, 2, SW1, 4);

// Begin SSD1306 128x64 OLED in fast mode
u8x8.begin();
u8x8.setFont(u8x8_font_pxplusibmcgathin_r);
u8x8.setContrast(0);

// Timer1 is needed for encoder interrupts
Timer1.initialize(1000);
Timer1.attachInterrupt(timerIsr);

// Initialize the scheduler.
// takePhotoTask is enabled / disabled by pressing the button (in tick())
// blitDisplayTask is ran every 100ms if variable blit = true
scheduler.init();

}

void loop(void) {
tick();               // tick inputs
scheduler.execute();  // tick scheduler
}

void takePhoto() {
/* Takes a single photo */
if (focus) {
digitalWrite(CAMERA_FOCUS, HIGH);
delay(10);
digitalWrite(CAMERA_FOCUS, LOW);
}
digitalWrite(CAMERA_SHUTTER, HIGH);
delay(10);
digitalWrite(CAMERA_SHUTTER, LOW);
shootCount++;
blit = true;
}

void blitActive() {
if (timelapseRunning) {
switch(activityToggle) {
case 0:
u8x8.drawString(15, 7, "/");
break;
case 1:
u8x8.drawString(15, 7, "|");
break;
case 2:
u8x8.drawString(15, 7, "\\");
break;
case 3:
u8x8.drawString(15, 7, "-");
break;
}
activityToggle++;
if (activityToggle > 3) activityToggle = 0;
}
}

void blitDisplay() {
/* This function is called once every 100 ms by blitDisplayTask */
/* OLED: 16 cols, 8 rows*/
if (blit) {   // draw only if necessary
// interval
char buf[10];
sprintf(buf, "%02d:%02d", timelapseInterval/60 ,timelapseInterval%60);
u8x8.drawString(5, 3, buf);

//photos taken
sprintf(buf, "#%03d", shootCount);
u8x8.drawString(0, 7, buf);

//ON / OFF ?
u8x8.drawString(13, 7, timelapseRunning ? "ON " : "OFF");
}
blit = false;
}

void tick(void) {
// Check encoder's button
if ((encoder->getButton() == ClickEncoder::Clicked)) {
if (!isSleeping) {
timelapseRunning = !timelapseRunning;
if (timelapseRunning) {
}
else {
shootCount = 0;
}
blit = true;
}
else {
displayWake();
}
}

// Check rotary encoder's delta -> update interval in seconds
int8_t encoder_value = encoder->getValue();
if (encoder_value != 0) {
if (!isSleeping) {
if (!timelapseRunning) {
timelapseInterval += encoder_value;
if (timelapseInterval < 0)
timelapseInterval = 0;
}
blit = true;
}
else {
displayWake();
}
}

}

void displaySleep() {
u8x8.setPowerSave(true);
isSleeping = true;
}

void displayWake() {
u8x8.setPowerSave(false);
isSleeping = false;
}

```

### Reading one Rotary Encoder from a Raspberry Pi with Processing 3

Reading one Rotary Encoder from a Raspberry Pi with Processing 3: rotary_encoder.pde
```/*
Reading one Rotary Encoder from a Raspberry Pi

Translated from C to Processing by Heracles Papatheodorou

GND 	MIDDLE encoder leg
GPIO22	GPIO23	LEFT and RIGHT legs
3.3V			LEFT and RIGHT, splits to two 10k resistors for pull-up

Processing doesn't support pull-ups, hardware pull-up required:
https://learn.sparkfun.com/tutorials/pull-up-resistors/what-is-a-pull-up-resistor

Processing reference:
https://github.com/processing/processing/wiki/Raspberry-Pi
https://processing.org/reference/libraries/io/index.html

Reading rotary encoders on the RaspPi:
https://projects.drogon.net/raspberry-pi/wiringpi/functions/
*/

import processing.io.*; // import the hardware IO library

int pin_a = 22;
int pin_b = 23;
long value = 0;
int lastEncoded = 0;

void setup() {
noCursor();

GPIO.pinMode(pin_a, GPIO.INPUT);
GPIO.pinMode(pin_b, GPIO.INPUT);

//pullUpDnControl(pin_a, PUD_UP); //Processing doesn't support pull-ups so far
//pullUpDnControl(pin_b, PUD_UP);

GPIO.attachInterrupt(pin_a, this, "updateEncoder", GPIO.CHANGE);
GPIO.attachInterrupt(pin_b, this, "updateEncoder", GPIO.CHANGE);
}

void draw() {

}

void updateEncoder(int pin) {

int encoded = (MSB << 1) | LSB;
int sum = (lastEncoded << 2) | encoded;

if (sum == unbinary("1101") || sum == unbinary("0100") || sum == unbinary("0010") || sum == unbinary("1011")) {
value++;
}
if (sum == unbinary("1110") || sum == unbinary("0111") || sum == unbinary("0001") || sum == unbinary("1000")) {
value--;
}

lastEncoded = encoded;

println(value); //DEBUG
}

```
• Public Snippets
• Channels Snippets