Parzival
Parzival

Reputation: 2064

using C++ to get data from a LEGO EV3 sensor?

I'm trying to use C++ to communicate with a LEGO Mindstorms EV3 brick. I cloned the ev3sources repo, which allows me to do that via Bluetooth - for instance, to start the motor connected to port A we can do this:

#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);
}

But how do I get data back from the EV3 brick? For instance, suppose I want to read the data captured by whatever sensor is connected to port 1. Based on the repo examples I know that I need something that looks a bit like this:

#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);
}

But something is missing - the above snippet doesn't return any errors but I don't know where the sensor data is. So, how do I retrieve it? I imagine it's sent back via Bluetooth as well, but how do I capture that?

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

Upvotes: 1

Views: 3698

Answers (2)

a3f
a3f

Reputation: 8657

Maybe not exactly the answer you were looking for, but might be useful to someone who finds himself in the same situation:

As part of c4ev3, We open-sourced our EV3 uploader, which can also be used to send connection-agnostic commands to the device.

check out https://github.com/c4ev3/ev3duder/blob/master/moveEv3.pl for an example.

The nice thing about doing it that way, is that your code doesn't have to worry about the connection method: Whether the connection is realized over Bluetooth, Wi-Fi or USB is completely transparent to you. You just open 2 pipes to ./ev3duder tunnel and use those.

Upvotes: 0

David Lechner
David Lechner

Reputation: 1824

You need to read from bt after you write. Like the data you are sending, the first two bytes are the size, so read 2 bytes first and use that to figure out how many more bytes you need to read.

#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
// ...

EDIT: Complete code based on comments

#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
}

Upvotes: 1

Related Questions