539|0

107

帖子

0

资源

一粒金砂(中级)

【ESP32-S2-Kaluga-1测评】5. 图片显示,按键以及RGB LED操作 [复制链接]

这一周弄了弄板载的按键以及RGB LED。

下面说一下具体实现的功能,使用官方提供的例程进行修改,显示了自己的一个logo图片

4.jpg

 

接着是操作RGB LED,在官方例程中进行修改,代码如下,

改代码的含义是,红蓝绿交替显示:

 

显示效果如下:


 

接下来是按钮的控制,ESP32S2的按键是连接在ADC上面的,所以需要配合ADC读取相应的电压值,不同的按键或者组合按键按下去有不同的电压值,需要ADC进行采集

电路原理图如下:

2.jpg

 

注意,这个原理图上对按钮1的电压值标注不对,我最开始的时候使用按钮K1,用2.41V怎么都不对,检测不出来,其他按键都是可以的,然后我用串口debug了一下,K1采集出来是2.3V

如下图:

3.jpg

然后使用2.3V可以正常识别。

 

我写的程序是RGB LED和按键分别用了两个不同的任务,按下按键K1就暂停RGB LED任务,松开按键K1就继续RGB LED任务。

 

效果如下:


 

f((1 == key_pressed_status[0]) && (0 == Last_key_pressed_status[0])){     // pressed
        vTaskSuspend(RGBLEDTask_Handler);  
        ESP_LOGI(TAG, "K1 activated");
    }else if((0 == key_pressed_status[0]) && (1 == Last_key_pressed_status[0])){      // released
        vTaskResume(RGBLEDTask_Handler);
        ESP_LOGI(TAG, "K1 inactivated");
    }else{

    }

 

下面我贴上源代码。

但是需要注意的是,除了修改main.c中的代码之外,还需要修改Kconfig.probuild以及CMakeLists.txt文件

5.jpg

源代码(main.c):

/* 
Autor: hehung
*/
#include <stdio.h>
#include <stdint.h>
#include <stddef.h>
#include <string.h>

#include "esp_wifi.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_spiffs.h"

#include "lcd.h"
#include "jpeg.h"
#include "board.h"
#include "sccb.h"
#include "cam.h"

#include "ov2640.h"
#include "ov3660.h"
#include "sensor.h"

#include "driver/gpio.h"
#include "driver/adc.h"
#include "driver/rmt.h"
#include "led_strip.h"

static const char *TAG = "main";

/******** Start Macro Definition ********/
/* Picture - Start up picture */
/* LCD */
#define IMAGE_MAX_SIZE (100 * 1024)/**< The maximum size of a single picture in the boot animation */
#define IMAGE_WIDTH    (320) /*!< width of jpeg file */
#define IMAGE_HIGHT    (240) /*!< height of jpeg file */

/* Camera */
#define CAM_WIDTH   (320)       /* camera width */
#define CAM_HIGH    (240)       /* camera height */

/* ADC Button */
#define DEFAULT_VREF    1100                            /*!< Use adc2_vref_to_gpio() to obtain a better estimate */
#define NO_OF_SAMPLES   64
#define SAMPLE_TIME     200                             /*!< Sampling time(ms) */
#define DEVIATION 0.1
/******** End Macro Definition ********/

/******** Start Variables Declaration  ********/
/* LED */
static led_strip_t *strip;
/* ADC Button */
static const adc_channel_t channel = ADC_CHANNEL_5;     /*!< PIO7 if ADC1, GPIO17 if ADC2 */
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;

static const adc_atten_t atten = ADC_ATTEN_DB_11;
static const adc_unit_t unit = ADC_UNIT_1;
static xQueueHandle adc_queue = NULL;

/* freertos tasks handler */
TaskHandle_t RGBLEDTask_Handler;		//RGB LED任务句柄
TaskHandle_t ButtonTask_Handler;		//RGB LED任务句柄
TaskHandle_t CameraTask_Handler;		//RGB LED任务句柄
/******** End Variables Declaration  ********/

/******** Start Function Declaration  ********/
static void start_display(void);
static void cam_task(void *arg);
void button_task(void *arg);
void led_task(void *arg);
esp_err_t Rmt_init(uint8_t gpio_num, int led_number, uint8_t rmt_channel);
void adc_init(void);
void button_task(void *arg);
double adc_voltage_conversion(uint32_t adc_reading);
void Button_Selection(double voltage);
/******** End Function Declaration  ********/


