10

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

在此处输入图像描述

我为 I²C 使用了两个 2000 欧姆的上拉电阻,所有板都是Arduino Duemilanoves。I²C 设置和控制设置在彼此断开连接时都能正常运行,但在连接时,只要wire.write调用第一个函数,Arduino 就会变得无响应。我停止接收串行消息,从 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

4 回答 4

4

“接收事件”在 ISR 中,在事件函数返回之前不会退出

哦,顺便说一句,AVR 硬件将 I2C 总线保持在冻结状态,直到此事件退出,也称为时钟拉伸

哦,你猜怎么着,Wire 没有将 FIFO 变量声明为 volatile,所以即使他有 while (Wire.available()),这也会变成一个无限循环,因为 available() 永远不会改变,因为这一切都发生在中断和rxBufferIndex 和 rxBufferLength 未声明为 volatile

http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_volatile

这是一个可能的原因

在这里插入关于 Arduino 及其糟糕的库的愤怒咆哮

解决方案?使用另一个库,“Wire.h”借用的TWI实用程序,如果你知道如何,可以直接使用,而且很棒,我一直在使用它。

于 2012-11-10T05:10:56.647 回答
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

于 2012-11-09T15:30:24.560 回答
0

你不能在receiveEvent里面写

receiveEvent 定义命令,然后主机应该调用 requestFrom 并请求值,从机处理 (requestEvent) 并在那里使用 write。

即1-主线。写入(命令名称)

2- slave:处理(receiveEvent)并获取命令ID

3- Master 发送 requestFrom

4- 从机处理(requestEvent)并根据命令 ID 向主机发送回复。

于 2014-04-20T21:19:52.633 回答
0

与其尝试使用多个从属设备,不如先使用单主设备和单从设备配置启动。并尽量保持程序尽可能简单。您创建功能,如接收和发送到主/从

于 2014-01-08T11:35:58.177 回答