Please help me finish a project (Rotary Encoder)

Hello all

I am almost at the end of my first project, but I must admit, I am in way over my head. I am hoping that someone here might be able to help.

I am working on a project that has 8 push buttons, each creating a different keyboard.press. I have that part working fine, but the next part is giving me a headache trying to work out.

I would like to also add a rotary encoder to mimic a mouse wheel (scroll up/down), but I have absolutely no idea where to start. Could somebody be kind enough to help?

Below is a really bad mockup of how I have the hardware layed out (I really am sorry for how bad it is), and also I have added the sketch that I am using. As you will see, I have modified an example sketch found on another website. I know there are bits of code in there that arent needed and looks messy. If you could help tidy it up and remove un-needed parts at the same time, it would be greatly appreciated.

Hardware Layout

Sketch

#include "Keyboard.h"

const int buttonPin[] = {2, 3, 4, 5, 6, 7, 8, 9,};
int pinCount = 8;

int potPin = 2;
int prevPotState = -1;
int potState = -1;
int potTolerance = 1;
long potDebounceDelay = 20;

int buttonState[] = {1, 1, 1, 1, 1, 1, 1, 1};
int prevButtonState[] = {HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH, HIGH};
long startedPressing[] = {0, 0, 0, 0, 0, 0, 0, 0};
boolean longPressing[] = {false, false, false, false, false, false, false, false};

long lastDebounceTime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; // 1 more for the pot

long debounceDelay = 0;

boolean testHardware = false;

int keyComb(char key1 = 0, char key2 = 0, char key3 = 0, char key4 = 0) {
  if (key1 != 0) { Keyboard.press(key1); }
  if (key2 != 0) { Keyboard.press(key2); }
  if (key3 != 0) { Keyboard.press(key3); }
  if (key4 != 0) { Keyboard.press(key4); }
  delay(100);
  Keyboard.releaseAll();
}

int sendLine(char const * line) {
  Keyboard.print(line);
  delay(750);
  keyComb(KEY_RETURN);
}

// Output actions. Probably the only part that you need to change
int outputAction(int currentButton, int typeOfPress = 0) {
  // typeOfPress 1: on push; 2: on release; 3: on long press; 4: on lingering press.
  // actions on release, on long press and lingering press include the action press. Action lingering press cancels action release and long press.

  if (testHardware) {
    Keyboard.print(currentButton + 1);
    if (typeOfPress == 1) {
      Keyboard.print(" pressed ");
    }
    if (typeOfPress == 2) {
      Keyboard.print(" released ");
    }
    if (typeOfPress == 3) {
      Keyboard.print(" long ");
    }
    if (typeOfPress == 4) {
      Keyboard.print(" lingering ");
    }
    Keyboard.print(millis());
    Keyboard.print(" ");
    Keyboard.print(lastDebounceTime[currentButton]);
    keyComb(KEY_RETURN);
  } else {

    if (currentButton + 1 == 1) {
      if (typeOfPress == 1) {
        Keyboard.press('n'); // Keystroke
        Keyboard.releaseAll();
      }
      
    }
  
    if (currentButton + 1 == 2) {
      if (typeOfPress == 1) {
        Keyboard.press('a'); // Keystroke
        Keyboard.releaseAll();
      }

    }
  
    if (currentButton + 1 == 3) {
      if (typeOfPress == 1) {
        Keyboard.press('l'); // Keystroke
        Keyboard.releaseAll();
      }
      
    }
  
    if (currentButton + 1 == 4) {
      if (typeOfPress == 1) {
        Keyboard.press('u'); // Keystroke
        Keyboard.releaseAll();
      }

    }
  
    if (currentButton + 1 == 5) {
      if (typeOfPress == 1) {
        Keyboard.press('w'); // Keystroke
        Keyboard.releaseAll();
      }

    }
  
    if (currentButton + 1 == 6) {
      if (typeOfPress == 1) {
        Keyboard.press('d'); // Keystroke
        Keyboard.releaseAll();
      }

    }
  
    if (currentButton + 1 == 7) {
      if (typeOfPress == 1) {
        Keyboard.press('c'); // Keystroke
        Keyboard.releaseAll();
      }

    }
  
    if (currentButton + 1 == 8) {
      if (typeOfPress == 1) {
        Keyboard.press('r'); // Keystroke
        Keyboard.releaseAll();

      }
    }
  }
}

void setup() {

  for (int thisPin = pinCount - 1; thisPin >= 0; thisPin--) {
    pinMode(buttonPin[thisPin], INPUT_PULLUP);
    digitalWrite(buttonPin[thisPin], HIGH); // In some versions use INPUT_PULLUP to use the built-in pull up resistor
  }
  Keyboard.begin();
}

