Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devel #45

Open
wants to merge 6 commits into
base: devel
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions servo/example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#include "servo.h"

// Define servo configuration (replace with your values)
ledc_channel_t channel = LEDC_CHANNEL_0;
ledc_mode_t mode = LEDC_HIGH_SPEED_MODE;
int min_angle = 0;
int max_angle = 180;
uint32_t timer_freq = 50; // Adjust timer frequency if needed

// Create servo object
servo_t* myservo = servo_create(channel, mode, min_angle, max_angle, linear_angle_to_duty_ratio, timer_freq);
if (myservo == NULL) {
printf("Failed to create servo object\n");
// Handle error, perhaps by exiting the program or taking appropriate action
return 1;
}

// Attach the servo
int attach_result = servo_attach(myservo);
if (attach_result != 0) {
printf("Failed to attach servo: %s\n", servo_get_error_message(attach_result));
// Handle error, perhaps by detaching the servo and exiting the program or taking appropriate action
servo_detach(myservo);
return 1;
}

// Control the servo
servo_write(myservo, 90); // Set servo to 90 degrees
servo_writeMicroseconds(myservo, 1500); // Set pulse width to 1500 microseconds

// Detach the servo when finished
int detach_result = servo_detach(myservo);
if (detach_result != 0) {
printf("Failed to detach servo: %s\n", servo_get_error_message(detach_result));
// Handle error, perhaps by exiting the program or taking appropriate action
return 1;
}

return 0;
104 changes: 104 additions & 0 deletions servo/servo.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
#include "servo.h"
#include "esp_log.h"

static const char* TAG = "Servo";
servo_t* servo_create(ledc_channel_t channel, ledc_mode_t mode, int min_angle, int max_angle,
float (*angle_to_duty_ratio)(int angle), uint32_t timer_freq) {
servo_t* servo = (servo_t*)malloc(sizeof(servo_t));
if (servo == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory for servo");
return NULL;
}

servo->channel = channel;
servo->mode = mode;
servo->min_angle = min_angle;
servo->max_angle = max_angle;
if (angle_to_duty_ratio == NULL) {
ESP_LOGE(TAG, "Invalid angle_to_duty_ratio function");
free(servo);
return NULL;
}
servo->angle_to_duty_ratio = angle_to_duty_ratio;
servo->timer_freq = timer_freq;
return servo;
}

void servo_attach(servo_t* servo) {
if (servo == NULL) {
ESP_LOGE(TAG, "Invalid servo pointer");
return;
}

ledc_config_t ledc_config;
ledc_config.duty_resolution = LEDC_TIMER_13_BIT;
ledc_config.freq_hz = servo->timer_freq; // Use specified timer frequency
ledc_config.speed_mode = servo->mode;
ledc_config.clk_cfg = LEDC_AUTO_CLK;
ledc_config.gpio_sel = (ledc_channel_config_t){
.channel = servo->channel,
.duty = 0,
.gpio_num = -1, // Let hardware pick a free GPIO pin
.intr_type = LEDC_INTR_DISABLE,
.duty_cycle = 0,
.hpoint = 0,
};
if (ledc_config_channel(servo->channel, &ledc_config)!= ESP_OK) {
ESP_LOGE(TAG, "Failed to configure LEDC channel");
}
}

void servo_detach(servo_t* servo) {
if (servo == NULL) {
ESP_LOGE(TAG, "Invalid servo pointer");
return;
}

ledc_stop(servo->channel, servo->mode);
free(servo);
}

void servo_write(servo_t* servo, int angle) {
if (servo == NULL) {
ESP_LOGE(TAG, "Invalid servo pointer");
return;
}

// Clip angle to valid range
angle = constrain(angle, servo->min_angle, servo->max_angle);

// Calculate duty cycle based on angle
float duty_ratio = servo->angle_to_duty_ratio(angle);

// Convert duty ratio to LEDC units
uint32_t duty = (duty_ratio * ((1 << LEDC_TIMER_13_BIT) - 1));

// Set LEDC duty cycle
ledc_set_duty(servo->mode, servo->channel, duty);
ledc_update_duty(servo->mode, servo->channel);
}

void servo_writeMicroseconds(servo_t* servo, int pulse_width) {
if (servo == NULL) {
ESP_LOGE(TAG, "Invalid servo pointer");
return;
}

// Clip pulse width to valid range
pulse_width = constrain(pulse_width, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);

// Calculate duty cycle from pulse width and frequency
float duty_ratio = (float)pulse_width / (1000000.0f / servo->timer_freq);

// Convert duty ratio to LEDC units
uint32_t duty = (duty_ratio * ((1 << LEDC_TIMER_13_BIT) - 1));

// Set LEDC duty cycle
ledc_set_duty(servo->mode, servo->channel, duty);
ledc_update_duty(servo->mode, servo->channel);
}

float linear_angle_to_duty_ratio(int angle) {
// Adjust this function based on your servo motor's characteristics
return (angle - 0) / (180.0f - 0.0f);
}
30 changes: 30 additions & 0 deletions servo/servo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef SERVO_H
#define SERVO_H

#include <driver/ledc.h>

#define MIN_PULSE_WIDTH 500 // Minimum pulse width for servo (in microseconds)
#define MAX_PULSE_WIDTH 2500 // Maximum pulse width for servo (in microseconds)

typedef struct {
ledc_channel_t channel;
ledc_mode_t mode;
int min_angle;
int max_angle;
float (*angle_to_duty_ratio)(int angle);
uint32_t timer_freq; // PWM timer frequency (in Hz)
} servo_t;

// Default angle to duty ratio function
float default_angle_to_duty_ratio(int angle);

servo_t* servo_create(ledc_channel_t channel, ledc_mode_t mode, int min_angle, int max_angle,
float (*angle_to_duty_ratio)(int angle), uint32_t timer_freq);
servo_t* servo_create_default(ledc_channel_t channel, ledc_mode_t mode, int min_angle, int max_angle, uint32_t timer_freq);

void servo_attach(servo_t* servo);
void servo_detach(servo_t* servo);
void servo_write(servo_t* servo, int angle);
void servo_writeMicroseconds(servo_t* servo, int pulse_width); // Similar to Arduino writeMicroseconds

#endif