0% found this document useful (0 votes)
14 views5 pages

LED Control with OLED Display Code

Uploaded by

Dang Quang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views5 pages

LED Control with OLED Display Code

Uploaded by

Dang Quang
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd

#include "main.

h"
#include "ssd1306.h"
#include "ssd1306_fonts.h"
#include "stdio.h"
#include <math.h>

/* I2C và Timer ---------------------------------------------------------------*/


I2C_HandleTypeDef hi2c1;
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim3;

/* Private function prototypes ------------------------------------------------*/


void SystemClock_Config(void);
static void MPU_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM1_Init(void);
static void MX_TIM3_Init(void);

uint8_t ui_page = 0; // 0 = Main, 1 = Setting


volatile uint8_t button_pressing = 0;
volatile uint32_t button_press_tick = 0;

/* ------------------ LED Param ------------------ */


#define LUMEN_WARM 4000.0f
#define LUMEN_COOL 5100.0f

float max_watt = 120.0f; // Công suất tối đa giả lập


float min_power = 30.0f; // 0% mới = 30% cũ

/* Encoder + Button -----------------------------------------------------------*/


volatile uint8_t button_flag = 0;
volatile float target_power = 50.0f; // %
volatile float target_temp = 30.0f; // %

/* Slider hiển thị mượt */


float slider_power = 50;
float slider_temp = 30;

uint8_t current_select = 0; // 0 = Power, 1 = Temp


char buf[20];

/* ------------------ Button Callback ------------------ */


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if(GPIO_Pin == GPIO_PIN_2) // Button
{
if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_2) == GPIO_PIN_RESET)
{
// Bắt đầu nhấn
button_pressing = 1;
button_press_tick = HAL_GetTick();
}
else
{
// Nhả nút
button_pressing = 0;
uint32_t press_time = HAL_GetTick() - button_press_tick;
if(press_time < 500) // Nhấn ngắn
{
button_flag = 1;
}
else if(press_time >= 1500) // Nhấn giữ >1.5s
{
ui_page = !ui_page; // Đổi trang Main/Setting
}
}
}
}

/* ------------------ Vẽ Slider ------------------ */


void draw_slider(uint8_t x, uint8_t y, uint8_t width, uint8_t height, float
percent, uint8_t selected)
{
if(percent < 0) percent = 0;
if(percent > 100) percent = 100;

SSD1306_COLOR color = White;


uint8_t fill_width = (uint8_t)((percent * (width-2)) / 100.0f);

for(uint8_t i = 0; i < height; i++)


{
if(fill_width > 0)
ssd1306_Line(x + 1, y + i, x + 1 + fill_width, y + i, color);
}

// Viền
ssd1306_Line(x, y, x + width, y, color);
ssd1306_Line(x, y + height, x + width, y + height, color);
ssd1306_Line(x, y, x, y + height, color);
ssd1306_Line(x + width, y, x + width, y + height, color);

if(selected)
{
ssd1306_Line(x-1, y-1, x+width+1, y-1, color);
ssd1306_Line(x-1, y+height+1, x+width+1, y+height+1, color);
ssd1306_Line(x-1, y-1, x-1, y+height+1, color);
ssd1306_Line(x+width+1, y-1, x+width+1, y+height+1, color);
}
}

/* ------------------ Update LED PWM ------------------ */


