I2C Kommunikation EV3Basic <--> Arduino

NXC, C/C++, Lejos, pbLua, RobotC...

Moderator: Moderatoren

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 21. Sep 2015 14:40

hallo,
an alle EV3Basic Benutzer und natürlich an Copperdragon, den Entwickler...:

I2C scheint der einzige Weg zu sein, damit der EV3 mit der Arduinowelt kommunizieren kann, denn UART ist auf ihm nicht programmierbar.

Meine Frage: wie läst sich eine EV3Basic <--> Arduino (Due 3.3V) Kommunikation per I2C programmieren?

Der Due bietet sich hier besonders an, weil beide Gräte dieselben Signal-Levels haben, und weil der Due einen 2. I2C Port hat, der sich als Slave konfigurieren lässt - und sein 1. I2C Port könnte weiterhin Master bleiben für eigene Sensoren.

Die Kommunikatio sollte in der Lage sein, jeweils einen (edit:) 32 Byte "breiten" Array hin- und her zu schicken.
(32 ist die Grenze auf dem EV3)
D.h. beide Geräte haben einen

byte SendArray[32];
byte RecvArray[32];

in denen jeweils die Nachricht zum anderen bzw. vom anderen Gerät abgelegt wird.
EV3 nutzt leider 2 Bytes für Adresse und Register, also bleiben netto 30 Bytes zum Senden übrig.
Zum Empfang stehen aber wahrscheinlich 32 zur Verfügung.

Die ersten 4 Bytes sollen Kontrollzwecke erfüllen:
1. Byte: 0xff zur Start- und Verbindungs-Erkennung (sync byte control)
2. Byte: eine Checksum (Summe aller Byte-Werte ab 5.Byte-30.Byte, davon dann das LowByte) (data transmission control)
3. Byte: eine ID des Slaves (transmission direction control)
4. Byte: Acknowlege-Flag-Byte: Ok=1 => sende neue Daten, wiederholen=127 => sende alte Daten erneut (msg order control)
Der Rest sind beliebige zu versendende Daten-Bytes.

Die Byte-Arrays sollen zum Gegenpart per Pingpong-System verschickt werden, wenn die vorherige Nachricht angekommen ist.

Ich habe für NXT plus Arduino per I2C und für 2 Arduinos per UART bereits so etwas geschrieben, das Prinzip soll sein:

Code: Alles auswählen

1. EV3 sendet eine Nachricht

2. Arduino wartet, bis eine Nachricht da ist.
Dann wird auf Korrektheit überprüft (Bytes 1-3), wenn alles OK dann können die Daten verarbeitet werden.
Wenn nicht, wird ein Array mit Flagbyte 127 produziert zur Wiederholung
Ansonsten wird ein "echter" Daten-Array an den EV3 bereitgestellt.

3. Mittlerweile wartet der EV3 auf die Verfügbarkeit eines Arrays (Message) vom Arduino (Empfangs-Task)
Ist eine Message vorhanden, wird sie ausgewertet.
Enthält sie das Flagbyte 127, wird die alte Nachricht erneut gesendet, ansonsten eine neue.

4. wie (2.)... usw....


welche Nachrichten genau geschickt werden sollen, ist jedem selber überlassen.
Mir wäre es wichtig, dass der EV3 mindestes seine Encoderwerte (4x 32bit) und Sensorwerte (3x 16bit evtl plus Daisy-Chaining) verschickt,
was der Arduino schickt ist zunächst egal, es könnten z.B. ebenfalls Sensorwerte (auch Potis oder Taster) und Motorkommandos sein.

Jetzt geht es aber erstmal ums reine Array-hin-und-her-verschicken.

Wie ist dieser Teil lösbar auf dem EV3 mit EV3Basic?
Wenn jemand einen ersten Testcode als Basis zeigen könnte, werde ich den Arduino-Teil dazu programmieren und dann wieder hier posten.

Anhang:
Voransicht:
EV3Basic Arduino20151002_223338.jpg
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino (Due 3.3V) I2C

Beitragvon HaWe » 21. Sep 2015 21:43

Für Arduino und NXT/NXC habe ich es ja prinzipiell selber schon hier gezeigt: http://www.mindstormsforum.de/viewtopic.php?f=70&t=8624&p=67236#p67236, ein Code-Beispiel für Arduino und EV3-G gibt es von Dexter Industries: http://www.dexterindustries.com/howto/connecting-ev3-arduino/).

Für den Arduino verwende ich den folgenden Code (wird hier immer aktualisiert auf die neueste Version):

Code: Alles auswählen

//  Arduino code
//  to interface an Arduino to an EV3
//  Arduino as an I2C slave
//  compiles for MEGA and DUE, IDE 1.6.5
//  ver. 0.004a

#include  <SPI.h>
#include  <Wire.h>


//#include <ardustdio.h>

//=====================================================================================
// misc.
//=====================================================================================

#define  clock()      millis()


//=====================================================================================
// I2C EV3 Communication
//=====================================================================================

#define  I2CSLVADDR     0x04
#define  I2CMASTADDR    0x00
#define  MSGSIZE        31
byte     recvarray[MSGSIZE];
byte     sendarray[MSGSIZE];

int32_t  flag=0;


//=====================================================================================
//=====================================================================================
void setup() {
   char sbuf[128];   
   int32_t  i=0;

   // Serial terminal window
   i=115200;
   Serial.begin(i);
   Serial.print("Serial started, baud="); Serial.println(i);

   // Wire (i2c)
   Wire.begin(I2CSLVADDR  );  //  start Arduino as a I2C slave, addr=0x04 (7-bit coded)
   Wire.onReceive(receiveData );
   Wire.onRequest(sendData );
   memset(sendarray, 0, sizeof(sendarray) );
   memset(recvarray, 0, sizeof(recvarray) );   
   Serial.println("I2C init: done.");

   sprintf(sbuf, "setup(): done.");
   Serial.println(); Serial.println(sbuf);   

}


//=====================================================================================


uint8_t  calcchecksum(uint8_t array[]) {
  int32_t  sum=0;
  for(int i=4; i<MSGSIZE; ++i) sum+=(array[i]);
  return (sum & 0x00ff);
}

//=====================================================================================

