news 2026/1/13 21:26:00

Jetson Xavier NX I2C总线应用:从零实现传感器读取

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Jetson Xavier NX I2C总线应用:从零实现传感器读取

从零开始在 Jetson Xavier NX 上玩转 I2C:用 Python 实现温湿度传感器读取

你有没有遇到过这样的场景?手握一块性能强大的Jetson Xavier NX,准备大干一场做边缘 AI 感知系统,结果发现——连最基础的温湿度都读不出来?

别笑,这事儿太常见了。很多人以为有了 GPU 就能搞定一切,但现实是:没有传感器数据,AI 再聪明也“瞎”着呢

今天我们就来解决这个“卡脖子”的问题:如何在 Jetson Xavier NX 上通过 I2C 总线,把外部传感器的数据稳稳地读出来,并用 Python 写出可复用的采集程序。

整个过程不讲虚的,从硬件接线到代码运行,一步步带你打通“感知层”到“计算层”的最后一公里。


为什么选 I2C?它到底香在哪?

在嵌入式世界里,通信协议就那么几种:UART、SPI、I2C。为什么我们偏偏要拿 I2C 开刀?

很简单——省引脚、拓扑灵活、适合多传感器挂载

想象一下你要接五个传感器:

  • UART 要每个都占两根线(TX/RX),还得加电平转换;
  • SPI 虽然快,但每增加一个设备就得多个片选(CS)线,GPIO 很快就被吃光;
  • 而 I2C 呢?只需要两根线(SDA + SCL),所有设备并联上去就行,靠地址区分彼此。

对于像 Jetson Xavier NX 这种 GPIO 数量有限但算力爆棚的平台来说,I2C 简直就是为它量身定做的“外设高速公路”。

而且 Linux 内核对 I2C 的支持非常成熟,用户空间可以直接访问/dev/i2c-*设备节点,完全不用写驱动就能和传感器对话。


先搞清楚:Xavier NX 上的 I2C 接口长啥样?

Jetson Xavier NX 使用的是 Tegra SoC,内置多达 6 条 I2C 控制器(i2c-1 到 i2c-6)。不过并不是所有都引出来了。

我们在开发板的40-pin 扩展头上最常用的是这两个:

引脚功能BCM 编号对应总线
PIN 3SDAGPIO 2i2c-1
PIN 5SCLGPIO 3i2c-1

也就是说,默认情况下,只要你把传感器接到这两个引脚上,就可以使用i2c-1进行通信。

⚠️ 注意:不同载板设计可能略有差异,请以官方 Carrier Board Design Guide 为准。

那怎么确认你的 I2C 总线已经启用?一句话命令搞定:

sudo i2cdetect -l

输出类似这样就说明 OK 了:

i2c-1 i2c 7000c000.i2c I2C adapter i2c-4 i2c 7000d000.i2c I2C adapter

看到i2c-1出现在列表里了吗?恭喜,你可以继续往下走了。


硬件连接不能马虎:三步避坑指南

再好的软件也架不住接错线。以下是新手最容易踩的三个坑:

✅ 第一步:正确连线

把你的传感器 SDA 接到 PIN 3,SCL 接到 PIN 5。电源接 3.3V(不是 5V!Tegra IO 是 3.3V 安全电压)。

Sensor ↔ Jetson Xavier NX ------------------------------- VCC → 3.3V (PIN 1) GND → GND (PIN 6) SDA → SDA (PIN 3) SCL → SCL (PIN 5)

✅ 第二步:加上拉电阻

I2C 是开漏输出,必须外加上拉电阻!否则信号拉不起来,通信失败。

推荐阻值:2.2kΩ ~ 4.7kΩ,分别接到 SDA 和 SCL 到 3.3V。

如果你用的是模块化传感器(比如 GY-HDC1080),通常内部已经有上拉电阻,可以跳过这步。不确定的话查手册或用万用表测一下。

✅ 第三步:检查电平匹配

有些传感器工作在 5V 逻辑(如某些老款 Arduino 模块),而 Xavier NX 只支持 3.3V 输入。直接连会烧芯片!

解决方案:使用双向电平转换器,例如PCA9306BSS138搭建的电平移位电路。


扫描总线:看看谁在线?

硬件接好了,下一步就是“打招呼”——扫描 I2C 总线上有哪些设备。

Linux 提供了一个超实用工具:i2cdetect

安装方法(如果还没装):

sudo apt update sudo apt install i2c-tools

然后执行扫描命令:

sudo i2cdetect -y 1

你会看到一个 16x16 的表格,显示当前 i2c-1 上检测到的设备地址。

正常情况输出如下:

0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- ... 40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

如果你看到40这个位置有数字(比如 HDC1080 地址是 0x40),那就说明通信链路通了!

