81 lines
2.7 KiB
C
81 lines
2.7 KiB
C
#include <stdio.h>
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "freertos/queue.h"
|
|
#include "sdkconfig.h"
|
|
#include "driver/ledc.h"
|
|
|
|
/*
|
|
According to the datasheet, the frequency should be 50Hz, which means that each period lasts 20 ms.
|
|
|
|
For our pulse width:
|
|
Position "0" (1.5 ms pulse) is middle, "90" (~2ms pulse) is all the way to the right,
|
|
"-90" (~1ms pulse) is all the way to the left.
|
|
|
|
We are working with 15 bit duty resolutions here, so the maximum value is 2^15 - 1 = 32767.
|
|
1 ms and 2 ms are respectively "full" left and "full" right. Its corresponding duty value is 1638 and 3276 (since 1638 / 32767 ≈ 1ms / 20ms and 3276 / 32767 ≈ 2ms / 20ms)
|
|
|
|
We want the servo to rotate from left to right then reverse the direction once done. This operation is repeated infinitely.
|
|
|
|
We start from our initial duty cycle of 1638 then increment its value to 3276 then reduce it back to 1638.
|
|
The boolean value stores the direction. So once the duty reaches its minimum or maximum value, the direction should change itself.
|
|
|
|
Doing it a little bit of Maths. We can can set the delta / step to be 14, and the number of iteration for the duty cycle to reach the
|
|
maximum from the inital minimum value is 117 as:
|
|
|
|
1638 + 14 * 117 = 3276
|
|
*/
|
|
|
|
void servoRotate_task(void *args) {
|
|
|
|
int duty = 1638 ; // The duty will vary from 1638 to 3276
|
|
int step = 14; // each iteration, the duty increments itself by this step
|
|
int total_cycles = 117; // 117 iterations in total
|
|
bool pos_direction = true; // true = up, false = down
|
|
int iteration_time = 10; // msecs
|
|
|
|
ledc_timer_config_t timer_conf = {
|
|
.duty_resolution = LEDC_TIMER_15_BIT,
|
|
.freq_hz = 50,
|
|
.speed_mode = LEDC_LOW_SPEED_MODE,
|
|
.timer_num = LEDC_TIMER_0,
|
|
.clk_cfg = LEDC_AUTO_CLK,
|
|
};
|
|
|
|
ledc_timer_config(&timer_conf); // Apply timer config
|
|
|
|
ledc_channel_config_t ledc_conf = {
|
|
.channel = LEDC_CHANNEL_0,
|
|
.duty = duty,
|
|
.gpio_num = 20,
|
|
.intr_type = LEDC_INTR_DISABLE,
|
|
.speed_mode = LEDC_LOW_SPEED_MODE,
|
|
.timer_sel = LEDC_TIMER_0,
|
|
};
|
|
|
|
ledc_channel_config(&ledc_conf); // Apply channel config
|
|
|
|
int i;
|
|
while(1) {
|
|
for (i=0; i < total_cycles; i++) {
|
|
// If the direction is positive, the duty increments itself, otherwise it will be reduced in value
|
|
pos_direction ? (duty += step) : (duty -= step);
|
|
|
|
// Set the new duty and update it in each iteration
|
|
|
|
ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, duty);
|
|
ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0);
|
|
|
|
// Wait for 10 microseconds
|
|
vTaskDelay(iteration_time/portTICK_PERIOD_MS);
|
|
}
|
|
// Change the direction
|
|
pos_direction = !pos_direction;
|
|
}
|
|
}
|
|
|
|
void app_main()
|
|
{
|
|
xTaskCreate(&servoRotate_task,"servoRotate_task",2048,NULL,5,NULL);
|
|
}
|