跳到主要内容

设备开发

物联网设备开发是物联网系统的起点,涉及嵌入式系统、传感器接口、通信协议等技术。本文将介绍物联网设备开发的核心技术和实践方法。

设备开发概述

开发流程

需求分析 → 硬件选型 → 软件架构 → 编码开发 → 测试验证 → 生产部署

技术栈

层次技术选型
开发语言C/C++、MicroPython、Rust
操作系统FreeRTOS、RT-Thread、Zephyr、Linux
开发框架ESP-IDF、Arduino、STM32 HAL
调试工具JTAG、SWD、串口调试

硬件平台

常用开发板

开发板MCU特点适用场景
ESP32Xtensa LX6WiFi+BLE、便宜智能家居、原型开发
ESP8266Xtensa L106WiFi、超便宜简单 IoT 设备
STM32ARM Cortex-M工业级、丰富外设工业物联网
ArduinoAVR/ARM简单易用教育、原型
Raspberry Pi PicoRP2040便宜、性能好教育、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 Sleep20-30mA
Light Sleep0.8mA
Deep Sleep10-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();
}

开发最佳实践

代码规范

  1. 模块化设计:功能模块独立封装
  2. 错误处理:检查返回值、处理异常
  3. 资源管理:及时释放资源
  4. 日志记录:关键操作记录日志

安全实践

  1. 安全存储:密钥安全存储
  2. 安全通信:TLS 加密
  3. 安全启动:固件签名验证
  4. 访问控制:设备认证

性能优化

  1. 内存优化:减少内存占用
  2. 功耗优化:低功耗设计
  3. 通信优化:减少通信开销
  4. 代码优化:关键路径优化

小结

物联网设备开发涉及硬件选型、传感器接口、通信协议、低功耗设计等多个方面。选择合适的硬件平台和开发框架,掌握常用的传感器接口和通信技术,是开发高质量物联网设备的基础。

下一步,我们将学习后端开发,了解消息中间件和数据存储的核心技术。