前提说明,本文是基于【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());
    }
}
posted on 2025-01-07 13:54  shaochang123  阅读(3939)  评论(0)    收藏  举报