Tom Eilers
Published © GPL3+

Another LEGO EV3 to NXT mindstorms communication solution

Using a ATmega328PB as I2C dual port memory, for communication between EV3 and NXT.

IntermediateFull instructions provided8 hours1,420
Another LEGO EV3 to NXT mindstorms communication solution

Things used in this project

Hardware components

ATmega328PB microcontroller
Microchip ATmega328PB microcontroller
×1
Mindstorms EV3 Programming Brick / Kit
LEGO Mindstorms EV3 Programming Brick / Kit
×1
Mindstorms NXT Programming Brick / Kit
LEGO Mindstorms NXT Programming Brick / Kit
×1
Resistors 82k
×4
LEGO cables
×2
Reichelt RND 455-00054 Plastic housing - 65x38x22 mm
×1

Story

Read more

Schematics

Schematic

connections

Code

Arduino EV3toNXT.ino

Arduino
I2C dual port memory
#include <Wire.h>
#include <Wire1.h>
#define SLAVE_ADDRESS 0x54 // decimal 84 for EV3: decimal 168 for NXT
// This program will only work on microcontolers with 2 or more I2C ports like: Atmega328PB or Teensy 3.2
// The microcontroller must be able to work with 5V power supply and 5V tolerant inputs/outputs
// both I2C port  need to have 4k7 pullup resitors on SDA and SCL

// Lego EV3 or NXT wil send:
// Boolean write: ramaddress, number of bytes, one data byte    (number = 0) howmany =3
// Boolean read: ramaddress, number of bytes                    (number = 1) howmany =2
// Numeric write: ramaddress, number of bytes, four data bytes  (number = 0) howmany =6
// Numeric read: ramaddress, number of bytes                    (number = 4) howmany =2
// The combination of howmany bytes received and number of bytes,
// makes it possible to know:
// If data is written or read and howmany bytes to send back to EV3 or NXT.

//reserve 256 of memory
byte ram[256];

// variables wire or port 0
byte howMany = 0;
byte num = 0;
byte addr = 0;
byte buf[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

//variables wire1 or port1
byte howmany1 = 0;
byte num1 = 0;
byte addr1 = 0;
byte buf1[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

void setup() {
  Wire.begin(SLAVE_ADDRESS);
  Wire.onReceive(receiveEvent);
  Wire.onRequest(requestEvent);

  Wire1.begin(SLAVE_ADDRESS);
  Wire1.onReceive(receiveEvent1);
  Wire1.onRequest(requestEvent1);
}

void loop() {}


void receiveEvent(byte howMany) // receive howMany bytes data from master
{
  int j = 0;
  while (Wire.available()) {
    buf[j] = Wire.read();
    j = j + 1;
    if (j > howMany) j = 0;
  }
  addr = buf[0]; //ram address
  num = buf[1]; // number of bytes to send back to master
  switch (num)
  {
    case 0:
      if (howMany == 6)
      {
        ram[addr] = buf[2];
        ram[addr + 1] = buf[3];
        ram[addr + 2] = buf[4];
        ram[addr + 3] = buf[5];
      }
      else
      {
        ram[addr] = buf[2];
       }
      break;
    case 1:
      buf[2] = ram[addr];
      break;
    case 4:
      buf[2] = ram[addr];
      buf[3] = ram[addr + 1];
      buf[4] = ram[addr + 2];
      buf[5] = ram[addr + 3];
      break;
    default:
      // statements
      break;
  }
}

void receiveEvent1(byte howMany1) // receive howMany bytes data from master
{
  int j1 = 0;
  while (Wire1.available()) {
    buf1[j1] = Wire1.read();
    j1 = j1 + 1;
    if (j1 > howMany1) j1 = 0;
  }
  addr1 = buf1[0];
  num1 = buf1[1];
    
  switch (num1)
  {
    case 0:
      if (howMany1 == 6)
      {
        ram[addr1] = buf1[2];
        ram[addr1 + 1] = buf1[3];
        ram[addr1 + 2] = buf1[4];
        ram[addr1 + 3] = buf1[5];
      }
      else
      {
        ram[addr1] = buf1[2];
      }
      break;
    case 1:
      buf1[2] = ram[addr1];
      break;
    case 4:
      buf1[2] = ram[addr1];
      buf1[3] = ram[addr1 + 1];
      buf1[4] = ram[addr1 + 2];
      buf1[5] = ram[addr1 + 3];
      break;
    default:
      // statements
      break;
  }

}

// The address and size is also send, this makes my program simpler
// These first 2 bytes are not used in the EV3 or NXT

void requestEvent() {
  buf[2] = ram[addr];
  buf[3] = ram[addr + 1];
  buf[4] = ram[addr + 2];
  buf[5] = ram[addr + 3];

  if (num == 4)
  {
    Wire.write(buf, 6); // send 6 data bytes to master, EV3 reverses I2C receive buffer
  }
  else
  {
    Wire.write(buf, 3); // send 3 date bytes to master
  }
}

void requestEvent1() {
  buf1[2] = ram[addr1];
  buf1[3] = ram[addr1 + 1];
  buf1[4] = ram[addr1 + 2];
  buf1[5] = ram[addr1 + 3];

  if (num1 == 4)  {
    Wire1.write(buf1, 6); // send 6 data bytes to master, EV3 reverses I2C receive buffer
  }
  else
  {
    Wire1.write(buf1, 3); // send 3 data bytes to master
  }
}

EV3-G block

XML
Import in EV3-G software
No preview (download only).

EV3-G examples

XML
open in EV3-G
No preview (download only).

Credits

Tom Eilers

Tom Eilers

4 projects • 4 followers
Labview Expert progamming SCADA, DCS, Data Acq, Reporting etc.

Comments