RPi <-> Arduino über I2C Führt nicht jeden erhaltenen Befehl aus

Hallo,
ich bin ein kompletter Neuling im Bereich Coding, dass schonmal im vorraus :sweat_smile:

Mein Setup sieht momentan so aus:
RaspberryPi ist mit dem Arduino Mega über I2C verbunden. RPi ist Master und Arduino Slave. Am Arduino hängt ein 8 Channel Relay.

Verkabelung:
RPi zu Arduino
Ground <-> Ground
SDA <-> SDA
SCL <-> SCL

Arduino zu Relay
Pin 22-29 <-> Pin 1-7
Ground <-> Ground <-- Überhaupt nötig ? Schaltet auch ohne Verbindung
5V <-> VCC <-- Für Elektronik

Externes Netzteil zu Relay
5V <-> JD-VCC <-- Zum Schalten der Relays
Ground <-> Ground

RPi und Arduino haben jeweils ein eigenes Externes Netzteil.

Wenn ich dem Arduino vom RPi eine Zahl über I2C sende sollte dieser den entsprechenden Pin entweder HIGH oder LOW schalten, so dass das der entsprechende Channel aktiviert wird. Funktoniert auch, ich kann jeden Channel einzeln Schalten.

Nun zum Problem:
Hoffe ich kann das jetzt verständlich erklären :sweat_smile:
Wenn ich denselben Channel schalte dann funktoniert es jedesmal ohne Fehler, kann ihn so oft An- und Ausschalten wie ich möchte, aber sobald ich den nächsten oder ein anderen Channel Schalten will, muss ich den Befehl zwei mal Senden:
Sende Befehl für Ch1 -> Ch1 geht an
Sende Befehl für Ch2 -> Ch2 bleibt aus
Sende Befehl für Ch2 erneut -> Ch2 geht an <-- In diesem Zustand kann ich so oft wie ich will An- und Ausschalten.
Sende Befehl für Ch3 -> Ch3 bleibt aus
Sende Befehl für Ch4 -> Ch4 geht an <-- In diesem Zustand kann ich so oft wie ich will An- und Ausschalten.
Sende Befehl für Ch5 -> Ch5 gleibt aus
usw.
Ich kann auch querbeet durchwechseln erst Ch3 (bleibt aus), dann Ch8 (geht an) usw.
Es sieht so aus als ob nur jeder zweite befehl ankommt. Obwohl ich, wenn ein Channel angegangen ist, ich ihn so oft Schalten kann wie ich möchte, aber sobald ich den Channel wechsle, ich erst wieder zwei mal den Befehl senden muss.

Der Serielle Monitor zeigt mir aber an das jeder Befehl korrekt beim Arduino ankommt.

So nun noch zum Code:
Arduino

#include <Wire.h>

#define SLAVE_ADDRESS 0x04
int ZahlVonPi = 0;
int state = 0;

void setup() {
	for (int PinVonArdu = 22; PinVonArdu <= 29; PinVonArdu++){ //Definiert mehrere Pins, in dem Fall Pin 22-29
	pinMode(PinVonArdu,OUTPUT);
	}
    Serial.begin(9600); // Starte serial output
    Wire.begin(SLAVE_ADDRESS); //I2C Slave Adress
	// Definiere Empfang und Sendemodul fuer I2C Kommunikation
    Wire.onReceive(receiveData);
    Wire.onRequest(sendData);

    Serial.println("Bereit!");
}

void loop() {
}

void receiveData(int byteCount){

    while(Wire.available()) {
        ZahlVonPi = Wire.read();
        Serial.print("daten erhalten: ");
        Serial.println(ZahlVonPi);

	for (int PinVonArdu = 22; PinVonArdu <= 29; PinVonArdu++){	
		if (ZahlVonPi == PinVonArdu)
			
            if (state == 0){
                digitalWrite(PinVonArdu, HIGH);
                state = 1;
            }
            else{
                digitalWrite(PinVonArdu, LOW);
                state = 0;
            }
         }
     }
}

void sendData(){
    Wire.write(ZahlVonPi);
}