void loop()
{
  char sbuf[128];

  if(flag==1)
   {
      Serial.println(); Serial.println();

      // do something with the received data
      // and then do something to build the sendarray [4]...[31]
      sendarray[5] += 1;

      sendarray[0] = 0xff;
      sendarray[1] = calcchecksum(sendarray) ;
      sendarray[2] = I2CMASTADDR   ;           // to check by master: master address ID
      sendarray[3] = flag;                     // flag to master: 1= new data; 127=send again request
      sendarray[MSGSIZE-1] = I2CSLVADDR  ;     // to check by master: corrupted data ?
      //... feddisch!
      flag=0;     
   }
   else
   if(flag==127) {  // builds array with error flag 127
      Serial.println("ERROR! flag==127");
      memset(sendarray, 0, MSGSIZE);
      sendarray[0] = 0xff;
      sendarray[1] = calcchecksum(sendarray) ;
      sendarray[2] = I2CMASTADDR   ;           // to check by master: master address ID
      sendarray[3] = flag;                     // flag to master: 1= new data; 127=send again request
      sendarray[MSGSIZE-1] = I2CSLVADDR  ;     // to check by master: corrupted data ?
   }
   sprintf(sbuf, "Sendarr[4]=%4d,    [5]=%4d,    Recvarr[4]=%4d,    [5]=%4d",
                  sendarray[4], sendarray[5], recvarray[4], recvarray[5]) ;
   Serial.println(sbuf);

   delay(2);  // short break for the cpu and the bus
}


//=====================================================================================

void receiveData(int byteCount) {
    int32_t i;
    byte val;

    while(Wire.available()<MSGSIZE) ; // wait for 30  bytes to complete
    i=0;  // init counter var
    while(Wire.available()&& (i<MSGSIZE) )         // read all bytes
    {
      val=Wire.read();
      recvarray[i++]=val;
    }
    // check for first 3 bytes and via calcchecksum() function
    if( (recvarray[0]==0xff) && (recvarray[1]==calcchecksum(recvarray)) && (I2CSLVADDR  ==recvarray[2]) )   
    // if ok:
    flag=1;        // data ok
    else flag=127; // else handle receive error => flag =127  to send array back, request to send again
}

//=====================================================================================

void sendData(){
  // Wire.write writes data from a slave device in response to a request from a master
  Wire.write(sendarray, MSGSIZE); // send own 30 bytes back to master..
}


//=====================================================================================






ps,
Nachteil ist im Moment, dass EV3Basic nicht auf XP läuft. Ich kann nur auf einem fremden Win 7 Rechner testen, nicht aber zu Hause auf XP selber programmieren.
edit:
gelöst!
@Copperdragon: danke für den Patch, Reinhard! :prima:
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
c0pperdragon
Schreibt viel
Schreibt viel
Beiträge: 231
Registriert: 9. Feb 2015 00:29

Re: I2C Kommunikation EV3Basic <--> Arduino (Due 3.3V) I2C

Beitragvon c0pperdragon » 23. Sep 2015 23:26

Mit I2C kann man in der Tat am einfachsten mit Arduinos kommunizieren. Ich habe die beiden Arduinos (ein Micro, ein Uno) für meinen CubeTwister auch so angeschlossen.

UART geht in Prinzip schon auch, aber nur, wenn der Arduino vollständig das EV3-Sensor-Protokoll implementiert. Und dann kann man auch nicht beliebige Daten verschicken, sondern nur, was in das Schema hineinpasst. Aber möglicherweise wäre das sogar bei deinem Anwendungsfall gegeben. Wenn ich mich richtig erinnere, dann gehen da 32 Byte in ein Sensor-Datenpaket rein (das, was der Sensor zum EV3 schickt), in der anderen Richtung weiß ich es jetzt nicht genau, das ist aber ziemlich beliebig verwendbar.
Übertragungsgeschwindigkeit wäre wesentlich höher als mit I2C und laut Spec. darf der Sensor jede Millisekunde in Paket abfeuern. Allerdings kommt der EV3 damit dann nicht mehr wirklich zurecht, und aktualisiert seinen Buffer nur ca. alle 2 Millisekunden - schneller kriegt man das dann auch nicht ins EV3Basic rein. Trotzdem um Häuser schneller als mit I2C (braucht pro übertragenes Byte ca. eine Millisekunde - also für deine 30 hin und 30 zurück schon mal mindestens 60 ms).

Aber, wie gesagt, I2C ist sicher der einfachere Einstieg.
Wenn du ein Code-Beispiel für den Arduino brauchst, dann kannst du dir
https://github.com/c0pperdragon/CubeTwi ... /StopWatch
anschauen. Das ist der Code für den Arduino Uno, der die Zeit misst und meine LED-Ziffern ansteuert.

Habe sogar ein ganz kleines Code-Schnippsel für den EV3 um diese Stoppuhr anzusprechen:
https://github.com/c0pperdragon/CubeTwi ... tchTest.sb

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 27. Sep 2015 09:16

Dnke für deine Nachricht und deine Hinweise, ich habe sie jetzt eingearbeitet!

EV3Basic Programm kompiliert jetzt, Arduino Sketch Teil ebenfalls.
Beide Teilnehmer sollen zu Test- und Kontroll zwecken eine besondere Stelle im Array hochzählen und dann verändert wieder zurückschicken,
der EV3 nimmt dazu Stelle SendArray[4], der Arduino SendArray[5]. Das soll im Handshake passieren, das heißt, jeder Teilnehmer wartet erst auf den Eingang der Partner-Daten, bevor er selber wieder weiterrechnet und dann zurücksendet.

die Arduino-Sourcecodes wurden bereits oben aktualisiert:
Arduino-Code: http://www.mindstormsforum.de/viewtopic.php?f=25&t=8673#p67558

hier kommt jetzt das Gegenstück, der EV3-Basic-Code in der zuletzt aktualisierten Version:

Code: Alles auswählen

'//  EV3Basic code
'//  to interface an EV3 to an Arduino
'//  EV3 as an I2C master, Arduino as an I2C slave
'//  SmallBasic 1.0 or 1.5
'//  EV3Basic 1.07
'//  EV3 fw Lego 1.06
'//  ver. 0.004a

MSGSIZE = 31
I2CPORT = 4          '// EV3 sensor port 4
I2CSLVADDR  = 4      '// device addr=0x04
I2CMASTADDR = 0      '// master addr=0x00

sendmsg = Vector.Init(MSGSIZE, 0)
recvmsg = Vector.Init(MSGSIZE, 0)

datapacket = Vector.Init(MSGSIZE, 0)   '// msg buffer to sub calculatechecksum
checksum = 0                           '// global return value to sub calculatechecksum

