Уже довольно давно Dexter опубликовали способ взаимодействия EV3 и Arduino с использованием протокола i2c через один из портов датчиков. Этот способ позволяет передавать с Arduino любые данные, например показания подключенных к ней датчиков и использовать их в программе на EV3. Возможна передача данных и в противоположном направлении, например из программы на EV3 можно управлять моторами и реле, подключенными к Arduino.
Все бы хорошо, но способ этот работает только на EV3-G, так как основан на применении специального программного блока для этой среды программирования.
Мы же программируем на EV3 Basic и хотим использовать все преимущества такого межплатформенного взаимодействия в этом языке, поэтому написали аналог данного блока в среде EV3 Basic, он довольно простой, посмотрите:
'// EV3 Basic, код для взаимодействие с Arduino
'// EV3 - I2C master, Arduino - I2C slave
MSGSZEV3 = 30
MSGSZSLV = 30
// EV3 порт, к которому подключена Arduino
I2CPORT = 4
// i2c адрес Arduino, в нашем примере 0x04 '
I2CSLVADDR = 4 '
// массив байт, который мы будем передавать на Arduino
sendarray = Vector.Init(MSGSZEV3, 0)
// массив байт, который мы будем принимать с Arduino
recvarray = Vector.Init(MSGSZSLV, 0)
// далее выполняем в бесконечном цикле
While "True"
// Если нужно что-то отослать на Arduino - записываем это в массив sendarray
sendarray[0] = 255
// запускаем функцию взаимодействия по i2c, sendarray и принимаем данные
recvarray = Sensor.CommunicateI2C( I2CPORT, I2CSLVADDR , MSGSZEV3 , MSGSZSLV , sendarray )
// выводим на экран первый элемент массива recvarray
LCD.Text(1, 0, 0, 2, recvarray[0])
// необязательная задержка - чтобы успеть рассмотреть вывод на экран
Program.Delay(100)
// очищаем экран
LCD.Clear()
EndWhile
На Arduino можно залить стандартный код от Dexter или, например, вот такой модифицированный нами скетч:
#include <Wire.h>
#define SLAVE_ADDRESS 0x04
void setup()
{
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}
int pin,st,val=0,flag=0,index=0;
char buf[8];
byte b[1];
void loop()
{
if(flag==1)
{
flag=0;
Serial.println(pin);
val=analogRead(pin);
b[0] = map(val,0,1024, 100, 0);
}
}
void receiveData(int byteCount)
{
while(Wire.available()>0)
{
pin=Wire.read();
flag=1;
}
}
void sendData()
{
Wire.write(b,1);
}
Данный пример передает на EV3 данные с аналогового порта А0, пересчитав их в диапазон 0..100.
Конечно же, использовать можно не только Arduino Uno, как в примере от Dexter, но и более миниатюрные варианты плат, например мы использовали для теста Micro:
1. ИК-дальномер Sharp gp2y0a21yk0f, аналоговый, подключен к порту А0
2. Arduino Micro
3. Переходник на Mindstorms-кабель
4-5. Для питания Arduino (и дальномера через нее) используется кабель microUSB (4), подключаем в боковой разъем EV3 блока (5). Питания от порта датчика не всегда хватает, такой способ более надежный.
6. Кабель датчика втыкается в свободный порт EV3.
Все бы хорошо, но способ этот работает только на EV3-G, так как основан на применении специального программного блока для этой среды программирования.
Мы же программируем на EV3 Basic и хотим использовать все преимущества такого межплатформенного взаимодействия в этом языке, поэтому написали аналог данного блока в среде EV3 Basic, он довольно простой, посмотрите:
'// EV3 Basic, код для взаимодействие с Arduino
'// EV3 - I2C master, Arduino - I2C slave
MSGSZEV3 = 30
MSGSZSLV = 30
// EV3 порт, к которому подключена Arduino
I2CPORT = 4
// i2c адрес Arduino, в нашем примере 0x04 '
I2CSLVADDR = 4 '
// массив байт, который мы будем передавать на Arduino
sendarray = Vector.Init(MSGSZEV3, 0)
// массив байт, который мы будем принимать с Arduino
recvarray = Vector.Init(MSGSZSLV, 0)
// далее выполняем в бесконечном цикле
While "True"
// Если нужно что-то отослать на Arduino - записываем это в массив sendarray
sendarray[0] = 255
// запускаем функцию взаимодействия по i2c, sendarray и принимаем данные
recvarray = Sensor.CommunicateI2C( I2CPORT, I2CSLVADDR , MSGSZEV3 , MSGSZSLV , sendarray )
// выводим на экран первый элемент массива recvarray
LCD.Text(1, 0, 0, 2, recvarray[0])
// необязательная задержка - чтобы успеть рассмотреть вывод на экран
Program.Delay(100)
// очищаем экран
LCD.Clear()
EndWhile
На Arduino можно залить стандартный код от Dexter или, например, вот такой модифицированный нами скетч:
#include <Wire.h>
#define SLAVE_ADDRESS 0x04
void setup()
{
Wire.begin(SLAVE_ADDRESS);
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}
int pin,st,val=0,flag=0,index=0;
char buf[8];
byte b[1];
void loop()
{
if(flag==1)
{
flag=0;
Serial.println(pin);
val=analogRead(pin);
b[0] = map(val,0,1024, 100, 0);
}
}
void receiveData(int byteCount)
{
while(Wire.available()>0)
{
pin=Wire.read();
flag=1;
}
}
void sendData()
{
Wire.write(b,1);
}
Данный пример передает на EV3 данные с аналогового порта А0, пересчитав их в диапазон 0..100.
Конечно же, использовать можно не только Arduino Uno, как в примере от Dexter, но и более миниатюрные варианты плат, например мы использовали для теста Micro:
1. ИК-дальномер Sharp gp2y0a21yk0f, аналоговый, подключен к порту А0
2. Arduino Micro
3. Переходник на Mindstorms-кабель
4-5. Для питания Arduino (и дальномера через нее) используется кабель microUSB (4), подключаем в боковой разъем EV3 блока (5). Питания от порта датчика не всегда хватает, такой способ более надежный.
6. Кабель датчика втыкается в свободный порт EV3.
А зачем такой огород ради одного датчика? Этот шарп же можно напрямую к еве3 подключить с одним только резистором. И скорость работы будет гораздо выше, чем по I2C.
ОтветитьУдалитьПочему же одного. Это в примере он один. А подключить можно хоть десяток и все на один порт EV3.
УдалитьДоброго времени суток. Буду очень признателен (как и другие читатели Вашего блока) за наводку на специализированные вилочки RJ11 (6p6c) для LEGO (защёлка справа) и модуль с розеткой LEGO для использования с макеткой. Заранее благодарен!
ОтветитьУдалитьБрали вот здесь
Удалитьhttp://www.mindsensors.com/51-cables-connectors
Готовые кабели тоже хороши в этом плане, не надо обжимать - разрезал и получится пара переходников на Arduino.