基于Dragonboard 410c的燃气烟雾检测器(三)

2024-03-09 10:48

本文主要是介绍基于Dragonboard 410c的燃气烟雾检测器(三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  燃气烟雾检测模块MQ-2在上篇博客中已经写好了,接下来是温湿度检测模块dht11了,模块信息在前面已经介绍过了,这里就不再赘述了,直接看程序:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/workqueue.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/serio.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/clk.h>
#include <linux/wait.h>
#include <linux/sched.h>
#include <linux/cdev.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/of_gpio.h>
#include <linux/delay.h>
#include <linux/printk.h>
#include <linux/time.h>
#include <linux/irq.h>
#include <asm-generic/uaccess.h>
 
#define DEVICE_NAME "dht11"
#define DEVICE_MAJOR 0
 
struct dht11_sensor_dev{
    int pin;
    unsigned char value[5];
    int signal;
    int time;
    int count;
    dev_t devno;
    struct class *dht11_class;
    struct cdev cdev;
    struct mutex read_data;
    struct timeval lasttv;
    struct timeval tv;
    struct work_struct dht11_work;
};
 
static struct dht11_sensor_dev *dht11_dev;
 
static int read_byte(void){
        unsigned char data;
        int i = 0;
    for(i = 0; i < 8; i++){
        while(!gpio_get_value(dht11_dev->pin));
        udelay(30);
        data <<= 1;
        if(gpio_get_value(dht11_dev->pin) == 1){
            data |=0x01;
            while(gpio_get_value(dht11_dev->pin));
        }else{
            data |=0x00;
        }        
    }
    return data;
}
 
static void dht11_read(void){
 
    int i = 0;
 
    dht11_dev->signal = gpio_get_value(dht11_dev->pin);
    if(dht11_dev->signal == 0){
        while(!gpio_get_value(dht11_dev->pin));
        while(gpio_get_value(dht11_dev->pin));
        for(i = 0; i < 5; i++){
            dht11_dev->value[i] = read_byte();
        }
    }
}
 
static int dht11_start(void)
{
    gpio_direction_output(dht11_dev->pin, 0);    
    msleep(20);
    gpio_set_value(dht11_dev->pin,1);
    udelay(20);
    gpio_direction_input(dht11_dev->pin);
    do_gettimeofday(&dht11_dev->lasttv);
    dht11_dev->count=0;
    return 0;
}
 
 
static int dht11_checksum(struct dht11_sensor_dev *dev)
{
    int tmp = 0;
    tmp = dev->value[0] + dev->value[1] + dev->value[2] + dev->value[3];
    
 
    if((tmp != dev->value[4]) || (dev->value[4] == 0) || (tmp == 0) ){
        printk(KERN_INFO "[%s] %d %d\n", __func__, dev->value[4], tmp);
        return -1;
    }
    return 1;
}
 
static int dht11_sensor_open(struct inode *inode, struct file *filp)
{
    printk("dht11_sensor_open\n");    
    return 0;
}
 
static ssize_t dht11_sensor_read(struct file *filp,char __user *buf,size_t  
size,loff_t *f_pos)
{
    int result = 0;
    dht11_dev->value[0] = 0;
    dht11_dev->value[1] = 0;
    dht11_dev->value[2] = 0;
    dht11_dev->value[3] = 0;
    dht11_dev->value[4] = 0;
 
    printk("dht11_sensor_read\n");
    dht11_start();
    dht11_read();
    msleep(10);
    result=dht11_checksum(dht11_dev);
    if(result<0)
            return -EAGAIN;  
 
    printk("---Humidity=%d.%d%%RH\n---Temperature=%d.%dC\n",\
            dht11_dev->value[0], dht11_dev->value[1], \
            dht11_dev->value[2], dht11_dev->value[3]);
    result=copy_to_user(buf,&dht11_dev->value,4);
    if(result<0)
    {
         printk("copy to user err\n");
         return -EAGAIN;
    }  
    return  result;            
}
 
static int dht11_sensor_release(struct inode *inode,struct file *filp)
{
    module_put(THIS_MODULE);
    return 0;
}
 
static struct file_operations dht11_sensor_fops={
    .owner   = THIS_MODULE,
    .open    = dht11_sensor_open,
    .read    = dht11_sensor_read,
    .release = dht11_sensor_release,
};
 
//static int dht11_gpio_init(void)
static int parse_dt (struct platform_device *pdev,struct dht11_sensor_dev *data){
    int result;
    struct device_node *node = pdev->dev.of_node;
    data->pin = of_get_named_gpio(node,"thunder,gpio_data",0);
    if(gpio_is_valid(data->pin)){
    result=gpio_request(data->pin, "dht11_gpio");
    if(result)
    {
        printk(KERN_INFO "[%s] gpio_request \n", __func__);
        return -1;
    }
    gpio_direction_output(data->pin,1);
    }
    return 0;
}
 
 
static int dht11_sensor_setup_cdev(void)
{
    int ret;
    cdev_init(&(dht11_dev->cdev), &dht11_sensor_fops);
    dht11_dev->cdev.owner = THIS_MODULE;
    ret=cdev_add(&(dht11_dev->cdev),dht11_dev->devno, 1);
    if(ret)
    {
        printk(KERN_NOTICE"erro %d adding %s\n",ret,DEVICE_NAME);
    }
    return ret;
}
 
static int dht11_probe(struct platform_device *pdev){
    int result;
    dht11_dev=kmalloc(sizeof(struct dht11_sensor_dev),GFP_KERNEL);
    if(!dht11_dev)
    {
        result=-ENOMEM;
        goto allocate_memory_fail;
    }
    if(DEVICE_MAJOR)
    {
        result = register_chrdev_region(dht11_dev->devno, 1, DEVICE_NAME);
    }
    else
    {
        result = alloc_chrdev_region(&dht11_dev->devno, 0, 1, DEVICE_NAME);
    }
    if(result < 0)
    {
        printk("register_chrdev_region err!\n");
        goto chardev_region_fail;
    }
    dht11_dev->dht11_class = class_create(THIS_MODULE, DEVICE_NAME);
    if(IS_ERR(dht11_dev->dht11_class))
    {
             printk("Err: failed in creating class.\n");
             goto class_create_fail;
    }  
    device_create(dht11_dev->dht11_class, NULL,dht11_dev->devno, NULL,  
DEVICE_NAME);
    result = parse_dt(pdev,dht11_dev);
    if(result<0)
        goto gpio_request_fail;
    result=dht11_sensor_setup_cdev();
    if(result<0)
        goto cdev_fail;
    mutex_init(&dht11_dev->read_data);
    printk("dht11 init ok!\n");
    return 0;
    
gpio_request_fail:
    cdev_del(&dht11_dev->cdev);
cdev_fail:
    device_destroy(dht11_dev->dht11_class,dht11_dev->devno);
    class_destroy(dht11_dev->dht11_class);
class_create_fail:
    unregister_chrdev_region(dht11_dev->devno,1);
chardev_region_fail:
allocate_memory_fail:
    kfree(dht11_dev);
    return result;
}
 
static int dht11_remove(struct platform_device *pdev)
{
    cdev_del(&dht11_dev->cdev);
    device_destroy(dht11_dev->dht11_class,dht11_dev->devno);
    class_destroy(dht11_dev->dht11_class);    
    unregister_chrdev_region(dht11_dev->devno, 1);
    kfree(dht11_dev);
 
    return 0;
}
 
static struct of_device_id dht11_match_table[] = {
    { .compatible = "thunder,dht11",},
    { },
};
 
static struct platform_driver dht11_driver = {
 
    .probe = dht11_probe,
    .remove = dht11_remove,
    .driver = {
        .owner = THIS_MODULE,
        .name = DEVICE_NAME,
        .of_match_table = dht11_match_table,
    },
};
 
module_platform_driver(dht11_driver);
 
MODULE_AUTHOR("wi");
MODULE_DESCRIPTION("DHT11 Driver");
MODULE_LICENSE("GPL");


这个模块用的是单总线,所以时序要特别注意一下,设备节点:/dev/dht11

为了检测数据的正确性,以及节点是否可用,写了下面一个小程序进行测试:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main(){

    int fd;
    int ret;
    int i = 0;
    unsigned char buf[4];

    fd = open("/dev/dht11", O_RDONLY);
    if(fd < 0){
        printf("open the dht11 id failed\n");
        return fd;
    }
    
    ret = read(fd, buf, 4);
    if(ret < 0){                 //下面三个输出可以了解一下,对于打开,读写节点失败的调试很有帮助的。
        printf("errno= %d\n", errno);
        printf("Mesg----%s\n",strerror(errno));       
        perror("read failed");
        return ret;
    }
    printf("---Humidity=%d.%d%%RH\n---Temperature=%d.%dC\n", buf[0], buf[1], buf[2], buf[3]);
    close(fd);

    return 0;
}

经过测试是没有问题的。到此温湿度检测模块dht11的底层驱动也完成了。

这篇关于基于Dragonboard 410c的燃气烟雾检测器(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/790450

相关文章

C# WPF燃气报警器记录读取串口工具

C# WPF燃气报警器记录读取串口工具 概要串口帧数据布局文件代码文件运行效果源码下载 概要 符合国标文件《GB+15322.2-2019.pdf》串口通信协议定义;可读取燃气报警器家用版设备历史记录信息等信息; 串口帧数据 串口通信如何确定一帧数据接收完成是个麻烦事,本文采用最后一次数据接收完成后再过多少毫秒认为一帧数据接收完成,开始解析出来。每次接收到数据更新一次re

可以进行非机动车违停、人员聚集、临街摆摊、垃圾满溢、烟雾火情等城市治理场景的智能识别的智慧城管开源了

智慧城管视觉监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。 基于深度学习技术及强大的专家团队,针对多个工业垂类场景进行算法优化,打造最优的工业AI算法模型,提供更加精准的工业AI模型库,客户可直接选择适合自己业务场景的模型,快速实现业务落地

算法/编程练习:强密码检测器

强密码检测器 1. 题目 题目来自LeetCode: https://leetcode-cn.com/problems/strong-password-checker/ 题目: 一个强密码应满足3个条件:1)由至少6个,至多20个字符组成;2)至少包含一个小写字母,一个大写字母,和一个数字;3)同一字符不能连续出现三次 (比如'.aaa.'不可以,但'.aa.a.'是可以的)。编写函

七. 部署YOLOv8检测器-load-save-tensor

目录 前言0. 简述1. 案例运行2. 补充说明3. 代码分析3.1 main.cpp3.2 create_data.py 结语下载链接参考 前言 自动驾驶之心推出的 《CUDA与TensorRT部署实战课程》,链接。记录下个人学习笔记,仅供自己参考 本次课程我们来学习课程第六章—部署分类器,一起来学习利用 cnpy 库加载和保存 tensor 课程大纲可以看下面的思维导图

yolov8训练野火烟雾识别检测模型

1.数据集下载 数据集下载链接:https://hyper.ai/datasets/33096 2. 数据集格式转换 需要将json中的标注信息转换为yolo格式的标注文件数据 import jsonimport osimport shutilimport cv2import matplotlib.pyplot as plttarget = "./data/val"def con

基于HTML5的燃气3D培训仿真系统

最近上线了的基于HTML5的燃气3D培训仿真系统,以前的老系统是采用基于C++和OpenGL的OpenSceneGraph引擎设计的,OSG引擎性能和渲染效果各方面还是不错的,但因为这次新产品需求要求能运行多移动终端,多年前基于MFC封装OSG的老系统架构也实在该退休了,这年头找能维护MFC这种古董级GUI的靠谱人也非易事。 系统最终采用HT for Web的3D框架实现,项目中的程序员也很高

原来用电热水器想换成燃气热水器可行吗?

有位网友在后台留言,问电热水器能改成燃气热水器吗?      感觉这个问题挺有意思的,和大家聊聊。      先分析一下,电热水器一般会放到卫生间里边,而燃气热水器必须要放到厨房里边。      如果是同一个位置去互换,那是不可能的。      想换燃气热水器,就必须把燃气热水器安到厨房里,这样就会出现一个问题,燃气热水器的水从哪来通到哪里去?      正常厨房洗菜盆的下边会有冷水和热水,安

城乡燃气安全监管平台 打造城市安全防护网

随着城市化进程的不断加快,燃气已成为现代生活中不可或缺的重要能源。然而,传统燃气管理方式的局限性逐渐显现,难以应对日益增长的安全监管需求。为此,旭华智能基于其在智慧城市领域的深厚积累,推出了燃气安全监管物联网平台,旨在通过数字化、可视化和智慧化的手段,全面提升燃气安全管理的效能。 一、燃气管理面临的挑战 传统的燃气管理主要依赖人工巡检和事后应急处理,这种方式存在着明显的不足。人工巡检受

9,DMA可以获取光照烟雾值

ADC多通道问题需要用到DMA,与ADC相比,省去了获取AD转换数值(转换后数据存储在数据寄存器中,需要把数据拿出来)的步骤 DMA:数据传输高速通道 DMA概述:直接存储器存取(DMA)用来提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。无须CPU干预,数据可以通过DMA快速地移动,这就节省了CPU的资源来做其他操作。 两个DMA 控制器有12个通道(DMA1有7个通道,DMA2有5

基于YOLOv5s的野火烟雾检测(附数据集与Coovally操作步骤)

本文主要内容:详细介绍了野火烟雾检测的整个过程,从创建数据集到训练模型再到预测结果全部可视化操作与分析。 文末有数据集获取方式,请先看检测效果 现状 近几年火灾频发,随着社会对火灾防控的重视程度不断提高,对野火烟雾预测的需求也日益增加。传统的人工检测通常依赖于巡查人员,其覆盖范围和效率受限于人员数量和体能,难以实现大面积、实时的烟雾检测。为了应对这一难题,应用野火烟雾检测算法显得很重