前提说明,本文是基于【2023年最新 ESP32 Arduino 教程(持续更新中)】写的,如果本文没看懂可以去看这个视频。
vscode下载以及platform插件安装
首先下载vscode(网上自行搜索),打开vscode后,在插件中搜索platformio并点击下载,下图是操作步骤(第一次安装可能会很慢,请耐心等待)。
如果可以的话,可以安装一个串口监视器Serial monitor,之后会用到。
安装完platformio之后,应该会在左侧出现一个特殊的图标,点进图标,再点击"PIO Home"下的"Open",进入主页界面,再点击"New projects"进行创建项目。
点击之后,项目配置如下:
点击右下角蓝色的“Finish”按钮,等待一会后,就可以创建成功了。
由于我们要做的只是一些简单的演示,故只要在src文件夹下编写main.cpp的代码就可以了。下面为main.cpp的图片(你们刚打开main.cpp时里面可能长的和我的不一样,但仔细看代码结构是一样的)
可以看到左下角有一个“”按键,表示编译;有个“”按键,表示烧录代码;最右边的写着“Auto”的按键可以自动检测COM端口。接下来我们就可以开始愉快地编写代码了。
ESP32介绍
一块普通的ESP32板长这样。
最关键的是其两侧的引脚(34个GPIO口),你可以发现每个引脚上都有唯一的字母和数字的组合,例如“3V3”,“GND”,“D12”等。其中3V3和VIN指的分别是电压为3.3V和5V的正极,而GND指的是阴极(接地),其余的则可以通过我们在vscode上编写的代码控制它们的输入或者输出模式,以及输出高电平或者低电平,那么我们在进行实验时,除了正极和负极之外这些引脚是否可以随便接呢?答案是否定的,有的时候必须接到对应的引脚上,每一个引脚都有其对应的作用,如下图,比如其中的22和21引脚就是esp32中的L2C通信接口。
面包板介绍
一块普通的面包板长这样
其中的小孔可以用来插入导线或者引脚,其旁边还有凹凸槽,可以用来和其他面包板拼接组成更大的面包板。
而其中的电路连接长这样
中间的小孔,以图中红色的线条(横向)相互连通,两侧的小孔,以图中的红色线条(竖向)相互连通。加入正负极以及电阻等部件,可以组成一个电路(回忆高中物理知识),这样子我们只需要插入或者拔出导线和引脚就可以组成电路,而不用去做焊接等一系列工作,简化了我们的开发流程。
串口通讯
在platformio的开发中,Serial
可以设置串口波特率以及向外发送消息
例如以下代码中,程序会在9600波特率中每隔1s向外发送一个“hello world”。
#include <Arduino.h>
void setup() {
Serial.begin(9600);
}
void loop() {
Serial.println("hello world");
delay(1000);
}
输入输出模式
引脚设置输出模式的代码为pinMode(pin,OUTPUT)
,然后用digitalWrite(pin,HIGH)
或digitalWrite(pin,1)
可以让其输出高电平,或者digitalWrite(pin,LOW)
或digitalWrite(pin,0)
可以让其输出低电平。设置输入模式把OUTPUT换成INPUT,同时可以设置引脚上拉电阻INPUT_PULLUP
或下拉电阻INPUT_PULLDOWN
。上拉电阻会让引脚初始时为高电平,当有低电平输入时会有电位变化,下拉电阻则相反。例如下面是通过按键控制LED亮灭的代码。
#include <Arduino.h>
#define pin1 12
#define pin2 13
void setup() {
pinMode(pin2,OUTPUT);
pinMode(pin1,INPUT_PULLDOWN);
}
void loop() {
if(digitalRead(pin1)){
delay(10);
if(digitalRead(pin1)){
digitalWrite(pin2,HIGH);
// delay(1000);
}
else digitalWrite(pin2,LOW);
}
else digitalWrite(pin2,LOW);
}
LED灯的点亮
接线
按照这样连接电路,一端接GND,一端接某个引脚
代码
首先我们可以通过对引脚设置高电平来点亮LED灯,其中setup函数是esp32最开始会执行的。
点击查看代码
#include<ARduino.h>
const int led=23;//这个是你接到的引脚的数字
void setup(){
pinMode(led,OUTPUT);//置为输出模式,毕竟要输出高电平
digitalWrite(led,HIGH);//设为高电平,其中HIGH是个宏定义,相当于1
}
void loop(){
}
如果要LED闪烁,可以用到loop函数,这个函数会不停地循环执行。
点击查看代码
#include <Arduino.h>
const int led=23;
void setup() {
pinMode(led,OUTPUT);
}
void loop() {
digitalWrite(led,HIGH);
delay(1000);//延时1000ms
digitalWrite(led,LOW);
delay(1000);
}//由于loop函数会不停的执行,LED会不停地闪烁
点击查看代码
#include <Arduino.h>//基于PWM实现呼吸灯的效果
const int led=23;
#define channel 0//通道
#define freq 2000//频率,越大LED灯变化越快
#define reso 8//变化范围,为2的reso方
void setup() {
ledcSetup(channel,freq,reso);
ledcAttachPin(led,channel);
}
void loop() {
for(int i=0;i<pow(2,reso);i++){//渐亮
ledcWrite(channel,i);
delay(10);
}
for(int i=pow(2,reso)-1;i>=0;i--){//渐暗
ledcWrite(channel,i);
delay(10);
}
}
点击查看代码
#include <Arduino.h>
const int led=23;
void setup() {
pinMode(led,OUTPUT);
}
void loop() {
for(int i=0;i<256;i++){//渐亮
analogWrite(led,i);
}
for(int i=255;i>=0;i--){//渐暗
analogWrite(led,i);
}
}
数码管和四位数码管
数码管按图上方式接线,单数码管中不同的引脚控制对应位置的亮灭,而四位数码管中,对seg1~seg4中哪个接低电平,就亮哪个位置的“8”。
四位数码管
下面是一个简单的通过四位数码管显示时间(从0开始)的代码
#include <Arduino.h>
#include<ctime>
int pin[8]={32,25,27,12,13,33,26,14};
int loc[4]={5,18,19,21};
void printnum(int mode,int pos);
int num[10][8]={ {1,1,1,1,1,1,0,0},
{0,1,1,0,0,0,0,0},
{1,1,0,1,1,0,1,0},
{1,1,1,1,0,0,1,0},
{0,1,1,0,0,1,1,0},
{1,0,1,1,0,1,1,0},
{1,0,1,1,1,1,1,0},
{1,1,1,0,0,0,0,0},
{1,1,1,1,1,1,1,0},
{1,1,1,1,0,1,1,0},
};
void setup() {
for(int i=0;i<8;i++)pinMode(pin[i],OUTPUT);
for(int i=0;i<4;i++)pinMode(loc[i],OUTPUT),digitalWrite(loc[i],HIGH);
}
void loop() {
time_t nowtime;
time(&nowtime);
tm* p = localtime(&nowtime);
int h=p->tm_hour;
int m=p->tm_min;
printnum(h/10%10,0);
printnum(h%10,1);
printnum(m/10%10,2);
printnum(m%10,3);
}
void printnum(int mode,int pos){
digitalWrite(loc[pos],LOW);
for(int i=0;i<8;i++){
if(num[mode][i]==1){
digitalWrite(pin[i],HIGH);
}
}
for(int i=0;i<8;i++){
if(num[mode][i]==1){
digitalWrite(pin[i],LOW);
}
}
digitalWrite(loc[pos],HIGH);
}
LCD1602的显示
LCD1602遵循L2C协议,按照ESP32上的L2C引脚(22号和21号)接就可以了。
#include <Arduino.h>
#include<LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2);//初始化一个LCD屏幕,这里的16和2代表它本身是16列2行的屏幕,0x27是默认值
void setup() {
lcd.init();//初始化
lcd.backlight();//背光,不然看不清
Serial.begin(9600);
}
void loop() {//在这个函数里,我们可以向串口发送数据,一旦检测到了数据发送,就把这个字符放到LCD屏幕上,如果是回车则清空
if(Serial.available()){
char ch=Serial.read();
if(ch=='\n')lcd.clear();//清除
else lcd.write(ch);//在LCD上写东西
}
}
OLED屏幕的使用
OLED屏幕使用SPI协议,不过由于屏幕本身的问题,我现在还没成功让屏幕亮起来。
温度传感器,震动传感器,倾斜传感器和干簧管
为什么要把这四个东西放在一块,因为这四个传感器的接线和代码是差不多的(其中干簧管是检测磁性物体的靠近),都是根据外界信息使得电位变化之类的。
震动传感器控制LED灯
步进电机
步进电机的原理不解释,按照一定顺序通电,便可以亮起来。
电机视频
#include <Arduino.h>
#define in1 13
#define in2 12
#define in3 14
#define in4 27
int delay_time =5;
void setup() {
pinMode(in1,OUTPUT);
pinMode(in2,OUTPUT);
pinMode(in3,OUTPUT);
pinMode(in4,OUTPUT);
}
void loop() {
for(int i=0;i<256;i++){
digitalWrite(in1,1);
digitalWrite(in2,0);
digitalWrite(in3,0);
digitalWrite(in4,0);
delay(delay_time);
digitalWrite(in1,1);
digitalWrite(in2,0);
digitalWrite(in3,1);
digitalWrite(in4,1);
delay(delay_time);
digitalWrite(in1,0);
digitalWrite(in2,0);
digitalWrite(in3,1);
digitalWrite(in4,0);
delay(delay_time);
digitalWrite(in1,1);
digitalWrite(in2,1);
digitalWrite(in3,1);
digitalWrite(in4,0);
delay(delay_time);
}
digitalWrite(in1,0);
digitalWrite(in2,0);
digitalWrite(in3,0);
digitalWrite(in4,0);
delay(1000);
}
有源蜂鸣器和无源蜂鸣器
有源蜂鸣器有电就有声音,无源蜂鸣器需要pwm信号才能有声音
有源蜂鸣器
8*8点阵屏
按照上图的连接,一端接高电平,一端接低电平就可以让对应的LED灯亮起来,例如对于共阴极点阵屏,想让第二列第二排的灯亮起来,就要给3接高电平,14接低电平。
继电器
继电器的作用是放大电流,或者隔离电路,使用方法也没啥特别的。
矩阵键盘
检验矩阵键盘哪一个按键被按下可以使用行列检测法,具体步骤是给每行一个上拉电阻,每列为输出模式,且为高电平,然后再依次给每列一个低电平,如果某个按键被按下了,相应行会检测出低电平,此时由于是列=列是一个一个通低电平的,所以列也能检测出来,这样
就成功定位了。下面是利用矩阵键盘在lcd屏幕上输入的实例。
#include <Arduino.h>
int row[4]={13,12,14,27};
int col[4]={26,25,33,32};
char key;
void setup() {
Serial.begin(9600);
for(int i=0;i<4;i++){
pinMode(row[i],INPUT_PULLUP);
}
for(int i=0;i<4;i++){
pinMode(col[i],OUTPUT);
digitalWrite(col[i],HIGH);
}
}
char read_keypad(){
char keys[4][4]={
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'},
};
for(int j=0;j<4;j++){
digitalWrite(col[j],LOW);
for(int i=0;i<4;i++){
if(!digitalRead(row[i])){
digitalWrite(col[j],HIGH);
return keys[i][j];
}
}
digitalWrite(col[j],HIGH);
}
return '?';
}
void loop() {
key = read_keypad();
if(key!='?'){
Serial.printf("you press the %c\n",key);
delay(1000);
}
}
#include <Arduino.h>
#include<string>
#include<LiquidCrystal_I2C.h>
int row[4]={13,12,14,27};
int col[4]={26,25,33,32};
char key;
std::string s="";
LiquidCrystal_I2C lcd(0x27,16,2);
void setup() {
for(int i=0;i<4;i++){
pinMode(row[i],INPUT_PULLUP);
}
for(int i=0;i<4;i++){
pinMode(col[i],OUTPUT);
digitalWrite(col[i],HIGH);
}
lcd.init();
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Enter password:");
lcd.setCursor(0,1);
}
char read_keypad(){
char keys[4][4]={
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'},
};
for(int j=0;j<4;j++){
digitalWrite(col[j],LOW);
for(int i=0;i<4;i++){
if(!digitalRead(row[i])){
digitalWrite(col[j],HIGH);
return keys[i][j];
}
}
digitalWrite(col[j],HIGH);
}
return '?';
}
void loop() {
key = read_keypad();
if(key!='?'){
delay(1000);
if(key=='A'){
if(s=="123456"){
lcd.clear();
lcd.setCursor(0,1);
lcd.print("RIGHT!");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Enter password:");
lcd.setCursor(0,1);
s="";
}
else{
lcd.clear();
lcd.setCursor(0,1);
lcd.print("WRONG PASSWORD!");
delay(2000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Enter password:");
lcd.setCursor(0,1);
s="";
}
}
else{
lcd.print(key);
s+=key;
}
}
}
舵机
WiFi模块
可以利用WiFi.begin()连接WiFi,并且创建自己的热点。
#include <Arduino.h>
#include <WiFi.h>
// 定义连接 Wi-Fi 路由器的 SSID 和密码
const char* ssid_router = "shaochang"; // 替换为实际的 Wi-Fi 名称
const char* password_router = "12345678.."; // 替换为实际的 Wi-Fi 密码
// 定义创建热点的 SSID 和密码
const char* ssid_ap = "test_hotspot"; // 替换为实际的热点名称
const char* password_ap = "12345678"; // 热点密码,必须至少8个字符
void setup() {
Serial.begin(9600);
// 连接到路由器
Serial.println("Connecting to Wi-Fi...");
WiFi.begin(ssid_router, password_router);
// 等待连接成功
while (WiFi.status() != WL_CONNECTED) {
delay(2000);
Serial.println("Connecting...");
}
Serial.println("Connected to Wi-Fi!");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
Serial.print("MAC Address: ");
Serial.println(WiFi.macAddress());
// 创建热点(SoftAP 模式)
bool apStatus = WiFi.softAP(ssid_ap, password_ap);
if (apStatus) {
Serial.println("Hotspot created successfully!");
Serial.print("Hotspot IP: ");
Serial.println(WiFi.softAPIP());
} else {
Serial.println("Failed to create hotspot!");
}
}
void loop() {
}
同时,还可以利用连接好的WiFi创建自己的服务器
#include <WiFi.h>
#include <WebServer.h>
// WiFi信息
const char* ssid = "shaochang";
const char* password = "12345678..";
// 创建WebServer对象,监听端口80
WebServer server(80);
void handleRoot() {
// 返回一个简单的HTML页面
server.send(200, "text/html", "<h1>Hello from ESP32 WebServer!</h1>");
}
void handleGetData() {
// 返回JSON数据
String jsonResponse = "{\"status\": \"success\", \"data\": \"Hello, PC!\"}";
server.send(200, "application/json", jsonResponse);
}
void handlePostData() {
// 处理POST请求数据
if (server.hasArg("plain")) {
String message = server.arg("plain");
Serial.println("Received POST data: " + message);
// 回复客户端
server.send(200, "text/plain", "Data received: " + message);
} else {
server.send(400, "text/plain", "No data received!");
}
}
void setup() {
Serial.begin(115200);
// 连接WiFi
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nConnected to WiFi");
Serial.print("IP Address: ");
Serial.println(WiFi.localIP());
// 配置路由
server.on("/", handleRoot);
server.on("/get-data", handleGetData);
server.on("/post-data", HTTP_POST, handlePostData);
// 启动WebServer
server.begin();
Serial.println("WebServer started");
}
void loop() {
// 处理客户端请求
server.handleClient();
}
python检测代码
import requests
# 替换为ESP32的实际IP地址
esp32_ip = "172.20.10.6"
# 访问根目录
response = requests.get(f"http://{esp32_ip}/")
print("GET / Response:", response.text)
# 访问 /get-data 获取JSON数据
response = requests.get(f"http://{esp32_ip}/get-data")
print("GET /get-data Response:", response.json())
# 向 /post-data 发送POST请求
payload = {"message": "Hello from PC!"}
response = requests.post(f"http://{esp32_ip}/post-data", json=payload)
print("POST /post-data Response:", response.text)
蓝牙模块
利用BluetoothSerial创建一个esp32的蓝牙,并且实现PC与esp32的互相通信。
#include "BluetoothSerial.h"
#include<Arduino.h>
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32_BT"); // 设置蓝牙设备名称
Serial.println("Bluetooth initialized. You can now pair with ESP32_BT.");
}
void loop() {
if (SerialBT.available()) {
String received = SerialBT.readString();
Serial.print("Received: ");
Serial.println(received);
}
if (Serial.available()) {
SerialBT.write(Serial.read());
}
}