资料介绍
描述
需要在距离您的项目太远的传感器位置添加 OLED 屏幕以获取有意义的报告?
I2C 总线上连接的传感器太多?那么你需要IO 扩展器!使用1-Wire® 到 I2C适配器,可以根据需要在 1-Wire® 总线上添加任意数量的 I2C 总线。
需要多条 1-Wire® 总线?IO Expander最多可同时支持 16 个。
需要更多?然后将最多 255 个IO 扩展器连接在一起;IO 扩展器真正提供了极致的连接性!
功能列表
- 使用便宜的 128x64 OLED 屏幕。
- 在单个 1-Wire® 总线上使用多个 OLED 屏幕。
- 使用不同的 OLED 屏幕尺寸。
- 根据需要添加尽可能多的 I2C 总线。
- 永远不要用完 I2C 地址。只需添加另一个 I2C 总线。
- 易于使用的图形命令。
- 1-Wire® 标准和过载,可实现快速屏幕更新。
- 无需 1-Wire® 驱动器。节省代码空间。
- 无需 OLED 驱动程序。节省代码空间。
- 不需要 OLED 字体。节省代码空间。
- 无需 DS18B20 温度驱动器。节省代码空间。
- 无需 I2C 传感器驱动程序。节省代码空间。
- 不需要额外的电源。
- 易于连接 RJ11 电话线。
- 易于在 1-Wire® 总线上添加传感器。
- 热插拔 1-Wire® 总线。
用于构建 OLED 演示的部件
- IO 扩展器
- 1-Wire® 至 I2C。
- 1-Wire® 接头
- 分路器
- 阿杜诺纳米。
- RJ11 Keystone 螺丝端子插孔。
- 50 英尺 4C4P RJ11 线。
- 7 英尺 4C4P RJ11 线。
- DHT22 温度/湿度传感器。
- I2C Si7021 温度/湿度传感器。
- SSD1306 128x32 OLED 0.91"。
- SSD1306 128x64 OLED 0.96"。
- SSD1106 128x64 OLED 1.3"。注意:屏幕易碎!确保您订购它们以装箱。
- SSD1309 128x64 OLED 2.42"。
- 2.54 毫米头线。
接线图

