#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/adc.h" //ADC - Analog Digital Converter driver
#include "esp_adc_cal.h" //ADC kalibracija
#include "driver/ledc.h" //LED driver
#include "ssd1306.h" //OLED display driver
#include "font8x8_basic.h" //OLED display font
//povezivanje GPIO pinova na ESP sa pojedinom bojom LEDice
#define LED_PIN_R GPIO_NUM_5
#define LED_PIN_G GPIO_NUM_18
#define LED_PIN_B GPIO_NUM_19
//LEDC konfiguracija
#define LEDC_TIMER LEDC_TIMER_0
#define LEDC_MODE LEDC_HIGH_SPEED_MODE
#define LEDC_RESOLUTION LEDC_TIMER_13_BIT
#define LEDC_FREQUENCY 5000
//povezivanje ADC pinova sa potencimetrom(POT) za kontrolu pojedine boje
#define POT_PIN_R ADC2_CHANNEL_3
#define POT_PIN_G ADC2_CHANNEL_2
#define POT_PIN_B ADC2_CHANNEL_0
//ADC konfiguracija
static esp_adc_cal_characteristics_t *adc_chars;
static const adc_atten_t atten = ADC_ATTEN_DB_11; //11db za raspon 0-3.3V, radi i sa 5v, ali je zadnja 1/3 pot@max
static const adc_unit_t unit = ADC_UNIT_2; //kako koristimo ESP na breadbordu, radi dimenzija možemo spajati pinove samo na jednu stranu, +3,3V i dispej pinovi su na istoj strani, stoga koistimo ADC2 kanal koji ima tri pina na istoj strani kao i +3,3V i disp.
void adc_inicijalizacija() {
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, 1100, adc_chars);
}
void adc_konfiguracija() {
//adc1_config_width(ADC_WIDTH_BIT_12); //dok je bilo prikopcano na ADC1, za ADC2 -The reading width of ADC2 is configured every time you take the reading
adc2_config_channel_atten(POT_PIN_R, atten);
adc2_config_channel_atten(POT_PIN_G, atten);
adc2_config_channel_atten(POT_PIN_B, atten);
}
void led_inicijalizacija(uint32_t timer, uint32_t channel, gpio_num_t gpio_num) {
// Configure LED PWM for a specific LED
ledc_timer_config_t ledc_timer = {
.duty_resolution = LEDC_RESOLUTION,
.freq_hz = LEDC_FREQUENCY,
.speed_mode = LEDC_MODE,
.timer_num = timer
};
ledc_timer_config(&ledc_timer);
ledc_channel_config_t ledc_channel = {
.channel = channel,
.duty = 0,
.gpio_num = gpio_num,
.speed_mode = LEDC_MODE,
.timer_sel = timer
};
ledc_channel_config(&ledc_channel);
}
void led_fade(uint32_t channel, float brightness) {
uint32_t duty = (uint32_t)(brightness * ((1 << LEDC_RESOLUTION) - 1));
ledc_set_duty(LEDC_MODE, channel, duty);
ledc_update_duty(LEDC_MODE, channel);
}
void app_main() {
//OLED inicijalizacija
SSD1306_t dev;
i2c_master_init(&dev, GPIO_NUM_21, GPIO_NUM_22, GPIO_NUM_33);
ssd1306_init(&dev, 128, 64);
ssd1306_contrast(&dev, 0xff);
//OLED pozdravni ekran nakon paljena 5sek
ssd1306_clear_screen(&dev, false);
ssd1306_display_text_x3(&dev, 0, "Hello", 5, false);
ssd1306_display_text_x3(&dev, 4, "IG&DT", 5, false);
vTaskDelay(500);
ssd1306_clear_screen(&dev, false);
//ADC i LED inicijalizacija
adc_inicijalizacija();
adc_konfiguracija();
led_inicijalizacija(LEDC_TIMER_0, LEDC_CHANNEL_0, LED_PIN_R);
led_inicijalizacija(LEDC_TIMER_1, LEDC_CHANNEL_1, LED_PIN_G);
led_inicijalizacija(LEDC_TIMER_2, LEDC_CHANNEL_2, LED_PIN_B);
while (1) {
//ocitavanje vrijednosti-pozicije potenciometra
//adc2_get_raw ima drugaciju sintaksu od adc1 - tri parametra
int pot_value_R, pot_value_G, pot_value_B;
adc2_get_raw(POT_PIN_R, ADC_WIDTH_BIT_12, &pot_value_R);
adc2_get_raw(POT_PIN_G, ADC_WIDTH_BIT_12, &pot_value_G);
adc2_get_raw(POT_PIN_B, ADC_WIDTH_BIT_12, &pot_value_B);
/*
//originalna konfiguracija sa adc1 koji ima pinove na drugoj strani i nemozemo koristiti kada je ESP na breadbordu
int pot_value_R = adc1_get_raw(POT_PIN_R);
int pot_value_G = adc1_get_raw(POT_PIN_G);
int pot_value_B = adc1_get_raw(POT_PIN_B);
*/
//preracunavanje vrijednosti potenciometra (0-4095) u vrijednosti za jačinu LED (0-1)
float brightness_R = (float)pot_value_R / 4095.0;
float brightness_G = (float)pot_value_G / 4095.0;
float brightness_B = (float)pot_value_B / 4095.0;
//preracunavanje vrijednosti jacine LED (0-1) u RGB vrijednost (0-255)
int intensity_R = (float)brightness_R * 255;
int intensity_G = (float)brightness_G * 255;
int intensity_B = (float)brightness_B * 255;
//postavljanje jacine svake LED boje na izracunatu vrijednost
led_fade(LEDC_CHANNEL_0, brightness_R);
led_fade(LEDC_CHANNEL_1, brightness_G);
led_fade(LEDC_CHANNEL_2, brightness_B);
//brise sadrzaj terminala i postavlja kursor u gornju lijevu poziciju
//potrebno kad se poveca brzina/vrijeme cekanja ispisa jer se ne moze procitati sadrzaj kad doda novi podatak
//ovako ispisuje podatke uvijek na istu poziciju i cini se da nepromijenjivi dio ostaje na mjestu, i da samo vrijednosti mijenjaju
printf("\e[1;1H\e[2J");
//prikaz vrijednosti potenciometra (0-4095) i RGB vrijednosti (0-255) u terminalu
printf("pot_R: %d, pot_G: %d, pot_B: %d\n", pot_value_R, pot_value_G, pot_value_B);
printf("R value: %d\n", intensity_R);
printf("G value: %d\n", intensity_G);
printf("B value: %d\n", intensity_B);
//prikaz naslovnog reda i RGB vrijednosti (0-255) na OLED displeju
ssd1306_display_text(&dev, 0, "RGB LED by IG&DT", 16, false);
char display_text[6];
sprintf(display_text, "R: %d ", intensity_R);
ssd1306_display_text(&dev, 2, display_text, 7, false);
sprintf(display_text, "G: %d ", intensity_G);
ssd1306_display_text(&dev, 4, display_text, 7, false);
sprintf(display_text, "B: %d ", intensity_B);
ssd1306_display_text(&dev, 6, display_text, 7, false);
//delay - cekanje 0,5sek za iducu iteraciju unutar while petlje -
//(ocitavanje vrijednosti pot., postavljanje jacine svake LED boje, prikaz vrijednosti u terminalu, prikaz vrijednosti na OLED displeju)
vTaskDelay(10);
}
}