использовать C++ для получения данных с датчика LEGO EV3?

Я пытаюсь использовать C++ для связи с кирпичом LEGO Mindstorms EV3. Я клонировал репозиторий ev3sources, что позволяет мне делать это через Bluetooth - например, запускать подключенный двигатель к порту А мы можем сделать это:

#include <unistd.h>
#include <fcntl.h>
#include "ev3sources/lms2012/c_com/source/c_com.h"

int main()
{

    // start motor on port A at speed 20
    unsigned const char start_motor[] {12, 0, 0, 0,
        DIRECT_COMMAND_NO_REPLY,
        0, 0,
        opOUTPUT_POWER, LC0(0), LC0(0x01), LC0(20),
        opOUTPUT_START, LC0(0), LC0(0x01)};

    // send above command to EV3 via Bluetooth
    int bt = open("/dev/tty.EV3-SerialPort", O_WRONLY);
    write(bt, start_motor, 14);
    close(bt);
}

Но как мне получить данные из блока EV3? Например, предположим, что я хочу прочитать данные, полученные любым датчиком, подключенным к порту 1. На основе примеры репо Я знаю, что мне нужно что-то вроде этого:

#include <unistd.h>
#include <fcntl.h>
#include "ev3sources/lms2012/c_com/source/c_com.h"

int main()
{

    // read sensor on port 1
    unsigned const char read_sensor[] {11, 0, 0, 0,
        DIRECT_COMMAND_REPLY,
        0, 0,
        opINPUT_READ, LC0(0), LC0(0), LC0(0), LC0(0), GV0(0)};

    // send above command to EV3 via Bluetooth
    int bt = open("/dev/tty.EV3-SerialPort", O_WRONLY);
    write(bt, read_sensor, 13);
    close(bt);
}

Но чего-то не хватает - приведенный выше фрагмент не возвращает никаких ошибок, но я не знаю, где находятся данные датчика. Итак, как мне его получить? Я предполагаю, что он также отправляется обратно через Bluetooth, но как мне это зафиксировать?

(OS X 10.9.3, Xcode 5.1.1, EV3 [31313])


person Parzival    schedule 16.06.2014    source источник
comment
откуда вы берете: #include ev3sources/lms2012/c_com/source/c_com.h?   -  person Karoh    schedule 23.12.2015
comment
github.com/mindboards/ev3sources/blob/master/ lms2012/c_com/   -  person Parzival    schedule 23.12.2015
comment
Спасибо Тьяго, так вы просто перетаскиваете весь каталог lms2012 или используете DLL?   -  person Karoh    schedule 23.12.2015
comment
Я перетаскиваю весь этот каталог lms2012.   -  person Parzival    schedule 23.12.2015
comment
Ну, я был - я перестал делать это на C++ год назад и сделал модуль Python, чтобы облегчить себе жизнь (github .com/thiagomarzagao/ev3py).   -  person Parzival    schedule 23.12.2015


Ответы (2)


Вам нужно читать из bt после того, как вы пишете. Как и данные, которые вы отправляете, первые два байта являются размером, поэтому сначала прочитайте 2 байта и используйте это, чтобы выяснить, сколько еще байтов вам нужно прочитать.

#define MAX_READ_SIZE 255
unsigned char read_data[MAX_READ_SIZE];
int read_data_size;

// existing code
// ...
write(bt, read_sensor, 13);
read(bt, read_data, 2);
read_size = read_data[0] + read_data[1] << 8;
read(bt, read_data, read_size);
close(bt);
// decode the data
// ...

РЕДАКТИРОВАТЬ: Полный код на основе комментариев

#include <unistd.h>
#include <fcntl.h>
#include "ev3sources/lms2012/c_com/source/c_com.h"

#define MAX_READ_SIZE 255

int main()
{
    unsigned char read_data[MAX_READ_SIZE];
    int read_data_size;

    // read sensor on port 1
    unsigned const char read_sensor[] {11, 0, 0, 0,
        DIRECT_COMMAND_REPLY,
        1, 0, // 1 global variable
        opINPUT_READ, LC0(0), LC0(0), LC0(0), LC0(0), GV0(0)};

    // send above command to EV3 via Bluetooth
    int bt = open("/dev/tty.EV3-SerialPort", O_RDWR);
    write(bt, read_sensor, 13);
    read(bt, read_data, 2);
    read_size = read_data[0] + read_data[1] << 8;
    read(bt, read_data, read_size);
    close(bt);
    // TODO: check that command was successful and so something with data
}
person David Lechner    schedule 17.06.2014
comment
Спасибо! Увы, каким-то образом это всегда приводит к read_size нулю. И когда я проверяю read_data[0] и read_data[1], они также всегда кажутся равными нулю (при условии, что printf("%x", read_data[i]); - правильный способ их проверки; я тоже пробовал cout << hex << read_data[i];, но это дает вопросительный знак вместо действительного вывода). Я думал, что проблема может заключаться в некоторой задержке отправки данных EV3, но вставка usleep(10000000); между write и первым read ничего не изменила. Есть предположения? - person Parzival; 17.06.2014
comment
read должен блокироваться до тех пор, пока не появятся данные, поэтому задержка не требуется. Попробуйте прочитать первые 2 байта и посмотрите, есть ли что-нибудь интересное. Вы можете проверить возвращаемое значение read, чтобы убедиться, что он действительно что-то читает. - person David Lechner; 17.06.2014
comment
Просто сделал; все остальные байты тоже равны нулю. read возвращает -1, поэтому я думаю, что ничего не читается. Я пробовал и датчик цвета, и датчик приближения, и это то же самое. Я не могу понять, что я делаю неправильно. - person Parzival; 17.06.2014
comment
Подождите, я идиот! Я забыл изменить O_WRONLY на O_RDWR. Теперь это работает! - person Parzival; 17.06.2014
comment
Что ж, это была одна из проблем. Теперь данные, которые я возвращаю, всегда одни и те же (30002000...) - даже когда датчик отключен. - person Parzival; 17.06.2014
comment
Я думаю, вам нужно установить байт 6 в 1, чтобы он знал, что вы используете 1 глобальную переменную. - person David Lechner; 18.06.2014
comment
Сделайте этот байт 5 (с прямым порядком байтов) ``` unsigned const char read_sensor[] {11, 0, 0, 0, DIRECT_COMMAND_REPLY, 1, 0, opINPUT_READ, LC0(0), LC0(0), LC0(0), LC0 (0), GV0(0)}; ``` - person David Lechner; 18.06.2014
comment
Это помогло. Теперь это действительно работает — я получаю то же значение (в шестнадцатеричном формате), которое отображается на дисплее EV3 (в представлении порта). Большое спасибо! - person Parzival; 18.06.2014

Возможно, это не совсем тот ответ, который вы искали, но он может быть полезен тому, кто оказался в такой же ситуации:

В рамках c4ev3 мы открыли исходный код нашего загрузчик EV3, который также можно использовать для отправки на устройство команд, не зависящих от соединения.

проверьте https://github.com/c4ev3/ev3duder/blob/master/moveEv3.pl для примера.

Хорошая вещь в том, чтобы сделать это таким образом, заключается в том, что вашему коду не нужно беспокоиться о методе подключения: реализовано ли соединение через Bluetooth, Wi-Fi или USB, это полностью прозрачно для вас. Вы просто открываете 2 трубы к ./ev3duder tunnel и используете их.

person a3f    schedule 08.06.2016