俯视图
运行此演示的 Arduino 代码。
/* IO Expander OLED sketch
*
* Make sure you increase the SERIAL_RX_BUFFER_SIZE in Arduino/hardware/arduino/avr/cores/arduino/HardwareSerial.h
* from 64 to 256.
*/
#define SERIAL_RX_BUFFER_SIZE 256
#include
#include
#include "IOExpander.h"
#define FAHRENHEIT
#define OLED_SCREENS 5
#define TEMP_SENSORS 4
#define HUMIDITY_SENSORS 2
#define ONEWIRE_TO_I2C_ROM1 "i4s51"
#define ONEWIRE_TO_I2C_ROM2 "i4s2e"
#define ONEWIRE_TO_I2C_ROM3 "i4s24"
#define ONEWIRE_TO_I2C_ROM4 "i4sc0"
#define ONEWIRE_TO_I2C_ROM5 "i2see"
#define ONEWIRE_TEMP_CONVERSION "t4s0;tt"
#define TEMP_SENSOR1 "t4r4c"
#define TEMP_SENSOR2 "t4r57"
#define TEMP_SENSOR3 "t4r76"
#define TEMP_SENSOR4 "t4r0300"
#define HUMIDITY_SENSOR1 "st8"
#define HUMIDITY_SENSOR2 "s6t5"
#define INIT_OLED_SSD1306_32 "st10;si128,32"
#define INIT_OLED_SSD1306_64 "st10;si128,64"
#define INIT_OLED_SSD1106 "st13;si128,64"
#define INIT_OLED_SSD1309 "g1o0,10;s2t10;si128,64"
#define SERIAL_DEBUG
#ifdef SERIAL_DEBUG
SoftwareSerial swSerial(8,7);
#endif
struct TS {
bool update;
float temp;
bool error;
};
struct HS {
bool update;
float temp;
float humidity;
bool error;
};
int led = 13;
#ifdef FAHRENHEIT
#define C2F(temp) CelsiusToFahrenheit(temp)
float CelsiusToFahrenheit(float celsius)
{
return ((celsius*9)/5)32;
}
#else
#define C2F(temp) (temp)
#endif
bool init_oled[OLED_SCREENS] = {true, true, true, true, true};
TS ts[TEMP_SENSORS];
HS hs[HUMIDITY_SENSORS];
void ReadTempSensor(TS* ts, char* ts_read)
{
float temp = ts->temp;
SerialCmd(ts_read);
ts->error = !SerialReadFloat(&ts->temp);
SerialReadUntilDone();
ts->temp = roundf(ts->temp * 10) / 10;
ts->update = (temp != ts->temp);
}
void ReadHumiditySensor(HS* hs)
{
float temp = hs->temp;
float humidity = hs->humidity;
SerialCmd("sr");
hs->error = !(SerialReadFloat(&hs->temp) && SerialReadFloat(&hs->humidity));
SerialReadUntilDone();
hs->temp = roundf(hs->temp * 10) / 10;
hs->humidity = roundf(hs->humidity * 10) / 10;
hs->update = (temp != hs->temp || humidity != hs->humidity);
}
void SerialPrintDecimal(const char* str, float decimal, char error)
{
Serial.print(str);
if (error) Serial.print(F("NA"));
else Serial.print(decimal, 1);
Serial.print(""");
}
void SerialPrintUnits(void)
{
Serial.print(",248,""
#ifdef FAHRENHEIT
"F"
#else
"C"
#endif
""");
}
void SerialDrawBorder(uint8_t height)
{
if (height == 32) Serial.print(";sh0,0,128;sh0,31,128;sv0,1,30;sv127,1,30");
else Serial.print(";sh0,0,128;sh0,63,128;sv0,1,62;sv127,1,62");
}
void setup() {
Serial.begin(115200);
Serial.setTimeout(5000); // 5 sec delay between DHT22 reads
#ifdef SERIAL_DEBUG
swSerial.begin(115200);
swSerialEcho = &swSerial;
#endif
pinMode(led, OUTPUT);
wdt_enable(WDTO_8S);
}
void loop() {
uint8_t i;
static uint32_t last_millis = 0;
static TS ts[TEMP_SENSORS];
static HS hs[HUMIDITY_SENSORS];
while (Serial.available()) Serial.read(); // Flush RX buffer
Serial.println();
if (SerialReadUntilDone()) {
// First do a 1-Wire temperature measurement on all DS18B20 sensors
SerialCmdDone(ONEWIRE_TEMP_CONVERSION);
// Read the Si7020 humidity sensor
if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM4)) {
if (SerialCmdDone(HUMIDITY_SENSOR1)) {
ReadHumiditySensor(&hs[0]);
}
}
else init_oled[3] = true;
// Read DHT22 humidity sensor every 2 seconds
if (millis() - last_millis >= 2000) {
SerialCmdDone(HUMIDITY_SENSOR2);
ReadHumiditySensor(&hs[1]);
last_millis = millis();
}
// Read 1-Wire temperature sensors
ReadTempSensor(&ts[0], TEMP_SENSOR1);
ReadTempSensor(&ts[1], TEMP_SENSOR2);
ReadTempSensor(&ts[2], TEMP_SENSOR3);
ReadTempSensor(&ts[3], TEMP_SENSOR4);
if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)) {
if (init_oled[0]) {
if (SerialCmdNoError(INIT_OLED_SSD1306_32)) {
init_oled[0] = false;
ts[0].update = true;
}
}
if (!init_oled[0] && ts[0].update) {
SerialPrintDecimal("st10;sc;sf1;sa2;sd63,8,"", C2F(ts[0].temp), ts[0].error);
if (!ts[0].error) SerialPrintUnits();
SerialDrawBorder(32);
SerialCmdDone(";sd");
ts[0].update = false;
}
}
else init_oled[0] = true;
if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM2)) {
if (init_oled[1]) {
if (SerialCmdNoError(INIT_OLED_SSD1306_64)) {
init_oled[1] = false;
ts[1].update = true;
}
}
if (!init_oled[1] && ts[1].update) {
SerialPrintDecimal("st10;sc;sf2;sa2;sd63,19,"", C2F(ts[1].temp), ts[1].error);
if (!ts[1].error) SerialPrintUnits();
SerialDrawBorder(64);
SerialCmdDone(";sd");
ts[1].update = false;
}
}
else init_oled[1] = true;
if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM3)) {
if (init_oled[2]) {
if (SerialCmdNoError(INIT_OLED_SSD1106)) {
init_oled[2] = false;
ts[2].update = true;
}
}
if (!init_oled[2] && ts[2].update) {
SerialPrintDecimal("st13;sc;sf2;sa2;sd63,19,"", C2F(ts[2].temp), ts[2].error);
if (!ts[2].error) SerialPrintUnits();
SerialDrawBorder(64);
SerialCmdDone(";sd");
ts[2].update = false;
}
}
else init_oled[2] = true;
if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM4)) {
if (init_oled[3]) {
if (SerialCmdNoError(INIT_OLED_SSD1106)) {
init_oled[3] = false;
ts[3].update = true;
}
}
if (!init_oled[3] && (ts[3].update || hs[0].update)) {
SerialPrintDecimal("st13;sc;sf1;sa1;sd60,12,"", C2F(hs[0].temp), hs[0].error);
SerialPrintUnits();
SerialPrintDecimal(";sd60,32,"", hs[0].humidity, hs[0].error);
Serial.print(","%"");
SerialPrintDecimal(";sd121,12,"", C2F(ts[3].temp), ts[3].error);
SerialPrintUnits();
SerialDrawBorder(64);
SerialCmdDone(";sd");
ts[3].update = false;
hs[0].update = false;
}
}
else init_oled[3] = true;
if (SerialCmdNoError(ONEWIRE_TO_I2C_ROM5)) {
if (init_oled[4]) {
if (SerialCmdNoError(INIT_OLED_SSD1309)) {
init_oled[4] = false;
hs[1].update = true;
}
}
if (!init_oled[4] && hs[1].update) {
SerialPrintDecimal("st10;sc;sf1;sa2;sd63,12,"", C2F(hs[1].temp), hs[1].error);
SerialPrintUnits();
SerialPrintDecimal(";sd63,32,"", hs[1].humidity, hs[1].error);
Serial.print(","%"");
SerialDrawBorder(64);
SerialCmdDone(";sd");
hs[1].update = false;
}
}
else init_oled[4] = true;
#ifdef SERIAL_DEBUG
#endif
}
else {
digitalWrite(led, HIGH); // blink Arduino led for IO Expander failure
delay(500);
digitalWrite(led, LOW);
delay(500);
for (i = 0; i < OLED_SCREENS; i++) init_oled[i] = true;
}
wdt_reset();
}
SSD1309 128x64 OLED 2.42"。
较大的 2.42" OLED 的文档不好,所以我添加了一些关于如何正确使用1-Wire® 到 I2C适配器的附加信息。
显示器默认为 SPI,因此您要做的第一件事就是将其转换为 I2C。这意味着您需要取出烙铁并移除并添加一些 SMD 0603 电阻器。

- 取下 R4 并将其放在 R3 上。
- 在 R5 和 R7 处添加 0 欧姆电阻。
- 将跳线添加到 CS-DS。这将有效地为 0x3C 的 I2C 地址选择提供 GND DC。如果您想使用 0x3D 的备用 I2C 地址,请移除跳线并将 DC 连接到 VCC (3V3)。
- 将一根电线从 RES 引脚连接到1-Wire® 到 I2C适配器上 PL1 (D2) 的未跳线引脚。这将用作 GPIO 线,以在 OLED 显示器上电后发送所需的复位脉冲。
此显示控制器需要在 VCC 稳定后发送 RES 引脚上的复位脉冲。根据SSD1309 显示控制器,您必须将 RES LOW 设置为至少 3us,然后再设置为 HIGH。在面板锁定的情况下访问此显示器上的重置线也很有用,您可以在其中重置和重新初始化它,而无需关闭整个系统的电源。
要使用 IO 扩展器发送复位脉冲,请在所选引脚上使用 gpio 命令并指定持续时间。这里我们使用引脚 [1] 上的 [g]pio 命令作为 [0] 的 [o] 输出或 [ 10]毫秒。持续时间之后,该引脚将保持高电平。
>g1o0,10
ok
>
较大的 2.42 OLED 显示器使用一个简单的内部开关电容电荷泵,可将输入的 3V3 转换为 OLED 的 15V 高电压驱动。显示器平均从 3.3V 电源汲取约 50mA 电流,但所需的浪涌电流,特别是在较长的电缆长度上,需要在输入 3V3 的 VCC 和 GND 之间添加一个额外的 470uF 电解电容器。确保将负极连接到 GND!如果您使用的是插头连接器,只需将电容器插入引脚即可。
对于较小的 SSD1106 1.3",它还使用内部电荷泵将输入的 3V3 转换为 7V 以驱动 OLED,因此对于更长的电缆长度,您还需要在输入的 3V3 处添加一个额外的 100uF 电解电容器。该演示使用分路器作为 1-Wire® 短截线,将1-Wire® 到 I2C适配器连接到 OLED 显示器和 I2C Si7021 传感器。
分路器用作 D1 和 D2 上的两个 1-Wire® 分接器,R1 和 R2 为 100Ω

为了将尽可能多的 1-Wire® 传感器连接到一根导线上,OLED 屏幕和传感器作为短截线连接到 1-Wire® 总线,但在分支点存在阻抗不匹配。来自短截线末端的反射返回到主干线,仅延迟信号通过短截线长度所需的时间。这些反射可能会导致网络上的其他从站出现问题。与短截线串联的电阻器将降低失配的严重程度和反射能量的幅度。该电阻器减轻了主干上的短截线产生的反射的不利影响
1-Wire协议
为了有效地运行 OLED 显示器,IO 扩展器支持在 100 英尺以上高达 75.47kHz 的主动驱动 1-Wire® Overdrive 速度!如果您需要走几百英尺,那么您仍然可以退回到较慢的标准速度 15.38kHz。像 DS18B20 这样的原生温度传感器不支持 Overdrive 速度,因此您可以混合具有不同速度的设备,IO 扩展器将自动改变速度以匹配同一 1-Wire 总线上的设备。Overdrive 速度低于连接到 OLED 屏幕的 I2C 总线上的 400kHz,但对于在传感器位置报告传感器状态来说已经足够快了。
为了使用 Overdrive 速度,您必须在尽可能靠近 CPU IO 引脚的地方使用 2.2k 的强上拉电阻。在这个演示中,我们使用了带有 2.2k 上拉电阻的引脚 4,但对于引脚 2,我们需要添加一个。最简单的方法是在 IO 扩展器 PCB 底部端口的 RJ11 插头上的引脚之间焊接一个 2.2k 0603 电阻。

IO 扩展器支持三种不同的命令来控制 1-Wire® 设备。
o - [o] 线直接控制。
i - 1-Wire® [i]2c 控制。
t - 1-Wire® [t] 温度传感器。
在引脚 [4] 上的 [o]newire 总线上,[f]找到所有 ROM。
>o4f
28ffe835c3160376
28ffea20c316034c
28ff19f4c2160300
28fffd34c3160357
197a28030000002e
19ad200300000051
19ed200300000024
198f1103000000c0
>
[i] 2c 引脚 [4] 上的设备,[f] 查找所有 ROM。
>i4f
197a28030000002e
19ad200300000051
19ed200300000024
198f1103000000c0
>
[t] 引脚 [4] 上的温度设备,[f] 找到所有 ROM。
>t4f
28ffe835c3160376
28ffea20c316034c
28ff19f4c2160300
28fffd34c3160357
>
那么使用IO Expander到底有多难呢?以身作则,自行判断。
[t] 引脚 [4] 上的温度传感器 [s] 选择 ROM [76]。执行 [t] 温度转换 [t],最后执行 [t] 温度 [r] 读取。
>t4s76;tt;tr
28ffe835c3160376
ok
17.9375
>
就这么容易!
可热插拔!
IO 扩展器的独特功能之一是它旨在支持热插拔设备。这意味着,如果您的传感器或 OLED 显示屏出现故障,您无需关闭系统即可更换它。当它仍然通电时,移除 RJ11 插头并重新连接新的传感器或 OLED 屏幕。此外,为了实现这一点,您必须确保您的代码已被编写为检测和重新初始化。一些传感器没有必要的保护,所以这样做需要您自担风险。任何 1-Wire 连接都应该没问题,因为IO 扩展器上的 1-Wire 驱动程序是专门为支持这一独特功能而编写的。因此,立即获取您的 IO 扩展器并构建您的系统!
- 使用MSP430 MCU简化温度、湿度和光学I2C传感器
- TMP100-EP带I2C接口的数字温度传感器数据表
- XV4001BC车载用SPI/I2C输出接口的数字输出
- 带LCD 1602 I2C显示的温湿度传感器
- APM32F103XE_I2C_加入六轴传感器后,I2C通讯EEPROM会挂
- 带补偿的I2C超声波传感器
- 硬件I2C与模拟I2C
- 传感器i2c与arduino连接_Nodemcu I2C接口连接Arduino
- 基于距离传感器的I2C通信(二)
- 使用单片机实现I2C接口温度传感器DS1621应用测试的C语言实例 10次下载
- ADT7420:±0.25°C精度、16位数字I2C温度传感器
- STM32单片机实现的TMP102温度传感器I2C读取的程序合集免费下载 140次下载
- 使用MPU6050传感器读取I2C总线数据的程序免费下载 15次下载
- STM32硬件i2c,CubeMX,Hal库 66次下载
- I2C Guid I2C指南
- I2C通信协议及其工作原理 4481次阅读
- Hi3861硬件i2c驱动oled 1106次阅读
- Linux I2C驱动入门知识科普 1516次阅读
- 长距离SPI/I2C通信解决方案 5269次阅读
- 如何操作I2C去显示oled屏幕 5368次阅读
- 什么是I2C通信协议? 7572次阅读
- i2c总线用来做什么_i2c总线数据传输过程 7086次阅读
- dfrobotSHT20 I2C防水型温湿传感器简介 2920次阅读
- I2C总线的工作原理以及优缺点解析 1.4w次阅读
- 基于MCS-51单片机I2C总线接口电路的设计 3245次阅读
- I2C总线的工作原理解析 6415次阅读
- I2C总线的特点与构成详解 1w次阅读
- 基于使用STM8单片机I2C方式实现读写操作 1.1w次阅读
- 详细讲解RT-Thread I2C设备驱动框架及相关函数 2w次阅读
- 基于I2C接口与上级无线传感器网络通信的环境监测系统 3240次阅读
下载排行
本周
- 1山景DSP芯片AP8248A2数据手册
- 1.06 MB | 532次下载 | 免费
- 2RK3399完整板原理图(支持平板,盒子VR)
- 3.28 MB | 339次下载 | 免费
- 3TC358743XBG评估板参考手册
- 1.36 MB | 330次下载 | 免费
- 4DFM软件使用教程
- 0.84 MB | 295次下载 | 免费
- 5元宇宙深度解析—未来的未来-风口还是泡沫
- 6.40 MB | 227次下载 | 免费
- 6迪文DGUS开发指南
- 31.67 MB | 194次下载 | 免费
- 7元宇宙底层硬件系列报告
- 13.42 MB | 182次下载 | 免费
- 8FP5207XR-G1中文应用手册
- 1.09 MB | 178次下载 | 免费
本月
- 1OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 2555集成电路应用800例(新编版)
- 0.00 MB | 33566次下载 | 免费
- 3接口电路图大全
- 未知 | 30323次下载 | 免费
- 4开关电源设计实例指南
- 未知 | 21549次下载 | 免费
- 5电气工程师手册免费下载(新编第二版pdf电子书)
- 0.00 MB | 15349次下载 | 免费
- 6数字电路基础pdf(下载)
- 未知 | 13750次下载 | 免费
- 7电子制作实例集锦 下载
- 未知 | 8113次下载 | 免费
- 8《LED驱动电路设计》 温德尔著
- 0.00 MB | 6656次下载 | 免费
总榜
- 1matlab软件下载入口
- 未知 | 935054次下载 | 免费
- 2protel99se软件下载(可英文版转中文版)
- 78.1 MB | 537798次下载 | 免费
- 3MATLAB 7.1 下载 (含软件介绍)
- 未知 | 420027次下载 | 免费
- 4OrCAD10.5下载OrCAD10.5中文版软件
- 0.00 MB | 234315次下载 | 免费
- 5Altium DXP2002下载入口
- 未知 | 233046次下载 | 免费
- 6电路仿真软件multisim 10.0免费下载
- 340992 | 191187次下载 | 免费
- 7十天学会AVR单片机与C语言视频教程 下载
- 158M | 183279次下载 | 免费
- 8proe5.0野火版下载(中文版免费下载)
- 未知 | 138040次下载 | 免费
评论