Created
September 13, 2022 13:45
-
-
Save zjor/0825db34b571a1414a28845d8b239094 to your computer and use it in GitHub Desktop.
Hue rotation of an RGB LED using ESP-IDF framework
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// color_utils.h | |
#ifndef _COLOR_UTILS_ | |
#define _COLOR_UTILS_ | |
typedef struct RGB { | |
unsigned char r; | |
unsigned char g; | |
unsigned char b; | |
} rgb_t; | |
typedef struct HSV { | |
double h; | |
double s; | |
double v; | |
} hsv_t; | |
rgb_t hsv_to_rgb(hsv_t hsv); | |
#endif | |
//color_utils.c | |
#include <math.h> | |
#include "color_utils.h" | |
rgb_t hsv_to_rgb(hsv_t hsv) { | |
double r = 0, g = 0, b = 0; | |
if (hsv.s == 0) | |
{ | |
r = hsv.v; | |
g = hsv.v; | |
b = hsv.v; | |
} | |
else | |
{ | |
int i; | |
double f, p, q, t; | |
if (hsv.h == 360) | |
hsv.h = 0; | |
else | |
hsv.h = hsv.h / 60; | |
i = (int)trunc(hsv.h); | |
f = hsv.h - i; | |
p = hsv.v * (1.0 - hsv.s); | |
q = hsv.v * (1.0 - (hsv.s * f)); | |
t = hsv.v * (1.0 - (hsv.s * (1.0 - f))); | |
switch (i) | |
{ | |
case 0: | |
r = hsv.v; | |
g = t; | |
b = p; | |
break; | |
case 1: | |
r = q; | |
g = hsv.v; | |
b = p; | |
break; | |
case 2: | |
r = p; | |
g = hsv.v; | |
b = t; | |
break; | |
case 3: | |
r = p; | |
g = q; | |
b = hsv.v; | |
break; | |
case 4: | |
r = t; | |
g = p; | |
b = hsv.v; | |
break; | |
default: | |
r = hsv.v; | |
g = p; | |
b = q; | |
break; | |
} | |
} | |
rgb_t rgb = { | |
.r = r * 255, | |
.g = g * 255, | |
.b = b * 255 | |
}; | |
return rgb; | |
} | |
//main.c | |
#include <stdio.h> | |
#include "driver/gpio.h" | |
#include "freertos/FreeRTOS.h" | |
#include "freertos/task.h" | |
#include "driver/ledc.h" | |
#include "color_utils.h" | |
#define GPIO_RED 14 | |
#define GPIO_GREEN 15 | |
#define GPIO_BLUE 27 | |
static ledc_channel_config_t r_ledc_channel; | |
static ledc_channel_config_t g_ledc_channel; | |
static ledc_channel_config_t b_ledc_channel; | |
static void config_ledc_channel(ledc_channel_config_t* c, int gpio_num, ledc_channel_t channel) { | |
c->channel = channel; | |
c->duty = 0; | |
c->gpio_num = gpio_num; | |
c->speed_mode = LEDC_HIGH_SPEED_MODE; | |
c->hpoint = 0; | |
c->timer_sel = LEDC_TIMER_0; | |
ledc_channel_config(c); | |
} | |
static void set_ledc_duty(ledc_channel_config_t c, int duty) { | |
ledc_set_duty(c.speed_mode, c.channel, duty); | |
ledc_update_duty(c.speed_mode, c.channel); | |
} | |
static void init_hw(void) { | |
ledc_timer_config_t ledc_timer = { | |
.duty_resolution = LEDC_TIMER_8_BIT, | |
.freq_hz = 1000, | |
.speed_mode = LEDC_HIGH_SPEED_MODE, | |
.timer_num = LEDC_TIMER_0, | |
.clk_cfg = LEDC_AUTO_CLK | |
}; | |
ledc_timer_config(&ledc_timer); | |
config_ledc_channel(&r_ledc_channel, GPIO_RED, LEDC_CHANNEL_0); | |
config_ledc_channel(&g_ledc_channel, GPIO_GREEN, LEDC_CHANNEL_1); | |
config_ledc_channel(&b_ledc_channel, GPIO_BLUE, LEDC_CHANNEL_2); | |
} | |
static hsv_t hsv = { | |
.h = 0, | |
.s = 1.0, | |
.v = 1.0 | |
}; | |
void loop(void) { | |
hsv.h++; | |
if (hsv.h == 360) { | |
hsv.h = 0; | |
} | |
rgb_t rgb = hsv_to_rgb(hsv); | |
set_ledc_duty(r_ledc_channel, 255 - rgb.r); | |
set_ledc_duty(g_ledc_channel, 255 - rgb.g); | |
set_ledc_duty(b_ledc_channel, 255 - rgb.b); | |
vTaskDelay(10 / portTICK_PERIOD_MS); | |
} | |
void app_main() { | |
init_hw(); | |
while (1) { | |
loop(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment