白小兔的小小站

既然选择了远方,便只顾风雨兼程

0%

ESP8266入门Hello World

最近团队Leader说大家都做下分享,很多人都进行了精彩的分享,我呢,也不知道分享什么好,突然想到我有两块吃灰的Arduino开发板,就想着把它俩拿出来写个”Hello World”程序分享下。大家不一定感兴趣,我也不一定说的清楚这是个什么玩意,但毕竟重在参与嘛,这篇日志主要也是做一个记录。我应该是几年前,偶然在知乎看到稚晖君的一个叫”逗比时钟“的视频后开始了解Arduino的,说是了解,也就搜了搜相关的视频,看了看它都可以做些什么。后来有段时间特想做一个孵化器,就是那种孵小鸡的,我觉得可以用这个开发板配合一些传感器、步进电机等来实现,然后就花了大几十块钱买了两块板子,一块Arduino uno,一块ESP8266 NodeMCU,外加一个温湿度传感器和一堆杜邦线、面包板,就开干了。结果在实现了恒温控制后,放弃了,因为要挺多材料的,去买有些贵,自己做又是对动手能力的巨大的考验。

Arduino

Arduino是一款便捷灵活、方便上手的开源电子原型平台,包含硬件(各种型号的Arduino板)和软件(Arduino IDE)。

Arduino能通过各种各样的传感器来感知环境,通过控制灯光、马达和其他的装置来反馈、影响环境。板子上的微控制器可以通过Arduino的编程语言来编写程序,编译成二进制文件,烧录进微控制器。对Arduino的编程是利用 Arduino编程语言 (基于 Wiring)和Arduino开发环境(基于Processing)来实现的。

硬件

arduino

arduino nano

软件

arduino ide

ESP8266

ESP8266是一款SoC芯片,集成了WiFi模块。

esp8266

NodeMCU

NodeMCU是一块搭载了ESP8266的开发板(包括板子的固件)

  • 电脑与开发板的通信方式

  • 开发板的针脚定义

esp8266 pin

继电器模块

波特率

波特率(Baud Rate)单位 bps – 每秒传送的字节数 Byte Per Second。

波特率表示每秒钟传送的码元符号的个数,是衡量数据传送速率的指标,它用单位时间内载波调制状态改变的次数来表示。波特率是指数据信号对载波的调制速率,它用单位时间内载波调制状态改变的次数来表示,其单位是波特(Baud)。

串口

在很多时候,Arduino需要和其他设备相互通讯,而最常见最简单的方式就是串口通讯。

在PC机上最常见的串行通讯协议是RS-232串行协议,而各种微控制器(单片机)上采用的是TTL串行协议,两者电平不同,需要经过相应电平转换才能进行相互通讯。

Arduino Uno R3开发板上,硬件串口位于Rx(0)和Tx(1)引脚上,Arduino的USB口通过转换芯片与这两个引脚连接。该转换芯片会通过USB接口在PC机上虚拟出一个用于Arduino通讯的串口,我们下载程序也是通过串口进行的。

串口通信为什么要设置波特率

有两种比较可靠的说法:

  1. 根据电、传输介质等的物理特性结合串口设备使用的要求

    为了保证有效通讯,根据电、传输介质等的物理特性结合串口设备使用的要求,确定RS232最大传输速率只能是115200,然后逐级二分得到57600,28800,19200……为适应这些速率,设计相应的晶振频率。

  2. 这是由电信线路特性决定的

    电话线路的带通是300~3KHz,当时hayes先搞的modem,所以用的2400HZ信号,对应波特率是2400。由于基本频率确定了,以后采用的提高通讯速率的方法都是在2400基础上倍频的,所以形成了9600、19200……

Hello World 1 (LED闪烁)

这里使用了ESP8266开发板自带的LED灯,并引入ESP8266库中带的示例代码,实现LED灯的闪烁效果。

1
2
3
4
5
6
7
8
9
10
11
void setup() {
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
}

// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on
delay(1000); // Wait for a second
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH
delay(2000); // Wait for two seconds (to demonstrate the active low LED)
}

Hello World 2 (控制继电器开合)

通过延时向数字引脚输出高低电平,达到让继电器以一定规律开合的目的。

1
2
3
4
5
6
7
8
9
10
11
12
13
#define RELAY_PIN 14

void setup() {
pinMode(RELAY_PIN, OUTPUT);
digitalWrite(RELAY_PIN, HIGH);
}

void loop() {
digitalWrite(RELAY_PIN, LOW);
delay(3000);
digitalWrite(RELAY_PIN, HIGH);
delay(3000);
}

Hello World 3 (点灯App控制继电器)

将上面的代码延伸一下,改用手机App控制继电器的开合,注意替换auth、ssid、pswd三个变量的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#define BLINKER_WIFI
#define LIGHT_PIN 14

#include <Blinker.h>

char auth[] = "blinker-secret-key";
char ssid[] = "wifi-ssid";
char pswd[] = "wifi-password";

BlinkerButton Light("bed-room-light");

void light_callback(const String & state) {
BLINKER_LOG("BLINKER_CALLBACK: ", state);
Blinker.vibrate();
lightPowerSwitch(state);
}

void lightPowerSwitch(const String & state) {
bool isTurnOn = state == "on";
digitalWrite(LIGHT_PIN, isTurnOn ? LOW : HIGH);
//Light.icon(isTurnOn ? "far fa-lightbulb-on" : "far fa-lightbulb");
//Light.color(isTurnOn ? "#07D33A" : "#E94929");
Light.text(isTurnOn ? "已打开" : "已关闭");
Light.print(state);
}

void dataRead(const String & data) {
BLINKER_LOG("Blinker readString: ", data);

Blinker.vibrate();

uint32_t BlinkerTime = millis();

Blinker.print("millis", BlinkerTime);
}

void setup() {
Serial.begin(115200);
BLINKER_DEBUG.stream(Serial);
BLINKER_DEBUG.debugAll();

pinMode(LIGHT_PIN, OUTPUT);
digitalWrite(LIGHT_PIN, HIGH);

Blinker.begin(auth, ssid, pswd);
Blinker.attachData(dataRead);

Light.attach(light_callback);
}

void loop() {
Blinker.run();
}

Hello World 4 (小爱同学控制继电器)

在上面代码的基础上加入以下代码,实现小爱同学接入。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define BLINKER_MIOT_LIGHT

void miotPowerState(const String & state) {
BLINKER_LOG("BLINKER_CMD: ", state);
if (state == BLINKER_CMD_ON) {
lightPowerSwitch(state);
BlinkerMIOT.powerState(state);
BlinkerMIOT.print();
} else if (state == BLINKER_CMD_OFF) {
lightPowerSwitch(state);
BlinkerMIOT.powerState(state);
BlinkerMIOT.print();
}
}

void miotQuery(int32_t queryCode) {
// BLINKER_LOG("MIOT Query codes: ", queryCode);
BlinkerMIOT.powerState(getLightState());
BlinkerMIOT.print();
}

const char* getLightState() {
return digitalRead(LIGHT_PIN) == LOW ? "on" : "off";
}

//setup()
BlinkerMIOT.attachPowerState(miotPowerState);
BlinkerMIOT.attachQuery(miotQuery);

实际应用

程序开发好后,可以根据自己的需要自行裁剪设计出满足需要的硬件,用于真实场景。这里在B站随便找了一位同学的设计过程

MQTT

MQTT是机器对机器(M2M)/物联网(IoT)连接协议。它被设计为一个极其轻量级的发布/订阅消息传输协议。对于需要较小代码占用空间和/或网络带宽非常宝贵的远程连接非常有用,是专为受限设备和低带宽、高延迟或不可靠的网络而设计。这些原则也使该协议成为新兴的“机器到机器”(M2M)或物联网(IoT)世界的连接设备,以及带宽和电池功率非常高的移动应用的理想选择。例如,它已被用于通过卫星链路与代理通信的传感器、与医疗服务提供者的拨号连接,以及一系列家庭自动化和小型设备场景。它也是移动应用的理想选择,因为它体积小,功耗低,数据包最小,并且可以有效地将信息分配给一个或多个接收器。

  1. 特点
  • 开放消息协议,简单易实现
  • 发布订阅模式,一对多消息发布
  • 基于TCP/IP网络连接,提供有序,无损,双向连接。
  • 1字节固定报头,2字节心跳报文,最小化传输开销和协议交换,有效减少网络流量。
  • 消息QoS支持,可靠传输保证
  1. 应用

    MQTT协议广泛应用于物联网、移动互联网、智能硬件、车联网、电力能源等领域。

    • 物联网M2M通信,物联网大数据采集
    • Android消息推送,WEB消息推送
    • 移动即时消息,例如Facebook Messenger
    • 智能硬件、智能家具、智能电器
    • 车联网通信,电动车站桩采集
    • 智慧城市、远程医疗、远程教育
    • 电力、石油与能源等行业市场