设备开发
物联网设备开发是物联网系统的起点,涉及嵌入式系统、传感器接口、通信协议等技术。本文将介绍物联网设备开发的核心技术和实践方法。
设备开发概述
开发流程
需求分析 → 硬件选型 → 软件架构 → 编码开发 → 测试验证 → 生产部署
技术栈
| 层次 | 技术选型 |
|---|---|
| 开发语言 | C/C++、MicroPython、Rust |
| 操作系统 | FreeRTOS、RT-Thread、Zephyr、Linux |
| 开发框架 | ESP-IDF、Arduino、STM32 HAL |
| 调试工具 | JTAG、SWD、串口调试 |
硬件平台
常用开发板
| 开发板 | MCU | 特点 | 适用场景 |
|---|---|---|---|
| ESP32 | Xtensa LX6 | WiFi+BLE、便宜 | 智能家居、原型开发 |
| ESP8266 | Xtensa L106 | WiFi、超便宜 | 简单 IoT 设备 |
| STM32 | ARM Cortex-M | 工业级、丰富外设 | 工业物联网 |
| Arduino | AVR/ARM | 简单易用 | 教育、原型 |
| Raspberry Pi Pico | RP2040 | 便宜、性能好 | 教育、DIY |
ESP32 开发
ESP32 特点:
- 双核 240MHz CPU
- 520KB SRAM
- WiFi 802.11 b/g/n
- 蓝牙 4.2 BR/EDR + BLE
- 丰富的外设接口
ESP-IDF 开发框架:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
static const char *TAG = "example";
void app_main(void)
{
ESP_LOGI(TAG, "Hello ESP32!");
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_NUM_2),
.mode = GPIO_MODE_OUTPUT,
.pull_up_en = 0,
.pull_down_en = 0,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&io_conf);
while(1) {
gpio_set_level(GPIO_NUM_2, 1);
vTaskDelay(1000 / portTICK_PERIOD_MS);
gpio_set_level(GPIO_NUM_2, 0);
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
Arduino 开发
Arduino 特点:
- 简单易用的 IDE
- 丰富的库支持
- 庞大的社区
- 适合快速原型
Arduino 示例:
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "your_ssid";
const char* password = "your_password";
const char* mqtt_server = "broker.example.com";
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
client.setServer(mqtt_server, 1883);
}
void loop() {
if (!client.connected()) {
while (!client.connected()) {
if (client.connect("ArduinoClient")) {
client.subscribe("home/light/command");
} else {
delay(5000);
}
}
}
client.loop();
}
传感器接口
GPIO
GPIO(通用输入输出)是最基础的接口,用于数字信号的输入输出。
// ESP32 GPIO 配置
#include "driver/gpio.h"
// 配置输出
gpio_config_t io_conf = {
.pin_bit_mask = (1ULL << GPIO_NUM_2),
.mode = GPIO_MODE_OUTPUT,
};
gpio_config(&io_conf);
gpio_set_level(GPIO_NUM_2, 1);
// 配置输入
gpio_config_t input_conf = {
.pin_bit_mask = (1ULL << GPIO_NUM_4),
.mode = GPIO_MODE_INPUT,
.pull_up_en = 1,
};
gpio_config(&input_conf);
int level = gpio_get_level(GPIO_NUM_4);
ADC
ADC(模数转换器)用于读取模拟传感器信号。
// ESP32 ADC 读取
#include "esp_adc/adc_oneshot.h"
adc_oneshot_unit_handle_t adc_handle;
adc_oneshot_unit_init_cfg_t init_config = {
.unit_id = ADC_UNIT_1,
};
adc_oneshot_new_unit(&init_config, &adc_handle);
adc_oneshot_chan_cfg_t config = {
.atten = ADC_ATTEN_DB_12,
.bitwidth = ADC_BITWIDTH_12,
};
adc_oneshot_config_channel(adc_handle, ADC_CHANNEL_0, &config);
int raw_value;
adc_oneshot_read(adc_handle, ADC_CHANNEL_0, &raw_value);
float voltage = raw_value * 3.3 / 4095;
I2C
I2C 是常用的传感器接口,支持多设备共享总线。
// ESP32 I2C 读取 BME280
#include "driver/i2c.h"
#define I2C_MASTER_SCL_IO 22
#define I2C_MASTER_SDA_IO 21
#define BME280_ADDR 0x76
i2c_config_t conf = {
.mode = I2C_MODE_MASTER,
.sda_io_num = I2C_MASTER_SDA_IO,
.scl_io_num = I2C_MASTER_SCL_IO,
.sda_pullup_en = GPIO_PULLUP_ENABLE,
.scl_pullup_en = GPIO_PULLUP_ENABLE,
.master.clk_speed = 100000,
};
i2c_param_config(I2C_NUM_0, &conf);
i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);
// 读取数据
uint8_t data[8];
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd, (BME280_ADDR << 1) | I2C_MASTER_READ, true);
i2c_master_read(cmd, data, 8, I2C_MASTER_LAST_NACK);
i2c_master_stop(cmd);
i2c_master_cmd_begin(I2C_NUM_0, cmd, 1000 / portTICK_PERIOD_MS);
i2c_cmd_link_delete(cmd);
SPI
SPI 是高速串行接口,适合需要高数据速率的传感器。
// ESP32 SPI 配置
#include "driver/spi_master.h"
spi_device_handle_t handle;
spi_device_interface_config_t devcfg = {
.clock_speed_hz = 1000000,
.mode = 0,
.spics_io_num = 5,
.queue_size = 7,
};
spi_bus_add_device(SPI2_HOST, &devcfg, &handle);
// 发送数据
spi_transaction_t t = {
.length = 8,
.tx_buffer = &data,
};
spi_device_transmit(handle, &t);
UART
UART 用于串口通信,常用于 GPS、蓝牙模块等。
// ESP32 UART 配置
#include "driver/uart.h"
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
};
uart_param_config(UART_NUM_1, &uart_config);
uart_set_pin(UART_NUM_1, 4, 5, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(UART_NUM_1, 1024, 0, 0, NULL, 0);
// 读取数据
uint8_t data[256];
int len = uart_read_bytes(UART_NUM_1, data, 256, 100 / portTICK_PERIOD_MS);
低功耗设计
功耗优化策略
| 策略 | 说明 |
|---|---|
| 睡眠模式 | 设备空闲时进入睡眠 |
| 唤醒源 | 定时唤醒、事件唤醒 |
| 外设管理 | 关闭不用的外设 |
| 通信优化 | 减少通信频率、批量传输 |
ESP32 低功耗模式
#include "esp_sleep.h"
// 定时唤醒
esp_sleep_enable_timer_wakeup(60 * 1000000); // 60秒
// GPIO 唤醒
esp_sleep_enable_ext0_wakeup(GPIO_NUM_4, 1);
// 进入深度睡眠
esp_deep_sleep_start();
功耗测量
| 模式 | ESP32 功耗 |
|---|---|
| 活跃模式 | 100-240mA |
| Modem Sleep | 20-30mA |
| Light Sleep | 0.8mA |
| Deep Sleep | 10-100μA |
OTA 固件升级
OTA 架构
┌─────────────────────────────────────────────────────────┐
│ 云服务器 │
│ 固件存储 │ 版本管理 │ 升级策略 │
├─────────────────────────────────────────────────────────┤
│ 设备端 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ OTA 分区布局 │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ Bootloader│ OTA-0 │ │ OTA-1 │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
ESP32 OTA 实现
#include "esp_ota_ops.h"
#include "esp_http_client.h"
void ota_update(const char *url) {
esp_http_client_config_t config = {
.url = url,
.cert_pem = NULL,
};
esp_http_client_handle_t client = esp_http_client_init(&config);
esp_http_client_open(client, 0);
esp_ota_handle_t update_handle;
const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
char buffer[4096];
int data_read;
while ((data_read = esp_http_client_read(client, buffer, sizeof(buffer))) > 0) {
esp_ota_write(update_handle, buffer, data_read);
}
esp_ota_end(update_handle);
esp_ota_set_boot_partition(update_partition);
esp_restart();
}
调试与测试
串口调试
// 日志输出
ESP_LOGI(TAG, "Temperature: %.2f", temperature);
ESP_LOGW(TAG, "Warning: high temperature");
ESP_LOGE(TAG, "Error: sensor read failed");
JTAG/SWD 调试
- JTAG:支持断点、单步执行、变量查看
- SWD:ARM Cortex-M 的简化调试接口
- 工具:OpenOCD、GDB、IDE 集成调试
单元测试
#include "unity.h"
void test_temperature_conversion(void) {
float celsius = 25.0;
float fahrenheit = celsius_to_fahrenheit(celsius);
TEST_ASSERT_EQUAL_FLOAT(77.0, fahrenheit);
}
void app_main(void) {
UNITY_BEGIN();
RUN_TEST(test_temperature_conversion);
UNITY_END();
}
开发最佳实践
代码规范
- 模块化设计:功能模块独立封装
- 错误处理:检查返回值、处理异常
- 资源管理:及时释放资源
- 日志记录:关键操作记录日志
安全实践
- 安全存储:密钥安全存储
- 安全通信:TLS 加密
- 安全启动:固件签名验证
- 访问控制:设备认证
性能优化
- 内存优化:减少内存占用
- 功耗优化:低功耗设计
- 通信优化:减少通信开销
- 代码优化:关键路径优化
小结
物联网设备开发涉及硬件选型、传感器接口、通信协议、低功耗设计等多个方面。选择合适的硬件平台和开发框架,掌握常用的传感器接口和通信技术,是开发高质量物联网设备的基础。
下一步,我们将学习后端开发,了解消息中间件和数据存储的核心技术。