I2C

2016-03-08 8 views
5

के माध्यम से रास्पबेरी पीआई के साथ अरुडिनो से डेटा कैसे पढ़ा जाए, मैंने रास्पबेरी पीआई 2 मॉडल बी को बाई-दिशात्मक स्तर शिफ्ट के माध्यम से अरुडिनो यूनो के साथ जोड़ा है।I2C

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

आशा है कि मेरा आई 2 सी कनेक्शन सही है?

और मेरा Arduino 8-चैनल रिले बोर्ड से जुड़ा हुआ है।

अब मैंने कोड लिखा है जिसमें मैं रास्पबेरी पाई द्वारा रिले बोर्ड को नियंत्रित कर सकता हूं। पूर्व के लिए यदि मैं '1' दबाता हूं तो रिले 1 ऊंचा हो जाता है।

अब मैं रिडबे 1 उच्च है या नहीं, अगर रिले 1 उच्च है या नहीं, तो मुझे कुछ डेटा वापस रास्पबेरी पीआई को भेजना चाहिए या नहीं, तो जांचने के लिए मैं आर्डिनो से रास्पबेरी पाई में डेटा वापस भेजना चाहता हूं।

मेरे आरपीआई कोड है

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 कोड:

#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); 
} 

अब अगर मैं 1 टाइप करें और कुछ ढीला कनेक्शन रिले के कारण 1 नहीं उच्च चला जाता है इस मामले में तो, मैं Arduino रिले बोर्ड से डेटा लेना चाहते हैं और इसे हर बार रास्पबेरी पाई भेजना चाहते हैं।

यह अच्छा होगा अगर कोई यह समझा सके कि यह कैसे काम करता है।

आशा है कि मैं समस्या की व्याख्या करने में सक्षम था। मैंने बहुत सारे शोध किए हैं लेकिन कुछ जवाब नहीं मिला।

मैं अजगर में एक नौसिखिया हूं इसलिए कृपया मेरी मदद करें।

अग्रिम धन्यवाद। इस

void sendData(){ 
    int relay_status; 
    relay_status=digitalRead(4); 
    Wire.write(relay_status); 
    } 
इसके अलावा हार्डवेयर में

तरह

+0

क्या आपके पास विद्युत माप उपकरण तक कोई पहुंच है? इस मामले में एक तर्क विश्लेषक आदर्श होगा कि यह निर्धारित करने के लिए कि बाड़ का कौन सा पक्ष समस्या मौजूद है। साथ ही, क्या आप अपने बिडरेक्शनल लेवल शिफ्ट का भाग संख्या दे सकते हैं? –

उत्तर

0

arduino कोड परिवर्तन में sendData() फ़ंक्शन एक 4 डिजिटल पिन (या किसी अन्य मुक्त आई/ओ पिन) इनपुट रिले से कनेक्ट।

आशा है कि यह मदद करता है :)

0

ठीक है, एक बहुत अच्छी शुरुआत की तरह दिखता है। दो चीजें मैं यहां सुझाव देना चाहता हूं।

सबसे पहले, अपने पायथन कार्यक्रम में आपको number प्रिंट करना चाहिए ताकि आप इसे मूल्य बदल सकें। यह Arduino से आपकी प्रतिक्रिया संग्रहीत कर रहा है, इसलिए आप स्क्रीन पर उस प्रतिक्रिया को प्रदर्शित करना चाहते हैं। यह number = readNumber() से print readNumber() को बदलने जैसा आसान है।

दूसरा, आपके Arduino कार्यक्रम में, क्या आप सुनिश्चित हैं कि Wire.read() पर कॉल करना आपको लगता है कि यह क्या करता है? ऐसा लगता है कि मुझे पढ़ना पसंद है() एक बाइट देता है। संभावना है कि जब आप 1 टाइप करते हैं तो इसे वास्तव में '1' के रूप में भेजा जा रहा है, न कि 1. बनाम बनाम Int। सही बात?

तो आप इसके बजाय if(number == '1') जांचना चाहेंगे। बस मेरे 2 ¢।

2

समस्या यह है कि आप receiveData के अंदर बहुत कुछ कर रहे हैं, जिसे I2C उपयोगिता कोड, twi.c के इंटरप्ट सेवा रूटीन से बुलाया जाता है।आप डेटा को तेज़ी से संभाल लें, और किसी भी अन्य दिनचर्या को कॉल न करें जो इंटरप्ट सक्षम होने पर निर्भर करता है (वे इस आईएसआर के दौरान अक्षम हैं)।

इसका मतलब है कि आप Serial.print पर कॉल नहीं कर सकते हैं, और आप किसी अन्य वायर भेजने के तरीकों को कॉल नहीं कर सकते हैं। यहां तक ​​कि millis() या micros() को भी निराश किया जाता है, क्योंकि वे उचित समय लेते हैं, और वे टिमर इंटरप्ट को संभालने पर निर्भर करते हैं।

बेशक, आप नि: शुल्क कॉल 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); 
    } 
} 

loop में delay अनावश्यक है, और समस्या पैदा हो सकती आप loop कुछ और जोड़ते हैं।

volatile कीवर्ड संकलक को loop अनुकूलित करने से रोकता है। उस कीवर्ड के बिना, लूप में newData के लिए परीक्षण गायब हो जाएगा क्योंकि संकलक सोचता है कि newDataloop के दौरान नहीं बदलता है। इसका परीक्षण क्यों करें? volatile newData संकलक को बताता है कि newData किसी भी समय बदल सकता है, जैसे receiveData आईएसआर के दौरान।

और आरपीआई कोड में number प्रिंट करना सुनिश्चित करें, क्योंकि फोल्ट्ज़ ने सुझाव दिया था!

0

आपकी आई 2 सी बस ठीक से कनेक्ट नहीं है। स्तरीय शिफ्ट को हटाएं, और एससीएल और एसडीए लाइनों पर 3.3 वी वीसीसी में 4.7 के पुल-अप जोड़ें। I2c चिप्स केवल लाइन को कम ड्राइव करते हैं, और लाइन को उच्च खींचने के लिए बाहरी प्रतिरोधकों की आवश्यकता होती है। यह आपको अपनी आई 2 सी बस पर वोल्टेज स्तर को काफी आसानी से मिश्रण करने देता है। फिर आप यह पता लगाने के लिए वापस जा सकते हैं कि आपका कोड क्या कर रहा है।

+0

मुझे Arduino से रास्पबेरी में डेटा भेजने के साथ समस्याएं हैं। – shivam

संबंधित मुद्दे