Skip to content

Instantly share code, notes, and snippets.

@zjor
Created September 13, 2022 13:45
Show Gist options
  • Save zjor/0825db34b571a1414a28845d8b239094 to your computer and use it in GitHub Desktop.
Save zjor/0825db34b571a1414a28845d8b239094 to your computer and use it in GitHub Desktop.
Hue rotation of an RGB LED using ESP-IDF framework
// 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