ESP32CAM使用Quirc识别二维码并连接WIFI

ESP32CAM使用Quirc识别二维码并连接WIFI

网上有教程,但是是要做出来很难,或者说做出来报错识别不了。

前提:搭建好ESP-IDF环境 CAMERA能成功初始化

此处用的二维码识别库是用的quirc,如下

这个和Github下载的差不多,加了个CMakeList,我会把这个传到我的Github上,感兴趣去下载Lesterbor/ESP32-QUIRC: 对ESP32CAM的二维码识别 (github.com)

下载到这个包之后放到自己工程目录下的components文件夹下,之后在main文件夹中新建app_qrcode.c这个文件,其内容如下

复制代码
copy
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : app_qrcode.c
  * @brief          : app_qrcode驱动库
  * @author         :「千樊」
  * @time           : 2024/03/03
  ******************************************************************************
  * @attention
  *
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/

    #include "app_qrcode.h"

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */

   uint8_t dump_info(struct quirc *q, uint8_t count, char *WifiStrBuff);

/* USER CODE END PV */

/* Function definition -------------------------------------------------------*/
/* USER CODE BEGIN FD */

/**
  * @Function name  QF_Camera_Init
  * @Introduce      Camera初始化
  * @Return         NULL
  */
uint8_t QF_QrReadWifiData(char *WifiStrBuff){

    camera_config_t *camera_config = (camera_config_t *)esp_camera_fb_get();

    // Save image width and height, avoid allocate memory repeatly.
    uint16_t old_width = 0;
    uint16_t old_height = 0;
    struct quirc *qr_recognizer;

    camera_fb_t *fb = NULL;
    uint8_t *image = NULL;
    int id_count = 0;

    //判断当前摄像头输出画幅
    if (camera_config->frame_size > FRAMESIZE_VGA) {
        printf("Camera Frame Size err %d", (camera_config->frame_size));
    }

    //构造一个二维码识别器
    printf("Construct a new QR-code recognizer(quirc).");
    qr_recognizer = quirc_new();
    if (!qr_recognizer) {
        printf("Can't create quirc object\r\n");
    }

    //获取不到正确结果不退出
    while (1) {
        fb = esp_camera_fb_get();
        if (!fb) {
            printf("Camera capture failed\r\n");
            continue;
        }

        if (old_width != fb->width || old_height != fb->height) {
            printf("Recognizer size change w h len: %d, %d, %d\r\n", fb->width, fb->height, fb->len);
            printf("Resize the QR-code recognizer.\r\n");
            // Resize the QR-code recognizer.
            if (quirc_resize(qr_recognizer, fb->width, fb->height) < 0) {
                printf("Resize the QR-code recognizer err.\r\n");
                continue;
            } else {
                old_width = fb->width;
                old_height = fb->height;
            }
        }

        image = quirc_begin(qr_recognizer, NULL, NULL);
        memcpy(image, fb->buf, fb->len);
        quirc_end(qr_recognizer);

        // Return the number of QR-codes identified in the last processed image.
        id_count = quirc_count(qr_recognizer);
        if (id_count == 0) {
            printf("..||");
            esp_camera_fb_return(fb);
            continue;
        }
        printf("\n");
        esp_camera_fb_return(fb);
        //判断解析是否成功 如果成功则返回true并且此时WifiStrBuff有效
        if(dump_info(qr_recognizer, id_count, WifiStrBuff)){
            return true;
        }
    }
    quirc_destroy(qr_recognizer);
}

uint8_t dump_info(struct quirc *q, uint8_t count, char *WifiStrBuff){
    for (int i = 0; i < count; i++) {
        struct quirc_code code;
        struct quirc_data data;

        quirc_extract(q, i, &code);

        quirc_decode_error_t err = quirc_decode(&code, &data);

        if (err) {
            printf("Decoding error:\n");
            return false;
        } else {
            printf("Decoding successful:\n");
            memcpy(WifiStrBuff, data.payload, data.payload_len); 
            return true;
        }
        printf("\n");
    }
    return false;
}
/* USER CODE END FD */
/************************ (C) COPYRIGHT 「千樊」 *****END OF FILE****/
复制代码

