Is it possible to mimic a rotary encoder with an arduino?
I have device I wish to hack, I want to write a program that will have the same effect as turning the dial 1 click at a time.
Looking originally for tutorial on this subject and found nothing. I found tons of "hack a button" tutorials which seem close, but nowhere anywhere close to a rotary encoder
Rather than give you some complicated code I'd suggest you start very simply. You need to generate two pulse trains that are in "pase quadrature" - which looks like this
Use the "blink without delay" example
to generate the A signal to an "A" LED
now adapt it to generate the SAME signal to an "B" LED eg
// constants won't change. Used here to set a pin number:
const int chA_Pin = 3; // put a led & reisitor on D3
const int chB_Pin = 4; // put a led & reisitor on D4
you now have two leds flashing together. (AB) 00 - 11 - 00 -etc
now add a counted loop to make the lights do this: (AB) 00 -01-11-10 - 00 - 01
Thats great, that will give me something simple to work on first, exactly what I am looking for. Lets say I achieve this, how will I wire the arduino to the 4 pins where the encoder used to go?
Yeah I understand what you mean. I have now figured out what the wires are (I think) after testing the encoder. I had planned to put vcc - vcc, gnd - gnd, output A - output A etc. I thought that the wiring would be different from encoder testing setup to trying to mimic the encoder.
I still have the arduino connected and wired to test the encoder, not sure if this can be used or just disassemble and proceed with the advice on post #4
Ok so I have followed your guidelines and I have managed to get an A led and B led both to flash on and off at the same time. I have hit a brick wall and just cannot figure out how to add the counted loop.
Anyway this was the code I am at right now:
/*
Blink without Delay
Turns on and off a light emitting diode (LED) connected to a digital pin,
without using the delay() function. This means that other code can run at the
same time without being interrupted by the LED code.
The circuit:
- Use the onboard LED.
- Note: Most Arduinos have an on-board LED you can control. On the UNO, MEGA
and ZERO it is attached to digital pin 13, on MKR1000 on pin 6. LED_BUILTIN
is set to the correct LED pin independent of which board is used.
If you want to know what pin the on-board LED is connected to on your
Arduino model, check the Technical Specs of your board at:
https://www.arduino.cc/en/Main/Products
created 2005
by David A. Mellis
modified 8 Feb 2010
by Paul Stoffregen
modified 11 Nov 2013
by Scott Fitzgerald
modified 9 Jan 2017
by Arturo Guadalupi
This example code is in the public domain.
https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
*/
// constants won't change. Used here to set a pin number:
const int ledPinA = 13; // the number of the LED pin
const int ledPinB = 12;
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
// constants won't change:
const long interval = 1000; // interval at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPinA, OUTPUT);
pinMode(ledPinB, OUTPUT);
}
void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPinA, ledState);
digitalWrite(ledPinB, ledState);
}
}
Yeah thats an interesting link. Dont know if I'll ever get my head around it but the two boolean arrays seem like the way to go. Tried uploading the code (changing to pin 12 and 13) and it makes the leds flash although not the way I expected. This code has 1 led constant and the other flashes on and off quickly.
/*
This simple sketch is an example showing how the switch - case structure can be used to implement a state machine
LEDs are connected to pins 2,3 on the nano, with 470 ohm resistors to ground
J. Errington 12 Jan 2023
*/
// assign pin numbers for the leds
const byte led_R = 4; //channel A
const byte led_Y = 3; //channel B
const byte dirSwitch = 9; //direction switch on pin 9
int qState = 0;
int dir;
const int phaseTime = 500; //duration of each phase in miliseconds
unsigned long timeStart, timeElapsed; //will hold the time the state started and the time elapsed in the current state
void setup() {
Serial.begin(57600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB
}
pinMode(led_R, OUTPUT);
pinMode(led_Y, OUTPUT);
pinMode(dirSwitch, INPUT_PULLUP);
qState = 0; //start with the amber on
timeStart = millis();
}
void loop() {
switch (qState) {
case 0: //00
{
digitalWrite(led_R, LOW);
digitalWrite(led_Y, LOW);
}
break;
case 1: //01
{
digitalWrite(led_R, LOW);
digitalWrite(led_Y, HIGH);
}
break;
case 2: //11
{
digitalWrite(led_R, HIGH);
digitalWrite(led_Y, HIGH);
}
break;
case 3: //10
{
digitalWrite(led_R, HIGH);
digitalWrite(led_Y, LOW);
}
break;
}
//is it time for the next state?
timeElapsed = millis() - timeStart;
if (timeElapsed > phaseTime) {
//restart the timer and change the state
timeStart = millis();
if(digitalRead(dirSwitch)) {dir = 1;} else {dir = -1;}
qState += dir;
if ((qState >= 4) && (dir == 1)) qState = 0; //restart from state zero if counting up;
if ((qState < 0 ) && (dir == -1)) qState = 3; //restart from state 3 if counting down
Serial.println(qState);
}
} //loop
apologies... I had forgotten to mention on this thread that the whole idea for this would be to control a hot plate via its rotary encoder. Ignore that post... oops
I just tried this code and it works perfectly, very cool Tested this with LED's. many thanks for this code.
I'm going to need to study this code somewhat. I understand some of this but the last has got me at the moment. I think this code is very handy, is it possible to stop this from looping over. I'd be looking to have this do 1 step, then stop for 10 seconds, 1 step then stop for 15 seconds, 1 step then 22 seconds etc.