-
ESP-IDF 쿨링팬 FG센서, PWM제어(vscode)소프트웨어 2023. 4. 11. 11:35
#esp32 윈도우 vscode 환경
#선행(필수) ESP-IDF 윈도우 개발환경 세팅(vscode)
#선행(필수) ESP-IDF 외부 폴더에서 예제 파일 실행(vscode)#선행(필수) ESP-IDF .c .h 참조 cMakeLists (vscode)
#선행(필수) ESP-IDF components 참조 cMakeLists (vscode)
#선행(필수) ESP-IDF GPIO 인풋, 아웃풋 (VSCODE)
#선행(필수) ESP-IDF PULSE COUNTER(vscode) (예정)#선행(필수) PWM(vscode) (예정)
#선행(필수) FreeRTOS - Create Task(vscode) (예정)
#선행(필수) ESP-IDF I2C OLED(vscode) (예정)#선행(필수) ESP-IDF ADC , DAC(vscode) (예정)
#선행(필수) ESP-IDF USB-C로 전원 인가 (예정)
1) 최종 결과
2) 결선
FAN : 24V / GND / FG 23 / PWM 12
포텐셜미터 : 3.3V / GND / 15
OLED : 3.3V / GND / SDA 21 / SCL 22EasyEDA - 회로
EasyEDA - 아트웍
3) 코드
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "ssd1306.h" #include "esp_timer.h" #include "driver/gpio.h" #include "driver/ledc.h" #include "esp_system.h" #include "driver/adc.h" #include "driver/pcnt.h" #define tag "SSD1306" #define V_REF 1100 const int pwmPin = 12; const gpio_num_t fgPin = GPIO_NUM_23; const gpio_num_t potPin = GPIO_NUM_15; #define POT_CHANNEL ADC1_CHANNEL_6 #define ADC_WIDTH ADC_WIDTH_BIT_12 #define ADC_ATTEN ADC_ATTEN_DB_11 #define PCNT_UNIT PCNT_UNIT_0 #define PCNT_CHANNEL PCNT_CHANNEL_0 #define PCNT_H_LIM_VAL 10000 #define PCNT_L_LIM_VAL 0 volatile int16_t pulseCount = 0; uint32_t lastMillis = 0; int16_t prevPulseCount = -1; const int frequency = 25000; const int resolution = 8; const int channel = 0; long fanRPM = 0; long prevRPM = -1; SSD1306_t dev; // Forward declaration for the tasks void rpmTask(void *pvParameters); void mainTask(void *pvParameters); void init_pulse_counter() { pcnt_config_t pcnt_config = { .pulse_gpio_num = fgPin, .ctrl_gpio_num = PCNT_PIN_NOT_USED, .channel = PCNT_CHANNEL_0, .unit = PCNT_UNIT, .pos_mode = PCNT_COUNT_INC, .neg_mode = PCNT_COUNT_DIS, .lctrl_mode = PCNT_MODE_KEEP, .hctrl_mode = PCNT_MODE_KEEP, .counter_h_lim = PCNT_H_LIM_VAL, .counter_l_lim = PCNT_L_LIM_VAL, }; pcnt_unit_config(&pcnt_config); // Set the GPIO filter value for the pulse counter pcnt_set_filter_value(PCNT_UNIT, 1000); // Increase filter value pcnt_filter_enable(PCNT_UNIT); pcnt_counter_pause(PCNT_UNIT); pcnt_counter_clear(PCNT_UNIT); pcnt_counter_resume(PCNT_UNIT); } void app_main(void) { gpio_set_direction(pwmPin, GPIO_MODE_OUTPUT); gpio_pulldown_dis(fgPin); gpio_pullup_en(fgPin); gpio_set_direction(fgPin, GPIO_MODE_INPUT); gpio_set_direction(potPin, GPIO_MODE_INPUT); init_pulse_counter(); ledc_timer_config_t ledc_timer = { .duty_resolution = LEDC_TIMER_8_BIT, .freq_hz = frequency, .speed_mode = LEDC_HIGH_SPEED_MODE, .timer_num = LEDC_TIMER_0, .clk_cfg = LEDC_AUTO_CLK }; ledc_timer_config(&ledc_timer); ledc_channel_config_t ledc_channel = { .channel = LEDC_CHANNEL_0, .duty = 0, .gpio_num = pwmPin, .speed_mode = LEDC_HIGH_SPEED_MODE, .hpoint = 0, .timer_sel = LEDC_TIMER_0 }; ledc_channel_config(&ledc_channel); i2c_master_init(&dev, CONFIG_SDA_GPIO, CONFIG_SCL_GPIO, false); ssd1306_init(&dev, 128, 64); ssd1306_clear_screen(&dev, false); adc1_config_width(ADC_WIDTH); adc1_config_channel_atten(POT_CHANNEL, ADC_ATTEN); // Create the tasks xTaskCreatePinnedToCore(&rpmTask, "RPM Task", 4096, NULL, 20, NULL, 1); xTaskCreatePinnedToCore(&mainTask, "Main Task", 4096, (void *)&dev, 1, NULL, 0); } void rpmTask(void *pvParameters) { while (1) { uint32_t currentMillis = esp_timer_get_time() / 1000; // Convert to milliseconds if (currentMillis - lastMillis >= 1000) { lastMillis = currentMillis; pcnt_get_counter_value(PCNT_UNIT, (int16_t *)&pulseCount); fanRPM = (pulseCount*60)/2; pcnt_counter_clear(PCNT_UNIT); if (fanRPM != prevPulseCount) { prevPulseCount = fanRPM; } } vTaskDelay(pdMS_TO_TICKS(10)); // Slight delay to reduce CPU usage } } void mainTask(void *pvParameters) { // SSD1306_t *dev = (SSD1306_t *)pvParameters; char rpmText[22]; char dutyRateText[25]; ssd1306_clear_screen(&dev, false); ssd1306_display_text(&dev, 1, " <FG , PWM>", strlen(" <FG , PWM>"), false); while (1) { int potValue = adc1_get_raw(POT_CHANNEL); uint32_t dutyCycle = (potValue * 255) / 4095; int dutyRate = (100 * dutyCycle) / 255; snprintf(dutyRateText, sizeof(dutyRateText), "Duty Rate: %d%% ", dutyRate); ledc_set_duty(LEDC_HIGH_SPEED_MODE, channel, dutyCycle); ledc_update_duty(LEDC_HIGH_SPEED_MODE, channel); snprintf(rpmText, sizeof(rpmText), "Speed: %ldRPM ", fanRPM); ssd1306_display_text(&dev, 3, rpmText, strlen(rpmText), false); ssd1306_display_text(&dev, 5, dutyRateText, strlen(dutyRateText), false); printf("rpmText: %s \n ", rpmText); vTaskDelay(pdMS_TO_TICKS(1000)); // Refresh display every 100ms } }
팬.com
YeHAUS
ESP-IDF 윈도우 개발환경 세팅 (VSCODE)
ESP-IDF 외부 폴더에서 예제 파일 실행 (VSCODE)
ESP-IDF GPIO 인풋, 아웃풋 (VSCODE)
ESP-IDF 인터럽트 (VSCODE)ESP-IDF 디바운싱 (esp32, vscode)
ESP-IDF .c .h 참조 cMakeLists (vscode)ESP-IDF components 참조 cMakeLists (vscode)
ESP-IDF LCD 출력(vscode)
ESP-IDF 메모리 - Flash (vscode)
ESP-IDF 메모리 - SRAM (vscode)
ESP-IDF FreeRTOS - buffer (vscode)
ESP-IDF 쿨링팬 FG센서, PWM제어(vscode)
<포스트 예정>
*ESP-IDF 메모리 - ROM*ESP32용 핀헤더 PCB 제작(easyEDA)
*LCD - 메뉴 만들고 버튼으로 메뉴 이동(터미널로 작업)
*LCD - 2차원 배열로 메뉴 진입, 뒤로가기(터미널로 작업)
*LCD - 메뉴 만든 것 LCD 출력
*LCD - 메뉴 UI 제작. 연두색 블럭은 메인 메뉴 회색 블럭은 서브 메뉴
(1.팬 1-1.ON 1-2.OFF 1-3.BACK 2.LED 2-1.밝기 약 2-2.밝기 중 2-3.밝기 강 2-4.BACK 3.빛 밝기 출력 lux(+PPFD 변환)
*Easy EDA툴 활용하여 커스텀 ESP32 보드 제작
*LCD - LCD , 팬 , 펌프 , ESP32 연결 가능한 PCB 제작 주문.
*LCD - 간이 스마트팜 제작
*ESP32 JTAG 디버그
*FreeRTOS - Create Task
*FreeRTOS - QUEUE
*FreeRTOS - timer
*FreeRTOS - Semaphore , mutex
*FreeRTOS - event group , notification*ESP-IDF ADC , DAC
*ESP-IDF PWM
*ESP-IDF I2C SPI UART
*ESP-IDF wifi
*ESP-IDF MQTT
*ESP-IDF Server (XAMPP 로컬 서버 연결)
*DIY 컨테이너 / 유리온실 스마트팜 제작*ESP-IDF USB-C로 전원 인가 (예정)
*ESP-IDF CAM
'소프트웨어' 카테고리의 다른 글
ESP-IDF RTC DS3231(vscode) (0) 2023.08.05 ESP32 PIN-OUT (0) 2023.04.12 ESP-IDF FreeRTOS - Buffer (vscode) (0) 2023.03.30 ESP-IDF 메모리 - SRAM (vscode) (0) 2023.03.28 ESP-IDF 메모리 - Flash (vscode) (0) 2023.03.25