Lego NXT per NXC: Arduino Daten über i2c auslesen/schreiben

hallo,
nachdem ich andernorts nicht weiterkomme (weiß wohl keiner was) versuche ich mein Glück jetzt auch mal hier, auch wenn die Chance sicher nicht groß ist, dass ich hier einen Kenner finde… aber wer weiß…:

Ich möchte einen Lego Mindstorms NXT als i2c master mit einem Arduino verbinden. Programmiersprache: NXC.
Für Java/Lejos gibt es eine Lösung, die hilft mir aber nicht, weil Java ein komplett anderes Betriebssystem mit völlig anderen API-Funktionen hat als NXC und die intern auch komplett anders arbeiten - und ich Java sowieso niemals nutzen werde.

Was ich bisher habe:

a) Arduino:

Der Arduino liest alle 20ms einen Taster an digital pin 2 aus (Taster an VCC über 100kOhm gegen GND)
value=digitalRead(signalpin);
und gibt das Ergebnis an ledpin 13 (interne LED) aus
digitalWrite(ledpin,value);

Bis hierhin funktioniert es.

Gleichzeitig wird er als devaddr 0x03 definiert
Wire.begin(3);

und soll auf i2c-request den Zustand des signalpins als byte an den i2c-Bus übergeben
void requestEvent() {
** Wire.write(signalpin); // respond with message of 1 byte**
}

// Arduino slave
// touch sensor with external Pullup at pin digital 2
// i2c as slave, dev addr. 0x03

#include <Wire.h> // serial lib

int  ledpin=13;  
byte signalpin=12;  
byte value=0;  

//*************************************************************************  
void setup()  
{  
  pinMode(ledpin,OUTPUT);    
  pinMode(signalpin,INPUT);
  
  Wire.begin(3);                // join i2c bus with dev address 0x03
  Wire.onRequest(requestEvent); // register event
}  

//*************************************************************************  
  
void requestEvent() {
    Wire.write(signalpin);         // respond with message of 1 byte
}

//*************************************************************************

void loop()  
{  
  value=digitalRead(signalpin);    
  digitalWrite(ledpin,value);

  delay(20);  
}

b) NXT:

// NXT i2c master

int ArduinoReadi2c(byte port, byte devaddr, byte cnt, byte &values[]){

  byte I2CMsg[];
  byte nByteReady = 0;
  int  result = 0;

  // enable / disable address shift:
  // devaddr=devaddr<<1; // ???  Arduino uses upper 7 of 8  bits  ???
  
  ArrayBuild(I2CMsg, devaddr);

  while (I2CStatus(port, nByteReady) == STAT_COMM_PENDING){ Yield(); }

  result=I2CBytes(port, I2CMsg, cnt, values);
  
  if(!result){
     PlayTone(100,500);
     Wait(750);
     ClearScreen();
  }
  return result;
}




task main() {
  int i2cresult;

  byte Arduinoport=S4,
       Arduinoaddr=0x03,
       i2creply[1],
       cnt=1;
  int  value;


  SetSleepTime(0);
  SetSensorLowspeed(S4);

  while(true) {

    i2cresult=ArduinoReadi2c(Arduinoport, Arduinoaddr, cnt, i2creply);  // Arduino 1 byte
    TextOut(0,LCD_LINE1,"i2cresult= ");
    NumOut(60,LCD_LINE1, i2cresult, DRAW_OPT_CLEAR_EOL );
    
    value=i2creply[0];
    TextOut(0,LCD_LINE2,"value0= ");
    NumOut(48,LCD_LINE2, value);

    Wait(50);
  }

}

Leider funktioniert es nicht mit dem NXT-Master und dem Arduino-Slave, der NXT meldet immer einen i2c-Verbindungsfehler.

i2c pullups sind 2x4.7k (laut einem lejos-Beispiel), SCL an analog4, SDA an analog5, alle GNDs sind verbunden (Arduino analogGND + Arduino digitalGND + NXT_rot ).

Also wo steckt der Fehler?

Ich nehme mal an Du hast einen Arduino UNO:

Du hast SDA und SCL vertauscht.

http://arduino.cc/en/Main/ArduinoBoardUno: TWI: A4 or SDA pin and A5 or SCL pin. Support TWI communication using the Wire library.

