ArduinoI²C启动后冻结

时间:2012-11-01 22:10:59

标签: arduino

我正在尝试I²C设置,其中一个主Arduino控制两个奴隶。

Enter image description here

我在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");
        }
    }
}

4 个答案:

答案 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数据表的公式

http://i.imgur.com/ZAByF.png

以下是ATMEGA数据表,有关I2C部分的信息,请参见第21节

http://www.atmel.com/Images/doc8161.pdf

答案 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。