sub calculatechecksum
  checksum = 0
  For i=4 To MSGSIZE-1
     checksum = checksum + datapacket[i]   
  endfor
  checksum = Math.Remainder(checksum,256)
endsub


LCD.StopUpdate()
LCD.Clear()

While "True"
   LCD.Text(1,  0,  0,  1, "Send Array")
     'LCD.Text(1,   0, 10,  1, sendmsg[0]+"    " )
     LCD.Text(1,   0, 10,  1, sendmsg[1]+"  " )
     LCD.Text(1,  30, 10,  1, sendmsg[2]+"  " )
     LCD.Text(1,  50, 10,  1, sendmsg[3]+"  " )
     LCD.Text(1,  70, 10,  1, sendmsg[4]+"  " )
     LCD.Text(1, 110, 10,  1, sendmsg[5]+"  " )
     LCD.Text(1, 150, 10,  1, sendmsg[6]+"  " )
   LCD.Text(1, 0,  40,  1, "Receive Array")
     'LCD.Text(1,   0, 50,  1, recvmsg[0] +"    ")
     LCD.Text(1,   0, 50,  1, recvmsg[1]+"  " )
     LCD.Text(1,  30, 50,  1, recvmsg[2]+"  " )
     LCD.Text(1,  50, 50,  1, recvmsg[3]+"  " )
     LCD.Text(1,  70, 50,  1, recvmsg[4]+"  " )
     LCD.Text(1, 110, 50,  1, recvmsg[5]+"  " )
     LCD.Text(1, 150, 50,  1, recvmsg[6]+"  " )
   
   sendmsg[0] = 255                '// start sync byte
   sendmsg[2] = I2CSLVADDR  '// for receiver check
   sendmsg[3] = 1                   '// error flag: ok=1
   
   sendmsg[4] = sendmsg[4] +1 '// test increment in each loop
   If sendmsg[4]>255 Then
      sendmsg[4]=0
   EndIf
   
   datapacket = sendmsg
   calculatechecksum()
   sendmsg[1] = checksum
   recvmsg    = Vector.Init(MSGSIZE, 0)   
   errflag = 127
   
   While(errflag=127)
      recvmsg = Sensor.CommunicateI2C( I2CPORT, I2CSLVADDR, MSGSIZE, MSGSIZE, sendmsg )
      errflag=recvmsg[3]
      If ( (recvmsg[MSGSIZE-1]<>I2CSLVADDR) Or (recvmsg[2]<>I2CMASTADDR) ) Then '//
         errflag=127
      EndIf
   EndWhile
   
   datapacket = recvmsg
   calculatechecksum()
   If  recvmsg[1]  <> checksum  Then   
      LCD.Text(1,  0, 100,  1, "CHKSUM ERROR" )
   Else
      LCD.Text(1,  0, 100,  1, "            " )
   EndIf
 
  Program.Delay(1)   '// yield()
 
EndWhile

Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 2. Okt 2015 14:03

update:

EV3Basic wartet auf Antwort vom Slave, bis dahin wird eine Endlosschleife durchlaufen.
Wenn Verbindung hergestellt ist, werden die Arrays abgearbeitet
Wenn die i2c-Kabel-Verbindung zwischendrin unterbrochen wird,
Fehler zur Zeit:
Wenn die Kabel-Verbindung erneut hergestellt ist, bleibt der EV3 in seiner Warteschleife zunächst noch hängen
Wenn dann der Slave aber resettet wird, geht's wieder weiter.

Codes sind oben wieder aktualisiert (Versionen 003)

Daten-Turnaround (EV3Basic im Online-Betrieb):
Arrays wurden in 1 Minute ca. 640 mal hin- und her geschickt,
also etwa 11 mal pro Sekunde.

Wie man den autonomen EV3-Betrieb startet, hab ich noch nicht raus ;)
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 2. Okt 2015 20:54

The first "big leap"!

Daten aus GPS Sensor am Arduino => => EV3 !!
1 Sensor, seine Daten (nur die wichtigsten!) verpackt in sage und schreibe 23 Daten-Bytes :shock:

hier die ersten Foto aus einer anderen, weit entfernten Galaxis (im Innenraum fotografiert, weit weg vom Fenster, daher kaum Satellitenempfang; Rundungsfehler von double auf Integer auf der letzten Dezimalstelle)...:

20151002_212014.jpg
20151002_212034.jpg

20151002_212054.jpg
20151002_223338.jpg


hier der Arduino-Code:

Code: Alles auswählen

//  Arduino code to interface an Arduino to an EV3
//  Arduino as an I2C slave
//  works  for MEGA but not DUE, IDE 1.6.5
//  ver. 0.003

/*
// (C) Helmut Wunder (HaWe) 2015
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach Genehmigung durch den Autor.
// Programming language: Arduino Sketch C/C++ (IDE 1.6.1 - 1.6.3)
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
*/

#include  <SPI.h>
#include  <Wire.h>

//#include <ardustdio.h>

//=====================================================================================
// misc.
//=====================================================================================

#define  clock()      millis()


//=====================================================================================
// I2C EV3 Communication
//=====================================================================================

#define  I2CSLVADDR     0x04
#define  I2CMASTADDR    0x00
#define  MSGSIZE        31
byte     recvarray[MSGSIZE];
byte     sendarray[MSGSIZE];

int32_t  flag=0;

//=====================================================================================
// GPS
//=====================================================================================
#include  <TinyGPS++.h>

static const uint32_t GPSBaud = 9600;
// The TinyGPS++ object
TinyGPSPlus gps;

//=====================================================================================
// TFT LCD
//=====================================================================================

#define   UTFT_SmallFont     8 // UTFT 8x10
#define   UTFT_MediumFont   12 // UTFT ++
#define   UTFT_BigFont      18 // UTFT +++
#define   _SmallFont_        1 // 9341 6x9
#define   _MediumFont_       2 // 9341 12x16
#define   _BigFont_          3 // 9341 18x23

int16_t  LCDmaxX , LCDmaxY ;                // display size
int16_t  _curx_, _cury_,                    // last x,y cursor pos on TFT screen
         _maxx_, _maxy_;                    // max. x,y cursor pos on TFT screen       



// set LCD TFT type
int16_t  LCDTYPE   =   -1;

#define  _UTFT_       4  // Henning Karlsen UTFT 2.2-2.4" 220x176 - 320x240 lib
                           // http://henningkarlsen.com/electronics/library.php?id=51   //
#define _ILI9341_     8  // https://github.com/adafruit/Adafruit_ILI9340
                           // https://github.com/adafruit/Adafruit-GFX-Library //