Grüße Uwe

stimmt, hatte ich
ich hab einen 2009 (ATMega168)

  • wie kam ich nur drauf? Ich bin sicher, bei mir stand SCL=4, SDA=5.

Habe es jetzt vertauscht, leider aber immer noch i2c error auf dem NXT.
im NXC Code ausprobiert,

  • sowohl mit Arduino-devaddr 3
  • als auch mit devaddr 3<<1 (= 6) wegen der möglichen oberen 7 bit-Codierung.

schade…! :frowning:

ok, das gesagte gilt auch für den Arduino 2009 mit ATmega168

http://mattallen37.wordpress.com/arduino-libraries/ http://www.dfrobot.com/community/interfacing-the-arduino-and-lego-mindstorms.html

Grüße Uwe

ah... seltsam... die Pullups sind hier je 82k zum NXT-VCC... ich hatte 4.7k zum Arduino-VCC...

witzig muss ich morgen gleich mal ausprobieren ;)

schade, dass kein NXC code dabei ist - RobotC hat auch eine eigene Firmware mit völlig anderen i2c-API-Befehlen. Es ist wirklich zum Ko**** :(

4,7kOhm sind schon ok.
Wenns mit denen nicht funktioniert, funktionierts schon gar nicht mit 82kOhm.

Wie lange sind die Kabel zwischen Arduino und NXT?

Grüße Uwe

Abstand ca. (edit, sry:) 30-40 cm zur Zeit ... aber , wie gesagt: die Pullups gingen bei mir zum Arduino (+), offenbar müssen sie aber zum NXT-(+)

Hallo, kann es sein, das Du einen Denkfehler in der Sache hast. Die LegoKiste ist doch Master, der Arduino auch. Einen von beiden mußt Du beibringen Slave zu sein. Gruß und Glück Andreas

Die LegoKiste ist doch Master, der Arduino auch. Einen von beiden mußt Du beibringen Slave zu sein.

Hat er doch; wenn man bei Wire.begin(3); eine Zahl angibt ist Arduino ein Slave mit dieser Adresse.

Abstand ca. (edit, sry:) 30-40 cm zur Zeit ... aber , wie gesagt: die Pullups gingen bei mir zum Arduino (+), offenbar müssen sie aber zum NXT-(+)

Wenn die GND zusammengeschaltet sind dann ist es egal woher die 5V für die Widerstände kommen. die GND müssen aber auf jeden Fall verbunden sein. Versuch mal möglichst kurze Kabel (einige cm).

Grüße Uwe

das geht z.Zt nicht kürzer, und später ist der Abstand höchstens noch größer. Immerhin hat der Arduino eingebaute pullups, da reichen wschl 0-5 kOhm. Der NXT braucht aber 47k-83k pullups zu seiner VCC(+).

Wenn man sich Beispielfotos anderer Lösungen (andere FW) anschaut, sind die Abstände aber auch nicht kleiner (eher noch größer). Aber auch die Programme auf NXT und Arduino sind deutlich komplizierter.

Ich bräuchte halt mal ein einfaches, funktionierendes NXC-Beispiel, ausbauen kann man es ja später immer noch. Kriegs aber nicht hin, i2c mit NXC war mir aber auch immer schon ein Greuel.

Hallo,
kommst Du damit weiter:

#include <Wire.h>


#define SLAVE_ADDRESS 0x04
int number = 0;
int state = 0;
 
void setup() {
    pinMode(13, 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(13, HIGH); // set the LED on
                state = 1;
            }
            else{
                digitalWrite(13, LOW); // set the LED off
                state = 0;
            }
         }
     }
}
 
// callback for sending data
void sendData(){
    Wire.write(number);
}

Gruß und Glück
Andreas

hallo, dankeschön, werd ich baldmöglichst testen. Vor allem wie man Werte auf i2c-Anfrage auf dem Arduino schreibt ist gut zu wissen.

Allerdings ist der Tel, der auf Anfrage einen Wert zurücksendet, der gleiche wie bei mir, und der alleine funktioniert ja bereits nicht. Oder siehst du irgendeinen Bug in meinem Code ganz oben?

Falls da keiner erkennbar ist, ist ansonsten wohl der NXC Code auf dem NXT fehlerhaft, was ich eigentlich befürchte. Also müsste mal der NXC-Code bitte gecheckt und ggf berichtigt werden!