/******** Start Function Definition  ********/
/* main */
void app_main()
{
    /* Show a picture */
    start_display();

    adc_queue = xQueueCreate(1, sizeof(double));
    adc_init();

    /* Show the Camera */
 //   xTaskCreate(cam_task, "cam_task", 2048, NULL, 3, &CameraTask_Handler);
    /*  */
    xTaskCreate(&button_task, "button_task", 3*1024, NULL, 4, &ButtonTask_Handler);
    xTaskCreate(&led_task, "led_task", 3*1024, NULL, 5, &RGBLEDTask_Handler);
//    vTaskStartScheduler();          //this is write in cpu_start.c
}

/*initialization the ADC */
void adc_init(void)
{
    if (unit == ADC_UNIT_1) {
        adc1_config_width(width);
        adc1_config_channel_atten(channel, atten);
    } else {
        adc2_config_channel_atten((adc2_channel_t)channel, atten);
    }

}

/* ADC conversion */
double adc_voltage_conversion(uint32_t adc_reading)
{
    double voltage = 0;

    voltage = (2.60 * adc_reading) / 8191;

    return voltage;
}

/* button task */
void button_task(void *arg)
{
     /*!<Continuously sample ADC1*/
    while (1) {
        uint32_t adc_reading = 0;
        double voltage = 0;

        /*!< Multisampling */
        for (int i = 0; i < NO_OF_SAMPLES; i++) {
            if (unit == ADC_UNIT_1) {
                adc_reading += adc1_get_raw((adc1_channel_t)channel);
            } else {
                int raw;
                adc2_get_raw((adc2_channel_t)channel, width, &raw);
                adc_reading += raw;
            }
        }

        adc_reading /= NO_OF_SAMPLES;

        voltage = adc_voltage_conversion(adc_reading);
        ESP_LOGD(TAG, "ADC%d CH%d Raw: %d   ; Voltage: %0.2lfV", unit, channel, adc_reading, voltage);
        ESP_LOGI(TAG, "Voltage: %0.2lfV", voltage);
        xQueueSend(adc_queue, (double *)&voltage, 0);
    //    xQueueReceive(adc_queue, &voltage, portMAX_DELAY);
        Button_Selection(voltage);
        vTaskDelay(pdMS_TO_TICKS(SAMPLE_TIME));
    }

    vTaskDelete(NULL);
}

/* Button Selection */
void Button_Selection(double voltage)
{
//    double voltage = 0;
//    xQueueReceive(adc_queue, &voltage, portMAX_DELAY);

    static bool key_pressed_status[6] = {0};
    static bool Last_key_pressed_status[6] = {0};

    if (voltage > 2.30 - DEVIATION  && voltage <= 2.30 + DEVIATION) {
        key_pressed_status[0] = 1;
        ESP_LOGI(TAG, "K1 Pressed");
    } else if (voltage > 1.98 - DEVIATION && voltage <= 1.98 + DEVIATION) {
        key_pressed_status[1] = 1;
        ESP_LOGI(TAG, "K2 Pressed");
    } else if (voltage > 1.65 - DEVIATION && voltage <= 1.65 + DEVIATION) {
        key_pressed_status[2] = 1;
        ESP_LOGI(TAG, "K3 Pressed");
    } else if (voltage > 1.11 - DEVIATION && voltage <= 1.11 + DEVIATION) {
        key_pressed_status[3] = 1;
        ESP_LOGI(TAG, "K4 Pressed");
    } else if (voltage > 0.82 - DEVIATION && voltage <= 0.82 + DEVIATION) {
        key_pressed_status[4] = 1;
        ESP_LOGI(TAG, "K5 Pressed");
    } else if (voltage > 0.38 - DEVIATION && voltage <= 0.38 + DEVIATION) {
        key_pressed_status[5] = 1;
        ESP_LOGI(TAG, "K6 Pressed");
    }else{
        key_pressed_status[0] = 0;
        key_pressed_status[1] = 0;
        key_pressed_status[2] = 0;
        key_pressed_status[3] = 0;
        key_pressed_status[4] = 0;
        key_pressed_status[5] = 0;
    }

    if((1 == key_pressed_status[0]) && (0 == Last_key_pressed_status[0])){     // pressed
        vTaskSuspend(RGBLEDTask_Handler);  
        ESP_LOGI(TAG, "K1 activated");
    }else if((0 == key_pressed_status[0]) && (1 == Last_key_pressed_status[0])){      // released
        vTaskResume(RGBLEDTask_Handler);
        ESP_LOGI(TAG, "K1 inactivated");
    }else{

    }

    Last_key_pressed_status[0] = key_pressed_status[0];
    Last_key_pressed_status[1] = key_pressed_status[1];
    Last_key_pressed_status[2] = key_pressed_status[2];
    Last_key_pressed_status[3] = key_pressed_status[3];
    Last_key_pressed_status[4] = key_pressed_status[4];
    Last_key_pressed_status[5] = key_pressed_status[5];

}

