Qt+ESP32+SQLite 智能大棚

环境简介

硬件环境

ESP32、光照传感器、温湿度传感器、继电器、蜂鸣器

基本工作流程

  1. 上位机先运行,下位机启动后尝试连接上位机
  2. 连接成功后定时上报传感器数据到上位机,上位机将信息进行处理展示
  3. 判断下位机传感器数据,如果超过设置的阈值,则下发控制命令控制下位机硬件
  4. 点击上位机控制按钮,即可下发控制指令控制硬件

上位机运行效果

硬件连接图

DHT11 温湿度传感器

接线图

VCC 3V3

GND GND

DATA GPIO21(D21)

读取代码

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "sdkconfig.h"

#define DHT11_PIN     (21)   //可通过宏定义,修改引脚

#define DHT11_CLR     gpio_set_level(DHT11_PIN, 0) 
#define DHT11_SET     gpio_set_level(DHT11_PIN, 1) 
#define DHT11_IN      gpio_set_direction(DHT11_PIN, GPIO_MODE_INPUT)
#define DHT11_OUT     gpio_set_direction(DHT11_PIN, GPIO_MODE_OUTPUT)

uint8_t DHT11Data[4]={0};
uint8_t Temp, Humi;

//us延时函数,误差不能太大
void DelayUs(  uint32_t nCount)  
{
    ets_delay_us(nCount);
}  

void DHT11_Start(void)
{ 
  DHT11_OUT;      //设置端口方向
  DHT11_CLR;      //拉低端口  
  DelayUs(19*1000);   
//   vTaskDelay(19 * portTICK_RATE_MS); //持续最低18ms;

  DHT11_SET;      //释放总线
  DelayUs(30);    //总线由上拉电阻拉高,主机延时30uS;
  DHT11_IN;       //设置端口方向

  while(!gpio_get_level(DHT11_PIN));   //DHT11等待80us低电平响应信号结束
  while(gpio_get_level(DHT11_PIN));//DHT11   将总线拉高80us
}

uint8_t DHT11_ReadValue(void)
{ 
  uint8_t i,sbuf=0;
  for(i=8;i>0;i--)
  {
    sbuf<<=1; 
    while(!gpio_get_level(DHT11_PIN));
    DelayUs(30);                        // 延时 30us 后检测数据线是否还是高电平 
    if(gpio_get_level(DHT11_PIN))
    {
      sbuf|=1;  
    }
    else
    {
      sbuf|=0;
    }
    while(gpio_get_level(DHT11_PIN));
  }
  return sbuf;   
}

uint8_t DHT11_ReadTemHum(uint8_t *buf)
{
  uint8_t check;

  buf[0]=DHT11_ReadValue();
  buf[1]=DHT11_ReadValue();
  buf[2]=DHT11_ReadValue();
  buf[3]=DHT11_ReadValue();
    
  check =DHT11_ReadValue();

  if(check == buf[0]+buf[1]+buf[2]+buf[3])
    return 1;
  else
    return 0;
} 

void app_main(void)
{
    printf("ESP32 DHT11 TEST:%s,%s!\r\n",__DATE__,__TIME__);
    gpio_pad_select_gpio(DHT11_PIN);
    while(1) {
        DHT11_Start();
        if(DHT11_ReadTemHum(DHT11Data))
        {
            Temp=DHT11Data[2];
            Humi=DHT11Data[0];      
            printf("Temp=%d, Humi=%d\r\n",Temp,Humi);
        }
        else
        {
            printf("DHT11 Error!\r\n");
        }
        vTaskDelay(1000);	//目前10s读取一次
    }
}

TEMT6000

接线图

VCC VCC

GND GND

OUT GPIO34(D34)

读取代码

#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

// ADC所接的通道  GPIO34 if ADC1  = ADC1_CHANNEL_6
#define ADC1_TEST_CHANNEL ADC1_CHANNEL_6 
// ADC斜率曲线
static esp_adc_cal_characteristics_t *adc_chars;
// 参考电压
#define DEFAULT_VREF				3300			//使用adc2_vref_to_gpio()获得更好的估计值


void check_efuse(void)
{
    //检查TP是否烧入eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
        printf("eFuse Two Point: Supported\n");
    } else {
        printf("eFuse Two Point: NOT supported\n");
    }
    //检查Vref是否烧入eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
        printf("eFuse Vref: Supported\n");
    } else {
        printf("eFuse Vref: NOT supported\n");
    }
}
void adc_init(void)
{
  adc1_config_width(ADC_WIDTH_BIT_12);// 12位分辨率
	adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_DB_11);// 电压输入衰减
  adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));	// 为斜率曲线分配内存
  esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
 // print_char_val_type(val_type);
}
void app_main(void)
{
  uint32_t read_raw;
  check_efuse();
	adc_init();
	while(1){
		read_raw = adc1_get_raw(ADC1_TEST_CHANNEL);// 采集ADC原始值//这里可以多次采样取平均值
		uint32_t voltage = esp_adc_cal_raw_to_voltage(read_raw, adc_chars);//通过一条斜率曲线把读取adc1_get_raw()的原始数值转变成了mV
		printf("ADC原始值: %d   转换电压值: %dmV\n", read_raw, voltage);
		vTaskDelay(1000 / portTICK_RATE_MS);
	}
}

延时1s

  • 1200 手电筒1档
  • 2688 手电筒2档
  • 4079 手电筒3档