但如果看到的是UU,表示该地址已被内核驱动占用(比如摄像头 EEPROM 占用了 i2c-4),你就不能再用smbus直接操作它。


Python 上场:用 smbus2 读取温湿度

终于到了激动人心的编码环节。

我们要读的是一款常见的数字温湿度传感器:TI HDC1080,I2C 地址为0x40,支持测量温度和相对湿度。

安装依赖库

pip3 install smbus2

smbus2是一个轻量级、线程安全的库,兼容 Python 3.x,比原生smbus更稳定,推荐使用。


完整代码实现

import time from smbus2 import SMBus, i2c_msg # 配置参数 I2C_BUS = 1 # 使用 i2c-1 SENSOR_ADDR = 0x40 # HDC1080 默认地址 # 寄存器映射 REG_TEMP = 0x00 # 温度寄存器 REG_HUMID = 0x01 # 湿度寄存器 def read_temperature(bus): """读取温度值""" write = i2c_msg.write(SENSOR_ADDR, [REG_TEMP]) read = i2c_msg.read(SENSOR_ADDR, 2) bus.i2c_rdwr(write, read) raw = int.from_bytes(bytes(read), 'big') # 转换公式:T = -40 + 165 * (raw / 65536) return -40.0 + 165.0 * raw / 65536.0 def read_humidity(bus): """读取湿度值""" write = i2c_msg.write(SENSOR_ADDR, [REG_HUMID]) read = i2c_msg.read(SENSOR_ADDR, 2) bus.i2c_rdwr(write, read) raw = int.from_bytes(bytes(read), 'big') # RH = 100 * (raw / 65536) return 100.0 * raw / 65536.0 def main(): try: with SMBus(I2C_BUS) as bus: print("✅ 开始读取 HDC1080 数据...") while True: temp = read_temperature(bus) humid = read_humidity(bus) print(f"🌡️ 温度: {temp:.2f} °C, 💧 湿度: {humid:.2f} %") time.sleep(2) except FileNotFoundError: print("❌ 错误:未找到 I2C 总线,请检查是否启用 i2c-1") except PermissionError: print("🔒 权限不足,请将用户加入 i2c 组:sudo usermod -aG i2c $USER") except Exception as e: print(f"🚨 未知错误: {e}") if __name__ == "__main__": main()

关键点解析

🔹i2c_msg实现组合事务

我们用了i2c_msg.write + i2c_msg.read配合i2c_rdwr(),这相当于一次“发送寄存器地址 + 立即读取数据”的原子操作,避免中间出现 Stop 条件导致某些传感器响应异常。

🔹 数据格式处理

HDC1080 返回的是 16 位大端(Big-Endian)数据,所以我们用int.from_bytes(..., 'big')正确解析。

🔹 异常处理全覆盖
  • FileNotFoundError:对应/dev/i2c-1不存在,可能是未加载驱动
  • PermissionError:权限问题,需加入i2c用户组
  • 其他异常兜底提示

常见问题与调试技巧(血泪经验)

❓ 问题 1:运行报错 “Permission denied”

原因:普通用户无权访问/dev/i2c-*

解决办法

sudo usermod -aG i2c $USER

然后注销重新登录生效。

验证是否成功:

ls -l /dev/i2c-1

应该能看到crw-rw---- 1 root i2c ...


❓ 问题 2:i2cdetect 扫不到设备

排查步骤:

  1. 检查电源是否正常(用万用表测 VCC-GND 是否有 3.3V)
  2. 查看接线是否反接(SDA/SCL 接反很常见)
  3. 确认传感器地址是否正确(有些模块可通过跳线改变地址)
  4. 加上拉电阻(特别是长线传输时)
  5. 降低 I2C 速率测试稳定性(见下文)

❓ 问题 3:读出来的数据全是 0 或 65535

典型症状:数值固定不变。

可能原因
- 寄存器地址写错了(查手册确认 REG_TEMP 是不是 0x00)
- 传感器未初始化或处于休眠状态
- I2C 时钟太快,设备跟不上

建议先尝试降低 I2C 总线频率。


如何修改 I2C 通信速率?

默认速率通常是 100kHz 或 400kHz,但对于老旧或低功耗传感器,可能需要降速。

编辑设备树片段即可(无需完整重编译 DTB):