Hallo, nimm das:

http://www.dexterindustries.com/files/Arduino_and_NXT_Code.zip Achtung, kommt gleich hoch.

Dann lese das: http://www.dexterindustries.com/howto/connect-the-arduino-and-the-lego-mindstorms-together/?PageSpeed=noscript

Wenn Du das auch nicht hinbekommst, dann melde Dich im feindlichen NXT-Forum an. Gruß und Spaß Andreas

dankeschön - aber den Link kenne ich schon, die Infos sind extrem unvollständig.

ABER:
Ich habe es hingekriegt :slight_smile:
1.) ich musste tatsächlich die Pullups 2x 47k (eigtl besser sogar 83k) zu NXT(+) führen - nicht je 4**,**7k zu Arduino(+)
2.) SDA an ana 4, SCL an ana 5 wie schon oben geschrieben.
3.) die Arduino-i2c-dev-Addr muss tatsächlich im NXC-code 1x linksgeshiftet werden (3<<1 = 6 !)

=> Kein i2c-Verbindungsfehler mehr!

Aber dann:
4.) tatsächlich ein Arduino-code-Fehler! Ich muss ntl nicht signalpin in den Bus schreiben, sondern den WERT des signalpins (ohjeojeoje).

Und:

ES KLAPPT, Juhuu! :smiley: :smiley: :D)

hier die beiden funktonierenden Codes:

// touch sensorwitht external Pullup at pin digital 2
// i2c as slave, dev addr. 0x03

#include <Wire.h> // serial lib

int  ledpin=13;   
byte signalpin=12;   
byte I2Cbyte=0;  

//*************************************************************************  
void setup()  
{  
  pinMode(ledpin,OUTPUT);    
  pinMode(signalpin,INPUT);
  
  Wire.begin(3);                // join i2c bus with dev address 0x03
  Wire.onRequest(requestEvent); // register event
}  

//*************************************************************************  
  
void requestEvent() {
 
  Wire.write(I2Cbyte);         // respond with message of 1 byte
}

//*************************************************************************

void loop()  
{  
  I2Cbyte=digitalRead(signalpin);    
  digitalWrite(ledpin,I2Cbyte);

  delay(20);  
}
// NXT i2c master

int ArduinoReadi2c(byte port, byte devaddr, byte cnt, byte &values[]){

  byte I2CMsg[];
  byte nByteReady = 0;
  int  result = 0;

  devaddr=devaddr<<1; //  Arduino uses upper 7 of 8  bits  !!!
  
  ArrayBuild(I2CMsg, devaddr);

  while (I2CStatus(port, nByteReady) == STAT_COMM_PENDING){ Yield(); }

  result=I2CBytes(port, I2CMsg, cnt, values);
  
  if(!result){
     PlayTone(100,500);
     Wait(750);
     ClearScreen();
  }
  return result;
}




task main() {
  int i2cresult;

  byte Arduinoport=S4,
       Arduinoaddr=0x03,
       i2creply[1],
       cnt=1;
  int  value;


  SetSleepTime(0);
  SetSensorLowspeed(S4);

  while(true) {

    i2cresult=ArduinoReadi2c(Arduinoport, Arduinoaddr, cnt, i2creply);  // Arduino 1 byte
    TextOut(0,LCD_LINE1,"i2cresult= ");
    NumOut(60,LCD_LINE1, i2cresult, DRAW_OPT_CLEAR_EOL );
    
    value=i2creply[0];
    TextOut(0,LCD_LINE2,"value0= ");
    NumOut(48,LCD_LINE2, value);

    Wait(50);
  }

}

Jetzt kanns ans analog-read und ans digital-write gehen :slight_smile:

Danke an alle für eure nette und unermüdliche Mithilfe!

(Aber das NXT-Forum ist doch auch nicht “feindlich” :wink: - wir haben doch schließlich alle dasselbe Hobby :sunglasses: )

so, und hier ist die erste lauffähige Version, die digitale und analoge Werte lesen und schreiben kann ! :smiley:
share and enjoy ! :smiley:

http://www.mindstormsforum.de/viewtopic.php?f=25&t=8302&p=65015#p65015