/* RGB LED Initialization */
esp_err_t Rmt_init(uint8_t gpio_num, int led_number, uint8_t rmt_channel)
{
    ESP_LOGI(TAG, "Initializing WS2812");
    rmt_config_t config = RMT_DEFAULT_CONFIG_TX(gpio_num, rmt_channel);

    /*!< set counter clock to 40MHz */
    config.clk_div = 2;

    ESP_ERROR_CHECK(rmt_config(&config));
    ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));

    led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(led_number, (led_strip_dev_t)config.channel);
    strip = led_strip_new_rmt_ws2812(&strip_config);

    if (!strip) {
        ESP_LOGE(TAG, "install WS2812 driver failed");
        return ESP_FAIL;
    }

    /*!< Clear LED strip (turn off all LEDs) */
    ESP_ERROR_CHECK(strip->clear(strip, 100));
    /*!< Show simple rainbow chasing pattern */

    return ESP_OK;
}

/* led task */
void led_task(void *arg)
{
    static unsigned char LED_change_count1 = 0u;
    static unsigned char LED_change_count2 = 0u;
    static unsigned char LED_change_count3 = 0u;

    /*!< WS2812 init*/
    ESP_ERROR_CHECK(Rmt_init(45, 4, RMT_CHANNEL_0));
    ESP_ERROR_CHECK(strip->set_pixel(strip, 0, 0, 0, 0));

    while (1) {
        if((LED_change_count1 != 255)
            && (LED_change_count2 == 0)
            && (LED_change_count3 == 0))
        {
            LED_change_count1 ++;
        }else if((LED_change_count1 == 255)
            && (LED_change_count2 != 255)
            && (LED_change_count3 == 0))
        {
            LED_change_count2 ++;
        }else if((LED_change_count1 == 255)
            && (LED_change_count2 == 255)
            && (LED_change_count3 != 255))
        {
            LED_change_count3 ++;
        }else if((LED_change_count1 != 0)
            && (LED_change_count2 == 255)
            && (LED_change_count3 == 255))
        {
            LED_change_count1 --;
        }else if((LED_change_count1 == 0)
            && (LED_change_count2 != 0)
            && (LED_change_count3 == 255))
        {
            LED_change_count2 --;
        }else if((LED_change_count1 == 0)
            && (LED_change_count2 == 0)
            && (LED_change_count3 != 0))
        {
            LED_change_count3 --;
        }else
        {
            
        }
        
        ESP_LOGI(TAG, "R-%d,G-%d,B-%d", LED_change_count1, LED_change_count2, LED_change_count3);
        ESP_ERROR_CHECK(strip->set_pixel(strip, 0, LED_change_count1, LED_change_count2, LED_change_count3));
        ESP_ERROR_CHECK(strip->refresh(strip, 0));
        
        vTaskDelay(pdMS_TO_TICKS(10));
    }

    vTaskDelete(NULL);
}

