first commit

This commit is contained in:
Ghassan Yusuf 2025-03-23 17:01:13 +03:00
commit 80b05f3ba7
3 changed files with 400 additions and 0 deletions

102
L298N_ESP32.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef L298N_ESP32_h
#define L298N_ESP32_h
#include <Arduino.h>
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

104
Servo_ESP32.h Normal file
View File

@ -0,0 +1,104 @@
#ifndef Servo_ESP32_h
#define Servo_ESP32_h
#include <Arduino.h>
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

194
WORKING-CAR-CODE.ino Normal file
View File

@ -0,0 +1,194 @@
#include <Arduino.h>
#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 <esp_now.h>
#include <WiFi.h>
// 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));
}
}