資料介紹
1.Beetle ESP32-C3簡介
Beetle ESP32-C3是一款基于ESP32-C3 RISC-V 32位單核處理器芯片的主控板,專為物聯(lián)網(wǎng) (IoT) 設(shè)備而設(shè)計(jì)。
Beetle ESP32-C3在僅硬幣大小的體積上引出了多達(dá)13個IO口,制作項(xiàng)目時不必再擔(dān)心IO口不夠用的情況,同時主控板還集成鋰電池充電管理功能,可以直接連接鋰電池,不需要外圍模塊,同時保證應(yīng)用體積和安全性。
Beetle ESP32-C3配套的擴(kuò)展板在未增加太大體積的情況下,引出了更多的電源,在制作項(xiàng)目時焊接更加方便,板載的GDI顯示屏接口解決使用屏幕時的接線煩惱。
Beetle ESP32-C3支持Wi-Fi 和 Bluetooth 5 (LE) 雙模通訊,降低了設(shè)備配網(wǎng)難度,同時還支持藍(lán)牙 Mesh (Bluetooth Mesh) 協(xié)議和樂鑫 Wi-Fi Mesh可以實(shí)現(xiàn)更高的通訊穩(wěn)定性和更大的覆蓋面積,適用于廣泛的物聯(lián)網(wǎng)應(yīng)用場景。
Beetle ESP32-C3擁有詳細(xì)的示例教程,通過教程可以輕松的使用控制器的無線功能,連接阿里云、IFTTT等物聯(lián)網(wǎng)平臺,同時DFRobot商城提供了上千種傳感器和執(zhí)行器,這些傳感器和執(zhí)行器也有詳細(xì)的教程,因此你可以輕松搭建出自己的物聯(lián)網(wǎng)系統(tǒng)。
Beetle ESP32-C3可以使用Arduino IDE、ESP-IDF、MicroPython進(jìn)行編程(MicroPython教程后續(xù)推出),C語言、python都可以輕松的操縱硬件。
2.產(chǎn)品特性
- 超小體積,尺寸僅25*20.5mm
- 板載鋰電池充電管理,充放電更安全
- 配套擴(kuò)展板,制作項(xiàng)目、使用屏幕更加方便
- RISC-V 32位內(nèi)核
- 支持Wi-Fi 和 Bluetooth 5 (LE) 雙模通訊
3.產(chǎn)品參數(shù)
基本參數(shù)
硬件信息
- 處理器:32 位 RISC-V 單核處理器
- 主頻:160 MHz
- SRAM:400KB
- ROM:384KB
- Flash:4MB
- RTC SRAM:8KB
- 時鐘:外置 (32 kHz) 晶振、內(nèi)置快速 RC 振蕩器時鐘 17.5 MHz(可調(diào)節(jié))、以及PLL時鐘
- USB: USB 2.0 可達(dá) 12Mbit/s
WIFI
- WIFI協(xié)議:IEEE 802.11b/g/n
- WIFI頻寬: 2.4 GHz 頻帶支持 20 MHz 和 40 MHz 頻寬
- WIFI模式:Station 模式、SoftAP 模式、SoftAP+Station 模式和混雜模式
- WIFI頻率:2.4GHz
- 幀聚合: TX/RX A-MPDU, TX/RX A-MSDU
藍(lán)牙
- 藍(lán)牙協(xié)議:Bluetooth 5、Bluetooth mesh
- 藍(lán)牙頻率:125 Kbps、500 Kbps、1 Mbps、2 Mbps
接口引腳
- 數(shù)字I/O x13
- LED PWM 控制器 6個通道
- SPI x1
- UART x2
- I2C x1
- I2S x1
- 紅外收發(fā)器:發(fā)送通道 x2、接收通道 x2,(任意管腳)
- 2 × 12 位 SAR 模/數(shù)轉(zhuǎn)換器, 6 個通道
- DMA 控制器,3 個接收通道和 3 個發(fā)送通道
4.功能引腳示意圖
功能指示
- Type-C:5V
- 10/LED:板載LED引腳
- ESP32-C3模組:樂鑫公司推出的最新ESP32-C3模組
- RST:復(fù)位引腳,短接觸點(diǎn)觸發(fā)復(fù)位
- TP4057:TP4057鋰電池充電管理芯片
- Charge:充電指示燈
- 熄滅:未接入電源或已充滿
- 常亮:充電中
- 閃爍:電池未接入
- 18Pin-FPC:GDI顯示屏接口
引腳示意
引腳概述
GDI顯示接口
此接口為DFRbot專用GDI顯示屏接口,使用18pin-FPC線連接,單線材連接屏幕,為您提供最簡捷的屏幕使用方式。
以下是GDI接口使用的引腳列表
FPC PINS | Beetle ESP32 C3 PINS | Description |
---|---|---|
VCC | 3V3 | 3.3V |
BLK(PWM調(diào)光) | 10 | 背光 |
GND | GND | GND |
SCLK | 4/SCK | SPI時鐘 |
MOSI | 6/MOSI | 主機(jī)輸出,從機(jī)輸入 |
MISO | 5/MISO | 主機(jī)輸入,從機(jī)輸出 |
DC | 1 | 數(shù)據(jù)/命令 |
RES | 2 | 復(fù)位 |
CS | 7 | TFT片選 |
SDCS | 0 | SD卡片選 |
FCS | NC | 字庫 |
TCS | 3 | 觸摸 |
SCL | 9/SCL | I2C時鐘 |
SDA | 8/SDA | I2C數(shù)據(jù) |
INT | NC | INT |
BUSY-TE | NC | 防撕裂引腳 |
X1 | NC | 自定義引腳1 |
X2 | NC | 自定義引腳2 |
使用FPC鏈接屏幕時根據(jù)GDL demo配置所需對應(yīng)的引腳號即可,通常只需要根據(jù)不同主控配置三個引腳
支持GDI的顯示屏:
- 1.54" 240x240 IPS廣視角TFT顯示屏
- 2.0" 320x240 IPS廣視角TFT顯示屏
- 2.8" 320x240 IPS TFT電阻觸摸顯示屏
- 3.5" 480x320 IPS TFT電容觸摸顯示屏
- 1.51”OLED 透明屏幕
5. 首次使用
5.1 Arduino環(huán)境配置
當(dāng)您首次使用Beetle-ESP32-C3,您需要了解以下步驟
- 添加IDE中的json鏈接
- 下載主控的核心
- 選擇開發(fā)板以及串口
- 打開示例程序并燒錄
- 了解串口監(jiān)視器
Arduino IDE 編譯環(huán)境配置
配置URL網(wǎng)址到Arduino IDE
打開Arduino IDE,點(diǎn)擊File->Preferences,如下圖所示:
- 在新打開的界面中,點(diǎn)擊如下圖紅色圓圈中的按鈕
- 將如下鏈接地址復(fù)制到新彈出的對話框中:https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
- 注意:如果您之前安裝過其它的環(huán)境,那么您可以在上一個鏈接地址開頭或末尾處直接回車并將上面鏈接粘貼在其上下任意一行
- 點(diǎn)擊OK
- 更新板卡
- 打開Tools->Board:->Boards Manager...,如下圖所示:
- Boards Manager會自動更新板卡,如下圖所示:
- 更新完成后,您可以在上方輸入esp32,出現(xiàn)如下情況時選擇esp32點(diǎn)擊安裝即可(當(dāng)前安裝為2.0.0版本):
- 等待如下進(jìn)度條結(jié)束:
- 安裝完成后,列表會顯示已經(jīng)安裝esp32主板,如下圖所示:
- 點(diǎn)擊Tools->Board:,選擇ESP32C3 Dev Module(通常在列表第一個)
- 在開始前您還需要配置如下設(shè)置(當(dāng)您選擇 Disabled 時,串口為RX(20)、TX(21),如果您需要通過USB在Arduino監(jiān)視器上打印,您需要選擇Enable)
- 點(diǎn)擊Port選擇對應(yīng)的串口
5.2 LED閃爍
板載LED燈默認(rèn)為引腳10
代碼
int led = 10;
void setup() {
pinMode(led,OUTPUT);
}
void loop() {
digitalWrite(led,HIGH);
delay(1000);
digitalWrite(led,LOW);
delay(1000);
}
Copy
- 將以上程序粘貼到程序框中
- 點(diǎn)擊箭頭等待程序編譯并燒錄至開發(fā)板
燒錄成功
如圖所示及燒錄成功
您會看見板載LED燈開始閃爍
仍不能燒錄?請點(diǎn)擊此處
6. Beetle-ESP32C3基礎(chǔ)教程(此處介紹為Arduino之間的差別處)
- 想了解Arduino基礎(chǔ)?點(diǎn)擊此處
6.1 PWM輸出
ESP32C3的PWM功能需要提前定義聲明
ledcAttachPin(GPIO, Channel)
說明:指定信號將出現(xiàn)在哪些 GPIO 上
參數(shù):
- GPIO: 輸出信號的GPIO
- Channel: 生成信號的GPIO
ledcWrite(Channel, dutyCycle)
說明:設(shè)置PWM信號生成通道
參數(shù):
- Channel: 信號生成通道
- dutyCycle: PWM值
ledcSetup(Channel, freq, resolution)
說明:設(shè)置PWM信號生成通道
參數(shù):
- LedChannel: 信號生成通道
- freq: PWM頻率
- resolution: PWM分辨率
示例
ESPC3的PWM由于其可以自由映射到其它端口進(jìn)行輸出,您需要進(jìn)行幾步設(shè)置,該案例將使用幫助您理解其中的步驟 該案例你可以看到LED燈逐漸變亮變暗
/*
* LED呼吸燈示例
*/
const int ledPin = 10; // PWM生成后實(shí)際輸出引腳
//設(shè)置PWM參數(shù)
const int freq = 5000;//PWM頻率
const int ledChannel = 0;//信號生成GPIO
const int resolution = 8;//8位分辨率
void setup(){
//PWM參數(shù)設(shè)置
ledcSetup(ledChannel, freq, resolution);
//將生成信號通道綁定到輸出通道上
ledcAttachPin(ledPin, ledChannel);
}
void loop(){
//逐漸變亮
for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
//逐漸變暗
for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
}
Copy
6.2 中斷
ESP32C3中斷可自由分配
pinMode(GPIO,INPUT_PULLUP);
說明:外部中斷引腳定義
參數(shù):
- GPIO:ESP32C3想要作為中斷的引腳號。
- INPUT_PULLINGUP:設(shè)置為上拉模式。
attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)
說明:外部中斷
參數(shù):
- pin:Arduino引腳號。
- ISR:發(fā)生中斷時要調(diào)用的ISR;此函數(shù)必須不帶任何參數(shù),并且不返回任何內(nèi)容。有時將此功能稱為中斷服務(wù)程序。
- mode:定義何時觸發(fā)中斷。預(yù)定義了三個常數(shù)作為有效值:
- CHANGE 當(dāng)引腳電平發(fā)生變化時觸發(fā)中斷引腳
- RISING 當(dāng)引腳電平由低電平變?yōu)楦唠娖綍r觸發(fā)中斷引腳
- FALLING 當(dāng)引腳電平由高電平變?yōu)榈碗娖綍r觸發(fā)中斷引腳
detachInterrupt(digitalPinToInterrupt(pin))
說明:關(guān)閉給定的中斷。
參數(shù):
- pin:需要禁用的中斷引腳
interrupts()
說明:重新啟用中斷(在被noInterrupts()禁用之后。中斷允許某些重要任務(wù)在后臺發(fā)生并默認(rèn)啟用。當(dāng)禁用中斷時,某些功能將不起作用,并且傳入通信可能會被忽略。可能會稍微破壞代碼的時序,但是對于特別關(guān)鍵的代碼部分可能會被禁用。
noInterrupts()
說明:禁用中斷(您可以使用來重新啟用它們interrupts())。中斷允許某些重要任務(wù)在后臺發(fā)生,并且默認(rèn)情況下啟用。禁用中斷時,某些功能將不起作用,并且傳入的通信可能會被忽略。但是,中斷可能會稍微破壞代碼的時序,并且可能會在代碼的特別關(guān)鍵的部分將其禁用。
6.3 串口
ESP32C3串口初始化需要映射
- Serial1.begin(baud, config, rxPin, txPin);
說明:Serial1初始化
參數(shù):- baud:波特率。
- config:數(shù)據(jù)位和停止位設(shè)置。
- rxPin:RX引腳
- txPin:TX引腳
Serial1.begin(9600,SERIAL_8N1,/*rx =*/0,/*Tx =*/1);
Copy
6.4 舵機(jī)
ESP32-C3通過Servo庫不能驅(qū)動舵機(jī),可以在項(xiàng)目->加載庫->管理庫中搜索安裝ESP32_C3_ISR_Servo庫驅(qū)動舵機(jī)
7.進(jìn)階教程
7.1 使用SD庫
SD類
begin(cspin)
說明:初始化SD卡庫和 SD卡。當(dāng)使用SD.begin()時﹐默認(rèn)將Arduino SPI的SS引腳連接到SD卡的CS使能選擇端;也可以使用begin(cspin)指定一個引腳連接到SD卡的CS使能選擇端,但仍需保證 SPI 的SS引腳為輸出模式,否則SD卡庫將無法運(yùn)行。
參數(shù):cspin:連接到SD 卡CS端的Arduino引腳。
返回值: boolean型值,為 true表示初始化成功;為 false表示初始化失敗。
exists()
說明:檢查文件或文件夾是否存在于SD卡中。語法:SD. exists( filename)
參數(shù): filename:需要檢測的文件名。其中可以包含路徑,路徑用“/”分隔。
返回值: boolean型值,為 true表示文件或文件夾存在;為false表示文件或文件夾不存在。
open()
說明:打開SD卡上的一個文件。如果文件不存在,且以寫入方式打開,則Arduino會創(chuàng)建一個指定文件名的文件。(所在路徑必須事先存在)
語法:SD.open( filename)SD.open(filename,mode)
參數(shù):
filename:需要打開的文件名。其中可以包含路徑,路徑用“/”分隔。
mode(可選):打開文件的方式,默認(rèn)使用只讀方式打開。也可以使用以下兩種方式打開文件:
FILE_READ:只讀方式打開文件;FILE_WRITE,寫入方式打開文件。
返回值:返回被打開文件對應(yīng)的對象﹔如果文件不能打開,則返回false。
FILE_WRITE,寫入方式打開文件。
返回值:返回被打開文件對應(yīng)的對象;如果文件不能打開,則返回false。
remove()
說明:從SD卡移除一個文件。如果文件不存在,則函數(shù)返回值是不確定的,因此在移除文件之前,最好使用SD. exists(filename)先檢測文件是否存在。
語法:SD. remove( filename)
參數(shù): filename,需要移除的文件名。其中可以包含路徑,路徑用“!”分隔。
返回值: boolean型值,為true表示文件移除成功;為false表示文件移除失敗。
mkdir(filename)
說明:創(chuàng)建文件夾。
參數(shù):
- filename,需要創(chuàng)建的文件夾名。其中可以包含路徑,路徑用“/”分隔。返回值: boolean型值,為 true表示創(chuàng)建成功;為false表示創(chuàng)建失敗。
rmdir(filename)
說明:移除文件夾。被移除的文件夾必須是空的。語法:SD.rmdir( filename)
參數(shù):
- filename,需要移除的文件夾名。其中可以包含路徑,路徑用“/”分隔。
- 返回值* : boolean型值,為 true表示移除成功;為false表示移除失敗。
File類
File類提供了讀/寫文件的功能,該類的功能與之前使用的串口相關(guān)函數(shù)的功能非常類似。其成員函數(shù)如下。
available()
說明:檢查當(dāng)前文件中可讀數(shù)據(jù)的字節(jié)數(shù)。語法:file. available()
參數(shù):
- file:一個 File類型的對象。返回值:可用字節(jié)數(shù)。
close()
說明:關(guān)閉文件,并確保數(shù)據(jù)已經(jīng)被完全寫入SD卡中。語法:file. close()
參數(shù):
- file:一個 File類型的對象。返回值:無。
flush()
說明:確保數(shù)據(jù)已經(jīng)寫入SD卡。當(dāng)文件被關(guān)閉時,flush()會自動運(yùn)行。語法: file.flush
參數(shù):
- file:一個File類型的對象。返回值:無。
peek()
說明:讀取當(dāng)前所在字節(jié),但并不移動到下一個字節(jié)。
參數(shù)
- file:一個 File類型的對象。
- 返回值*:下一個字節(jié)或者下一個字符。如果沒有可讀數(shù)據(jù),則返回一1。
position( )
說明:獲取當(dāng)前在文件中的位置(即下一個被讀/寫的字節(jié)的位置)。語法:file. position()
參數(shù):
- file:一個 File類型的對象。返回值:在當(dāng)前文件中的位置。
print()
說明:輸出數(shù)據(jù)到文件。要寫入的文件應(yīng)該已經(jīng)被打開,且等待寫入。語法:file. print(data)file. print(data,BASE)
參數(shù):
- file:一個 File類型的對象。
- data,要寫入的數(shù)據(jù)(可以是類型char, byte ,int .long 或 String)。
- BASE(可選),指定數(shù)據(jù)的輸出形式:BIN(二進(jìn)制);oCT(八進(jìn)制);DEC(十進(jìn)制);HEX(十六進(jìn)制)。 返回值;發(fā)送的字節(jié)數(shù)。
println()
說明:輸出數(shù)據(jù)到文件,并回車換行。語法:file. println(data)file,println(data,BASE)
參數(shù):
- file:一個 File類型的對象。
- data:要寫入的數(shù)據(jù)(類型可以是char , byte , int , long或String)。
- BASE(可選),指定數(shù)據(jù)的輸出形式:BIN(二進(jìn)制>;OCT(八進(jìn)制);DECK十進(jìn)制;HEX(十六進(jìn)制)返回值;發(fā)送的宇節(jié)數(shù)。
seek()
說明;跳轉(zhuǎn)到指定位置。該位置必須在·到該文件大小之間。語法:file. seek( pos)
參數(shù):
- file:一個 File類型的對象。pos,需要查找的位置。
- 返回值*: boolean型值,為 true表示跳轉(zhuǎn)成功;為false表示跳轉(zhuǎn)失敗。
size()
說明:獲取文件的大小。語法:filue. size()
參數(shù):
- file:一個File類型的對象。
- 返回值*:以字節(jié)為單位的文件大小。
read()
說明:讀取1B數(shù)據(jù)。語法:file.read參數(shù):
- file:一個 File類型的對象。
- 返回值*:下一個字節(jié)或者字符;如果沒有可讀數(shù)據(jù),則返回一1。
write()
說明;寫入數(shù)據(jù)到文件。語法:file. write(data)file. write(buf,len)
參數(shù):
- file:一個File類型的對象。
- data:要寫入的數(shù)據(jù),類型可以是 byte ,char或字符串(char * ) 。buf,一個字符數(shù)組或者寧節(jié)數(shù)據(jù)。
- len:buf數(shù)組的元素個數(shù)。
- 返回值*:發(fā)送的字節(jié)數(shù)。
isDirectory()
說明:判斷當(dāng)前文件是否為目錄。語法:file.isDirectory()
參數(shù):
- file:一個File類型的對象。
- 返回值*: boolcan型值;為 true表示是目錄;為 false表示不是目錄。
openNextFile()
說明:打開下一個文件。語法:file.openNextFile()
參數(shù):
- file:一個 File類型的對象。
- 返回值*:下一個文件對應(yīng)的對象。
rewindDirectory()
說明:回到當(dāng)前目錄中的第一個文件。語法:file.rewindDirectory()
參數(shù): file,一個File類型的對象。返回值:無。
7.2 ESP32-C3藍(lán)牙收發(fā)
7.2.1 ESP32-C3與手機(jī)藍(lán)牙通信
使用該實(shí)例演示ESP32-C3與手機(jī)之間的數(shù)據(jù)傳輸,如果需要修改或使用數(shù)據(jù),只需更改數(shù)據(jù)接收部分或數(shù)據(jù)發(fā)送部分代碼
/*
Video: https://www.youtube.com/watch?v=oCMOYS71NIU
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleNotify.cpp
Ported to Arduino ESP32 by Evandro Copercini
Create a BLE server that, once we receive a connection, will send periodic notifications.
The service advertises itself as: 6E400001-B5A3-F393-E0A9-E50E24DCCA9E
Has a characteristic of: 6E400002-B5A3-F393-E0A9-E50E24DCCA9E - used for receiving data with "WRITE"
Has a characteristic of: 6E400003-B5A3-F393-E0A9-E50E24DCCA9E - used to send data with "NOTIFY"
The design of creating the BLE server is:
1. Create a BLE Server
2. Create a BLE Service
3. Create a BLE Characteristic on the Service
4. Create a BLE Descriptor on the characteristic
5. Start the service.
6. Start advertising.
*/
/* 該示例演示了藍(lán)牙數(shù)據(jù)透傳,燒錄代碼,打開串口監(jiān)視器,打開手機(jī)的BLE調(diào)試助手
* 1.即可看見ESP32-C3發(fā)送的數(shù)據(jù)--見APP使用圖
* 2.通過BLE調(diào)試助手的輸入框可向ESP32-C3發(fā)送數(shù)據(jù)--見APP使用圖
* 該示例由BLE_uart示例更改而來
*/
#include
#include
#include
#include
BLEServer *pServer = NULL;
BLECharacteristic * pTxCharacteristic;
bool deviceConnected = false;
uint8_t txValue = 0;
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"
//藍(lán)牙連接/斷開處理。當(dāng)有連接/斷開事件發(fā)生時自動觸發(fā)
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) { //當(dāng)藍(lán)牙連接時會執(zhí)行該函數(shù)
Serial.println("藍(lán)牙已連接");
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) { //當(dāng)藍(lán)牙斷開連接時會執(zhí)行該函數(shù)
Serial.println("藍(lán)牙已斷開");
deviceConnected = false;
delay(500); // give the bluetooth stack the chance to get things ready
pServer->startAdvertising(); // restart advertising
}
};
/****************數(shù)據(jù)接收部分*************/
/****************************************/
//藍(lán)牙接收數(shù)據(jù)處理。當(dāng)收到數(shù)據(jù)時自動觸發(fā)
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();//接收數(shù)據(jù),并賦給rxValue
//if(rxValue == "ON"){Serial.println("開燈");} //判斷接收的字符是否為"ON"
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++){
Serial.print(rxValue[i]);
}
Serial.println();
Serial.println("*********");
}
}
};
/***************************************/
/****************************************/
void setup() {
Serial.begin(115200);
BLEBegin(); //初始化藍(lán)牙
}
void loop() {
/****************數(shù)據(jù)發(fā)送部分*************/
/****************************************/
if (deviceConnected) { //如果有藍(lán)牙連接,就發(fā)送數(shù)據(jù)
pTxCharacteristic->setValue("Hello"); //發(fā)送字符串
pTxCharacteristic->notify();
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
pTxCharacteristic->setValue("DFRobot"); //發(fā)送字符串
pTxCharacteristic->notify();
delay(10); // bluetooth stack will go into congestion, if too many packets are sent
}
/****************************************/
/****************************************/
}
void BLEBegin(){
// Create the BLE Device
BLEDevice::init(/*BLE名稱*/"UART Service");
// Create the BLE Server
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);
// Create a BLE Characteristic
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
BLECharacteristic * pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
// Start the service
pService->start();
// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");
}
Copy
7.2.2 兩個ESP32C3藍(lán)牙通訊
使用該實(shí)例演示ESP32-C3與ESP32-C3之間的數(shù)據(jù)傳輸,如果需要修改或使用數(shù)據(jù),只需更改數(shù)據(jù)接收部分或數(shù)據(jù)發(fā)送部分代碼
主機(jī)代碼
/**
* A BLE client example that is rich in capabilities.
* There is a lot new capabilities implemented.
* author unknown
* updated by chegewara
*/
#include "BLEDevice.h"
//#include "BLEScan.h"
// The remote service we wish to connect to.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The characteristic of the remote service we are interested in.
static BLEUUID charTXUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");
static BLEUUID charRXUUID("beb5483f-36e1-4688-b7f5-ea07361b26a8");
static boolean doConnect = false;
static boolean connected = false;
static boolean doScan = false;
static BLERemoteCharacteristic* pTXRemoteCharacteristic;
static BLERemoteCharacteristic* pRXRemoteCharacteristic;
static BLEAdvertisedDevice* myDevice;
/****************數(shù)據(jù)接收部分*************/
/****************************************/
//藍(lán)牙接收數(shù)據(jù)處理,當(dāng)收到數(shù)據(jù)時自動觸發(fā)
static void notifyCallback(BLERemoteCharacteristic* pBLERemoteCharacteristic, uint8_t* pData, size_t length, bool isNotify) { //傳入uint8_t* pData用于存放數(shù)據(jù)
String BLEData = "";
for(int i = 0; i < length; i++) //
BLEData += (char)pData[i];
Serial.println("*********");
Serial.print("Received Value: ");
Serial.println(BLEData);
Serial.println("*********");
//if(BLEData == "ON"){Serial.println("開燈");} //判斷接收的字符是否為"ON"
//Serial.print("Notify callback for characteristic ");
//Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
//Serial.print(" of data length ");
//Serial.println(length);
}
/****************************************/
/****************************************/
//藍(lán)牙連接/斷開處理。當(dāng)有連接/斷開事件發(fā)生時自動觸發(fā)
class MyClientCallback : public BLEClientCallbacks {
void onConnect(BLEClient* pclient) {
}
void onDisconnect(BLEClient* pclient) {
connected = false;
Serial.println("onDisconnect");
}
};
/**
* Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
//藍(lán)牙掃描處理事件。當(dāng)開啟掃描時自動觸發(fā)
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
/**
* Called for each advertising BLE server.
*/
void onResult(BLEAdvertisedDevice advertisedDevice) {
//Serial.print("BLE Advertised Device found: ");
//Serial.println(advertisedDevice.toString().c_str());
// We have found a device, let us now see if it contains the service we are looking for.
if (advertisedDevice.haveServiceUUID() && advertisedDevice.isAdvertisingService(serviceUUID)) {
BLEDevice::getScan()->stop();
myDevice = new BLEAdvertisedDevice(advertisedDevice);
doConnect = true;
doScan = true;
} // Found our server
} // onResult
}; // MyAdvertisedDeviceCallbacks
void setup() {
Serial.begin(115200);
Serial.println("Starting Arduino BLE Client application...");
bleBegin();
}
void loop() {
// If the flag "doConnect" is true then we have scanned for and found the desired
// BLE Server with which we wish to connect. Now we connect to it. Once we are
// connected we set the connected flag to be true.
if (doConnect == true) {
if (connectToServer()) {
Serial.println("We are now connected to the BLE Server.");
} else {
Serial.println("We have failed to connect to the server; there is nothin more we will do.");
}
doConnect = false;
}
/****************數(shù)據(jù)發(fā)送部分*************/
/****************************************/
if (connected) { //當(dāng)連接到藍(lán)牙從機(jī)時發(fā)送數(shù)據(jù)
pTXRemoteCharacteristic->writeValue("我是主機(jī)");
pTXRemoteCharacteristic->writeValue("Hello client");
}
if(!connected){ //當(dāng)沒有連接到藍(lán)牙從機(jī)時重新掃描
BLEDevice::getScan()->start(5,false); // this is just example to start scan after disconnect, most likely there is better way to do it in arduino
}
/****************************************/
/****************************************/
delay(1000);
}
void bleBegin()
{
BLEDevice::init("");
// Retrieve a Scanner and set the callback we want to use to be informed when we
// have detected a new device. Specify that we want active scanning and start the
// scan to run for 5 seconds.
BLEScan* pBLEScan = BLEDevice::getScan();
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());//掃描處理函數(shù)
pBLEScan->setInterval(1349);//設(shè)置掃描間隔時間
pBLEScan->setWindow(449);//主動掃描時間
pBLEScan->setActiveScan(true);
pBLEScan->start(5, false);//掃描時間,單位秒
}
//藍(lán)牙連接處理
bool connectToServer() {
Serial.print("Forming a connection to ");
Serial.println(myDevice->getAddress().toString().c_str());
BLEClient* pClient = BLEDevice::createClient();
Serial.println(" - Created client");
pClient->setClientCallbacks(new MyClientCallback());
// Connect to the remove BLE Server.
pClient->connect(myDevice); // if you pass BLEAdvertisedDevice instead of address, it will be recognized type of peer device address (public or private)
Serial.println(" - Connected to server");
pClient->setMTU(517); //set client to request maximum MTU from server (default is 23 otherwise)
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
if (pRemoteService == nullptr) {
Serial.print("Failed to find our service UUID: ");
Serial.println(serviceUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pTXRemoteCharacteristic = pRemoteService->getCharacteristic(charTXUUID);
if (pTXRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charTXUUID.toString().c_str());
pClient->disconnect();
return false;
}
pRXRemoteCharacteristic = pRemoteService->getCharacteristic(charRXUUID);
if (pRXRemoteCharacteristic == nullptr) {
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(charRXUUID.toString().c_str());
pClient->disconnect();
return false;
}
Serial.println(" - Found our characteristic");
if(pRXRemoteCharacteristic->canNotify())
pRXRemoteCharacteristic->registerForNotify(notifyCallback);
connected = true;
return true;
}
Copy
從機(jī)代碼
/*
Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
Ported to Arduino ESP32 by Evandro Copercini
updates by chegewara
*/
#include
#include
#include
#include
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID_RX "beb5483e-36e1-4688-b7f5-ea07361b26a8"
#define CHARACTERISTIC_UUID_TX "beb5483f-36e1-4688-b7f5-ea07361b26a8"
uint8_t txValue = 0;
bool deviceConnected = false;
BLECharacteristic *pTxCharacteristic;
//藍(lán)牙連接/斷開處理。當(dāng)有連接/斷開事件發(fā)生時自動觸發(fā)
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) { //當(dāng)藍(lán)牙連接時會執(zhí)行該函數(shù)
Serial.println("藍(lán)牙已連接");
deviceConnected = true;
};
void onDisconnect(BLEServer* pServer) { //當(dāng)藍(lán)牙斷開連接時會執(zhí)行該函數(shù)
Serial.println("藍(lán)牙已斷開");
deviceConnected = false;
delay(500); // give the bluetooth stack the chance to get things ready
BLEDevice::startAdvertising(); // restart advertising
}
};
/****************數(shù)據(jù)接收部分*************/
/****************************************/
//藍(lán)牙接收數(shù)據(jù)處理。當(dāng)收到數(shù)據(jù)時自動觸發(fā)
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue(); //使用rxValue接收數(shù)據(jù)
//if(rxValue == "ON"){Serial.println("開燈");} //判斷接收的字符是否為"ON"
if (rxValue.length() > 0) {
Serial.println("*********");
Serial.print("Received Value: ");
for (int i = 0; i < rxValue.length(); i++)
Serial.print(rxValue[i]); //將接收的數(shù)據(jù)打印出來
Serial.println();
Serial.println("*********");
}
}
};
/****************************************/
/****************************************/
void setup() {
Serial.begin(115200);
Serial.println("Starting BLE work!");
bleBegin();
}
/****************數(shù)據(jù)發(fā)送部分*************/
/****************************************/
void loop() {
if(deviceConnected){ //當(dāng)有設(shè)備連接時發(fā)送數(shù)據(jù)
pTxCharacteristic->setValue("我是從機(jī)");
pTxCharacteristic->notify();
pTxCharacteristic->setValue("Hello Sever");
pTxCharacteristic->notify();
}
/****************************************/
/****************************************/
delay(1000);
}
void bleBegin()
{
BLEDevice::init(/*BLE名稱*/"Long name works now");
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
BLEService *pService = pServer->createService(SERVICE_UUID);
BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);
pRxCharacteristic->setCallbacks(new MyCallbacks());
pTxCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);
pTxCharacteristic->addDescriptor(new BLE2902());
pService->start();
// BLEAdvertising *pAdvertising = pServer->getAdvertising(); // this still is working for backward compatibility
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // functions that help with iPhone connections issue
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
}
Copy
7.3 WIFI控制LED
ESP32C3具有WIFI功能,以下示例使用ESP32C3創(chuàng)建了一個wifi服務(wù)器,使用客戶端連接到該服務(wù)器,控制LED的亮滅
步驟
1.連接到WIFI”Beetle ESP32 C3“,已設(shè)置WIFI密碼:12345678
2.訪問網(wǎng)址 http://192.168.4.1/ON 來打開燈 訪問 http://192.168.4.1/OFF 來關(guān)閉燈
3.在訪問后通過點(diǎn)擊上下 here 來便捷控制燈的亮滅而不需要輸入網(wǎng)址進(jìn)行
代碼
/*
步驟:
1.連接到WIFI”Beetle ESP32 C3“,已設(shè)置WIFI密碼:12345678
2.訪問網(wǎng)址 http://192.168.4.1/ON 來打開燈 訪問 http://192.168.4.1/OFF 來關(guān)閉燈
3.在訪問后通過點(diǎn)擊上下 here 來便捷控制燈的亮滅而不需要輸入網(wǎng)址進(jìn)行
*/
#include
#include
#include
#define myLED 10 //設(shè)置引腳10為LED引腳
// 設(shè)置WIFI名稱以及密碼
const char *ssid = "Beetle ESP32 C3";//WIFI名稱
const char *password = "12345678";//密碼
WiFiServer server(80);//網(wǎng)頁服務(wù)端口默認(rèn)為80
void setup() {
pinMode(myLED, OUTPUT);
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
//如果想要無密碼開放網(wǎng)絡(luò)請刪除password
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
}
void loop() {
WiFiClient client = server.available(); // 檢測等待連接
if (client) { // 檢測是否連接
Serial.println("New Client.");
String currentLine = ""; // 創(chuàng)建String變量來保存數(shù)據(jù)
while (client.connected()) { // 保持連接時一直循環(huán)
if (client.available()) { // 檢測連接是否有數(shù)據(jù)
char c = client.read(); // 讀取接收的數(shù)據(jù)
//Serial.write(c); // 打印在串行監(jiān)視器
if (c == '\n') { // 如果讀取的是換行符
//結(jié)尾用換行符提醒結(jié)束
if (currentLine.length() == 0) {
client.println("HTTP/1.1 200 OK");
client.println("Content-type:text/html");
client.println();
//將字符與here連接
client.print("Click here to turn ON the LED.");
client.print("Click here to turn OFF the LED.");
// HTTP響應(yīng)為空行
client.println();
// 跳出循環(huán)
break;
} else { // 如果有一個換行符就清除變量緩存的數(shù)據(jù)
currentLine = "";
}
} else if (c != '\r') { // 如果獲得回車以外的字符
currentLine += c; // 獲得的字符添加到變量末尾
}
// 檢查是否獲得/ON或者/OFF
if (currentLine.endsWith("/ON")) {
digitalWrite(myLED, HIGH); //得到/ON時打開燈
}
if (currentLine.endsWith("/OFF")) {
digitalWrite(myLED, LOW); //得到/OFF時關(guān)閉燈
}
}
}
// 關(guān)閉連接
client.stop();
Serial.println("Client Disconnected.");
}
}
Copy
結(jié)果
使用手機(jī)連接該wifi,通過瀏覽器訪問192.168.4.1,如圖所示顯示ip地址為192.168.4.1,服務(wù)已開啟
使用瀏覽器訪問該ip地址得到如下圖所示
嘗試分別點(diǎn)擊鏈接控制LED吧
成員函數(shù)
WiFiServer server()
說明:設(shè)置服務(wù)器端口
softAP(ssid,password)
說明:將WiFi配置為AP模式,并設(shè)置名稱以及密碼
參數(shù):
- ssid: AP模式的wifi名字
- password: ap模式的wifi密碼
server.available()
說明:檢測服務(wù)端口是否有連接(WIFI是否連接)
client.connected()
說明:檢測連接狀態(tài)
返回值:true/false
client.available()
說明:檢測連接WIFI是否有數(shù)據(jù)輸入
client.read()
說明*:讀取WIFI接收數(shù)據(jù)
currentLine.endsWith()
說明*:檢測是否獲得括號內(nèi)容
client.stop()
說明*:斷開連接
8.應(yīng)用示例拓展
8.1 OLED顯示測量溫濕度
獲取溫濕度顯示在OLED屏幕上是非常直觀有趣的項(xiàng)目,下面你將學(xué)會基礎(chǔ)的OLED顯示以及使用I2C接口獲取溫濕度傳感器數(shù)據(jù)。
您還需準(zhǔn)備
- 0.96”128x64 IIC/SPI OLED單色顯示屏 x1
- 母母頭杜邦線 若干
- FermionSHT30溫濕度傳感器 x1 (或使用相同SHT3x代碼庫其它SHT溫濕度傳感器)
1.您需要先安裝SHT3x庫
關(guān)于如何安裝庫點(diǎn)擊這里
2.接線圖
按照上圖連接好線拷貝下面代碼,您將看見你周圍的溫濕度狀況。
代碼
#include
#include //導(dǎo)入字庫
//#include
#include
#include
/*
---顯示屏硬件I2C接口---
U8G2_R0 不旋轉(zhuǎn),橫向,繪制方向從左到右
U8G2_R1 順時針旋轉(zhuǎn)90度,繪制方向從上到下
U8G2_R2 順時針旋轉(zhuǎn)180度,繪制方向從右到左
U8G2_R3 順時針旋轉(zhuǎn)270度,繪制方向從下到上
U8G2_MIRROR 正常顯示鏡像內(nèi)容(v2.6.x版本以上使用) 注意:U8G2_MIRROR需要與setFlipMode()配搭使用.
U8x8_PIN_NONE 表示引腳為空,不會使用復(fù)位引腳
---顯示屏硬件SPI接口---
cs 按引腳接上即可(引腳可自己選擇)
dc 按引腳接上即可(引腳可自己選擇)
*/
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(/* rotation=*/U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
//當(dāng)ADR接VDD時可選擇0x45當(dāng)ADR接GND時可選擇0x44
//默認(rèn)為0x45,RST(復(fù)位腳)不用連接
DFRobot_SHT3x sht3x(&Wire,/*address=*/0x45,/*RST=*/4);
//使用SPI需要注釋上方代碼,使用下方代碼
//DFRobot_SHT3x sht3x;
void setup() {
Serial.begin(115200);
u8g2.begin();
u8g2.setFontPosTop();//使用drawStr顯示字符串時,默認(rèn)標(biāo)準(zhǔn)為顯示字符的左下角坐標(biāo)。本函數(shù)的功能可理解為將坐標(biāo)位置改為顯示字符串的左上角為坐標(biāo)標(biāo)準(zhǔn)。
//初始化傳感器
while (sht3x.begin() != 0) {
Serial.println("Failed to Initialize the chip, please confirm the wire connection");
delay(1000);
}
Serial.print("Chip serial number");
Serial.println(sht3x.readSerialNumber());
if(!sht3x.softReset()){
Serial.println("Failed to Initialize the chip....");
}
}
void loop() {
//清理屏幕
u8g2.clearBuffer();
//將溫度、濕度讀取賦值用于顯示
float temp = sht3x.getTemperatureC();
float humi = sht3x.getHumidityRH();
//顯示溫度
u8g2.setFont(u8g2_font_osb18_tf); // 選擇字體以及大?。ㄒ姽俜剑? u8g2.drawStr(5,10,"Temp");//在指定位置寫出字符
u8g2.setFont(u8g2_font_t0_18b_tr);
u8g2.setCursor(75, 15);//顯示從該位置開始
u8g2.print(temp);
//顯示濕度
u8g2.setFont(u8g2_font_osb18_tf);
u8g2.drawStr(5,40,"Humi");
u8g2.setFont(u8g2_font_t0_18b_tr);
u8g2.setCursor(75, 45);
u8g2.print(humi);
u8g2.sendBuffer();
delay(1000);
}
Copy
結(jié)果
成員函數(shù)
u8g2.drawStr(x,y,"Temp")
說明:指定屏幕位置顯示自定義內(nèi)容
參數(shù):
- X、Y: 開始寫的坐標(biāo)(顯示字體從左下角向右上角顯示)
- "Temp": 可填英文和數(shù)字
u8g2.setCursor(x,y)和u8g2.print()
說明:搭配使用,前者為顯示開始位置,后者同Arduino的print相同作用
參數(shù):
- X、Y: 開始寫的坐標(biāo)(顯示字體從左下角向右上角顯示)
8.2 WIFI獲取溫濕度
本示例參照示例8.3而來,進(jìn)一步學(xué)會局域網(wǎng)下Wifi的信息傳遞,你可以學(xué)會如何訪問局域網(wǎng)下的IP地址來獲得在另一處的SHT30的溫濕度傳感器狀態(tài)
您還需準(zhǔn)備
- FermionSHT30溫濕度傳感器 x1 (或使用相同SHT3x代碼庫其它SHT溫濕度傳感器)
- 母母頭杜邦線 若干
您還需要按照示例9.1中步驟安裝傳感器庫以及將其與ESP32連接。
接線圖
步驟
1.連接到WIFI”Beetle ESP32 C3“,已設(shè)置WIFI密碼:12345678
2.訪問網(wǎng)址 http://192.168.4.1/GET 來獲取局域網(wǎng)中的溫濕度信息
3.在溫濕度顯示網(wǎng)頁您可以通過刷新來更新傳感器的數(shù)據(jù)
代碼
/*
本示例是SHT30連接上ESPC3通過局域網(wǎng)獲取溫濕度
*/
#include
#include
#include
#include
//當(dāng)ADR接VDD時可選擇0x45當(dāng)ADR接GND時可選擇0x44
//默認(rèn)為0x45,RST(復(fù)位腳)不用連接
DFRobot_SHT3x sht3x(&Wire,/*address=*/0x45,/*RST=*/4);
//使用SPI需要注釋上方代碼,使用下方代碼
//DFRobot_SHT3x sht3x;
// 設(shè)置WIFI名稱以及密碼
const char *ssid = "Beetle ESP32 C3";//WIFI名稱
const char *password = "12345678";//密碼
WiFiServer server(80);//網(wǎng)頁服務(wù)端口默認(rèn)為80
// 顯示上次傳感器狀態(tài)反饋狀態(tài)
void setup() {
//pinMode(myLED, OUTPUT);
Serial.begin(115200);
Serial.println();
Serial.println("Configuring access point...");
//如果想要無密碼開放網(wǎng)絡(luò)請刪除password
WiFi.softAP(ssid, password);
IPAddress myIP = WiFi.softAPIP();
Serial.print("AP IP address: ");
Serial.println(myIP);
server.begin();
Serial.println("Server started");
//初始化傳感器
while (sht3x.begin() != 0) {
Serial.println("Failed to Initialize the chip, please confirm the wire connection");
delay(1000);
}
Serial.print("Chip serial number");
Serial.println(sht3x.readSerialNumber());
if(!sht3x.softReset()){
Serial.println("Failed to Initialize the chip....");
}
}
void loop() {
WiFiClient client = server.available(); // 檢測等待連接
if (client) { // 檢測是否連接
Serial.println("New Client.");
String currentLine = ""; // 創(chuàng)建String變量來保存數(shù)據(jù)
while (client.connected()) { // 保持連接時一直循環(huán)
if (client.available()) { // 檢測連接是否有數(shù)據(jù)
char c = client.read(); // 讀取接收的數(shù)據(jù)
//Serial.write(c); // 打印在串行監(jiān)視器
if (c == '\n') { // 如果讀取的是換行符
//清除掉緩存的內(nèi)容
if (currentLine.length() == 0) {
client.print(" ");
break;
} else { // 如果有一個換行符就清除變量緩存的數(shù)據(jù)
currentLine = "";
}
} else if (c != '\r') { // 如果獲得回車以外的字符
currentLine += c; // 獲得的字符添加到變量末尾
}
// 檢查是否有/GET在末尾
if (currentLine.endsWith("/GET")) {
//把溫度、濕度讀出
float temp = sht3x.getTemperatureC();
float humi = sht3x.getHumidityRH();
//打印在網(wǎng)頁
client.print("temp (C): "); client.println(temp);
client.print("humi (%RH): "); client.println(humi);
}
}
}
// 關(guān)閉連接
client.stop();
Serial.println("Client Disconnected.");
}
}
Copy
結(jié)果
您可以通過手機(jī),電腦等訪問網(wǎng)址以獲得如下結(jié)果(局域網(wǎng)下的溫濕度傳感器的溫濕度)。
成員函數(shù)
WiFi.softAP(ssid, password)
說明:類似將設(shè)置好的WIFI賬號密碼開熱點(diǎn)
參數(shù):
- ssid: WIFI名
- password: WIFI密碼
WiFi.softAPIP()
說明:WIFI的IP地址
8.3 WIFI獲取網(wǎng)絡(luò)時間
本實(shí)例演示了從網(wǎng)絡(luò)時間服務(wù)器獲取時間,并使用ESP32自帶的RTC時鐘保持時間更新
本示例來自CSDN博主「Naisu Xu」,原文鏈接:https://blog.csdn.net/Naisu_kun/article/details/115627629
#include
const char *ssid = "********"; //WIFI名稱
const char *password = "********"; //WIFI密碼
const char *ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600;
const int daylightOffset_sec = 0;
void printLocalTime()
{
struct tm timeinfo;
if (!getLocalTime(&timeinfo))
{
Serial.println("Failed to obtain time");
return;
}
Serial.println(&timeinfo, "%F %T %A"); // 格式化輸出
}
void setup()
{
Serial.begin(115200);
Serial.println();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println("WiFi connected!");
// 從網(wǎng)絡(luò)時間服務(wù)器上獲取并設(shè)置時間
// 獲取成功后芯片會使用RTC時鐘保持時間的更新
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
printLocalTime();
WiFi.disconnect(true);
WiFi.mode(WIFI_OFF);
Serial.println("WiFi disconnected!");
}
void loop()
{
delay(1000);
printLocalTime();
}
Copy
struct tm結(jié)構(gòu)體
struct tm {
int tm_sec; // 秒,取值0~59;
int tm_min; // 分,取值0~59;
int tm_hour; // 時,取值0~23;
int tm_mday; // 月中的日期,取值1~31;
int tm_mon; // 月,取值0~11;
int tm_year; // 年,其值等于實(shí)際年份減去1900;
int tm_wday; // 星期,取值0~6,0為周日,1為周一,依此類推;
int tm_yday; // 年中的日期,取值0~365,0代表1月1日,1代表1月2日,依此類推;
int tm_isdst; // 夏令時標(biāo)識符,實(shí)行夏令時的時候,tm_isdst為正;不實(shí)行夏令時的進(jìn)候,tm_isdst為0;不了解情況時,tm_isdst()為負(fù)
};
struct tm結(jié)構(gòu)體格式化輸出
格式化字符 | 輸出 |
---|---|
%a | 星期幾的簡寫 |
%A | 星期幾的全稱 |
%b | 月份的簡寫 |
%B | 月份的全稱 |
%c | 標(biāo)準(zhǔn)的日期的時間串 |
%C | 年份的后兩位數(shù)字 |
%d | 十進(jìn)制表示的每月的第幾天 |
%D | 月/天/年 |
%e | 在兩字符域中,十進(jìn)制表示的每月的第幾天 |
%F | 年-月-日 |
%g | 年份的后兩位數(shù)字,使用基于周的年 |
%G | 年分,使用基于周的年 |
%h | 簡寫的月份名 |
%H | 24小時制的小時 |
%I | 12小時制的小時 |
%j | 十進(jìn)制表示的每年的第幾天 |
%m | 十進(jìn)制表示的月份 |
%M | 十時制表示的分鐘數(shù) |
%p | 本地的AM或PM的等價(jià)顯示 |
%r | 12小時的時間 |
%R | 顯示小時和分鐘:hh:mm |
%S | 十進(jìn)制的秒數(shù) |
%t | 水平制表符 |
%T | 顯示時分秒:hh:mm:ss |
%u | 每周的第幾天,星期一為第一天 (值從0到6,星期一為0) |
%U | 第年的第幾周,把星期日做為第一天(值從0到53) |
%V | 每年的第幾周,使用基于周的年 |
%w | 十進(jìn)制表示的星期幾(值從0到6,星期天為0) |
%W | 每年的第幾周,把星期一做為第一天(值從0到53) |
%x | 標(biāo)準(zhǔn)的日期串 |
%X | 標(biāo)準(zhǔn)的時間串 |
%y | 不帶世紀(jì)的十進(jìn)制年份(值從0到99) |
%Y | 帶世紀(jì)部分的十進(jìn)制年份 |
%z | 時區(qū)名稱,如果不能得到時區(qū)名稱則返回空字符 |
8.4 WIFI獲取天氣
本示例用于讓你學(xué)會如何獲取天氣信息并讓你體會HTTP中獲取的信息通過Json提取數(shù)據(jù)并打印的
- 燒錄代碼前我們進(jìn)行以下幾個步驟
1.您需要安裝Arduino_JSON庫。通過 Arduino IDE Tools -> Manage Libraries 中輸入 Arduino_JSON 并安裝該庫
2.注冊O(shè)penWeather的賬號以獲取我們想要的天氣信息 打開瀏覽器并轉(zhuǎn)到 https://openweathermap.org/appid/ 按注冊按鈕并創(chuàng)建一個免費(fèi)帳戶。
點(diǎn)擊 My API Keys 進(jìn)入獲取API界面
復(fù)制這里的Key(這個Key是你從OpenWeather上獲取天氣信息的唯一鑰匙)
你可以將Key填入以下URL并填寫城市名以及它的國家以獲取城市天氣信息
http://api.openweathermap.org/data/2.5/weather?q=yourCityName,yourCountryCode&APPID=yourAPIkey
下面做個示例更換yourCityName你想要的數(shù)據(jù)的城市(比如成都),yourCountryCode與該城市的國家代碼(比如CN),填入yourAPIkey就是前面獲得的API密鑰,下面為中國成都加上API后的URL:
http://api.openweathermap.org/data/2.5/weather?q=ChengDu,CN&APPID=4de305d0a52ddaceaecba50a757e9968
將你的 URL 復(fù)制到您的瀏覽器中將返回一組與您當(dāng)?shù)靥鞖庀鄬?yīng)的信息。編寫本教程的那天,我們獲得了以下有關(guān)中國成都的天氣的信息。
代碼
/*
該示例通過學(xué)習(xí)以了解如何獲得天氣信息
*/
#include
#include
#include
//修改WIFI名稱以及密碼
const char* ssid = "******";//WIFI名稱
const char* password = "******";//WIFI密碼
//填入你獲得的API Key
String openWeatherMapApiKey = "4de305d0a52ddaceaecba50a757e9968";
//示例:
//String openWeatherMapApiKey = "4de305d0a52ddaceaecba50a757e9968";
// 填寫你的城市名以及國家簡寫
String city = "ChengDu";
String countryCode = "CN";
//示例:
//String city = "ChengDu";
//String countryCode = "CN";
//設(shè)置獲取信息的間隔時間,以下用于測試所以設(shè)置為10秒
//您應(yīng)當(dāng)根據(jù)你需要獲取數(shù)據(jù)的網(wǎng)站,規(guī)定時間內(nèi)訪問數(shù)據(jù)的次數(shù)上限來限制訪問時間的最小間隔
unsigned long lastTime = 0;
//設(shè)置每10分鐘獲得一次天氣數(shù)據(jù)
//unsigned long timerDelay = 600000;
//設(shè)置每10秒獲得一次天氣數(shù)據(jù)
unsigned long timerDelay = 10000;
String jsonBuffer;
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("Connecting");
//判斷WIFI是否連接
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
Serial.println("Timer set to 10 seconds (timerDelay variable), it will take 10 seconds before publishing the first reading.");
}
void loop() {
//發(fā)送HTTP獲取請求
if ((millis() - lastTime) > timerDelay) {
//檢測WIFI是否已經(jīng)連接
if(WiFi.status()== WL_CONNECTED){
String serverPath = "http://api.openweathermap.org/data/2.5/weather?q=" + city + "," + countryCode + "&APPID=" + openWeatherMapApiKey;
//將組合好的URL放入httpGETRequest函數(shù)中通過HTTP獲取請求以獲得文本
jsonBuffer = httpGETRequest(serverPath.c_str());
Serial.println(jsonBuffer);
//將解析的Json對象值儲存在Jsonu緩沖區(qū)中
JSONVar myObject = JSON.parse(jsonBuffer);
//判斷解析是否成功
if (JSON.typeof(myObject) == "undefined") {
Serial.println("Parsing input failed!");
return;
}
Serial.print("JSON object = ");
Serial.println(myObject);
Serial.print("Temperature: ");
//獲取到的溫度其實(shí)是開氏度。
//開氏度 = 攝氏度+273.15
double c = myObject["main"]["temp"];
c = c-273.15;
Serial.println(c);
Serial.print("Pressure: ");
//myObject["main"]["pressure"]前為{}前的引號內(nèi)容,后為讀取哪一個引號后數(shù)據(jù)
Serial.println(myObject["main"]["pressure"]);
Serial.print("Humidity: ");
Serial.println(myObject["main"]["humidity"]);
Serial.print("Wind Speed: ");
Serial.println(myObject["wind"]["speed"]);
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}
String httpGETRequest(const char* serverName) {
WiFiClient client;
HTTPClient http;
//連接網(wǎng)址
http.begin(client, serverName);
//發(fā)送HTTP站點(diǎn)請求
int httpResponseCode = http.GET();
//該數(shù)組用于儲存獲得的數(shù)據(jù)
String payload = "{}";
//將獲得的數(shù)據(jù)放入數(shù)組
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
payload = http.getString();
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
//釋放資源
http.end();
//返回獲得的數(shù)據(jù)用于Json處理
return payload;
}
Copy
結(jié)果
成員函數(shù)
httpGETRequest(serverPath.c_str());
說明:解析獲取的對象
JSON.typeof(myObject)
說明:判斷對象是否為已被解析的格式
8.5 阿里云IoT
什么是阿里云
阿里云IoT致力于實(shí)現(xiàn)萬物互聯(lián)的美好世界,為生態(tài)合作伙伴提供基于云端一體化、安全物聯(lián)網(wǎng)基礎(chǔ)平臺等,在通過該平臺高效連接,管理設(shè)備的同時,其開放能力使合作伙伴更高效、低成本地構(gòu)建各種創(chuàng)新的物聯(lián)網(wǎng)應(yīng)用場景。 阿里云物聯(lián)網(wǎng)平臺為設(shè)備提供安全可靠的連接通信能力,向下連接海量設(shè)備,支撐設(shè)備數(shù)據(jù)采集上云;向上提供云端API,指令數(shù)據(jù)通過API調(diào)用下發(fā)至設(shè)備端,實(shí)現(xiàn)遠(yuǎn)程控制。 此外阿里云IoT還提供了豐富的開發(fā)服務(wù),用戶可以直接在該平臺上搭建Web可視化、移動應(yīng)用、服務(wù)開發(fā)等開發(fā)服務(wù),這降低了物聯(lián)網(wǎng)項(xiàng)目開發(fā)的難度,有了它,用戶無需任何專業(yè)的開發(fā)技巧也可開發(fā)自己的項(xiàng)目。
點(diǎn)擊下載DFRobot_Iot庫
- 阿里云IOT請點(diǎn)擊這里了解具體詳情,使用時需將示例中的#include "DFRobot_Aliyun.h"替換為#include "DFRobot_Iot.h"
8.6 SmartConfig 一鍵配網(wǎng)+自動重連
通過該代碼可使用樂鑫的ESP-TOUCH進(jìn)行一鍵配網(wǎng)。
點(diǎn)擊下載安卓版
IOS版請?jiān)贏pp Store搜索Espressif Esptouch
#include
void SmartConfig()
{
WiFi.mode(WIFI_STA);
Serial.println("\r\nWait for Smartconfig...");
WiFi.beginSmartConfig();
while (1)
{
Serial.print(".");
delay(500); // wait for a second
if (WiFi.smartConfigDone())
{
Serial.println("SmartConfig Success");
Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
break;
}
}
}
bool AutoConfig()
{
WiFi.begin();
for (int i = 0; i < 20; i++)
{
int wstatus = WiFi.status();
if (wstatus == WL_CONNECTED)
{
Serial.println("WIFI SmartConfig Success");
Serial.printf("SSID:%s", WiFi.SSID().c_str());
Serial.printf(", PSW:%s\r\n", WiFi.psk().c_str());
Serial.print("LocalIP:");
Serial.print(WiFi.localIP());
Serial.print(" ,GateIP:");
Serial.println(WiFi.gatewayIP());
return true;
}
else
{
Serial.print("WIFI AutoConfig Waiting......");
Serial.println(wstatus);
delay(1000);
}
}
Serial.println("WIFI AutoConfig Faild!" );
return false;
}
void setup() {
Serial.begin(115200);
delay(100);
if (!AutoConfig())
{
SmartConfig();
}
}
void loop() {
}
Copy
常見問題
燒錄報(bào)錯
原因
如果Loop中延時過短或者不加延時會導(dǎo)致燒錄超時
錯誤的調(diào)用一些函數(shù)會導(dǎo)致計(jì)算機(jī)不能識別USB
解決辦法
- 將引腳9連接GND拉低,重新上電,再燒錄。
串口無打印
解決辦法
- 檢查USB CDC是否處于Enable狀態(tài)
- 使用其他的串口調(diào)試助手查看打印信息
更多問題及有趣的應(yīng)用,可以 訪問論壇 進(jìn)行查閱或發(fā)帖。
更多
- esp32-c3-mini-1 datasheet
- 原理圖
- 尺寸圖
- ESP32 Pico開發(fā)板開源
- 樂鑫ESP32-C3_技術(shù)規(guī)格書
- 樂鑫ESP32-C3_技術(shù)參考手冊
- 樂鑫ESP32-C3-MINI-1參考設(shè)計(jì)
- 樂鑫ESP32-C3-MINI-1U參考設(shè)計(jì)
- 樂鑫ESP32-C3-WROOM-02參考設(shè)計(jì)
- 樂鑫ESP32-C3-WROOM-02U參考設(shè)計(jì)
- 樂鑫ESP32-C3-MINI-1_&1U技術(shù)規(guī)格書
- 樂鑫ESP32-C3-WROOM-02_&02U技術(shù)規(guī)格書
- ESP32 S3 WROOM開發(fā)板
- ESP32開發(fā)板驅(qū)動下載 54次下載
- LoRa ESP32 TKoala開發(fā)板
- ESP32迷你開發(fā)板設(shè)計(jì)開源分享
- 荔枝糖RISC-V開發(fā)板原理圖 51次下載
- 基于esp32的開發(fā)板 105次下載
- GitHub Copilot+ESP開發(fā)實(shí)戰(zhàn)-SPI 261次閱讀
- GitHub Copilot+ESP開發(fā)實(shí)戰(zhàn)-I2C 310次閱讀
- ESP32-C3開發(fā)板設(shè)計(jì)指南 3653次閱讀
- ESP32-C3模塊使用問題集錦| C3的串口日志該如何禁用? 626次閱讀
- 基于ESP32-S3的高性能開發(fā)板介紹 8722次閱讀
- 基于形式的高效 RISC-V 處理器驗(yàn)證方法 549次閱讀
- ESP32-C3硬件定時器簡介及使用 4259次閱讀
- ESP32-C3 WIFI的工作模式 4478次閱讀
- 基于ESP32制造有趣的超級馬里奧主題時鐘 4024次閱讀
- RISC-V SIG成功將Chromium等桌面軟件適配到openEuler RISC-V 2018次閱讀
- 如何設(shè)計(jì)一個基于ESP32的微控制器開發(fā)板 3118次閱讀
- 基于RISC-V開發(fā)板的DDR演示的設(shè)計(jì)方案 2548次閱讀
- dfrobotBeetle-ESP32控制器簡介 2695次閱讀
- 5款追求極簡設(shè)計(jì)的ESP32-PICO-D4開發(fā)板 2.8w次閱讀
- 蜂鳥FPGA開發(fā)板及JTAG下載器詳細(xì)說明 2w次閱讀
下載排行
本周
- 1山景DSP芯片AP8248A2數(shù)據(jù)手冊
- 1.06 MB | 532次下載 | 免費(fèi)
- 2RK3399完整板原理圖(支持平板,盒子VR)
- 3.28 MB | 339次下載 | 免費(fèi)
- 3TC358743XBG評估板參考手冊
- 1.36 MB | 330次下載 | 免費(fèi)
- 4DFM軟件使用教程
- 0.84 MB | 295次下載 | 免費(fèi)
- 5元宇宙深度解析—未來的未來-風(fēng)口還是泡沫
- 6.40 MB | 227次下載 | 免費(fèi)
- 6迪文DGUS開發(fā)指南
- 31.67 MB | 194次下載 | 免費(fèi)
- 7元宇宙底層硬件系列報(bào)告
- 13.42 MB | 182次下載 | 免費(fèi)
- 8FP5207XR-G1中文應(yīng)用手冊
- 1.09 MB | 178次下載 | 免費(fèi)
本月
- 1OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 2555集成電路應(yīng)用800例(新編版)
- 0.00 MB | 33566次下載 | 免費(fèi)
- 3接口電路圖大全
- 未知 | 30323次下載 | 免費(fèi)
- 4開關(guān)電源設(shè)計(jì)實(shí)例指南
- 未知 | 21549次下載 | 免費(fèi)
- 5電氣工程師手冊免費(fèi)下載(新編第二版pdf電子書)
- 0.00 MB | 15349次下載 | 免費(fèi)
- 6數(shù)字電路基礎(chǔ)pdf(下載)
- 未知 | 13750次下載 | 免費(fèi)
- 7電子制作實(shí)例集錦 下載
- 未知 | 8113次下載 | 免費(fèi)
- 8《LED驅(qū)動電路設(shè)計(jì)》 溫德爾著
- 0.00 MB | 6656次下載 | 免費(fèi)
總榜
- 1matlab軟件下載入口
- 未知 | 935054次下載 | 免費(fèi)
- 2protel99se軟件下載(可英文版轉(zhuǎn)中文版)
- 78.1 MB | 537798次下載 | 免費(fèi)
- 3MATLAB 7.1 下載 (含軟件介紹)
- 未知 | 420027次下載 | 免費(fèi)
- 4OrCAD10.5下載OrCAD10.5中文版軟件
- 0.00 MB | 234315次下載 | 免費(fèi)
- 5Altium DXP2002下載入口
- 未知 | 233046次下載 | 免費(fèi)
- 6電路仿真軟件multisim 10.0免費(fèi)下載
- 340992 | 191187次下載 | 免費(fèi)
- 7十天學(xué)會AVR單片機(jī)與C語言視頻教程 下載
- 158M | 183279次下載 | 免費(fèi)
- 8proe5.0野火版下載(中文版免費(fèi)下載)
- 未知 | 138040次下載 | 免費(fèi)
評論
查看更多