void loop() {

  
  for (int thisPin = pinCount - 1; thisPin >= 0; thisPin--) {
    buttonState[thisPin] = digitalRead(buttonPin[thisPin]);
    // HIGH = state 1 <- button not pressed
    // LOW  = state 0 <- button pressed

    // On longer press
    if ((startedPressing[thisPin] == 0) || ((millis() - startedPressing[thisPin]) <= 1200)) {

      if (((buttonState[thisPin] != prevButtonState[thisPin])) && ((millis() - lastDebounceTime[thisPin]) > debounceDelay)) {
      if ((buttonState[thisPin] != prevButtonState[thisPin])) {

        if (buttonState[thisPin] == 0) {
          // Standard press action
          startedPressing[thisPin] = millis();
          outputAction(thisPin, 1);
        } else {

          if (!longPressing[thisPin]) {
            if ((millis() - startedPressing[thisPin]) < 500) {
              // On release (to avoid standard action if is incompatible with Long or Longer action)
              outputAction(thisPin, 2);
            } else {
              // Long action (+standard action already sent)
              outputAction(thisPin, 3);
            }
          }

          startedPressing[thisPin] = 0;
          longPressing[thisPin] = false;
        }
        lastDebounceTime[thisPin] = millis();
      }
    } else {
      outputAction(thisPin, 4);
      
      longPressing[thisPin] = true;
      startedPressing[thisPin] = 0;
    }

    prevButtonState[thisPin] = buttonState[thisPin];
  }
  }
}

If someone could please help with adding the encoder (what pins to connect to, and also code), I would very much appreciate it.

Thanks for reading :slight_smile:

Tim

Probably the most useful pins for an encoder are pins 2 and 3, so think about moving the pushbuttons to other pins.

Please, Tim. Explain how you think a mouse wheel works and then explain why you gave absolutely specifications on your encoder. And then think someone can help.

Paul

TheMemberFormerlyKnownAsAWOL:
Probably the most useful pins for an encoder are pins 2 and 3, so think about moving the pushbuttons to other pins.

Would it be possible to use pins 14, 15 instead of moving the buttons?

Paul_KD7HB:
Please, Tim. Explain how you think a mouse wheel works and then explain why you gave absolutely specifications on your encoder. And then think someone can help.

Paul

I'm not quite sure what you are getting at. All I am asking for is a little help with getting an encoder to work. I have been looking online for what seems like an eternity and my head is about to explode. As I said in my original post, I am in way over my head. I am trying my best to learn for myself, but I cant seem to get my head around it. I would have thought it was obvious by the messy sketch. :slight_smile:

The best help I can provide is to ask you to Purchase the Arduino cookbook and read it, this will give you some basics. Also use the online tutorials and videos available, there are many good ones on this web site. At this point you will be able to define the problem and may have already solved it. It helps if you define the problem with specifications including a flow chart, schematic, power requirements, and EMI requirements if any. This will be a big help in your future courses. Your mouse wheel uses quadrature detection. You can duplicate it and ut only uses two pins 6, 7, plus VCC and ground: How Rotary Encoder Works and How To Use It with Arduino - HowToMechatronics
It has a push button and that would require another input pin.

scoobielover2018:
All I am asking for is a little help with getting an encoder to work.

Have a look: encoder library

Thank you all for your input. I seem to be a step further with getting an encoderto work. Below is the very basic code I am working with. I am half way there. The problem is that the encoder will only go one way. Clockwise moves up, Counter Clockwise also moves up. Any ideas?

#include <Encoder.h>
#include <Keyboard.h>
#include <Mouse.h>

Encoder encTune(0,1);

void setup() {
  Keyboard.begin();
  Mouse.begin();

  int T = 0;

}

void loop() {
  int T = encTune.read();
if (T > 2) // Up
  { delay(15); Mouse.move(0, 0, 1); encTune.write(0); }
if (T < -2) // Down
  { delay(15); Mouse.move(0, 0, -1); encTune.write(0); }

}

Once I have the encoder working how it should, I think I could then add the botton functions to this. Your help really is appreciated :slight_smile:

scoobielover2018:
Encoder encTune(0,1);

Try using two other uncommitted pins. Board looks like a NANO, which I'm not famililar with, but, 0 and 1 might be being used for serial comm.

dougp:
Try using two other uncommitted pins. Board looks like a NANO, which I'm not famililar with, but, 0 and 1 might be being used for serial comm.

The board is Pro Micro (Leonardo ATMega32u4)

I think I might have this worked out now. It appears that the encoder that I am using might not be the best option, so I have used another and it seems to be working as it should. Next step is to add the button functions to the encoder sketch and the job should be a good'un :slight_smile: