Arduino 的各种传感器使用笔记-附带源码示例

1,843 阅读11分钟
专栏: 
单片机学习
智能总结
复制
重新生成

这篇文章是作者学习 Arduino 开发的笔记,记录了各种传感器的使用,包括开发板引脚、宏定义、常用函数等。还介绍了继电器的原理和使用代码,以及 DS18B20 等多种传感器的参数、特点、示例代码和应用场景,如温度、湿度、液位、光照检测等,同时提到了项目需求规划。

关联问题: DS18B20如何校准 液位传感器易坏吗 光敏电阻咋选

前言:

最近正在学习arduino开发,0经验产品入门,期望后续能实现自己需求自己实现,由于本地markdown不方便编辑分享其他在线文档记录也不太清晰不方便自己持续更新,所以采取掘金在线编辑,如果能顺便帮助其他和我一样的小伙伴也算是一件好事。

目前失业在家想实现一个自动化种植水培菜园,目前正在学习如何使用单片机获取环境数据,先上一个月的种植成果。

PS:最近总是在急于寻找各种模块的示例代码忽视了GPT老师的重要性,今天使用gpt老师帮忙写了几个获取模块的示例很顺利,建议各位使用会节省很多检索时间

f378d5623c96a9f0b2adbfe9ca88901.jpg fbc3adc482c837610427bf29c034416.jpg

本笔记重点记录内容是各种传感器模块的使用,由于是自用不能体现得过于详尽各位看到的老哥如果觉得有优化建议欢迎评论指正。

需求规划

  • 需求展望

    希望最终能实现植物全生命周期管理从播种,育苗,采摘可以做到,自动播种、识别坑位幼苗是否存活如果育苗失败自动补种,菜苗成熟后可以实现提醒采摘

    环境监测可以做到能检测水体氧含量、微生物、营养液浓度,液体温度、液体液位情况,通过不同的环境数据可以自动补充纯水、营养液、氧气输送

    能量管理,目前电源使用的是太阳能pwm控制器,后面想实现手搓一套MPPT控制器,电能管理主要用来给单片机和水泵、气泵传感器供电。

  • 第一阶段需求

    目前能力有限且正在学习中,第一阶段准备先从环境数据采集和模块应用学习开始

开发板引脚示意图

放引脚图担心卖我板子的商家跑路后面找不到了 ESP32-S3-N16R8 入手价26 在这里插入图片描述

ESP32-WROOM-32 引脚 入手价 15 在这里插入图片描述

8266引脚入手价 12.4 在这里插入图片描述

arduino uno R3改进版引脚 入手价 17.5

在这里插入图片描述 在这里插入图片描述

宏定义

#define 宏名称+针脚号 用法

#define LED 5

注意事项:宏定义区别主要在于宏定义程序执行时是在预处理时执行不需要占用内存空间,变量则是在编译时执行,需要占用内存空间 宏定义不需要类型申明,变量需要类型申明

常用函数:

  • pinMode函数 (针脚模式) 值:INPUT输入模式、OUTPUT输出模式、INPUT_PULLU上拉电阻使之一直保持高电平 用法:
pinMode(引脚, INPUT);
  • digitalWrite函数(数字信号写入) 值:HIGH高电平、LOW低电平 用法:
  pinMode(引脚, OUTPUT);
  digitalWrite(引脚, LOW);

注意事项:该函数必须是输出模式才生效

  • digitalRead函数 (读取数字信号) 值:引脚 用法:
pinMode(引脚,INPUT);
int value = digitalRead(引脚);

注意事项:针脚模式必须设置为输入模式

  • analogWrite函数(模拟信号输出) 值:引脚、脉宽信号值(0~255) 用法:
pinMode(引脚, OUTPUT);
analogWrite(引脚, 230);

注意事项:输出信号为PWM,模式必须为输出模式

  • anologRead函数(模拟信号读取) 值:引脚 用法:
pinMode(引脚, INPUT);
int value = analogRead(引脚);

注意事项:模式必须设置为输入模式,返回值在0~1023之间

  • delay函数(延迟) 值:数值单位(毫秒) 用法:
delay(10000);

注意事项:该函数属于阻塞延迟函数,延迟期间单片机无法执行其他指令,数值单位为毫秒

  • delayMicroseconds函数 值:数值单位(微秒) 用法:
delayMicroseconds(100);
  • Serial.begin(波特率设置) 值:数值 用法
Serial.begin(115200);

注意事项:波特率默认为9600

  • Serial.println(打印串口监视) 值:串口变量 用法:
变量名.analogRead (引脚);
Serial.println(变量名);

注意事项:读取打印之前需要设置读取参数

继电器

描述

继电器就是一个可编程控制的开关,我们可以通过往信号线上输出高电平或者低电平来控制继电器的开合。输出高电平是,继电器常开端口关闭,常闭端口打开,输出低电平是常开端口打开,常闭端口关闭。 继电器的工作原理

继电器是一种电气控制装置,通常用于控制大功率电路的开关。其工作原理基于电磁感应和机械运动两个方面。

当继电器的输入电路(也称为控制电路)通电时,通过它的线圈会产生一个磁场。这个磁场可以吸引或释放继电器中的移动元件,如触点或臂ature。这个移动元件的运动状态将决定继电器的输出电路(也称为负载电路)是否断开或闭合。

举个例子,当一个继电器用于控制一个灯泡的电路时,输入电路将连接到一个开关或其他控制设备。在没有通电的情况下,继电器的输出电路将处于断开状态,灯泡不会发光。当输入电路通电时,继电器的线圈将产生一个磁场,使得移动元件移动并使输出电路连接,从而让电流流经灯泡并使其发光。

继电器的工作原理在电气控制系统中得到广泛应用,例如在自动化控制、电力系统保护、通信系统中等。 在这里插入图片描述

控制端

IN1:信号线

VCC:直流供电正极

GND:直流供电负极

开关端口

公共:无论常开模式还是常闭模式都需要连接的端口; 常开:控制端不通电的情况下,常开端口与公共端口是断开状态,通电后变成闭合状态; 常闭:控制段不通电的情况下,常闭端口与公共端口是闭合状态,通电后变成端口状态;

使用loop函数delay方法延时代码示例: 在这里插入图片描述

#define PUMP 4 //定义引脚


void setup() {
  pinMode (PUMP,OUTPUT); //设置为输出模式
}

void loop() {
 digitalWrite(PUMP,HIGH);//默认高电平开启
 delay(3000);//维持时间
 digitalWrite(PUMP,LOW);//保持低电平
 delay(10000);//维持时间

使用中断函数定义延时

在这里插入图片描述

#define RELAY_PIN   15

// 初始化硬件定时器对象
hw_timer_t *timer = NULL;


void timer_interrupt() {
  digitalWrite(RELAY_PIN, !digitalRead(RELAY_PIN));}

void setup() {
  // 配置 D15 为 GPIO 输出
  pinMode(RELAY_PIN, OUTPUT);

  // 初始化定时器
  timer = timerBegin(0, 80, true);

  // 配置定时器
  timerAttachInterrupt(timer, timer_interrupt, true);

  // 设置定时器模式
  timerAlarmWrite(timer, 500000, true);

  // 启动定时器
  timerAlarmEnable(timer);
}

void loop() {

}

DS18B20温度传感器

参数读取正常,不过只适合测环境温,不防水

00c3696f13f92841eb5f1eddc778a73.jpg 示例代码:

#include <OneWire.h>
#include <DallasTemperature.h>


// 定义DS18B20数据口连接arduino的2号IO上
#define ONE_WIRE_BUS 5

// 初始连接在单总线上的单总线设备
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(void)
{
  // 设置串口通信波特率
  Serial.begin(115200);
  Serial.println("Dallas Temperature IC Control Library Demo");
  // 初始库
  sensors.begin();
}

void loop(void)
{
  Serial.print("获取温度...");
  sensors.requestTemperatures(); // 发送命令获取温度
  Serial.println("成功");
  
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));
  delay(500);  
}

DH111温湿度传感器+TM1637数码管展示温湿度

入手价5.92(第一次购买模块,PDD下单纯纯大冤种)

同DS18B20模块一样也是不防水模块,但是有一点很奇怪加上LED后脱机就没法显示了需要注意,我用的开发板是ESP8266UNO正常,UNO测DS18B20接反L和ON常亮好像烧坏,由于不是我需要的部件暂时不纠结。 d7b0bf6afd49aec6e8f0d4fc0ca96ad.jpg 示例代码:

#include <Arduino.h>
#include "TM1637.h"
#include <Adafruit_Sensor.h>
#include <DHT.h>
#include <DHT_U.h>

// 数码管显示对象的创建
TM1637 tm(8, 9);
DHT_Unified dht(10, DHT11);

void setup() {
    Serial.begin(115200);
    tm.init();
    tm.setBrightness(3);
    dht.begin();
}

void loop() {
    // 1. 读取温湿度数据
    sensors_event_t event;
    dht.temperature().getEvent(&event);
    if (isnan(event.temperature)) {
        Serial.println(F("Error reading temperature!"));
    } else {
        Serial.print(F("Temperature: "));
        Serial.print(event.temperature);
        Serial.println(F("°C"));
        // 显示温度
        tm.display(event.temperature, true, true, 0);
        delay(1000);
    }
    // Get humidity event and print its value.
    dht.humidity().getEvent(&event);
    if (isnan(event.relative_humidity)) {
        Serial.println(F("Error reading humidity!"));
    } else {
        Serial.print(F("Humidity: "));
        Serial.print(event.relative_humidity);
        Serial.println(F("%"));
        // 显示湿度
        tm.display(event.relative_humidity, true, true, 0);
        delay(1000);
    }

}

DS18B20防水探头温度传感器

TB入手价2.6

实测可以用,开发板使用的是nodeMCU 8266

引脚界限在代码里面有说明,nodeMCU的引脚号和I0号标注有点区别需要特别注意。

这种传感器是不锈钢封装的DS18B20芯片优点是防水实时性高,这种芯片支持唯一端口号识别,可以实现同时检测不同区域的多个探头数据,我的想法是把探头布置在各个管道和营养液桶内

c8060f257c6a76eb699718651f92f19.jpg 358729f1f41425dd7dcd3281d226653.jpg

示例代码:

#include <OneWire.h>
#include <DallasTemperature.h>


// 定义DS18B20数据口连接8622的2号IO上,引脚号D4
#define ONE_WIRE_BUS 2

// 初始连接在单总线上的单总线设备
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

void setup(void)
{
  // 设置串口通信波特率
  Serial.begin(115200);
  Serial.println("Dallas Temperature IC Control Library Demo");
  // 初始库
  sensors.begin();
}

void loop(void)
{
  //获取数据局
  Serial.print("获取温度...");
  sensors.requestTemperatures(); // 发送命令获取温度
  Serial.println("成功");
  //打印当前温度
  Serial.print("设备当前温度为: ");
  //采集端口号设为0
  Serial.println(sensors.getTempCByIndex(0));
  delay(500);  
}

}

红外传感器

品牌:WAVGAT 购入价3.7 遥控加模块

测试了其他遥控只要能获取到编码都可以用,模块淘宝5毛钱以内可以搞定

823c67b77618908b4ac62c780926e61.jpg 示例代码:

#include <Arduino.h>
#include <IRremote.hpp>

#define IR_RECEIVE_PIN 15  // 红外信号接收器连接的引脚
#define LED 13   // LED正极引脚

const IRRawDataType OK_BUTTON = 0xBF40FF00;  // OK按钮的编码值

void setup() {
    Serial.begin(9600);
    pinMode(LED, OUTPUT);
    IrReceiver.begin(IR_RECEIVE_PIN, ENABLE_LED_FEEDBACK);
}

void loop() {
    if (IrReceiver.decode()) {
        Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX);
        if (IrReceiver.decodedIRData.decodedRawData == OK_BUTTON) {
            digitalWrite(LED, !digitalRead(LED));
        }
        IrReceiver.resume();
    }
}