烟雾传感器

接线图

3V3

VCC

GND

GND

DO

GPIO15

AO

GPIO2

读取代码

/* ADC1 Example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"

#define DEFAULT_VREF    1100        //Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES   64          //Multisampling

static esp_adc_cal_characteristics_t *adc_chars;
#if CONFIG_IDF_TARGET_ESP32
static const adc_channel_t channel = ADC_CHANNEL_6;     //GPIO34 if ADC1, GPIO14 if ADC2
static const adc_bits_width_t width = ADC_WIDTH_BIT_12;
#elif CONFIG_IDF_TARGET_ESP32S2
static const adc_channel_t channel = ADC_CHANNEL_6;     // GPIO7 if ADC1, GPIO17 if ADC2
static const adc_bits_width_t width = ADC_WIDTH_BIT_13;
#endif
static const adc_atten_t atten = ADC_ATTEN_DB_0;
static const adc_unit_t unit = ADC_UNIT_1;


static void check_efuse(void)
{
#if CONFIG_IDF_TARGET_ESP32
    //Check if TP is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
        printf("eFuse Two Point: Supported\n");
    } else {
        printf("eFuse Two Point: NOT supported\n");
    }
    //Check Vref is burned into eFuse
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
        printf("eFuse Vref: Supported\n");
    } else {
        printf("eFuse Vref: NOT supported\n");
    }
#elif CONFIG_IDF_TARGET_ESP32S2
    if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
        printf("eFuse Two Point: Supported\n");
    } else {
        printf("Cannot retrieve eFuse Two Point calibration values. Default calibration values will be used.\n");
    }
#else
#error "This example is configured for ESP32/ESP32S2."
#endif
}


static void print_char_val_type(esp_adc_cal_value_t val_type)
{
    if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
        printf("Characterized using Two Point Value\n");
    } else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
        printf("Characterized using eFuse Vref\n");
    } else {
        printf("Characterized using Default Vref\n");
    }
}


void app_main(void)
{
    //Check if Two Point or Vref are burned into eFuse
    check_efuse();

    //Configure ADC
    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);
    }

    //Characterize ADC
    adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
    esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, width, DEFAULT_VREF, adc_chars);
    print_char_val_type(val_type);

    //Continuously sample ADC1
    while (1) {
        uint32_t adc_reading = 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;
        //Convert adc_reading to voltage in mV
        uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
        printf("Raw: %d\tVoltage: %dmV\n", adc_reading, voltage);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

蜂鸣器

接线图

VCC VCC

GND GND

I/O D2(GPIO2)

设置代码

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "driver/gpio.h"
 
#define LED_PIN 2
 
 
void app_main(void)
{
     gpio_reset_pin(LED_PIN);                         //引脚复位
     gpio_pad_select_gpio(LED_PIN);                   //GPIO引脚功能选择
     gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);   //设置方向为输出
     while (1)
     {
        gpio_set_level(LED_PIN,1);                    //设置LED_PIN为高电平
        sleep(1);
        gpio_set_level(LED_PIN,0);                    //设置LED_PIN为低电平
        sleep(1);
     }
}

继电器

DC+(VCC) 接 1口

DC- (GND)接 6 口

IN1 接 7 口

系统整体代码

Github仓库地址

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Qt 和 VS 使用 SQLite 数据库的步骤如下: 1. 在 Qt 中添加 SQLite 驱动程序。可以通过 Qt Maintenance 工具来完成。打开 Qt Maintenance 工具,选择“添加或删除组件”,在“Qt”下找到“Qt版本”,选择“Qt 5.15.0”(或者其他版本),在右侧的“Qt 5.15.0”区域里勾选“Qt SQL”,然后点击“安装”按钮。 2. 在 Qt 项目中添加 SQLite 的头文件和库文件。在 Qt 项目中的 .pro 文件中添加以下代码: ``` QT += sql LIBS += -lsqlite3 ``` 3. 在 Qt 项目中使用 QSqlDatabase 类连接 SQLite 数据库。可以在 main 函数中添加以下代码: ``` #include <QtSql/QSqlDatabase> #include <QtSql/QSqlQuery> int main(int argc, char *argv[]) { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("mydatabase.db"); if (!db.open()) { qDebug() << "Cannot open database"; return 1; } QSqlQuery query; query.exec("CREATE TABLE IF NOT EXISTS mytable (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)"); query.exec("INSERT INTO mytable (name) VALUES ('John')"); query.exec("INSERT INTO mytable (name) VALUES ('Jane')"); query.exec("SELECT * FROM mytable"); while (query.next()) { int id = query.value(0).toInt(); QString name = query.value(1).toString(); qDebug() << QString("id=%1, name=%2").arg(id).arg(name); } db.close(); return 0; } ``` 这段代码会创建一个名为“mydatabase.db”的 SQLite 数据库文件,并在其中创建一个名为“mytable”的表格,然后插入两条记录(John 和 Jane),最后查询表格中的所有记录,并输出到控制台。 4. 编译并运行 Qt 项目。在 VS 中编译并运行 Qt 项目,可以看到控制台输出了两条记录(John 和 Jane)。 以上就是使用 Qt 和 VS 使用 SQLite 数据库的基本步骤。需要注意的是,在实际开发中,可能需要更加复杂的操作,比如使用 QSqlTableModel 类来操作数据库表格,使用 QSqlRelationalTableModel 类来操作多个相关表格等等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值