之后再main/inlcude文件夹下新建app_qrcode.h其内容如下

复制代码
copy
/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : app_qrcode.h
  * @brief          : Header for app_qrcode.c file.
  *                   This file provides code for the configuration
  *                   of the app_qrcode instances
  * @author         : 「千樊」
  * @time           : 2024/03/03
  ******************************************************************************
  * @attention
  *
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __APP_QRCODE_H_
#define __APP_QRCODE_H_

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

  #include <stdio.h>
  #include <stdlib.h>
  #include <string.h>

  #include "freertos/FreeRTOS.h"
  #include "freertos/task.h"
  #include "esp_camera.h"
  #include "quirc.h"

/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PT */


/* USER CODE END PT */
/* Exported functions prototypes ---------------------------------------------*/
/* USER CODE BEGIN EFP */

    uint8_t QF_QrReadWifiData(char *WifiStrBuff);

/* USER CODE END EFP */

#endif /* __APP_QRCODE_H_ */
/************************ (C) COPYRIGHT 「千樊」 *****END OF FILE*************/
复制代码

之后再main文件夹中的CMakeList.txt中注册组件引用app_qrcode.c,如下图所示

 ok这样我们就可以调用QF_QrReadWifiData该函数来获取二维码解析之后的字符串,在main中声明以下函数即可解析扫描到的Wifi信息

复制代码
copy
void parse_string(const char *input, char *ssid, char *password) {  
    // 寻找SSID开始的位置  
    char *ssid_start = strstr(input, "S:");  
    if (ssid_start) {  
        ssid_start += 2; // 跳过 "S:"  
  
        // 寻找SSID结束的位置,即下一个分号  
        char *ssid_end = strchr(ssid_start, ';');  
        if (ssid_end) {  
            // 提取SSID  
            size_t ssid_len = ssid_end - ssid_start;  
            strncpy(ssid, ssid_start, ssid_len);  
            ssid[ssid_len] = '\0'; // 确保字符串以null字符结尾  
        }  
    }  
  
    // 寻找密码开始的位置  
    char *password_start = strstr(input, "P:");  
    if (password_start) {  
        password_start += 2; // 跳过 "P:"  
  
        // 寻找密码结束的位置,即下一个分号  
        char *password_end = strchr(password_start, ';');  
        if (password_end) {  
            // 提取密码  
            size_t password_len = password_end - password_start;  
            strncpy(password, password_start, password_len);  
            password[password_len] = '\0'; // 确保字符串以null字符结尾  
        }  
    }  
}  

void QF_WifiQrConfig(void){
    uint8_t userWifiStrBuff[100] = {0};
    QF_QrReadWifiData(&userWifiStrBuff);
    printf("---M---:WifiBuffStr:%s\r\n",userWifiStrBuff);

    parse_string(&userWifiStrBuff,&wifi_config.sta.ssid,&wifi_config.sta.password);
    printf("---M---:WIFI SSID:%s\r\n",wifi_config.sta.ssid);
    printf("---M---:WIFI PASS:%s\r\n",wifi_config.sta.password);

    QF_WifiLink(wifi_config);
}
复制代码

对了wifi_config这个变量需要你自己定义以下,这个变量可以直接传给esp_wifi_set_config,之后调用esp_wifi_start即可开始连接WIFI

当然,需要你自己理解去写,直接复制应该是有部分报错的,理解之后什么都就好写了。

这里说一下过程中遇到的坑

1.初始化的时候不要翻转图像,也就是不要执行这句话s->set_vflip(s, 1);,需要把1改成0,因为该二维码识别库不支持镜像

2.图像格式必须为灰度图像也就是.pixel_format = PIXFORMAT_GRAYSCALE,该库只能识别灰度图像

3.图像大小设置为640*480,也就是.frame_size = FRAMESIZE_VGA,其他的可能应该也行?我使用的是该大小所以其他的也没试

 

本文作者:千樊

本文链接:https://www.cnblogs.com/lesterbor/p/18054809

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

转载请注明出处

改编代码请注明原作者

posted @   千樊  阅读(910)  评论(0编辑  收藏  举报
 
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起