Rotary encoder and long wires
Posted: Mon Sep 19, 2016 12:54 pm
Hi guys, I am working on a little project. It uses V-USB. It is a USB pedal that controls the audio player on my computer..
I have run into a problem and maybe someone here can help me
I have a rotary encoder set to increase and decrease the track number, and immediately pause the player by sending a key stroke like a keyboard (Space)
If I connect the rotary encoder next to the arduino, short wires, it works well. But i wan't to place it about 1.5 meters away from the board. It doesn't work very well. It takes longer to change the tracks, when it changes them. Sometimes only pauses without moving to the next/previous track. Sometimes it moves without pausing. So, clearly there is some noise or some other problem caused by the longer cable.
Here is the code I'm using: I have modified it to suit my needs. I'm not a programmer as you know I wonder if there is a simple hardware solution to overcome this problem.. Capacitors didn't work and actually made the problem worse..
Thanks in advance for your help..
João
I have run into a problem and maybe someone here can help me
I have a rotary encoder set to increase and decrease the track number, and immediately pause the player by sending a key stroke like a keyboard (Space)
If I connect the rotary encoder next to the arduino, short wires, it works well. But i wan't to place it about 1.5 meters away from the board. It doesn't work very well. It takes longer to change the tracks, when it changes them. Sometimes only pauses without moving to the next/previous track. Sometimes it moves without pausing. So, clearly there is some noise or some other problem caused by the longer cable.
Here is the code I'm using: I have modified it to suit my needs. I'm not a programmer as you know I wonder if there is a simple hardware solution to overcome this problem.. Capacitors didn't work and actually made the problem worse..
Thanks in advance for your help..
João
Code: Select all
#include <ProTrinketHidCombo.h>
#define PIN_ENCODER_A 3
#define PIN_ENCODER_B 5
#define TRINKET_PINx PIND
//#define TRINKET_PIN_BUTTONS PINB //This also doesn't work. I can only use "D" :-(
#define PIN_ENCODER_SWITCH 4
#define PIN_PREVIOUS 1
#define PIN_NEXT 0
#define PIN_PLAY 6
//#define PIN_STOP 10
int LedPin = 13;
static uint8_t enc_prev_pos = 0;
static uint8_t enc_flags = 0;
static char sw_was_pressed = 0;
static char PREVIOUS_was_pressed = 0;
static char NEXT_was_pressed = 0;
static char PLAY_was_pressed = 0;
//static char STOP_was_pressed = 0;
void setup()
{
// set pins as input with internal pull-up resistors enabled
pinMode(PIN_ENCODER_A, INPUT_PULLUP);
pinMode(PIN_ENCODER_B, INPUT_PULLUP);
pinMode(PIN_ENCODER_SWITCH, INPUT_PULLUP);
pinMode(PIN_PREVIOUS, INPUT_PULLUP);
pinMode(PIN_NEXT, INPUT_PULLUP);
pinMode(PIN_PLAY, INPUT_PULLUP);
pinMode(LedPin, OUTPUT);
TrinketHidCombo.begin(); // start the USB device engine and enumerate
// get an initial reading on the encoder pins
if (digitalRead(PIN_ENCODER_A) == LOW) {
enc_prev_pos |= (1 << 0);
}
if (digitalRead(PIN_ENCODER_B) == LOW) {
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 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(TRINKET_PINx, PIN_ENCODER_A)) {
enc_cur_pos |= (1 << 0);
}
if (bit_is_clear(TRINKET_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) {
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_NEXT_TRACK); // Clockwise, send multimedia volume up
digitalWrite(LedPin, HIGH);
delay(20); // debounce delay
digitalWrite(LedPin, LOW);
delay(110); // debounce delay
TrinketHidCombo.typeChar(KEYCODE_3);
}
else if (enc_action < 0) {
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_PREV_TRACK); // Counterclockwise, is multimedia volume down
digitalWrite(LedPin, HIGH);
delay(20); // debounce delay
digitalWrite(LedPin, LOW);
delay(110); // debounce delay
TrinketHidCombo.typeChar(KEYCODE_3);
}
// remember that the switch is active low
if (bit_is_clear(TRINKET_PINx, PIN_ENCODER_SWITCH))
{
if (sw_was_pressed == 0) // only on initial press, so the keystroke is not repeated while the button is held down
{
TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE); // Encoder pushed down, toggle mute or not
delay(5); // debounce delay,
// digitalWrite(LedPin, HIGH);
}
sw_was_pressed = 1;
LedBlink();
}
else
{
if (sw_was_pressed != 0) {
delay(5); // debounce delay
// digitalWrite(LedPin, LOW);
}
sw_was_pressed = 0;
}
// remember that the switch PREVIOUS is active low
if (bit_is_clear(TRINKET_PINx, PIN_PREVIOUS))
{
if (PREVIOUS_was_pressed == 0) // only on initial press, so the keystroke is not repeated while the button is held down
{
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_PREV_TRACK); // Encoder pushed down, toggle mute or not
delay(80); // debounce delay
TrinketHidCombo.typeChar(KEYCODE_3);
}
PREVIOUS_was_pressed = 1;
LedBlink();
}
else
{
if (PREVIOUS_was_pressed != 0) {
delay(15); // debounce delay
digitalWrite(LedPin, LOW);
}
PREVIOUS_was_pressed = 0;
}
// remember that the switch NEXT is active low
if (bit_is_clear(TRINKET_PINx, PIN_NEXT))
{
if (NEXT_was_pressed == 0) // only on initial press, so the keystroke is not repeated while the button is held down
{
TrinketHidCombo.pressMultimediaKey(MMKEY_SCAN_NEXT_TRACK); // Encoder pushed down, toggle mute or not
delay(80); // debounce delay
TrinketHidCombo.typeChar(KEYCODE_3);
}
NEXT_was_pressed = 1;
LedBlink();
}
else
{
if (NEXT_was_pressed != 0) {
delay(15); // debounce delay
digitalWrite(LedPin, LOW);
}
NEXT_was_pressed = 0;
}
// remember that the switch PLAY is active low
if (bit_is_clear(TRINKET_PINx, PIN_PLAY))
{
if (PLAY_was_pressed == 0) // only on initial press, so the keystroke is not repeated while the button is held down
{
TrinketHidCombo.pressMultimediaKey(MMKEY_PLAYPAUSE); // Encoder pushed down, toggle mute or not
delay(15); // debounce delay
}
PLAY_was_pressed = 1;
LedBlink();
}
else
{
if (PLAY_was_pressed != 0) {
// delay(15); // debounce delay
// digitalWrite(LedPin, LOW);
}
PLAY_was_pressed = 0;
}
TrinketHidCombo.poll(); // check if USB needs anything done, do every 10 ms or so
}
void LedBlink() {
digitalWrite(LedPin, HIGH);
delay(15); // debounce delay
digitalWrite(LedPin, LOW);
delay(100); // debounce delay
}