雨水传感器

TB入手价 1.58

目前对我的项目没有帮助,唯一能想到的就是检测是否下雨提醒收被子

a05f30293c72faf3faa1386b3488949.jpg

d683c018d13bfa305640b0d8650a5a1.jpg


int rainAnalogPin = A0;
int rainDigitalPin = 2;

void setup() {
  pinMode(rainAnalogPin, INPUT);
  pinMode(rainDigitalPin, INPUT);
  Serial.begin(9600);
}

void loop() {
  //读取模拟引脚A0上的输入
  int sensorAnalogValue = analogRead(rainAnalogPin);
  Serial.print("雨量传感器模拟值: ");
  Serial.println(sensorAnalogValue);

  // 读取数字引脚 2 上的输入
  int sensorDigitalValue = digitalRead(rainDigitalPin);
  Serial.print("雨量传感器数字值:");
  Serial.println(sensorDigitalValue);

  //数字输出
  if (sensorDigitalValue == LOW) //低表示检测到雨; 在某些情况下反之亦然
  {
    Serial.println("下雨了收衣服了");
  }
  else {
    Serial.println("未检测到雨水");
  }
  delay(2000);
}

mdc04 液位传感器

说明 目前最理想的是B站一个I2C接口电极mdc04传感器,淘宝单个价格要5蚊运费5,芯片最低2.5元,我是买了芯片2.5感觉亏了还要自己焊接,不过官方有提供PCB工程图可以直接导入嘉立创EDA,不过嘉立创EDA不能编辑想玩邮票孔拼板有点吃力

image.png 这里要谴责下卖家,商品没有标注是批量价让我补差价,一个芯片要5块,pcb也才5块,由于只是做样品验证代码可行性我选择直接买5块+5块邮费的pcb了

image.png

我真的服了pcb也涨价了,直接坐地起价啊

代码是GPT写的暂时没验证

需求 由于MDC04可以通过电极检测水位的高低值,所以可以用来给我的各个区域都使用上检测液位状态做水泵供水指令反馈,如果低于就供水,长时间低于就预警可能出现水管脱落,如果高于就预警常见情况是水管堵塞会高于平均值。

image.png

image.png

B站UP的视频 【水位检测传感器I2C接口】

示例代码

#include <Wire.h>  // 引入 I2C 库
#include <ESP8266WiFi.h>

const int sensorAddr = 0x44;  // 传感器的 I2C 地址
const int levelSensorPin = D1;  // 液位传感器连接的引脚

void setup() {
  Wire.begin();  // 初始化 I2C 总线
  pinMode(levelSensorPin, INPUT);  // 设置液位传感器引脚为输入模式
  Serial.begin(9600);  // 初始化串口通信
  connectToWiFi();  // 连接到 WiFi
}

void loop() {
  int liquidLevel = analogRead(levelSensorPin);  // 读取液位传感器数值
  float capacity = map(liquidLevel, 0, 1023, 0, 100);  // 将传感器数值映射到容量范围
  Serial.print("Liquid Capacity: ");
  Serial.print(capacity);
  Serial.println("%");
  delay(1000);  // 延时 1 秒
}

void connectToWiFi() {
  // 添加连接到 WiFi 的代码
}

光敏传感器

说明 该示例代码为通过AO口读取模拟信号,也可以通过DO口读取数字信号,光敏信号的数值范围为(0~1024)通过读取数字信号进行条件判断 需求 光敏电阻读取数字信号可以帮助我采集全天光照情况,结合数据可以实现当全天光照低于阈值时,晚上使用补光策略

数字信号读取示例代码

const int sensorPin = D2;  // 光敏传感器连接到的引脚

void setup() {
  Serial.begin(9600);  // 初始化串口通信
}

void loop() {
  int sensorValue = analogRead(sensorPin);  // 读取光敏传感器的数值
  Serial.println(sensorValue);  // 打印光敏传感器的数值到串口监视器
  delay(1000);  // 延时 1 秒
}