我正在尝试I²C设置,其中一个主Arduino控制两个奴隶。
我在I²C上使用两个2000欧姆上拉电阻,所有电路板都是Arduino Duemilanoves。 I²C设置和控制设置在彼此断开连接时都能正常工作,但连接后,只要调用第一个wire.write
功能,Arduinos就会无响应。我停止接收串行消息,从属Arduinos停止接收来自主设备的消息,并且我无法使用按钮打开和关闭系统。
我尝试在每个wire.write
功能之后添加短延迟,并尝试使用各种上拉电阻来解决问题,但似乎没有任何效果。我该如何解决这个问题?
主码:
#include <Wire.h>
int potPin1 = 0; // Select the input pin for the potentiometer
int potPin2 = 1;
int potVal1; // Variable to store the value coming from the sensor
int potVal2;
int times=0; // All the below variables are used to control an on-off button
int state=0;
int lastState=0;
boolean pot=false;
void setup()
{
pinMode(13, OUTPUT); //LED that turns on when system is activated
pinMode(3, INPUT); //Button that turns on system
Serial.begin(9600);
Wire.begin();
}
void loop(){
state=digitalRead(3);
if(state != lastState){
if(state==HIGH){
times++;
Serial.println(times);
}
else{
Serial.println("off");
}
}
lastState=state;
if(times%2 ==1)
{
turnPotOn();
}
else
{
turnPotOff();
}
//到此为止的循环中的所有代码都会在按下按钮时打开和关闭系统。 //以下代码对应I²C,基于电位计读数。
if(pot==true)
{
potVal1 = analogRead(potPin1); // Read the value from the sensor
potVal2 = analogRead(potPin2);
if((potVal1>700) && (300<potVal2) && (potVal2<700))
{
arduino1_motor1();
}
else if ((potVal1<330) && (336<potVal2) && (potVal2<683))
{
arduino1_motor2();
}
else if ((potVal2>683) && (330<potVal1) && (potVal1<640))
{
arduino2_motor3();
}
else if ((potVal2<336) && (330<potVal1) && (potVal1<640))
{
arduino2_motor4();
}
else if ((potVal2<336) && (potVal1<330))
{
arduino12_motor24();
}
else if ((potVal2>683) && (potVal1>640))
{
arduino12_motor23();
}
else if ((potVal2>683) && (potVal1<640))
{
arduino11_motor23();
}
else if ((potVal2<336) && (potVal1>330))
{
arduino11_motor24();
}
else
{
arduino12_still();
}
}
else
{
// arduino1_still();
// arduino2_still();
Serial.println("OFF");
}
}
void turnPotOff()
{
digitalWrite(13, LOW);
pot=false;
}
void turnPotOn()
{
digitalWrite(13, HIGH);
pot=true;
}
void arduino1_motor1()
{
Wire.beginTransmission(5);
Wire.write('A');
Wire.endTransmission();
arduino2_still();
Serial.println("A1 in M1 d");
}
void arduino1_motor2()
{
Wire.beginTransmission(5);
Wire.write('B');
Wire.endTransmission();
arduino2_still();
Serial.println("A1 in m2 d");
}
void arduino12_still()
{
arduino1_still();
arduino2_still();
Serial.println("A1 & A2 stl");
}
void arduino2_motor3()
{
arduino1_still();
Wire.beginTransmission(10);
Wire.write('M3');
Wire.endTransmission();
Serial.println("A2 in M3 d");
}
void arduino2_motor4()
{
arduino1_still();
Wire.beginTransmission(10);
Wire.write('D');
Wire.endTransmission();
Serial.println("A2 in M4 d");
}
void arduino12_motor24()
{
Wire.beginTransmission(5);
Wire.write('B');
Wire.endTransmission();
Wire.beginTransmission(10);
Wire.write('D');
Wire.endTransmission();
Serial.println("A1 & A2 in M2 and M4 d");
}
void arduino12_motor23()
{
Wire.beginTransmission(5);
Wire.write('B');
Wire.endTransmission();
Wire.beginTransmission(10);
Wire.write('C');
Wire.endTransmission();
Serial.println("A1 & A2 in M2 and M3 d");
}
void arduino11_motor24()
{
Wire.beginTransmission(5);
Wire.write('A');
Wire.endTransmission();
Wire.beginTransmission(10);
Wire.write('D');
Wire.endTransmission();
Serial.println("A1 & A2 in M1 and M4 d");
}
void arduino11_motor23()
{
Wire.beginTransmission(5);
Wire.write('A');
Wire.endTransmission();
Wire.beginTransmission(5);
Wire.write('C');
Wire.endTransmission();
Serial.println("A1 & A2 in M1 and M3 d");
}
void arduino1_still()
{
Wire.beginTransmission(5);
Wire.write('S');
Wire.endTransmission();
}
void arduino2_still()
{
Wire.beginTransmission(10);
Wire.write('S');
Wire.endTransmission();
}
从属1代码:
#include <Servo.h>
#include <Wire.h>
Servo myservo1;
Servo myservo2;
void setup()
{
Serial.begin(9600); // setup serial
myservo1.attach(2);
myservo2.attach(3);
Wire.begin(5);
Wire.onReceive(receiveEvent);
}
void loop()
{
}
void receiveEvent(int howMany)
{
while(Wire.available())
{
char v = Wire.read();
if(v == 'A')
{
myservo1.write(0);
myservo2.write(180);
Serial.println("Arduino 1 in motor 1 direction");
}
else if(v == 'B')
{
myservo1.write(180);
myservo2.write(0);
Serial.println("Arduino 1 in motor 2 direction");
}
else
{
myservo1.write(90);
myservo2.write(85);
Serial.println("Arduino 1 still");
}
}
}
奴隶2:
#include <Servo.h>
#include <Wire.h>
Servo myservo3;
Servo myservo4;
void setup()
{
Serial.begin(9600); // Setup serial
myservo3.attach(2);
myservo4.attach(3);
Wire.begin(10);
Wire.onReceive(receiveEvent);
}
void loop()
{
}
void receiveEvent(int howMany)
{
while(Wire.available())
{
char v = Wire.read();
if(v == 'C')
{
myservo3.write(0);
myservo4.write(180);
Serial.println("Arduino 2 in motor 3 direction");
}
else if(v == 'D')
{
myservo3.write(180);
myservo4.write(0);
Serial.println("Arduino 2 in motor 4 direction");
}
else
{
myservo3.write(90);
myservo4.write(90);
Serial.println("Arduino 2 still");
}
}
}
答案 0 :(得分:4)
&#34;接收活动&#34;在ISR中,在事件函数返回之前不会退出
顺便说一下,AVR硬件将I2C总线保持在冻结状态,直到此事件退出,也称为时钟延长哦,猜猜看,Wire没有将FIFO变量声明为volatile,所以即使他有while(Wire.available()),也会变成无限循环,因为available()永远不会改变,因为它&# 39; s全部发生在中断中,rxBufferIndex和rxBufferLength未声明为volatile
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_volatile
这是一个可能的原因
在这里插入关于Arduino及其可怕图书馆的愤怒咆哮
溶液?使用另一个库,TWI实用程序&#34; Wire.h&#34;借用可以直接使用,如果你知道如何,并且它很棒,我会一直使用它。
答案 1 :(得分:1)
这可能对你有所帮助:
好的,所以这将是一个文本墙,我已经在发布之前一次关闭了标签,所以我可能听起来很生气,因为Arduino的这个“功能”真的很糟糕,如果它会花费你你将3.3v设备插入其中。 您正在使用Wire Library,它可以在SDA和SCL引脚上实现非常糟糕的20k内部上拉。
每个ARDUINO。您的总上拉电阻现在已被堵塞(拧紧)。 您需要研究如何禁用内部上拉。我建议修改库。出于整体原因,这种控制绝不应该用软件来完成。 仔细检查所需外部上拉的数学计算。 Arduino上每个SCL / SDA引脚的电容应为10pF。
这是直接来自ATMEGA数据表的公式
以下是ATMEGA数据表,有关I2C部分的信息,请参见第21节
答案 2 :(得分:0)
不是尝试使用多个从站,而是使用单主站和单从站配置进行首次启动。并尽量保持程序尽可能简单。您可以创建接收和发送到主/从
等功能答案 3 :(得分:0)
你不能写在receiveEvent里面
receiveEvent定义命令 然后主设备应该调用requestFrom并请求值,并且slave处理(requestEvent)并在那里使用write。
即。 1-主线。写(命令名)
2- slave:handle(receiveEvent)并获取命令ID
3- Master发送requestFrom
4- slave handle(requestEvent)并根据命令ID将回复发送给master。