新手求助:如何为Arduino Nano RP2040 Connect软件模拟I2C连接多台AM2320?
解决相同地址AM2320多传感器读取方案(基于SoftwareWire)
核心思路
因为硬件I2C总线只能区分不同地址的设备,而你的AM2320地址无法修改,所以给每个传感器分配一组独立的软件模拟I2C引脚,用SoftwareWire库分别创建I2C总线实例,实现独立通信。
步骤1:安装SoftwareWire库
在Arduino IDE中打开「库管理器」,搜索SoftwareWire,找到并安装该库。
步骤2:硬件接线
给四个AM2320分别分配不同的数字引脚对(SDA/SCL),比如:
- 传感器1:SDA=D2,SCL=D3
- 传感器2:SDA=D4,SCL=D5
- 传感器3:SDA=D6,SCL=D7
- 传感器4:SDA=D8,SCL=D9
每个传感器的VCC接3.3V(AM2320兼容3.3V/5V,Nano RP2040的IO是3.3V,建议用3.3V),GND接开发板GND,注意每个I2C总线建议加10kΩ上拉电阻(如果传感器自带可以不加)。
步骤3:完整代码示例
#include <SoftwareWire.h> // 为每个传感器创建独立的SoftwareWire实例 SoftwareWire wire1(2, 3); // SDA=2, SCL=3 SoftwareWire wire2(4, 5); // SDA=4, SCL=5 SoftwareWire wire3(6, 7); // SDA=6, SCL=7 SoftwareWire wire4(8, 9); // SDA=8, SCL=9 // AM2320的I2C地址(固定0x5C) #define AM2320_ADDR 0x5C void setup() { Serial.begin(115200); // 初始化所有软件I2C总线 wire1.begin(); wire2.begin(); wire3.begin(); wire4.begin(); delay(1000); } // 封装AM2320读取函数,接收SoftwareWire实例作为参数 bool readAM2320(SoftwareWire &wire, float &temp, float &hum) { // 第一步:唤醒传感器(AM2320默认休眠,需先发送空数据唤醒) wire.beginTransmission(AM2320_ADDR); wire.endTransmission(); delay(10); // 等待传感器唤醒 // 第二步:发送读取命令(读取4字节数据:湿度高、低,温度高、低) wire.beginTransmission(AM2320_ADDR); wire.write(0x03); // 读取寄存器命令 wire.write(0x00); // 起始寄存器地址 wire.write(0x04); // 读取字节数 int ack = wire.endTransmission(false); // 发送后不释放总线 if (ack != 0) { Serial.println("传感器无响应"); return false; } // 第三步:读取传感器返回的数据 wire.requestFrom(AM2320_ADDR, 6); // 共返回6字节:命令码、字节数、湿度2字节、温度2字节、校验码 if (wire.available() != 6) { Serial.println("数据长度错误"); return false; } // 解析数据 byte cmd = wire.read(); byte len = wire.read(); byte humHigh = wire.read(); byte humLow = wire.read(); byte tempHigh = wire.read(); byte tempLow = wire.read(); byte checksum = wire.read(); // 校验数据 byte calcChecksum = cmd + len + humHigh + humLow + tempHigh + tempLow; if (calcChecksum != checksum) { Serial.println("数据校验失败"); return false; } // 转换为实际数值 hum = (humHigh << 8 | humLow) / 10.0; temp = ((tempHigh & 0x7F) << 8 | tempLow) / 10.0; if (tempHigh & 0x80) { // 温度为负 temp = -temp; } return true; } void loop() { float temp1, hum1; float temp2, hum2; float temp3, hum3; float temp4, hum4; // 依次读取四个传感器 Serial.println("=== 传感器1数据 ==="); if (readAM2320(wire1, temp1, hum1)) { Serial.print("湿度: "); Serial.print(hum1); Serial.print("% 温度: "); Serial.print(temp1); Serial.println("℃"); } Serial.println("=== 传感器2数据 ==="); if (readAM2320(wire2, temp2, hum2)) { Serial.print("湿度: "); Serial.print(hum2); Serial.print("% 温度: "); Serial.print(temp2); Serial.println("℃"); } Serial.println("=== 传感器3数据 ==="); if (readAM2320(wire3, temp3, hum3)) { Serial.print("湿度: "); Serial.print(hum3); Serial.print("% 温度: "); Serial.print(temp3); Serial.println("℃"); } Serial.println("=== 传感器4数据 ==="); if (readAM2320(wire4, temp4, hum4)) { Serial.print("湿度: "); Serial.print(hum4); Serial.print("% 温度: "); Serial.print(temp4); Serial.println("℃"); } Serial.println("------------------------"); delay(2000); // 每2秒读取一次 }
关键代码解释
- SoftwareWire实例化:每个
SoftwareWire wireX(sdaPin, sclPin)对应一组独立的模拟I2C总线,引脚可以选任意可用的数字引脚。 - AM2320读取逻辑:AM2320需要先唤醒(发送空传输),再发送读取命令,最后解析返回数据并校验。把读取逻辑封装成函数,传入不同的SoftwareWire实例即可复用。
- 数据校验:必须校验返回的校验码,避免读取到错误数据。
常见问题排查
- 如果传感器无响应:检查接线是否正确,上拉电阻是否添加,引脚是否接反。
- 如果数据校验失败:可能是通信干扰,尝试增加延迟,或者检查电源稳定性。
- 引脚冲突:确保所选数字引脚没有被其他功能占用(比如串口、SPI引脚)。
内容的提问来源于stack exchange,提问作者Kristóf Varga
相关产品推荐
相关产品推荐

