#include <IRremote.h> // This library is compatible with both ESP8266 and ESP32
#include <IRsend.h> // Required for sending IR signals
// --- Pin Definitions for ESP32 ---
// Assign a GPIO pin for the IR LED. GPIO27 is a common choice on ESP32 development boards.
const int IR_LED_PIN = 27; // Connect your IR LED (with a current-limiting resistor) to GPIO27
// Define analog pins for joysticks on ESP32.
// ESP32 has multiple Analog-to-Digital Converter (ADC) pins.
// We'll use common ADC-capable GPIOs for two joysticks.
// Check ESP32 pinout diagrams for specific ADC channels if needed.
//
// Joystick 1 (e.g., for vehicle movement control)
const int JOYSTICK1_X_PIN = 34; // ADC1_CH6 on most ESP32s (GPIO34)
const int JOYSTICK1_Y_PIN = 35; // ADC1_CH7 on most ESP32s (GPIO35)
// Joystick 2 (e.g., for vehicle function control like crane, forklift, dump)
const int JOYSTICK2_X_PIN = 36; // ADC1_CH0 on most ESP32s (GPIO36 - often labeled VP)
const int JOYSTICK2_Y_PIN = 39; // ADC1_CH3 on most ESP32s (GPIO39 - often labeled VN)
// Initialize the IRsend object with the IR LED pin.
// This object handles the transmission of IR signals.
IRsend irsend(IR_LED_PIN);
// --- Joystick Threshold Definitions for ESP32's 12-bit ADC ---
// ESP32's ADC provides readings from 0 to 4095 by default (12-bit resolution).
// The original code used 10-bit thresholds (0-1023), so these values are scaled accordingly.
// (Original value * 4 = New 12-bit value)
const int JOYSTICK_CENTER_MIN = 1800; // Roughly 450 * 4 (lower bound for center position)
const int JOYSTICK_CENTER_MAX = 2200; // Roughly 550 * 4 (upper bound for center position)
const int JOYSTICK_THRESHOLD_HIGH = 2800; // Roughly 700 * 4 (value above which a "high" action is triggered)
const int JOYSTICK_THRESHOLD_LOW = 1200; // Roughly 300 * 4 (value below which a "low" action is triggered)
// --- IR Codes for Vehicle Actions ---
// IMPORTANT: Replace these example codes with the actual IR codes from your
// vehicle's remote control! Use an IR receiver and the IRremoteESP8266 library's
// 'IRrecvDumpV2' example to capture and decode your remote's signals.
// These are example NEC protocol codes. Your remote might use a different protocol.
const unsigned long IR_CODE_FORWARD = 0x00FF6897; // Example NEC code for forward movement
const unsigned long IR_CODE_BACKWARD = 0x00FF9867; // Example NEC code for backward movement
const unsigned long IR_CODE_TURN_LEFT = 0x00FFB04F; // Example NEC code for turning left
const unsigned long IR_CODE_TURN_RIGHT = 0x00FF48B7; // Example NEC code for turning right
const unsigned long IR_CODE_CRANE_UP = 0x00FF30CF; // Example NEC code for crane up
const unsigned long IR_CODE_CRANE_DOWN = 0x00FF708F; // Example NEC code for crane down
const unsigned long IR_CODE_FORKLIFT_UP = 0x00FF10EF; // Example NEC code for forklift up
const unsigned long IR_CODE_FORKLIFT_DOWN = 0x00FF50AF; // Example NEC code for forklift down
const unsigned long IR_CODE_DUMP_TRUCK_LIFT = 0x00FF00FF; // Example NEC code for dump truck lift
const unsigned long IR_CODE_DUMP_TRUCK_LOWER = 0x00FF20DF; // Example NEC code for dump truck lower
const unsigned long IR_CODE_STOP_MOVEMENT = 0x00FF02FD; // Example NEC code for stopping current action
// Define the IR protocol type and the number of bits for the codes.
// Ensure these match your remote's protocol (e.g., NEC, RAW, RC5, SONY, etc.).
const decode_type_t IR_PROTOCOL_TYPE = NEC; // Change this if your remote uses a different protocol
const int IR_BITS = 32; // Number of bits for the IR protocol (e.g., 32 for NEC, 12 for SONY)
void setup() {
// Initialize serial communication for debugging output.
// This will show joystick readings and triggered actions in Wokwi's serial monitor.
Serial.begin(115200);
Serial.println("ESP32 IR Joystick Controller Started.");
// Initialize the IR sender. This prepares the specified pin for IR output.
irsend.begin();
// Analog pins are set as input by default, so no explicit pinMode() calls are needed for them.
// ESP32's ADC resolution is 12-bit (0-4095) by default. If you prefer a 0-1023 range,
// you could use analogReadResolution(10); here, but then the thresholds above would need to be adjusted back.
}
void loop() {
// Read raw joystick values from the analog pins.
// The analogRead() function on ESP32 will return values from 0 to 4095.
int current_joystick1X = analogRead(JOYSTICK1_X_PIN);
int current_joystick1Y = analogRead(JOYSTICK1_Y_PIN);
int current_joystick2X = analogRead(JOYSTICK2_X_PIN);
int current_joystick2Y = analogRead(JOYSTICK2_Y_PIN);
// Print current joystick values to the serial monitor for debugging.
Serial.print("J1X: "); Serial.print(current_joystick1X);
Serial.print("\tJ1Y: "); Serial.print(current_joystick1Y);
Serial.print("\tJ2X: "); Serial.print(current_joystick2X);
Serial.print("\tJ2Y: "); Serial.println(current_joystick2Y);
Serial.println("---"); // Separator for readability
// --- Joystick 1 Logic: Movement Control (e.g., Y-axis for Fwd/Bwd, X-axis for Left/Right) ---
// Control Forward/Backward Movement based on Joystick 1 Y-axis.
if (current_joystick1Y > JOYSTICK_THRESHOLD_HIGH) {
Serial.println("Action: Moving Forward");
irsend.send(IR_PROTOCOL_TYPE, IR_CODE_FORWARD, IR_BITS);
} else if (current_joystick1Y < JOYSTICK_THRESHOLD_LOW) {
Serial.println("Action: Moving Backward");
irsend.send(IR_PROTOCOL_TYPE, IR_CODE_BACKWARD, IR_BITS);
} else if (current_joystick1Y >= JOYSTICK_CENTER_MIN && current_joystick1Y <= JOYSTICK_CENTER_MAX) {
// If the Y-axis is in the center range, it means no forward/backward movement is requested.
// Optionally, send a specific "stop movement" code if your vehicle responds to it.
// Serial.println("Action: J1 Y-axis Centered - No Fwd/Bwd");
// irsend.send(IR_PROTOCOL_TYPE, IR_CODE_STOP_MOVEMENT, IR_BITS); // Uncomment if a stop code is needed
}
// Control Left/Right Turning based on Joystick 1 X-axis.
if (current_joystick1X < JOYSTICK_THRESHOLD_LOW) {
Serial.println("Action: Turning Left");
irsend.send(IR_PROTOCOL_TYPE, IR_CODE_TURN_LEFT, IR_BITS);
} else if (current_joystick1X > JOYSTICK_THRESHOLD_HIGH) {
Serial.println("Action: Turning Right");
irsend.send(IR_PROTOCOL_TYPE, IR_CODE_TURN_RIGHT, IR_BITS);
} else if (current_joystick1X >= JOYSTICK_CENTER_MIN && current_joystick1X <= JOYSTICK_CENTER_MAX) {
// If the X-axis is in the center range, no turning is requested.
// Serial.println("Action: J1 X-axis Centered - No Turn");
// irsend.send(IR_PROTOCOL_TYPE, IR_CODE_STOP_TURN, IR_BITS); // Uncomment if a stop turn code exists
}
// --- Joystick 2 Logic: Function Control (e.g., Y-axis for Up/Down, X-axis for other functions) ---
// Control Crane/Forklift/Dump Truck Up/Down Functions based on Joystick 2 Y-axis.
if (current_joystick2Y > JOYSTICK_THRESHOLD_HIGH) {
Serial.println("Action: Function Up (e.g., Crane/Forklift/Dump Lift)");
irsend.send(IR_PROTOCOL_TYPE, IR_CODE_CRANE_UP, IR_BITS); // Example: assuming crane up
} else if (current_joystick2Y < JOYSTICK_THRESHOLD_LOW) {
Serial.println("Action: Function Down (e.g., Crane/Forklift/Dump Lower)");
irsend.send(IR_PROTOCOL_TYPE, IR_CODE_CRANE_DOWN, IR_BITS); // Example: assuming crane down
} else if (current_joystick2Y >= JOYSTICK_CENTER_MIN && current_joystick2Y <= JOYSTICK_CENTER_MAX) {
// Serial.println("Action: J2 Y-axis Centered - No Function Up/Down");
}
// Joystick 2 X-axis for additional functions (e.g., rotation, extend, vehicle selection).
if (current_joystick2X < JOYSTICK_THRESHOLD_LOW) {
Serial.println("Action: Function X-Left (e.g., Rotate Left)");
// irsend.send(IR_PROTOCOL_TYPE, IR_CODE_FUNCTION_X_LEFT, IR_BITS); // Uncomment and define this code
} else if (current_joystick2X > JOYSTICK_THRESHOLD_HIGH) {
Serial.println("Action: Function X-Right (e.g., Rotate Right)");
// irsend.send(IR_PROTOCOL_TYPE, IR_CODE_FUNCTION_X_RIGHT, IR_BITS); // Uncomment and define this code
} else if (current_joystick2X >= JOYSTICK_CENTER_MIN && current_joystick2X <= JOYSTICK_CENTER_MAX) {
// Serial.println("Action: J2 X-axis Centered - No Function X-Left/Right");
}
// Small delay to prevent sending too many IR signals too quickly and to stabilize readings.
// Adjust this value based on how responsive you want the controls to be and how your receiver responds.
delay(100); // 100 milliseconds delay
}