10

1つのマスターArduinoが2つのスレーブを制御するI²Cセットアップを試みています。

ここに画像の説明を入力してください

I²Cに2つの2000オームプルアップ抵抗を使用しており、すべてのボードはArduinoDuemilanovesです。I²Cセットアップと制御セットアップは、互いに切断すると正しく機能しますが、接続すると、最初のwire.write機能が呼び出されるとすぐにArduinoが応答しなくなります。シリアルメッセージの受信を停止し、スレーブArduinoがマスターからのメッセージの受信を停止し、ボタンを使用してシステムのオンとオフを切り替える機能を失います。

各機能の後に短い遅延を追加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

これは考えられる原因の 1 つです

Arduino とそのひどいライブラリについての怒りをここに挿入してください

解決?別のライブラリを使用すると、「Wire.h」が借りる TWI ユーティリティは、方法がわかれば直接使用できます。

于 2012-11-10T05:10:56.647 に答える
1

これはあなたを少し助けるかもしれません:

さて、これはテキストの壁になります。投稿する前に誤ってタブを閉じてしまったので、怒っているように聞こえるかもしれません.Arduinoのこの「機能」は本当に悪く、それに3.3vデバイス。SDA および SCL ピンで非常に悪い 20k 内部プルアップを有効にする Wire Library を使用しています。

各 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 に答える