From 80b05f3ba75e283287c8a4b46cedf69df87ece62 Mon Sep 17 00:00:00 2001 From: GhassanYusuf Date: Sun, 23 Mar 2025 17:01:13 +0300 Subject: [PATCH] first commit --- L298N_ESP32.h | 102 +++++++++++++++++++++++ Servo_ESP32.h | 104 +++++++++++++++++++++++ WORKING-CAR-CODE.ino | 194 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 400 insertions(+) create mode 100644 L298N_ESP32.h create mode 100644 Servo_ESP32.h create mode 100644 WORKING-CAR-CODE.ino diff --git a/L298N_ESP32.h b/L298N_ESP32.h new file mode 100644 index 0000000..1654147 --- /dev/null +++ b/L298N_ESP32.h @@ -0,0 +1,102 @@ +#ifndef L298N_ESP32_h +#define L298N_ESP32_h + +#include + +class L298N_ESP32 { +private: + uint8_t in1Pin; + uint8_t in2Pin; + uint8_t enPin; + uint8_t pwmChannel; + uint8_t _speed; + uint8_t _min_speed = 0; + uint8_t _max_speed = 255; + bool _invert = false; + + void checkWrite(uint8_t value) { + if (_speed != value) { + _speed = value; + ledcWrite(pwmChannel, _speed); + } + } + +public: + L298N_ESP32(uint8_t in1, uint8_t in2, uint8_t en, uint8_t channel = 0) : + in1Pin(in1), in2Pin(in2), enPin(en), pwmChannel(channel), _speed(0) {} + + void begin() { + pinMode(in1Pin, OUTPUT); + pinMode(in2Pin, OUTPUT); + ledcAttachChannel(pwmChannel, 30000, 8, enPin); // 30kHz frequency, 8-bit resolution + digitalWrite(in1Pin, LOW); + digitalWrite(in2Pin, LOW); + checkWrite(0); + } + + void setMin(uint8_t value) { + _min_speed = value; + } + + void setMax(uint8_t value) { + _max_speed = value; + } + + void invert() { + _invert = !_invert; + } + + void forward() { + if (!_invert) { + digitalWrite(in1Pin, LOW); + digitalWrite(in2Pin, HIGH); + } else { + digitalWrite(in1Pin, HIGH); + digitalWrite(in2Pin, LOW); + } + } + + void backward() { + if (!_invert) { + digitalWrite(in1Pin, HIGH); + digitalWrite(in2Pin, LOW); + } else { + digitalWrite(in1Pin, LOW); + digitalWrite(in2Pin, HIGH); + } + } + + void goMin() { + checkWrite(_min_speed); + } + + void goMax() { + checkWrite(_max_speed); + } + + void setSpeed(uint8_t speed) { + speed = constrain(speed, _min_speed, _max_speed); + checkWrite(speed); + } + + void setPercentage(uint8_t percentage) { + if (percentage == 0) { + checkWrite(0); + } else { + uint8_t speed = map(percentage, 1, 100, _min_speed, _max_speed); + checkWrite(speed); + } + } + + void override(uint8_t value) { + ledcWrite(pwmChannel, value); + } + + void stop() { + digitalWrite(in1Pin, LOW); + digitalWrite(in2Pin, LOW); + checkWrite(0); + } +}; + +#endif diff --git a/Servo_ESP32.h b/Servo_ESP32.h new file mode 100644 index 0000000..072dc1e --- /dev/null +++ b/Servo_ESP32.h @@ -0,0 +1,104 @@ +#ifndef Servo_ESP32_h +#define Servo_ESP32_h + +#include + +class Servo_ESP32 { +private: + uint8_t servoPin; + uint8_t pwmChannel; + int minPulseWidth; + int maxPulseWidth; + int currentAngle; + const int freq = 50; // 50Hz for standard servos + const int resolution = 16; // 16-bit resolution for smoother control + bool _invert = false; + uint8_t _min_pos = 0; + uint8_t _max_pos = 180; + uint8_t _init_pos = 90; + uint8_t _prv_pos = 0; + + bool verify(uint8_t input) { + if (input != _prv_pos) { + _prv_pos = input; + return true; + } + return false; + } + +public: + Servo_ESP32() {} + Servo_ESP32(uint8_t pin, uint8_t channel, int minPulse = 500, int maxPulse = 2500) : + servoPin(pin), pwmChannel(channel), minPulseWidth(minPulse), maxPulseWidth(maxPulse), currentAngle(0) {} + + void begin() { + ledcAttachChannel(pwmChannel, freq, resolution, servoPin); // Correct order: channel, freq, resolution, pin + write(_init_pos); + } + + void setPin(uint8_t pin) { + servoPin = pin; + } + + void invert() { + _invert = !_invert; + } + + void setMin(uint8_t start) { + _min_pos = start; + } + + void setMax(uint8_t stop) { + _max_pos = stop; + } + + void setInit(uint8_t init) { + _init_pos = init; + } + + void goMax() { + write(_max_pos); + } + + void goMin() { + write(_min_pos); + } + + void goInit() { + write(_init_pos); + } + + void write(int angle) { + if (!verify(angle)) return; + currentAngle = _invert ? 180 - angle : angle; + currentAngle = constrain(currentAngle, 0, 180); + int dutyCycle = map(currentAngle, 0, 180, + minPulseWidth, + maxPulseWidth); + ledcWrite(pwmChannel, dutyCycle); + } + + int read() { + return currentAngle; + } + + void move(uint8_t pos) { + pos = constrain(pos, _min_pos, _max_pos); + write(pos); + } + + void percent(uint8_t pos) { + pos = map(pos, 0, 100, _min_pos, _max_pos); + write(pos); + } + + void override(uint8_t pos) { + write(pos); + } + + // Add these functions to access the private attributes + uint8_t getMin() const { return _min_pos; } + uint8_t getMax() const { return _max_pos; } +}; + +#endif diff --git a/WORKING-CAR-CODE.ino b/WORKING-CAR-CODE.ino new file mode 100644 index 0000000..c08361f --- /dev/null +++ b/WORKING-CAR-CODE.ino @@ -0,0 +1,194 @@ +#include +#include "L298N_ESP32.h" +#include "Servo_ESP32.h" + +// Motor 1 Pins +#define MOTOR1_PIN1 27 +#define MOTOR1_PIN2 26 +#define MOTOR1_ENABLE 14 + +// Motor 2 Pins +#define MOTOR2_PIN1 25 +#define MOTOR2_PIN2 33 +#define MOTOR2_ENABLE 32 + +// Servo Pins +#define SERVO1_PIN 13 +#define SERVO2_PIN 12 + +// Motor Objects +L298N_ESP32 motor1(MOTOR1_PIN1, MOTOR1_PIN2, MOTOR1_ENABLE, 0); +L298N_ESP32 motor2(MOTOR2_PIN1, MOTOR2_PIN2, MOTOR2_ENABLE, 1); + +// Servo Objects +Servo_ESP32 servo1(SERVO1_PIN, 2, 1000, 2000); +Servo_ESP32 servo2(SERVO2_PIN, 3, 1000, 2000); + +// ESPNOW +#include +#include + +// Packet Data Structure +struct PacketData { + uint8_t X; // Steering (left/right) + uint8_t Y; // Throttle (forward/backward) + bool B; // Button +}; + +// Data Received From Remote +PacketData data; + +// Constants +const unsigned long MOTOR_ACTION_DELAY = 5000; // Delay between motor actions +const int SERVO1_START = 10; +const int SERVO1_END = 170; +const int SERVO2_START = 20; +const int SERVO2_END = 160; + +enum MotorState { + STOPPED, + FORWARD_M1, + BACKWARD_M1, + FORWARD_M2, + BACKWARD_M2 +}; + +MotorState currentMotorState = STOPPED; +unsigned long motorStateStartTime = 0; + +void setup() { + + Serial.begin(115200); + + // Initialize Motors + motor1.begin(); + motor2.begin(); + + // Initialize Servos + servo1.begin(); + servo2.begin(); + + Serial.println("Initialization complete."); + + // ESP-NOW setup + WiFi.mode(WIFI_STA); + if (esp_now_init() != ESP_OK) { + Serial.println("ESP-NOW init failed"); + return; + } + + // When Receive Data Execute OnDataRecv Function + esp_now_register_recv_cb(OnDataRecv); + +} + +void loop() { + + // Non Blocking Motor control + if(millis() - motorStateStartTime >= MOTOR_ACTION_DELAY) { + + motorStateStartTime = millis(); + + switch (currentMotorState) { + + case STOPPED: + Serial.println("Moving motor 1 forward..."); + motor1.forward(); + motor1.setPercentage(75); //PWM set percentage + motor2.stop(); + currentMotorState = FORWARD_M1; + break; + case FORWARD_M1: + Serial.println("Moving motor 1 backward..."); + motor1.backward(); + motor1.setPercentage(50); //PWM set percentage + motor2.stop(); + currentMotorState = BACKWARD_M1; + break; + case BACKWARD_M1: + Serial.println("Moving motor 2 forward..."); + motor1.stop(); + motor2.forward(); + motor2.setPercentage(25); //PWM set percentage + currentMotorState = FORWARD_M2; + break; + case FORWARD_M2: + Serial.println("Moving motor 2 backward..."); + motor1.stop(); + motor2.backward(); + motor2.setPercentage(100); //PWM set percentage + currentMotorState = BACKWARD_M2; + break; + case BACKWARD_M2: + Serial.println("Stopping motors ..."); + motor1.stop(); + motor2.stop(); + currentMotorState = STOPPED; + break; + + } + + } + + //Non Blocking Servos + static unsigned long servoTimer = 0; + static int servo1Pos = SERVO1_START; + static int servo2Pos = SERVO2_START; + static bool servoForward = true; + unsigned long currentTime = millis(); + + if(currentTime - servoTimer >= 20) { // Adjust for speed + + servoTimer = currentTime; + + if (servoForward) { + servo1Pos++; + if (servo1Pos >= SERVO1_END) { + servoForward = false; + } + } else { + servo1Pos--; + if (servo1Pos <= SERVO1_START) { + servoForward = true; + } + } + + servo1.write(servo1Pos); + + } + + //Non Blocking Servos + static unsigned long servoTimer2 = 0; + static int servo2Pos2 = SERVO2_START; + static bool servoForward2 = true; + unsigned long currentTime2 = millis(); + + if(currentTime2 - servoTimer2 >= 20) { // Adjust for speed + + servoTimer2 = currentTime2; + + if (servoForward2) { + servo2Pos2++; + if (servo2Pos2 >= SERVO2_END) { + servoForward2 = false; + } + } else { + servo2Pos2--; + if (servo2Pos2 <= SERVO2_START) { + servoForward2 = true; + } + } + + servo2.write(servo2Pos2); + + } + +} + +// ESP-NOW callback +void OnDataRecv(const esp_now_recv_info *info, const uint8_t *data, int len) { + if (len == sizeof(PacketData)) { + memcpy(&data, data, sizeof(PacketData)); + } +} + \ No newline at end of file