#define _ILI9341due_  9  // ILI9341_due NEW lib by Marek Buriak
                           // http://marekburiak.github.io/ILI9341_due/ //
                           
//--------------------------------------------------------------------------------------------------
#define    tft_cs     49
#define    tft_dc     48
#define    tft_rst     0                       
                         
//=====================================================================================
// UTFT Henning Karlsen
//=====================================================================================
#include <UTFTQD.h>  // patch for QD220A

//UTFT   qdUTFT(Model,  SDA=MOSI,   SCL,      CS,     RESET,   RS)    // Due: 3 exposed SS pins: 4,10,52
  UTFT   qdUTFT(QD220A,   A2,       A1,       A5,     A4,      A3);   // adjust model parameter and pins!

 extern  uint8_t SmallFont[];
 
//=====================================================================================
// TFT Adafruit LIL9340/ILI9341
//=====================================================================================
#include <Adafruit_GFX.h>
#include <Adafruit_ILI9341.h>

Adafruit_ILI9341  tft = Adafruit_ILI9341(tft_cs, tft_dc, tft_rst);


//=====================================================================================
// TFT ILI9341_due // http://marekburiak.github.io/ILI9341_due/ //
//=====================================================================================
#include <ILI9341_due_config.h>
#include <ILI9341_due.h>
#include <SystemFont5x7.h>

ILI9341_due      dtft = ILI9341_due(tft_cs, tft_dc);

// Color set
#define  BLACK          0x0000
#define RED             0xF800
#define GREEN           0x07E0
//#define BLUE            0x001F
#define BLUE            0x102E
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define ORANGE          0xFD20
#define GREENYELLOW     0xAFE5
#define DARKGREEN       0x03E0
#define WHITE           0xFFFF

uint16_t  color;

//--------------------------------------------------------------------------------------------------

#define  lcdWhiteBlack()  {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(  0,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(WHITE, BLACK) ;} \
}

#define  lcdNormal()      {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(  0,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(WHITE, BLACK) ;} \
}

#define  lcdInvers()      {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(  0,  0,  0); qdUTFT.setBackColor(255,255,255);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9341_BLACK, ILI9341_WHITE) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(BLACK, WHITE) ;} \
}

#define  lcdWhiteRed()    {                                                                 \
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,255); qdUTFT.setBackColor(255,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9341_WHITE, ILI9341_RED) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(WHITE, RED) ;} \
}

#define  lcdRedBlack()    {                                                                 \   
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,  0,  0); qdUTFT.setBackColor(  0,  0,  0);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9341_RED, ILI9341_BLACK) ;} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(RED, BLACK) ;} \
}

#define  lcdYellowBlue()  {                                                                 \     
   if(LCDTYPE==_UTFT_)      { qdUTFT.setColor(255,255,  0); qdUTFT.setBackColor( 64, 64, 64);} \
   else if(LCDTYPE==_ILI9341_)   { tft.setTextColor(ILI9341_YELLOW, ILI9341_BLUE);} \
   else if(LCDTYPE==_ILI9341due_)   { dtft.setTextColor(YELLOW, BLUE);} \
}



int16_t  fontwi= 8;  // default
int16_t  fonthi=10;  // default


void putfonttype(uint8_t fsize) {
  if(LCDTYPE==_UTFT_)  {
    fontwi= qdUTFT.getFontXsize();
    fonthi= qdUTFT.getFontYsize();
  }
  else
  if(LCDTYPE==_ILI9341_) {
     if(fsize==_SmallFont_)     { fontwi= 6; fonthi=9; }  // 5x7 + overhead
     else
     if(fsize==_MediumFont_)    { fontwi=12; fonthi=16; } // ?
     else
     if(fsize==_BigFont_)       { fontwi=18; fonthi=23; } // ?
  }
  else
  if(LCDTYPE==_ILI9341due_) {
     if(fsize==_SmallFont_)     { fontwi= 6; fonthi=9; }  // 5x7 + overhead
  }
  _maxx_ = LCDmaxX / fontwi;    // max number of letters x>>
  _maxy_ = LCDmaxY / fonthi;    // max number of letters y^^
}


void setlcdorient(int16_t orient) {
 
  if(LCDTYPE==_ILI9341_) {
      tft.setRotation(orient);
      LCDmaxX=tft.width();
      LCDmaxY=tft.height();       
   }
   else
   if(LCDTYPE==_ILI9341due_) {
      dtft.setRotation( (iliRotation)orient);
      LCDmaxX=dtft.width();
      LCDmaxY=dtft.height();   
   }
     
}

void lcdcls()  {                                                         
   if(LCDTYPE==_UTFT_)       { qdUTFT.clrScr();                } 
   else
   if(LCDTYPE==_ILI9341_)    { tft.fillScreen(ILI9341_BLACK);  }
   else
   if(LCDTYPE==_ILI9341due_) { dtft.fillScreen(BLACK);  }
   _curx_ =0;  _cury_ =0;
}

void curlf()   {                                                       
   _curx_=0;
   if( _cury_ <=(LCDmaxY-10) ) _cury_+=fonthi;
   else _cury_=0;
     
   if(LCDTYPE==_ILI9341_)    { tft.setCursor(0, _cury_); } 
   else
   if(LCDTYPE==_ILI9341due_) { dtft.cursorToXY(0, _cury_); } 
}



void curxy(int16_t  x,  int16_t  y) {
   _curx_ = x;
   _cury_ = y;
   if(LCDTYPE==_ILI9341_)      {tft.setCursor(x, y); }
   else
   if(LCDTYPE==_ILI9341due_)   {dtft.cursorToXY(x, y); }
}



void lcdprintxy(int16_t x, int16_t y, char * str) {
   if(LCDTYPE==_UTFT_)          {
     qdUTFT.print(str,x,y);
     _curx_=x+strlen(str)*fontwi;
     _cury_=y;
   }
   else if(LCDTYPE==_ILI9341_)  {
      tft.setCursor(x,y);     
      tft.print(str);
      _curx_=tft.getCursorX();
      _cury_=tft.getCursorY();
   }
   else if(LCDTYPE==_ILI9341due_)  {
      dtft.cursorToXY(x,y);     
      dtft.printAt(str, x, y);
      _curx_=x+strlen(str)*fontwi;
      _cury_=y;
   }
}