/* Cmera task */
static void cam_task(void *arg)
{
    cam_config_t cam_config = {
        .bit_width    = 8,
#ifdef CONFIG_CAMERA_JPEG_MODE
        .mode.jpeg    = 1,
#else
        .mode.jpeg    = 0,
#endif
        .xclk_fre     = 16 * 1000 * 1000,
        .pin  = {
            .xclk     = CAM_XCLK,
            .pclk     = CAM_PCLK,
            .vsync    = CAM_VSYNC,
            .hsync    = CAM_HSYNC,
        },
        .pin_data     = {CAM_D0, CAM_D1, CAM_D2, CAM_D3, CAM_D4, CAM_D5, CAM_D6, CAM_D7},
        .vsync_invert = true,
        .hsync_invert = false,
        .size = {
            .width    = CAM_WIDTH,
            .high     = CAM_HIGH,
        },
        .max_buffer_size = 8 * 1024,
        .task_stack      = 1024,
        .task_pri        = configMAX_PRIORITIES
    };

    /*!< With PingPang buffers, the frame rate is higher, or you can use a separate buffer to save memory */
    cam_config.frame1_buffer = (uint8_t *)heap_caps_malloc(CAM_WIDTH * CAM_HIGH * 2 * sizeof(uint8_t), MALLOC_CAP_SPIRAM);
    cam_config.frame2_buffer = (uint8_t *)heap_caps_malloc(CAM_WIDTH * CAM_HIGH * 2 * sizeof(uint8_t), MALLOC_CAP_SPIRAM);

    cam_init(&cam_config);

    sensor_t sensor;
    int camera_version = 0;      /*!<If the camera version is determined, it can be set to manual mode */
    SCCB_Init(CAM_SDA, CAM_SCL);
    sensor.slv_addr = SCCB_Probe();
    ESP_LOGI(TAG, "sensor_id: 0x%x\n", sensor.slv_addr);

#ifdef CONFIG_CAMERA_OV2640
    camera_version = 2640;
#endif
#ifdef CONFIG_CAMERA_OV3660
    camera_version = 3660;
#endif
#ifdef CONFIG_CAMERA_AUTO
    /*!< If you choose this mode, Dont insert the Audio board, audio will affect the camera register read. */
#endif
    if (sensor.slv_addr == 0x30 || camera_version == 2640) { /*!< Camera: OV2640 */
        ESP_LOGI(TAG, "OV2640 init start...");

        if (OV2640_Init(0, 1) != 0) {
            goto fail;
        }

        if (cam_config.mode.jpeg) {
            OV2640_JPEG_Mode();
        } else {
            OV2640_RGB565_Mode(false);	/*!< RGB565 mode */
        }

        OV2640_ImageSize_Set(800, 600);
        OV2640_ImageWin_Set(0, 0, 800, 600);
        OV2640_OutSize_Set(CAM_WIDTH, CAM_HIGH);
    } else if (sensor.slv_addr == 0x3C || camera_version == 3660) { /*!< Camera: OV3660 */

        sensor.slv_addr = 0x3C; /*!< In special cases, slv_addr may change */
        ESP_LOGI(TAG, "OV3660 init start...");
        ov3660_init(&sensor);
        sensor.init_status(&sensor);

        if (sensor.reset(&sensor) != 0) {
            goto fail;
        }

        if (cam_config.mode.jpeg) {
            sensor.set_pixformat(&sensor, PIXFORMAT_JPEG);
        } else {
            sensor.set_pixformat(&sensor, PIXFORMAT_RGB565);
        }

        /*!< TotalX gets smaller, frame rate goes up */
        /*!< TotalY gets smaller, frame rate goes up, vsync gets shorter */
        sensor.set_res_raw(&sensor, 0, 0, 2079, 1547, 8, 2, 1920, 800, CAM_WIDTH, CAM_HIGH, true, true);
        sensor.set_vflip(&sensor, 1);
        sensor.set_hmirror(&sensor, 1);
        sensor.set_pll(&sensor, false, 15, 1, 0, false, 0, true, 5); /*!< ov3660: 39 fps */
    } else {
        ESP_LOGE(TAG, "sensor is temporarily not supported\n");
        goto fail;
    }

    ESP_LOGI(TAG, "camera init done\n");
    cam_start();

    while (1) {
        uint8_t *cam_buf = NULL;
        cam_take(&cam_buf);
#ifdef CONFIG_CAMERA_JPEG_MODE

        int w, h;
        uint8_t *img = jpeg_decode(cam_buf, &w, &h);

        if (img) {
            ESP_LOGI(TAG, "jpeg: w: %d, h: %d\n", w, h);
            lcd_set_index(0, 0, w - 1, h - 1);
            lcd_write_data(img, w * h * sizeof(uint16_t));
            free(img);
        }

#else
        lcd_set_index(0, 0, CAM_WIDTH - 1, CAM_HIGH - 1);
        lcd_write_data(cam_buf, CAM_WIDTH * CAM_HIGH * 2);
#endif
        cam_give(cam_buf);
        /*!< Use a logic analyzer to observe the frame rate */
        gpio_set_level(LCD_BK, 1);
        gpio_set_level(LCD_BK, 0);
    }

fail:
    free(cam_config.frame1_buffer);
    free(cam_config.frame2_buffer);
    cam_deinit();
    vTaskDelete(NULL);
}

