Cirkit Designer LogoCirkit DesignerYour all-in-one circuit design IDE Launch Cirkit Designer App

Arduino Nano Controlled Joystick and Rotary Encoder Interface with OLED Display and Multi-Color LED Feedback

View and Edit Project In Cirkit DesignerImage of Arduino Nano Controlled Joystick and Rotary Encoder Interface with OLED Display and Multi-Color LED Feedback

Circuit Documentation

Summary

This circuit is designed to interface an Arduino Nano with various peripherals including a joystick module, a rotary encoder, an OLED display, and multiple LEDs with corresponding resistors. The circuit allows for user interaction through the joystick and rotary encoder, with visual feedback provided by the LEDs and the OLED display. The Arduino Nano serves as the central processing unit, running embedded code to manage input devices and control outputs based on user actions.

Component List

Arduino Nano

I/O Expansion Shield For Arduino Nano

Joystick Module

0.96" OLED

LEDs (Red, Green, Yellow, Blue)

Resistors

Rotary Encoder

Wiring Details

Arduino Nano

I/O Expansion Shield For Arduino Nano

Joystick Module

0.96" OLED

LEDs (Red, Green, Yellow, Blue)

Resistors

Rotary Encoder

Documented Code

#include <U8g2lib.h>

// Rotary Encoder Pins
#define ENCODER_CLK 6
#define ENCODER_DT 7
#define ENCODER_SW 8

// Joystick Pins
#define JOYSTICK_VRX A0
#define JOYSTICK_VRY A1
#define JOYSTICK_SW 4

// LED Pins
#define RED_LED_PIN 5
#define YELLOW_LED_PIN 11
#define BLUE_LED_PIN 12
#define GREEN_LED_PIN 10

// OLED display settings
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

// Variables for rotary encoder
int lastClk = HIGH;
int lastDt = HIGH;
int currentBrightness = 128; // Initial brightness (0-255)
bool isBlinking = false;
bool isLEDOn = true; // Variable to track LED on/off state
unsigned long lastBlinkTime = 0;
const unsigned long blinkInterval = 500; // 500ms interval for blinking

// Array of LED pins
const int ledPins[] = {RED_LED_PIN, YELLOW_LED_PIN, BLUE_LED_PIN, GREEN_LED_PIN};
const char* colorNames[] = {"Red", "Yellow", "Blue", "Green"};

// Dead zone threshold for joystick
const int deadZone = 100;

// Constants for debounce delay and dead zone
const int debounceDelay = 50;
const int joystickDelay = 200;
const int blinkToggleDelay = 500;
const int joystickCenter = 512;

// Variable to keep track of the current LED color
int currentColor = 0; // Initial color (0: Red, 1: Yellow, 2: Blue, 3: Green)

void setup() {
  // Initialize serial communication
  Serial.begin(9600);

  // Initialize OLED display
  u8g2.begin();

  // Initialize rotary encoder pins
  pinMode(ENCODER_CLK, INPUT);
  pinMode(ENCODER_DT, INPUT);
  pinMode(ENCODER_SW, INPUT_PULLUP);

  // Initialize joystick pins
  pinMode(JOYSTICK_SW, INPUT_PULLUP);

  // Initialize LED pins
  for (int i = 0; i < 4; i++) {
    pinMode(ledPins[i], OUTPUT);
    analogWrite(ledPins[i], 0);
  }

  // Display initial brightness
  updateDisplay();
}

void loop() {
  // Read the rotary encoder
  int clkState = digitalRead(ENCODER_CLK);
  int dtState = digitalRead(ENCODER_DT);

  if (clkState == LOW && lastClk == HIGH) {
    if (dtState == HIGH) {
      currentBrightness = min(currentBrightness + 10, 255); // Increase brightness
    } else {
      currentBrightness = max(currentBrightness - 10, 0); // Decrease brightness
    }
    Serial.print("Brightness: ");
    Serial.println(currentBrightness);
    updateDisplay();
  }
  lastClk = clkState;

  // Check if the rotary encoder button is pressed
  if (isButtonPressed(ENCODER_SW)) {
    isLEDOn = !isLEDOn;
    Serial.print("LED: ");
    Serial.println(isLEDOn ? "On" : "Off");
    updateDisplay();
    delay(blinkToggleDelay); // Prevent multiple toggles
  }

  // Read the joystick
  int vrxValue = analogRead(JOYSTICK_VRX);
  int vryValue = analogRead(JOYSTICK_VRY);

  // Map joystick X-axis to change color with dead zone
  if (vrxValue < (joystickCenter - deadZone)) {
    currentColor = (currentColor - 1 + 4) % 4;
    Serial.print("Color: ");
    Serial.println(colorNames[currentColor]);
    updateDisplay();
    delay(joystickDelay); // Delay to prevent rapid changes
  } else if (vrxValue > (joystickCenter + deadZone)) {
    currentColor = (currentColor + 1) % 4;
    Serial.print("Color: ");
    Serial.println(colorNames[currentColor]);
    updateDisplay();
    delay(joystickDelay); // Delay to prevent rapid changes
  }

  // Map joystick Y-axis to toggle blinking mode with dead zone
  if (vryValue < (joystickCenter - deadZone) || vryValue > (joystickCenter + deadZone)) {
    isBlinking = !isBlinking;
    Serial.print("Mode: ");
    Serial.println(isBlinking ? "Blinking" : "Solid");
    updateDisplay();
    delay(blinkToggleDelay); // Delay to prevent rapid toggles
  }

  // Check if the joystick button is pressed
  if (isButtonPressed(JOYSTICK_SW)) {
    isBlinking = !isBlinking;
    Serial.println("Joystick button pressed. Toggling blinking mode.");
    Serial.print("isBlinking: ");
    Serial.println(isBlinking);
    updateDisplay();
    delay(blinkToggleDelay); // Prevent multiple toggles
  }

  // Update LED state
  updateLEDs();
}

void updateDisplay() {
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_5x8_tr); // Use a smaller font to fit more text

  // Column 1
  u8g2.setCursor(0, 8);
  u8g2.print("Brightness:");
  u8g2.setCursor(0, 18);
  u8g2.print(currentBrightness);

  u8g2.setCursor(0, 28);
  u8g2.print("Mode:");
  u8g2.setCursor(0, 38);
  u8g2.print(isBlinking ? "Blinking" : "Solid");

  // Column 2
  u8g2.setCursor(64, 8);
  u8g2.print("Color:");
  u8g2.setCursor(64, 18);
  u8g2.print(colorNames[currentColor]);

  u8g2.setCursor(64, 28);
  u8g2.print("LED:");
  u8g2.setCursor(64, 38);
  u8g2.print(isLEDOn ? "On" : "Off");

  u8g2.sendBuffer();
}

void updateLEDs() {
  unsigned long currentTime = millis();
  bool ledState = true;

  if (isBlinking) {
    if (currentTime - lastBlinkTime >= blinkInterval) {
      lastBlinkTime = currentTime;
      ledState = !digitalRead(ledPins[currentColor]);
    } else {
      ledState = digitalRead(led