void lcdprint(char * str) {
    if(LCDTYPE==_UTFT_)     {
      qdUTFT.print(str, _curx_, _cury_);
      _curx_=_curx_+strlen(str)*fontwi;
    }
    else if(LCDTYPE==_ILI9341_)  {
       tft.setCursor(_curx_, _cury_);
       tft.print(str);
       _curx_=tft.getCursorX();
       _cury_=tft.getCursorY();
    }
    else if(LCDTYPE==_ILI9341due_)  {
       dtft.cursorToXY(_curx_, _cury_);
       dtft.printAt(str, _curx_, _cury_ );
      _curx_=_curx_+strlen(str)*fontwi;
    }
}


void initLCD(uint8_t orientation) { // 0,2==Portrait  1,3==Landscape
   if(LCDTYPE==_UTFT_) {
      qdUTFT.InitLCD(orientation%2);
      LCDmaxX=qdUTFT.getDisplayXSize();
      LCDmaxY=qdUTFT.getDisplayYSize();
      qdUTFT.setFont(SmallFont);
      putfonttype(UTFT_SmallFont);
   }
   else
   if(LCDTYPE==_ILI9341_) {
      tft.begin();
      setlcdorient(orientation);       
      tft.setTextSize(_SmallFont_);
      putfonttype(_SmallFont_);
   }
   else
   if(LCDTYPE==_ILI9341due_) {
      dtft.begin();
      setlcdorient(orientation);       
      dtft.setFont(SystemFont5x7);
      putfonttype(_SmallFont_);
   } 



//=====================================================================================
// maths
//=====================================================================================

double frac(double param) {
   double fractpart, intpart;
   fractpart = modf (param , &intpart);
   return fractpart;
}

double intp(double param) {
   double fractpart, intpart;
   fractpart = modf (param , &intpart);
   return intpart;
}


//=====================================================================================


uint8_t lowbyte(uint32_t longval) {
   return(longval & 0x000000ff);   
}


uint8_t highbyte(uint32_t longval) {
   return((longval>>8) & 0x000000ff);   
}


uint8_t low3byte(uint32_t longval) {
   return((longval>>16) & 0x000000ff);   
}


uint8_t high4byte(uint32_t longval) {
   return((longval>>24) & 0x000000ff);   
}


//=====================================================================================

#define d2r (M_PI / 180.0)


//=====================================================================================

//calculate haversine distance for linear distance

double dist( double lat1, double lat2, double long1, double long2 )
{
    double dlong = (long2 - long1) * d2r;
    double dlat = (lat2 - lat1) * d2r;
    double a = pow(sin(dlat/2.0), 2) + cos(lat1*d2r) * cos(lat2*d2r) * pow(sin(dlong/2.0), 2);
    double c = 2 * atan2(sqrt(a), sqrt(1-a));
    double d = 6367 * c;

    return d;
}


//=====================================================================================

uint8_t  calcchecksum(uint8_t array[]) {
  uint32_t  sum=0;
  for(int16_t i=4; i<MSGSIZE; ++i) sum+=(array[i]);
  return lowbyte(sum);
}



//=====================================================================================
// GPS functions
//=====================================================================================
byte databuf[MSGSIZE];

void initGPS() {
  char sbuf[128];
 
  Serial1.begin(GPSBaud);

  Serial.println(F("DeviceExample.ino"));
  Serial.println(F("A simple demonstration of TinyGPS++ with an attached GPS module"));
  Serial.print(F("Testing TinyGPS++ library v. "));
  Serial.println(TinyGPSPlus::libraryVersion());
  Serial.println(F("by Mikal Hart"));
  Serial.println();
 
  Serial.println("setup: GPS test....");
  delay(1000);

  while (Serial1.available() > 0)
    if (gps.encode(Serial1.read())) {       
      GPSdisplayInfo();
      Serial.println("setup: GPS OK! ");
    }

  if (millis() > 5000 && gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
    while(true);
  } 
}

//=====================================================================================

void GPSdisplayInfo()
{
  char sbuf[128];   
  static   double   fLatt=0, fLong=0, fmin, fdecsec,
                    fLattold=0, fLongold=0, fLattmean, fLongmean, fdist=0, ETA=0.7;
  uint16_t decdeg, decmin,
           dday, dmonth, dyear,
           dhour, dmin, dsec, dcsec, nsat;
  int16_t  Iintpart;
  uint32_t Ifracpart;  // frac*10000
 
 
 
  if (gps.location.isValid())
  {
    fLattold = fLatt ;
    fLongold = fLong ;
       
    fLatt = (double)gps.location.lat();
    fLong = (double)gps.location.lng();
   
    fLattmean = ETA*fLatt + (1-ETA)*fLattold;  // Lowpass-Filter
    fLongmean = ETA*fLong + (1-ETA)*fLongold;
   
    fdist = dist ( fLattmean, fLattold, fLongmean, fLongold );
   
    //.......... Lattitude ....................
   
    sprintf(sbuf, "Latt: %+012.7f " , fLattmean );     
    //Serial.print(sbuf);   
    //lcdprintxy(0, 60, sbuf);
   
    decdeg = (int16_t)fLattmean;                        // 1 byte latt degrees
    fmin   = ( fLattmean - (double)decdeg ) * 60;
    decmin = (int16_t)(fmin);                           // 1 byte latt minutes
    fdecsec= ( fmin - (double)decmin ) * 60 ;
    Iintpart=  (int16_t)intp(fdecsec);                  // 1 byte latt seconds
    Ifracpart= (uint32_t)(10000.0*frac(fdecsec));       // => 4 bytes sec-fracts   
     
    databuf[4]=(byte)decdeg;
    databuf[5]=(byte)decmin;
    databuf[6]=lowbyte(Iintpart); 
    databuf[7]=lowbyte(Ifracpart);   // einfacher: memcpy(array+7*sizeof(byte), &Ifracpart, sizeof(int32_t));
    databuf[8]=highbyte(Ifracpart);
    databuf[9]=low3byte(Ifracpart);
    databuf[10]=high4byte(Ifracpart);
   

   
    sprintf(sbuf, "Latt: %+04d:%02d'%7.4f ", decdeg, decmin, fdecsec);
    Serial.print(sbuf);
    lcdprintxy(0, 60, sbuf);

    //........... Longitude ...................

    sprintf(sbuf, "Long: %+012.7f ", fLongmean );
    //Serial.print(sbuf);
    //lcdprintxy(0, 70, sbuf);
   
    decdeg = (int16_t)fLongmean;                        // 1 byte latt degrees
    fmin   = ( fLongmean - (double)decdeg ) * 60;
    decmin = (int16_t)(fmin);                           // 1 byte latt degrees
    fdecsec= ( fmin - (double)decmin ) * 60 ;
    Iintpart=  (int16_t)intp(fdecsec);                  // 1 byte latt seconds
    Ifracpart= (uint32_t)(10000.0*frac(fdecsec));       // => 4 bytes sec-fracts
    databuf[11]=(byte)decdeg;
    databuf[12]=(byte)decmin;
    databuf[13]=lowbyte(Iintpart);
    databuf[14]=lowbyte(Ifracpart);      // einfacher: memcpy(array+14*sizeof(byte), &Ifracpart, sizeof(int32_t));
    databuf[15]=highbyte(Ifracpart);
    databuf[16]=low3byte(Ifracpart);
    databuf[17]=high4byte(Ifracpart);
   
    sprintf(sbuf, "Long: %+04d:%02d'%7.4f ", decdeg, decmin, fdecsec);
    Serial.print(sbuf);
    lcdprintxy(0, 70, sbuf);
  }
  else
  {
    sprintf(sbuf, "Location:  INVALID  ");
    Serial.print(sbuf);
   
  }

  //........... Date ...................

  if (gps.date.isValid())
  {     
    dday=gps.date.day();
    dmonth=gps.date.month();   
    dyear=gps.date.year();
    sprintf(sbuf, "Date: %02d/%02d/%04d ", dday, dmonth, dyear);
    databuf[18]=(byte)dday;
    databuf[19]=(byte)dmonth;
    databuf[20]=(byte)(dyear-2000);
    Serial.print(sbuf);
    lcdprintxy(0, 80, sbuf);
  }
  else
  {
    sprintf(sbuf, "  Date:  INVALID  ");
    //Serial.print(sbuf);   
  }

  //........... Time ...................

  if (gps.time.isValid())
  {
    dhour=gps.time.hour();
    dmin= gps.time.minute();
    dsec= gps.time.second();
    //dcsec=gps.time.centisecond();
    databuf[21]=(byte)dhour;
    databuf[22]=(byte)dmin;
    databuf[23]=(byte)dsec;
   
    sprintf(sbuf, "UTC :  %02d:%02d:%02d  ", dhour, dmin, dsec);
    Serial.print(sbuf);
    lcdprintxy(0, 90, sbuf);

    //........... n Sat ...................

    nsat =gps.satellites.value();
    databuf[24]=(byte)nsat;
    sprintf(sbuf, "nSat: %02d  ", nsat);
    Serial.print(sbuf);
    lcdprintxy(0,100, sbuf);
  }
  else
  {
    sprintf(sbuf, "  Time:  INVALID  ");
    Serial.print(sbuf);
  }

   if(fdist>=1.0) sprintf(sbuf, "noise~km=%-9.4f ", fdist);
   else sprintf(sbuf, "noise~m = %-7.2f ", fdist*1000);
   Serial.print(sbuf);
  lcdprintxy(0,110, sbuf);

  Serial.println();
}

//=====================================================================================
// setup
//=====================================================================================
void setup() {
   char sbuf[128];   
   int32_t  i=0;

   // Serial USB terminal
   i=115200;
   Serial.begin(i);
   Serial.print("Serial started, baud="); Serial.println(i);

   // TFT LCD
   Serial.println();
   LCDTYPE = _UTFT_;
   Serial.print("LCD init ...");
   initLCD(1);   
   Serial.println(" done.");   
   lcdcls();
   sprintf(sbuf, "LCD=%d wi%dxhi%d Font %dx%d",LCDTYPE,LCDmaxX,LCDmaxY,fontwi,fonthi);
   Serial.println(sbuf);
   Serial.println();
   curlf(); lcdprint(sbuf);

   // setup Serial1 for GPS
   initGPS();
   sprintf(sbuf, "GPS init: done.");
   Serial.println(sbuf);
   curlf(); lcdprint(sbuf);
 
   // Wire (i2c)
   Wire.begin(I2CSLVADDR  );  //  start Arduino as a I2C slave, addr=0x04 (7-bit coded)
   Wire.onReceive(receiveData );
   Wire.onRequest(sendData );
   memset(sendarray, 0, sizeof(sendarray) );
   memset(recvarray, 0, sizeof(recvarray) );   
   sprintf(sbuf, "I2C init: done.");
   Serial.println(sbuf);
   curlf(); lcdprint(sbuf);

   sprintf(sbuf, "setup(): done.");
   Serial.println(); Serial.println(sbuf);   
   
   lcdcls();
}




//=====================================================================================
// loop
//=====================================================================================

void loop()
{
   char sbuf[128];
   uint8_t cks;

   Serial.println(); Serial.println();   

   //.................... GPS ....................

   // This sketch displays information every time a new sentence is correctly encoded.
   while ( Serial1.available() > 0)
      if ( gps.encode(Serial1.read() ) )
        GPSdisplayInfo();

   if (millis() > 5000 && gps.charsProcessed() < 10)
   {
      Serial.println(F("No GPS detected: check wiring."));
      while(true);
   }

   //.................... i2c ....................
   if(flag==1)
   {
     Serial.println(); Serial.println();

     // do something with the received data
     // and then build the sendarray [4]...[31]
     memcpy(sendarray, databuf, MSGSIZE);
     
     sendarray[0] = 0xff;
     sendarray[2] = I2CMASTADDR   ;           // to check by master: master address ID
     sendarray[3] = flag;                     // flag to master: 1= new data; 127=send again request
     sendarray[MSGSIZE-1] = I2CSLVADDR  ;     // to check by master: corrupted data ?
     cks = calcchecksum(sendarray);
     sendarray[1] = cks;
     flag=0;     
   }
   else
   if(flag==127) {  // builds array with error flag 127
     Serial.println("ERROR! flag==127");
     memset(sendarray, 0, MSGSIZE);
     sendarray[0] = 0xff;
     sendarray[2] = I2CMASTADDR   ;           // to check by master: master address ID
     sendarray[3] = flag;                     // flag to master: 1= new data; 127=send again request
     sendarray[MSGSIZE-1] = I2CSLVADDR  ;     // to check by master: corrupted data ?
     cks = calcchecksum(sendarray);
     sendarray[1] = cks;
   }
   sprintf(sbuf, "Sendarr[4]=%4d, [5]=%4d,  Recvarr[4]=%4d,  5]=%4d, [1]=%4d, chksum=%4d",
                  sendarray[4], sendarray[5], recvarray[4], recvarray[5], recvarray[5], cks ) ;
   Serial.println(sbuf);

   delay(2);  // short break for the cpu and the bus
   
}


//=====================================================================================

void receiveData(int byteCount) {
    int32_t i;
    byte val;

    while(Wire.available()<MSGSIZE) ; // wait for 30  bytes to complete
    i=0;  // init counter var
    while(Wire.available()&& (i<MSGSIZE) )         // read all bytes
    {
      val=Wire.read();
      recvarray[i++]=val;
    }
    // check for first 3 bytes and via calcchecksum() function
    if( (recvarray[0]==0xff) && (recvarray[1]==calcchecksum(recvarray)) && (I2CSLVADDR  ==recvarray[2]) )   
    // if ok:
    flag=1;        // data ok
    else flag=127; // else handle receive error => flag =127  to send array back, request to send again
}

//=====================================================================================

void sendData(){
  // Wire.write writes data from a slave device in response to a request from a master
  Wire.write(sendarray, MSGSIZE); // send own 30 bytes back to master..
}


//=====================================================================================
    


hier der EV3Basic-Teil:

Code: Alles auswählen


'//  EV3Basic code to interface an EV3 to an Arduino
'//  EV3 as an I2C master, Arduino as an I2C slave
'//  SmallBasic 1.0 or 1.5
'//  EV3Basic 1.07
'//  EV3 fw Lego 1.06
'//  ver. 0.008

/*
// (C) Helmut Wunder (HaWe) 2015
// freie Verwendung für private Zwecke
// für kommerzielle Zwecke nur nach Genehmigung durch den Autor.
// Programming language: Arduino Sketch C/C++ (IDE 1.6.1 - 1.6.3)
// protected under the friendly Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License
// http://creativecommons.org/licenses/by-nc-sa/3.0/
*/

MSGSIZE = 31
I2CPORT = 4          '// EV3 sensor port 4
I2CSLVADDR  = 4      '// device addr=0x04
I2CMASTADDR = 0      '// master addr=0x00

sendmsg = Vector.Init(MSGSIZE, 0)
recvmsg = Vector.Init(MSGSIZE, 0)

datapacket = Vector.Init(MSGSIZE, 0)   '// msg buffer to sub calculatechecksum
checksum = 0                           '// global return value to sub calculatechecksum

sub calculatechecksum
  checksum = 0
  For i=4 To MSGSIZE-1
     checksum = checksum + datapacket[i]   
  endfor
  checksum = Math.Remainder(checksum,256)
endsub


LCD.StopUpdate()
LCD.Clear()

While "True"

   
   sendmsg[0] = 255          '// start sync byte
   sendmsg[2] = I2CSLVADDR   '// for receiver check
   sendmsg[3] = 1            '// error flag: ok=1
   
   sendmsg[4] = sendmsg[4] +1 '// test increment in each loop (for future sensors)
   If sendmsg[4]>255 Then
      sendmsg[4]=0
   EndIf 
   
   datapacket = sendmsg
   calculatechecksum()
   sendmsg[1] = checksum
   recvmsg    = Vector.Init(MSGSIZE, 0)   
   errflag = 127
   
   While(errflag=127)
      recvmsg = Sensor.CommunicateI2C( I2CPORT, I2CSLVADDR, MSGSIZE, MSGSIZE, sendmsg )
      errflag=recvmsg[2]
      If ( (recvmsg[MSGSIZE-1]<>I2CSLVADDR) Or (recvmsg[2]<>I2CMASTADDR) ) Then
         errflag=127
      EndIf
   EndWhile
   
   datapacket = recvmsg
   calculatechecksum()
   If  recvmsg[1]  <> checksum  Then   
      'LCD.Text(1,  0, 100,  1, "CHKSUM ERROR" )
   Else
      'LCD.Text(1,  0, 100,  1, "            " )
   EndIf
   
   Lattdeg=recvmsg[4]+256*recvmsg[5]
   Lattmin=recvmsg[6]
   Lattsec=recvmsg[7]
   Lattsecfrac1=recvmsg[8]
   Lattsecfrac2=recvmsg[9]*256
   Lattsecfrac3=recvmsg[10]*256*256
   Lattsecfrac4=recvmsg[11]*256*256*256
   Lattsecfrac=Lattsecfrac1+Lattsecfrac2+Lattsecfrac3+Lattsecfrac4
     
   If Lattdeg>127 Then   
       Lattdeg=Lattdeg-128 
       EndIf
       
    LCD.Text(1,  0, 60,  1, "Latt: "+ Lattdeg + ":" + Lattmin + "'" + Lattsec + "." + Lattsecfrac+"  ")
   
   
   Longdeg=recvmsg[12]+256*recvmsg[13]
   Longmin=recvmsg[14]
   Longsec=recvmsg[15]
   Longsecfrac1=recvmsg[16]
   Longsecfrac2=recvmsg[17]*256
   Longsecfrac3=recvmsg[18]*256*256
   Longsecfrac4=recvmsg[19]*256*256*256
   Longsecfrac=Longsecfrac1+Longsecfrac2+Longsecfrac3+Longsecfrac4
     
    If Longdeg>32767 Then   
       Longdeg=Longdeg-65536 
     EndIf
     
     LCD.Text(1,  0, 70,  1, "Long: "+ Longdeg + ":" + Longmin + "'" + Longsec + "." + Longsecfrac+"  ")
     
     dday=recvmsg[20]
     dmonth=recvmsg[21]
     dyear=recvmsg[22]+2000
     
     LCD.Text(1, 0, 90, 1, "Date: " + dday +  "." + dmonth +  "." + dyear)
   
     dhour=recvmsg[23]
     dmin=recvmsg[24]
     dsec=recvmsg[25]
     dhourfmt=""
     dminfmt=":"
     dsecfmt=":"
     If dhour<10 Then   
       dhourfmt="0" 
     EndIf
     If dmin<10 Then   
       dminfmt=":0" 
     EndIf
     If dsec<10 Then   
       dsecfmt=":0" 
     EndIf
     
     LCD.Text(1, 0, 100, 1, "Time: " + dhour +  dminfmt + dmin + dsecfmt + dsec)
   
   
   
  Program.Delay(1)   '// yield()
 
EndWhile

 
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
c0pperdragon
Schreibt viel
Schreibt viel
Beiträge: 231
Registriert: 9. Feb 2015 00:29

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon c0pperdragon » 2. Okt 2015 22:38

Spitze, dass das schon so schön geht.
Ich nehme an, du hast den EV3 noch am PC hängen, und der führt das Basic-Programm aus?
Weil mit dem autonomen Modus ist da noch ein Hund drinnen mit der I2C-Kommunikation. Habe ich
schon ausgebessert, aber noch keine neue Version gebaut. Wenn du das schnell brauchen würdest,
könnte ich das auch morgen rasch erledigen.

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 2. Okt 2015 22:46

genau 8-)
aber eilt nicht - nur gut dass du's sagst, sonst hätt'st du morgen jemand toben hören können :D
...und tausend Dank für deine Mühe und die vielen Hilfstellungen und Tipps :prima:

morgen will ich mal versuchen, den IR Sensor am EV3 in Gang zu kriegen und dann seine Daten an den Arduino rüberzushicken!
Und dann kommt der DUE dran mit TWI-1 ! :wink:
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 4. Okt 2015 16:55

update zu Arduino DUE:

weder Wire (Rx/Tx) noch Wire1 (Rx1/Tx1) funktionieren.
Der Code mit Wire funktioniert dagegen nach wie vor einwandfrei mit dem Mega.

Damit steht die ganze 12c Geschichte natürlich extremst auf der Kippe, denn für den DUE war es ja eigentlich gedacht.

Notlösung:
EV3 an Mega per i2c,
Mega an Due über UART.

Aber was wäre das für ein Aufwand, nur um 1 oder 2 Ev3 Sensoren auslesen zu können ... :-/
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
c0pperdragon
Schreibt viel
Schreibt viel
Beiträge: 231
Registriert: 9. Feb 2015 00:29

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon c0pperdragon » 5. Okt 2015 19:37

Ich kann gar nicht glauben, dass man das I2C am Arduino Due nicht zum laufen bringen kann. Hast du schon mal versucht, von Arduino zu Arduino zu kommunizieren? Den Arduino Due als Slave konfiguriert, eben. Wenn das mal ginge, dann weißt du wenigstens, dass der Arduino Due richtig arbeitet.

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 5. Okt 2015 20:04

