2016-03-08 8 views
5

私は、ラズベリーpi2モデルBとArduino unoを双方向レベルシフターを介して接続しました。ラズベリーパイとArduinoのデータをI2Cで読み取る方法

Raspberry pi GND ---------- GND  Arduino 
       3.3v ---------- 5v 
       SCL ---------- A5 
       SDA ---------- A4 

私のI2C接続は正しいですか?

私のArduinoは8チャンネルリレーボードに接続されています。

今、私はラズベリーパイによってリレーボードを制御できるコードを書いています。例えば、「1」を押すと、リレー1が高くなります。

Relay 1が高いかどうかを確認するために、arduinoからラズベリーパイにデータを戻したい場合、Relay 1が高い場合、Raspberry piにデータを戻す必要があります。

マイRPIコードが

import smbus 
import time 
# for RPI version 1, use "bus = smbus.SMBus(0)" 
bus = smbus.SMBus(1) 

# This is the address we setup in the Arduino Program 
address = 0x04 

def writeNumber(value): 
    bus.write_byte(address, value) 
    # bus.write_byte_data(address, 0, value) 
    return -1 

def readNumber(): 
    number = bus.read_byte(address) 
    # number = bus.read_byte_data(address, 1) 
    return number 

while True: 
    var = input("") 
    if not var: 
     continue 

    writeNumber(var) 
    number = readNumber() 

私のArduinoのコードです:私は、私は1を入力し、何らかの接触不良リレー1にあれば

#include <Wire.h> 

#define SLAVE_ADDRESS 0x04 
#define RELAY1 9 

int number = 0; 
int state = 0; 

void setup() { 
    pinMode(RELAY1, OUTPUT); 

    Serial.begin(9600); // start serial for output 
    // initialize i2c as slave 
    Wire.begin(SLAVE_ADDRESS); 

    // define callbacks for i2c communication 
    Wire.onReceive(receiveData); 
    Wire.onRequest(sendData); 

    Serial.println("Ready!"); 
} 

void loop() { 
    delay(100); 
} 

// callback for received data 
void receiveData(int byteCount){ 

    while(Wire.available()) { 
     number = Wire.read(); 
     Serial.print("data received: "); 
     Serial.println(number); 

     if (number == 1){ 

      if (state == 0){ 
       digitalWrite(RELAY1, HIGH); // set the LED on 
       state = 1; 
      } 
      else{ 
       digitalWrite(RELAY1, LOW); // set the LED off 
       state = 0; 
      } 
     } 
    } 
} 

// callback for sending data 
void sendData(){ 
    Wire.write(number); 
} 

今すぐハイになっていませんので、この場合、 Arduinoがリレーボードからデータを取得し、毎回ラズベリーに送信するようにしてください。

誰かがそれがどのように機能するかを説明することができれば、素晴らしいことになります。

私は問題を説明することができました。私は多くの研究をしましたが、何らかの答えを見つけることができませんでした。

私は初心者ですので、私を助けてください。

ありがとうございます。ハードウェアでも、この

void sendData(){ 
    int relay_status; 
    relay_status=digitalRead(4); 
    Wire.write(relay_status); 
    } 

等Arduinoのコード 変化

+0

電気計測機器はありますか?この場合、フェンスのどちらの側に問題が存在するかを判断するには、ロジックアナライザが理想的です。また、双方向レベルシフタの部品番号を教えてください。 –

答えて

0

のsendData()関数は、入力を中継する一つの第4デジタルピン(または任意の他のフリーI/Oピン)を接続します。

助けて欲しいと思っています。

0

[OK]を、かなり良いスタートのように見えます。私がここで提案したい2つの事柄。

まず、Pythonプログラムでは、numberを印刷して、値の変更を確認してください。 Arduinoからのフィードバックが保存されているので、そのフィードバックを画面に表示したいと考えています。これは、number = readNumber()print readNumber()に変更するのと同じくらい簡単です。

第2に、あなたのArduinoプログラムでは、Wire.read()を呼び出すと、あなたが思っていることが返ってくることを確かめますか?私はread()がバイトを返すように見えます。チャンスは、あなたが1を入力すると、実際には1ではなく、1として送られている可能性があります。Char vs. Int。理にかなっている?

代わりにif(number == '1')にチェックしてください。ちょうど私の2¢。

2

問題は、I2Cユーティリティーコードtwi.cの割り込みサービスルーチンから呼び出されたreceiveDataの内部で多すぎることです。がすばやくデータを処理する必要があり、割り込みが有効になっている他のルーチンを呼び出さないでください(このISR中に無効になっています)。

これはSerial.printに電話をかけることができないことを意味し、他の電線送付方法を呼び出すことはできません。 millis()またはmicros()に電話することも、かなりの時間がかかり、処理されるTIMER割り込みに依存するので、お勧めしません。

もちろん、Wire.available()Wire.read()は無料です。実際には、byteCountは利用可能なバイト数を示しますので、Wire.available()に再度電話する必要はありません。

基本的に、あなたのreceivedDataルーチンは、あなたがすぐにそれを処理しようとしている場合、ルーチン内のデータを読み取ることができます。 の場合は、(揮発性)フラグを設定してから、loopで監視することしかできません。

// variables that allow signalling between receiveData ISR and loop 
volatile bool newData = false; 
volatile uint8_t state = false; 

// callback for received data 
void receiveData(int byteCount) 
{ 
    // Read all the bytes; only the last one changes the relay state 
    while (byteCount-- > 0) 
     number = Wire.read(); 

    if (state != number) { 
     state = number; 
     newData = true; 
    } 
} 

// callback for sending data 
void sendData(){ 
    Wire.write(number); 
} 

void loop() 
{ 
    if (newData) { 
    newData = false; // clear the flag for next time 

    if (number == 1){ 
     digitalWrite(RELAY1, HIGH); // set the LED on 
    } else { 
     digitalWrite(RELAY1, LOW); // set the LED off 
    } 

    Serial.print("data received: "); 
    Serial.println(number); 
    } 
} 

delayloopに不要であり、あなたがloopに何か他のものを追加した場合に問題を引き起こすことがあります。私はあなたのスケッチに表示されるものと、あなたはこのような何かを行うことができます。

キーワードvolatileは、コンパイラがloopを最適化しないようにします。そのキーワードがなければ、ループ内のnewDataのテストは、loopの間に変更されないnewDataとコンパイラが考えるので消えます。なぜそれをテストするのですか? volatile newDataは、newDatareceiveData ISRのようにいつでも変更できることをコンパイラに伝えます。

また、をrpiコードで印刷することをお勧めします。

0

i2cバスが正しく接続されていません。レベルシフタを取り外し、4.7kのプルアップをsclとsdaの3.3V vccに追加します。 I2cチップはラインをローに駆動するだけで、ラインをハイに引き上げるには外部抵抗が必要です。これにより、i2cバスの電圧レベルをかなり簡単に混合することができます。次に、あなたのコードが何をしているのかを知ることに戻ることができます。

+0

私はarduinoからラズベリーにデータを送信する際に問題があります。 – shivam

関連する問題