&i2c1 { clock-frequency = <100000>; // 设置为 100 kHz status = "okay"; };

保存后使用dtoverlay动态加载,或者集成进系统镜像。

修改后记得重启,否则设置不生效。


进阶思路:不只是读一个传感器

实际项目中,你往往要同时读多个设备,比如:

  • BME280(温湿压)
  • CCS811(CO₂ 和 TVOC)
  • SI1145(紫外线/光照)

它们都可以挂在同一组 I2C 总线上,只要地址不冲突。

你可以封装一个通用类:

class I2CSensor: def __init__(self, bus_num, addr): self.bus = SMBus(bus_num) self.addr = addr def read_register(self, reg, length=2): write = i2c_msg.write(self.addr, [reg]) read = i2c_msg.read(self.addr, length) self.bus.i2c_rdwr(write, read) return int.from_bytes(bytes(read), 'big')

然后派生出HDC1080Sensor(BME280Sensor)等具体实现,做到插件式扩展。


生产环境建议:静态声明 vs 动态探测

虽然本文用的是动态探测方式(用户空间直接操作),但在生产环境中更推荐设备树静态声明

例如,在.dtsi文件中添加:

&i2c1 { status = "okay"; hdc1080@40 { compatible = "ti,hdc1080"; reg = <0x40>; status = "okay"; }; };

好处是:
- 内核自动绑定驱动
- 支持 sysfs 接口暴露(如/sys/class/hwmon/
- 更利于系统管理和监控

当然,前提是你要掌握设备树编译流程。


结语:让 AI 真正“感知”世界

Jetson Xavier NX 不只是一个推理盒子,它是智能终端的大脑。而 I2C 就是它的“神经末梢”,负责收集来自物理世界的原始信号。

掌握了 I2C 通信,你就打通了从“看得懂模型”到“摸得着世界”的关键一环。

下次当你部署一个空气质量监测机器人、智慧农业网关或工业预测性维护系统时,希望你能想起今天这一课:
再强的 AI,也要靠一个个字节的传感器数据喂出来

如果你正在做类似的项目,欢迎在评论区分享你的传感器清单和遇到的坑,我们一起讨论优化方案!


📌小贴士:本文代码已测试通过于 JetPack 4.6 / 5.0 环境,适用于 Ubuntu 18.04/20.04 系统。完整示例仓库可在 GitHub 搜索jetson-i2c-hdc1080获取。

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/1/8 13:05:16

2、C++基础入门:数据类型、变量与操作全解析

C++基础入门:数据类型、变量与操作全解析 1. 简单数据类型 在C++里,存在多种简单数据类型,可分为整数类型、浮点类型和布尔类型。 1.1 整数类型 整数类型有五种,分别是 char 、 wchar_t 、 short int 、 int 和 long int ,它们也被称作整型。 short int 和…

作者头像 李华
网站建设 2025/12/27 0:03:07

Hearthstone-Script全攻略:解锁炉石传说智能自动化新体验

Hearthstone-Script全攻略&#xff1a;解锁炉石传说智能自动化新体验 【免费下载链接】Hearthstone-Script Hearthstone script&#xff08;炉石传说脚本&#xff09;&#xff08;2024.01.25停更至国服回归&#xff09; 项目地址: https://gitcode.com/gh_mirrors/he/Hearths…

作者头像 李华
网站建设 2026/1/10 8:26:07

终极Android打印指南:如何让手机轻松连接任何网络打印机

还在为手机无法直接打印文档而烦恼吗&#xff1f;AndroidCupsPrint项目为你提供了完美的解决方案&#xff01;这个基于CUPS协议的开源工具&#xff0c;能够将你的Android设备变成专业的无线打印终端。无论你是在家办公、远程工作还是校园学习&#xff0c;只需简单配置&#xff…

作者头像 李华
网站建设 2025/12/30 9:51:16

14.5 因果发现方法:PC算法、基于约束与基于分数的学习

14.5 因果发现方法:PC算法、基于约束与基于分数的学习 因果发现旨在仅从观测数据中推断变量间潜在的因果结构,是因果科学中一项基础而核心的任务。与基于干预实验的“黄金标准”不同,因果发现试图在无法进行主动实验的场景下,从被动收集的数据中揭示数据生成机制。其主流方…

作者头像 李华
网站建设 2026/1/9 20:13:57

15.4 分布外检测:异常检测、新颖性检测与领域适应

15.4 分布外检测:异常检测、新颖性检测与领域适应 机器学习模型在现实世界中的可靠部署,面临一个根本性挑战:训练数据所代表的“已知世界”与测试数据可能来自的“未知世界”之间存在差异。当模型遇到与训练分布不一致的样本时,其预测往往会变得不可靠甚至完全错误,这对自…

作者头像 李华
网站建设 2026/1/13 14:21:29

手把手教你完成工控机JLink接线全过程

手把手带你搞定工控机JLink接线&#xff1a;从识别到连通的完整实战指南 你有没有遇到过这样的场景&#xff1f;一台现场部署的工控机突然“变砖”&#xff0c;串口无响应&#xff0c;网络不通&#xff0c;远程升级失败……一切常规手段都失效了。这时候&#xff0c;唯一能救场…

作者头像 李华