ich weiß, dass der DUE feste Pullups auf Wire hat, und ich weiß auch, dass die DUE Wire1 lib fehlerhaft und unvollständig ist.
Selbst wenn ich es aber hinbekäme, ist mir nicht weitergeholfen, denn was nützt es mir zu wissen, dass es grundsätzlich geht oder auch nicht?
Denn egal wie oder was oder auch nicht, ich bräuchte es ja ausschließlich für den EV3...!
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 6. Okt 2015 13:59

zufällig gerade ein Post im Arduino-Forum gelesen:
Für DUE-Master zu DUE-Slave geht es wenn beide Wire benutzen, aber nicht, wenn einer von beiden Wire1 benutzt.
Für Slave-Betrieb zu EV3 scheidet aber Wire aus, da interne Pullups nicht abschaltbar.
Wire1 geht aber wohl gar nicht korrekt als DUE-Slave.
Habe es bei Github berichtet, aber bis DIE was an den libs ändern und die Bugs fixen... wenn überhaupt jemals... (der DUE wird da sowie ziemlich stiefmütterlich behandelt :evil: )
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
c0pperdragon
Schreibt viel
Schreibt viel
Beiträge: 231
Registriert: 9. Feb 2015 00:29

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon c0pperdragon » 6. Okt 2015 22:51

