如何使用Arduino IDE在两个不同的地址上通过I2C总线写消息?

如何解决如何使用Arduino IDE在两个不同的地址上通过I2C总线写消息?

我有一个由nodeMCU(master)和arduino nano(slave)组成的主从设置。我想在两个不同的I2C地址上发送两种不同类型的数据。数据类型1是整数,数据类型2是字符。

我已经编写了这两个代码,它们在某种程度上达到了我的预期,但结果不一致。

Master(nodeMCU):

#include <Wire.h>

void setup() {
 Serial.begin(9600); /* begin serial for debug */
 Wire.begin(5,4); /* join i2c bus with SDA=D1 and SCL=D2 of NodeMCU */
}

void loop() {

 int r =5;
 Wire.beginTransmission(8); /* begin with device address 8 */
 Wire.write(r);  
 Wire.endTransmission();
  delay(100);
 String bod = "message";
 Wire.beginTransmission(9);
 Wire.write(bod.c_str());  
 Wire.endTransmission();
  delay(100);

}

奴隶(arduino nano)

#include <Wire.h>


void setup() {
  
 /* register request event */
 Serial.begin(9600);           /* start serial for debug */
}

void loop() {
 Wire.begin(8);                /* join i2c bus with address 8 */
 Wire.onReceive(receiveEvent1); /* register receive event */
 Wire.begin(9);                /* join i2c bus with address 9 */
 Wire.onReceive(receiveEvent2); 

 
}

// function that executes whenever data is received from master

void receiveEvent1(int howMany) {
 while (0 <Wire.available()) {
    int c = Wire.read();   
    /* receive byte as int */
    Serial.print(c);           /* print the int */
  }
 Serial.println();             /* to newline */
}

void receiveEvent2(char howMany) {
 while (0 <Wire.available()) {
   char d = Wire.read();   
    /* receive byte as a character */
    Serial.print(d);           /* print the character */
  }
 Serial.println();             /* to newline */
}

我得到的输出也会在短时间后停止:

5
message

5
5
5
10910111511597103101

5
10910111511597103101

message
5
message
5
10910111511597103101
10910111511597103101
10910111511597103101
5
message
message


message
5
message
message


message
5

期望的输出在那里,但不是以一致的方式,例如:

5
message
5
message
5
message

有没有办法得到这样的输出?并有一种方法可以解决短时间后停止输出的问题吗?

解决方法

我想在两个不同的I2C地址上发送两种不同类型的数据。

Arduino的Wire库设计为每个设备具有一个I2C地址。它的实现使用一组全局资源。这意味着,如果您动态更改接收方Arduino设备的地址,则还需要同步主设备,以了解要使用的地址。

将单个地址分配给从设备并让主设备指示要发送的数据类型会更简单。这可以通过发送JSON或键/值对来完成。例如主机可以在任何整数之前发送前缀on_hand_qty=fields.Float(related='qty_available',string="Your Field") ,在任何字符串之前发送int:。从站可以使用前缀来解释传输模式。

解释输出

10910111511597103101

这是整数str:的ASCII字符。即109、101、115、115、97、103、101

message正在处理通过I2C总线发送的数据,并将每个字节输出为整数。

receiveEvent1()中调用Wire.begin()Wire.onReceive()将更改全局loop() singleton中的设置。基础twi library也具有一组资源。

更改地址和接收处理程序(反复在TwoWire中)的结果是一组竞争条件以及两个接收处理程序的未定义使用。

这似乎包括loop()按照您的意图处理“ 5”和receiveEvent1()处理“消息”。它还包括receiveEvent2()处理“消息”,从而产生数字序列。

明显的空行很可能receiveEvent1()处理“ 5”,因此可能正在输出一个不可打印的ASCII ENQ(查询)字符。有时也可能没有正确配置处理程序,并且某些消息被丢弃或忽略。

,

您不应使用 2 个地址与单个从设备进行通信。相反,您应该使用一个地址,并指定您将要发送的数据类型。

您如何指定要发送的数据类型?

就像 Ben T 所说,您可以使用 JSON 来实现这一点,但我认为这对您的应用程序来说有点过头了。

一个更简单的实现,需要更少的字节来选择你正在传输的数据类型,就是在软件方面定义 2 个不同的地址;一种用于接收整数,一种用于接收字符。

在您的主设备中,您将拥有如下内容:

// First sending the integer
Wire.beginTransmission(8); //slave address is 0x08
Wire.write(0); // this is your "propriatary" address for sending integers!
Wire.write(r); // write your integer
Wire.endTransmission();

// Then sending the characters
Wire.beginTransmission(8);
Wire.write(1); // this is the address for sending characters!
Wire.write(bod.c_str());
Wire.endTransmission();

在你的奴隶的 setup() 函数中,你应该有类似的东西:

Wire.begin(8); // slave address
Wire.onReceive(dataReceived);

这就是回调 dataReceived 的样子:

void dataReceived() {
    char address = Wire.read(); // get the "propriatary" address
    switch(address) {
        case 0: // receiving integers
            receiveEvent1();
            break;
        case 1: // receiving characters
            receiveEvent2();
            break;
        default:
            break; // if we received an invalid address,do nothing
    }
}
,

如果阅读还没结束就被截断了,是不是就意味着你不期待了? 确保主代码传输所有! 确定以后在slav里读数据的时候都得到吗?

while (Serial.available() > 0) { //Seri porttan gönderilmiş ama; henüz okunmamış tampon bellekte duran byte sayısını verir.
    // get the new byte:
    char inChar = (char)Serial.read();
    // add it to the inputString:
    inputString += inChar;
    // if the incoming character is a newline,set a flag so the main loop can
    // do something about it:
    if (inChar == '\n') {
      Serial.println(inputString);
      stringComplete = true;
    }

您可以尝试读取这样的终止符和字符串!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-