RaspberryPi

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("Enter Pin number: ")
    if not var:
        continue

    writeNumber(var)
    print "RPI: Hi Arduino, I sent you ", var

    number = readNumber()
    print "Arduino: Hey RPI, I received a digit ", number
    print

Hoffe Ihr versteht was ich meine :slight_smile:
Mit freundlichen Grüßen
MasterTroll

Hallo,

ich blick zwar nicht ganz durch, sehe aber das Deine loop() leer ist. Aus meiner Sicht resetet sich der Arduino jedesmal oder wird resetet sobald der Raspberry ein Signal schickt. Denn wenn er sich nicht reseten würde, dann würde überhaupt nichts passieren, weil die loop() leer ist. Der Arduino muß also durch einen Reset ständig das setup aufrufen können. Was jedoch nicht Sinn der Sache ist - denke ich ...

for (int PinVonArdu = 13; PinVonArdu <= 30; PinVonArdu++){	
		if (ZahlVonPi == PinVonArdu)
			
            if (state == 0){
                digitalWrite(PinVonArdu, HIGH);
                state = 1;
            }
            else{
                digitalWrite(PinVonArdu, LOW);
                state = 0;
            }
         }
     }

Der I2C Bus ist auf dem Arduino MEGA auf den Pins 20 und 21. Du kannst nicht diese Pins als Ausgang definieren bzw als Ausgänge verwenden.

Arduino zu Relay
Pin 22-29 <-> Pin 1-7
Ground <-> Ground <-- Überhaupt nötig ? Schaltet auch ohne Verbindung
5V <-> VCC <-- Für Elektronik

Weiß nicht, meine Kristallkugel spuck nicht aus, was für ein Relaismodul Du hast..

Grüße Uwe

Ohh sry war veralteter Code definiert sind nur Pin 22-29
Relay:

MasterTroll:
Ohh sry war veralteter Code definiert sind nur Pin 22-29

Dann bitte den neuen Sketch der Dir Probleme macht.
Grüße Uwe

Habe ich schon im ersten Post angepasst :slight_smile:

MasterTroll:
Habe ich schon im ersten Post angepasst :slight_smile:

Das habe ich nicht erwartet. sorry.

Das Problem ist die Variable state.
Du verwendest sie als Statusvariable für alle Pins. Du brauchst eine Statusvariable pro pin.

Sende Befehl für Ch1 -> Ch1 geht an //status=0 Ausgang wird gesetzt status wird 1
Sende Befehl für Ch2 -> Ch2 bleibt aus //status=1 Ausgang wird ausgeschaltet. status wird 0
Sende Befehl für Ch2 erneut -> Ch2 geht an <-- In diesem Zustand kann ich so oft wie ich will An- und Ausschalten. //status=0 Ausgang wird gesetzt status wird 1
Sende Befehl für Ch3 -> Ch3 bleibt aus //status=1 Ausgang wird ausgeschaltet. status wird 0
Sende Befehl für Ch4 -> Ch4 geht an <-- In diesem Zustand kann ich so oft wie ich will An- und Ausschalten. //status=0 Ausgang wird gesetzt status wird 1
Sende Befehl für Ch5 -> Ch5 gleibt aus
usw.

Grüße Uwe

Hallo,

okay, hätte jetzt nich gedacht das es mit leerer loop() so funktioniert. Sorry.

Was ich noch anmerken möchte. Ist Dir bewußt das Du 3,3V und 5V per I2C Bus verbunden hast?
Gegen was hast Du die Leitung terminiert? Ich hoffe nicht gegen 5V. Die I/Os vom Raspberry arbeiten nur mit 3,3V.
Du hast nicht zufällig einen Pegelwandler in der I2C Leitung drin?

Das ist mir wieder nicht aufgefallen. 8) 8) 8)
Grüße Uwe

Doc_Arduino:
okay, hätte jetzt nich gedacht das es mit leerer loop() so funktioniert. Sorry.

Der Eventhandler wird automatisch am Ende von loop() aufgerufen

http://arduino.cc/en/Tutorial/SerialEvent

Hallo,

aha, alles klar. :wink:

@uwefed
Danke für die Hilfe :slight_smile: Jetzt funktoniert alles wie es soll ^^