Ich glaube, ich hätte da schon eine Idee zu dem Problem. Der EV3 kann am I2C-Port ja keine starken Pullups überwinden. Zumindest lese ich das aus dem Schema heraus, weil er ein 4K7 Widerstand in Serie zum Ausgang hat, und das dann nie und nimmer gegen den 1K5-Pullup vom Due ankommt. Das ist sicher auch der Grund, warum die I2C-Geschwindigkeit am EV3 so begrenzt ist, weil durch den vorgeschriebenen 82K-Pullup am I2C-Sensor die Pegel nur recht langsam hochgezogen werden.
Wenn das so ist, dann könnte man sich eine einfache Schaltung (Transisor,Widerstand,Diode oder so pro Leitung) ausdenken, um den EV3 beim Ziehen auf den 0-Pegel zu unterstützten. Ich werde das morgen vielleicht mal versuchen. Dazu hänge ich mal einen 1K5-Widerstand an meinem Arduino Micro um das Verhalten des Arduino Due zu simulieren, und schaue mal, ob ich den EV3 nicht doch dabei unterstützen kann, dagegen anzukommen.

Benutzeravatar
HaWe
Administrator
Administrator
Beiträge: 5288
Registriert: 11. Jan 2006 21:01
Wohnort: ein kleiner Planet in der Nähe von Beteigeuze

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon HaWe » 7. Okt 2015 07:48

WIMRI liegt das mit der Geschwindigkeit vor allem am I2C-Software-Bitbang vom Brick (EV3 oder NXT). Es gibt alternative Bitbang Protokolle, die am NXT durchaus 100k erreicht haben, ohne die eingebauten Pullup-Widerstände zu ändern (leJOS, nxtOSEK). Das Problem sind tatsächlich die geringen 1.5k Due-Widerstände, denn wenn man sie zu den 47k von Lego parallel schaltet, bleibt von den letzteren nichts mehr übrig:
(1/ (1/47k + 1/1,5k)) = 1,45k
Aber ich bin beileibe kein Elektronikfachmann.
Die Arduinos arbeiten aber mit 1k-80k auch noch einwandfrei.
Gruß,
HaWe
±·≠≈²³αβγδε∂ζλμνπξφωΔΦ≡ΠΣΨΩ∫√∀∃∈∉∧∨¬⊂⊄∩∪∅∞®
NXT NXC SCHACHROBOTER: https://www.youtube.com/watch?v=Cv-yzuebC7E

Benutzeravatar
c0pperdragon
Schreibt viel
Schreibt viel
Beiträge: 231
Registriert: 9. Feb 2015 00:29

Re: I2C Kommunikation EV3Basic <--> Arduino

Beitragvon c0pperdragon » 7. Okt 2015 08:31

Ich habe zwar 4K5 Widerstände geschrieben (also 4500 Ohm), und es ist auch keine Parallelschaltung, sondern eine Serienschaltung.
Aber das ist ja nicht so wichtig. Ich werde trotzdem mal versuchen, was sich machen lässt.


Zurück zu „textbasierte Programmiersoftware“

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 11 Gäste

Lego Mindstorms EV3, NXT und RCX Forum : Haftungsauschluss