/*start display show*/
static void start_display(void)
{
    lcd_config_t lcd_config = {
#ifdef CONFIG_LCD_ST7789
        .clk_fre         = 80 * 1000 * 1000, /*!< ILI9341 Stable frequency configuration */
#endif
#ifdef CONFIG_LCD_ILI9341
        .clk_fre         = 40 * 1000 * 1000, /*!< ILI9341 Stable frequency configuration */
#endif
        .pin_clk         = LCD_CLK,
        .pin_mosi        = LCD_MOSI,
        .pin_dc          = LCD_DC,
        .pin_cs          = LCD_CS,
        .pin_rst         = LCD_RST,
        .pin_bk          = LCD_BK,
        .max_buffer_size = 2 * 1024,
        .horizontal      = 2 /*!< 2: UP, 3: DOWN */
    };

    lcd_init(&lcd_config);

    ESP_LOGI(TAG, "My Project Start ....");
    esp_vfs_spiffs_conf_t conf = {
        .base_path = "/spiffs",
        .partition_label = NULL,
        .max_files = 5,
        .format_if_mount_failed = false
    };

    /*!< Use settings defined above to initialize and mount SPIFFS filesystem. */
    /*!< Note: esp_vfs_spiffs_register is an all-in-one convenience function. */
    ESP_ERROR_CHECK(esp_vfs_spiffs_register(&conf));
    size_t total = 0, used = 0;
    ESP_ERROR_CHECK(esp_spiffs_info(NULL, &total, &used));

    uint8_t *img = NULL;
    uint8_t *buf = malloc(IMAGE_MAX_SIZE);
    int read_bytes = 0;
    int width = 0, height = 0;

    FILE *fd = fopen("/spiffs/1.jpg", "r");

    read_bytes = fread(buf, 1, IMAGE_MAX_SIZE, fd);
    ESP_LOGI(TAG, "spiffs:read_bytes:%d  fd: %p", read_bytes, fd);
    fclose(fd);

    img = jpeg_decode(buf, &width, &height);
    lcd_set_index(0, 0, IMAGE_WIDTH - 1, IMAGE_HIGHT - 1);
    lcd_write_data(img, IMAGE_WIDTH * IMAGE_HIGHT * sizeof(uint16_t));
    free(buf);
    vTaskDelay(2000 / portTICK_RATE_MS);
}
/******** End Function Definition  ********/

 

Kconfig.probuild文件,这个文件是mebuconfig的例程配置文件:

menu "Example Configuration"
  
    choice CAMERA_PAD_TYPE
        prompt "camera pad type"
        default CAMERA_PAD_ESP32_S2_KALUGA_V1_3
        config CAMERA_PAD_ESP32_S2_KALUGA_V1_3
            bool "ESP32-S2-KALUGA_V1.3"
        config CAMERA_PAD_ESP32_S2_KALUGA_V1_2
            bool "ESP32-S2-KALUGA_V1.2"
        config CAMERA_PAD_ESP32_S2_KALUGA_V1_1
            bool "ESP32-S2-KALUGA_V1.1"
    endchoice

    choice LCD_PAD_TYPE
       prompt "LCD pad type"
        default LCD_PAD_ESP32_S2_KALUGA_V1_3
        config LCD_PAD_ESP32_S2_KALUGA_V1_3
            bool "ESP32-S2-KALUGA_V1.3"
        config LCD_PAD_ESP32_S2_KALUGA_V1_2
            bool "ESP32-S2-KALUGA_V1.2"
        config LCD_PAD_ESP32_S2_KALUGA_V1_1
            bool "ESP32-S2-KALUGA_V1.1"
    endchoice

    choice CAMERA_VERSION
        prompt "Camera version"
        default CAMERA_OV2640
        config CAMERA_OV2640
            bool "OV2640"
        config CAMERA_OV3660
            bool "OV3660"
        config CAMERA_AUTO
            bool "Auto (If you choose this mode, Dont insert the Audio board!)"
        help
            Set camera version
    endchoice

    choice LCD_VERSION
        prompt "LCD version"
        default ILI9341
        config LCD_ST7789
            bool "ST7789"
        config LCD_ILI9341
            bool "ILI9341"
        help
            Set LCD version
    endchoice
        
    config  CAMERA_JPEG_MODE
        bool "jpeg mode"
        
endmenu

 

CmakeLists.txt文件:

# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)

set(EXTRA_COMPONENT_DIRS "../../components/board"
                         "../../components/lcd"
                         "../../components/jpeg"
                         "../../components/cam"
                         "../../components/sensors"
                         "../../components/led_strip"
)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)
add_compile_options (-fdiagnostics-color=always)
project(esp32-s2-hmi)

 

然后使用终端进入工程文件夹,设置环境变量:. $HOME/esp/esp-idf/export.sh

设置编译类型以及进入menuconfig进行配置:idf.py set-target esp32s2 menuconfig

设置如下:

6.jpg

 

编译:idf.py build

下载:idf.py -p /dev/ttyUSB1 flash

监控:idf.py -p /dev/ttyUSB1 monitor

收工

 

 

 


回复
您需要登录后才可以回帖 登录 | 注册

最新文章 更多>>
    关闭
    站长推荐上一条 1/4 下一条

    About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

    站点相关: 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

    北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

    电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2020 EEWORLD.com.cn, Inc. All rights reserved
    快速回复 返回顶部 返回列表