@Doc_Arduino
Ich hab nichts in der Leitung hängen. Hab mich auf ein Tutorial verlassen:
http://blog.oscarliang.net/raspberry-pi-arduino-connected-i2c/

How Does It Work? Is It Safe?

The Raspberry Pi is running at 3.3 Volts while the Arduino is running at 5 Volts. There are tutorials suggest using a level converter for the I2C communication. This is NOT needed if the Raspberry Pi is running as “master” and the Arduino is running as “slave”.

The reason it works is because the Arduino does not have any pull-ups resistors installed, but the P1 header on the Raspberry Pi has 1k8 ohms resistors to the 3.3 volts power rail. Data is transmitted by pulling the lines to 0v, for a “high” logic signal. For “low” logic signal, it’s pulled up to the supply rail voltage level. Because there is no pull-up resistors in the Arduino and because 3.3 volts is within the “low” logic level range for the Arduino everything works as it should.
Remember though that if other I2C devices are added to the bus they must have their pull-up resistors removed.

Aber ich werde wahrscheinlich einen Bi-directional Logic Level Converter dazwischen hängen ^^

Hallo!
Das Tutorial passt für den UNO, der Mega bringt ja mit RN1B/C 10k Pullups mit...

mfg Martin

Hallo,

wenn ich solche Anleitungen lese wird mir immer etwas schlecht. Das mag genau für den Fall geradeso funktionieren. Aber wehe jemand läßt den Arduino mit seinen 5V etwas an den Raspberry senden. Dann wird's essig. Die nutzen hier nichts weiter als den Effekt aus, dass bei TTL Pegel ab 2V High Signal definiert ist. Mit 3,3V ist man da knapp drüber. Gilt aber hier eben nur wenn der Arduino empfängt. Ist aber nicht die feine englische Art und Weise. Ich würde einen I2C Pegelwandler einbauen. Dann kann man gefahrlos experimentieren. Oder alles mit 3,3V betreiben.

Doc_Arduino:
... Die nutzen hier nichts weiter als den Effekt aus, dass bei TTL Pegel ab 2V High Signal definiert ist. Mit 3,3V ist man da knapp drüber. Gilt aber hier eben nur wenn der Arduino empfängt. Ist aber nicht die feine englische Art und Weise. Ich würde einen I2C Pegelwandler einbauen. Dann kann man gefahrlos experimentieren. Oder alles mit 3,3V betreiben.

Das mag für TTL stimmen aber der Arduino-Controller ist nicht in TTL Technik aufgebaut.
Da sind die Limits für HIGH bei 5V Versorgungsspannung von 3V bis 5V und LOW von 0V bis 1,5V. Diese Werte ändern sich mit anderen Versorgungsspannungen. Genaue Werte in Tabelle "28.2 DC Characteristics" Seite 313 von http://www.atmel.com/Images/doc8161.pdf

Bezüglich der Gefahr den Rasberry abzuschießen wenn mal zufällig die Pins als Ausgänge deklariert werden und zufälligerweise HIGH sind gebe ich Dir völlig Recht :wink: :wink:

Grüße Uwe

Hallo Uwe,

jetzt kam ich erstmal ins grübeln wegen dem Datenblatt. Das sind ja Faktoren um die benötigten Logikpegel auszurechnen. Man oh man ... :slight_smile:

Dann hat die Anbindung der beiden ja nur 0,3V "Reserve". Dann ist die Funktionsfähigkeit noch mehr mit der heißen Nadel gestrickt wie eh schon angenommen. Und wie Du schon sagst, nur mal schnell einen anderen Sketch auf den Arduino zum probieren geladen und das wird es für den Raspi gewesen. Denn da sterben eh schon manche wegen unvorsichtiger Beschaltung, denn neben dem 3,3V Spannungspin sitzt noch einer für 5V. Ich habe einen meinem Neffen geschenkt und habe ihn "eingetrichtert" er soll ja aufpassen! :wink:

Ja, die Logikpegel hängen von der Versorgungsspannug Vcc ab und sind bei 5V Versorgungsspannung -0,5V bis 0,3Vcc und 0,6Vcc bis Vcc+0,5V .
Grüße Uwe