void update_led_pwm(float slider_power, float slider_temp)
{
/* Nhiệt độ màu từ 2500K -> 6500K */
float cct = 2500.0f + slider_temp * (6500.0f - 2500.0f) / 100.0f;

/* --- Curve studio: slider -> mapped power --- */


float k = 10.0f; // Hệ số log, càng lớn càng mượt vùng thấp
float x = slider_power / 100.0f;
float log_curve = logf(1.0f + k * x) / logf(1.0f + k);
float mapped_power = min_power + log_curve * (100.0f - min_power);

/* Gamma correction */
float gamma_power = powf(mapped_power / 100.0f, 2.2f);

/* --- Pha trộn warm / cool --- */


float warm_ratio = (6500.0f - cct) / (6500.0f - 2500.0f);
float cool_ratio = 1.0f - warm_ratio;

/* Bù quang thông */
float warm_eff = warm_ratio / LUMEN_WARM;
float cool_eff = cool_ratio / LUMEN_COOL;
float sum_eff = warm_eff + cool_eff;
warm_eff /= sum_eff;
cool_eff /= sum_eff;

/* Scale để luôn đạt tổng sáng tối đa */


float scale = 1.0f / fmaxf(warm_eff, cool_eff);

/* PWM duty */
uint16_t period = __HAL_TIM_GET_AUTORELOAD(&htim1);
float max_duty = (float)period;

uint16_t duty_warm = (uint16_t)(gamma_power * warm_eff * scale * max_duty);


uint16_t duty_cool = (uint16_t)(gamma_power * cool_eff * scale * max_duty);

__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, duty_warm);


__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, duty_cool);
}

/* ------------------ MAIN ------------------ */


int main(void)
{
MPU_Config();
HAL_Init();
SystemClock_Config();

MX_GPIO_Init();
MX_I2C1_Init();
MX_TIM1_Init();
MX_TIM3_Init();

ssd1306_Init();
/* Giao diện khởi động */
ssd1306_Fill(Black);
ssd1306_SetCursor(10, 10);
ssd1306_WriteString("LED STUDIO", Font_11x18, White);
ssd1306_SetCursor(30, 35);
ssd1306_WriteString("v1.0", Font_7x10, White);
ssd1306_UpdateScreen();
HAL_Delay(1500);

/* Start PWM và Encoder */


HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
__HAL_TIM_SET_COUNTER(&htim3, 0);

int16_t last_enc = 0;

while(1)
{
/* Xử lý nút nhấn */
if(button_flag)
{
current_select = !current_select;
button_flag = 0;
}

/* Đọc giá trị encoder */


int16_t enc_val = (int16_t)__HAL_TIM_GET_COUNTER(&htim3);
int16_t diff = enc_val - last_enc;
last_enc = enc_val;

/* Mỗi nấc ~0.5% để mượt hơn */


float step = 0.5f * diff;

/* Cập nhật giá trị */


if(current_select == 0)
{
target_power += step;
if(target_power < 0) target_power = 0;
if(target_power > 100) target_power = 100;
}
else
{
target_temp += step;
if(target_temp < 0) target_temp = 0;
if(target_temp > 100) target_temp = 100;
}

/* Slider mượt */
slider_power += (target_power - slider_power) * 0.2f;
slider_temp += (target_temp - slider_temp) * 0.2f;

if (fabsf(slider_power - target_power) < 0.5f)


slider_power = target_power;
if (fabsf(slider_temp - target_temp) < 0.5f)
slider_temp = target_temp;

/* Cập nhật PWM */


update_led_pwm(slider_power, slider_temp);

/* -------- Hiển thị OLED -------- */


ssd1306_Fill(Black);

float cct = 2500.0f + slider_temp * (6500.0f - 2500.0f) / 100.0f;


sprintf(buf, "Power:%3d%%", (int)slider_power);
ssd1306_SetCursor(0, 0);
ssd1306_WriteString(buf, Font_7x10, White);

sprintf(buf, "Temp:%4dK", (int)cct);


ssd1306_SetCursor(0, 10);
ssd1306_WriteString(buf, Font_7x10, White);

/* Hiển thị công suất giả lập theo slider */


int real_power = (int)(max_watt * slider_power / 100.0f + 0.5f);
sprintf(buf, "Load:%3dW", real_power);
ssd1306_SetCursor(0, 20);
ssd1306_WriteString(buf, Font_7x10, White);

draw_slider(10, 35, 108, 8, slider_power, current_select == 0);


draw_slider(10, 50, 108, 8, slider_temp, current_select == 1);
ssd1306_UpdateScreen();
HAL_Delay(10); // ~100FPS mượt
}
}

You might also like