LEGO MINDSTORMS EV3 Debian C library + Python, Ruby and Perl wrappers
 
 ____ __     ____   ___    ____ __         (((((()
| |_  \ \  /   ) ) | |  ) | |_  \ \  /  \(@)- /   
|_|__  \_\/  __)_) |_|_/  |_|__  \_\/   /(@)- \   
                                           ((())))
 

ev3dev-c 1.0c2 (for kernel 4.4.87-22-ev3dev-ev3)

The library hierarchic structure

Low-level

Low level contains functions for local and remote access to the file system of the EV3 brick. The following code will write "heartbeat" string to the specified file (if running on the brick) or will send both of the arguments to the brick using UDP message (if running on the remote computer).

ev3_write( "/sys/class/leds/ev3:red:right/trigger", "heartbeat" );

See also – io.c

For more information about remote access to the brick, please, read "ev3_link".

Mid-level

Mid-level provides the performance optimized library that is intended to cover all main functionality of "ev3dev".

To start working with the library, you have to call the library initialization ev3_init() which will connect to the brick over network if your program is running on a remote computer, then, to detect devices plugged to the brick, please call initialization for each of the necessary class of devices, e.g. ev3_tacho_init(). Do not forget to call ev3_uninit() at the program end.

All functions to access the device's attributes require the sequence number of device sn. You can find the sequence number in the descriptor table, which was filled during initialization, e.g. ev3_search_tacho(LEGO_EV3_L_MOTOR, &sn, 0).

Access to some frequently used string attributes can be performed by the index, for example, you can just check the mode index:

( get_sensor_mode_inx( sn ) == IR_IR_PROX )

instead of string comparison:

( get_sensor_mode( sn, buf, sizeof( buf )) && ( strcmp( buf, "IR-PROX" ) == 0 ))

See comprehensive example based on coroutines – drive.c

A few more examples:

• Using LEDs, see "Using LEDs":

int ok;
uint8_t val;
ok = get_led_brightness( EV3_GREEN_LEFT, &val );
if ( ok ) {
printf( "EV3_GREEN_LEFT is %s\n", ( val ) ? "ON" : "OFF" );
}

See also – rcx_led.c

• Using sensors, see "LEGO Sensor Class":

uint8_t sn;
int val;
if ( ev3_search_sensor( LEGO_EV3_TOUCH, &sn, 0 )) {
if ( get_sensor_value( 0, sn, &val )) {
printf( "TOUCH sensor value = %d\n", val );
}
}

See also – sensor.c

• Using tacho motors, see "Tacho Motor Class":

uint8_t sn;
if ( ev3_search_tacho( LEGO_EV3_L_MOTOR, &sn, 0 )) {
set_tacho_stop_action_inx( sn, TACHO_BRAKE );
set_tacho_speed_sp( sn, 500 );
set_tacho_time_sp( sn, 5000 );
set_tacho_ramp_up_sp( sn, 2000 );
set_tacho_command( sn, "run_timed" );
}

See also - tacho.c

• Using DC motors, see "DC Motor Class":

uint8_t sn, sn_port;
sn_port = ev3_search_port( OUTPUT_D, EXT_PORT__NONE_ );
set_port_mode_inx( sn_port, OUTPUT_DC_MOTOR );
if ( ev3_search_dc_plugged_in( OUTPUT_D, EXT_PORT__NONE_, &sn, 0 )) {
set_dc_command_inx( sn, DC_RUN_FOREVER );
usleep( 5000000 );
set_dc_command_inx( sn, DC_STOP );
}
set_port_mode_inx( sn_port, OUTPUT_AUTO );

See also - dc.c

• Using servo motors, see "Servo Motor Class":

uint8_t sn, sn_port;
sn_port = ev3_search_port( INPUT_1, EXT_PORT__NONE_ );
set_port_mode_inx( sn_port, INPUT_NXT_ANALOG );
set_port_set_device( sn_port, ( char *) ev3_sensor_type( MS_8CH_SERVO ));
if ( ev3_search_servo_plugged_in( INPUT_1, EXT_PORT__NONE_, 1, &sn, 0 )) {
set_servo_command_inx( sn, SERVO_RUN );
}
set_port_mode_inx( sn_port, INPUT_AUTO );

See also – servo.c

• Using EV3 ports, see "Input and Output Ports":

uint8_t sn;
char s[ 256 ];
sn = ev3_search_port( INPUT_2, EXT_PORT__NONE_ );
if ( get_port_mode( sn, s, sizeof( s ))) {
4 printf( "INPUT_2 mode = %s\n", s );
}

See also – port.c

• Using EV3 extended ports:

uint8_t sn, sn_port;
int val;
sn_port = ev3_search_port( INPUT_1, HT_NXT_SMUX_PORT_2 );
set_port_mode_inx( sn_port, INPUT_NXT_ANALOG );
set_port_set_device( sn_port, ( char *) ev3_sensor_type( LEGO_NXT_TOUCH ));
if ( ev3_search_sensor_plugged_in( INPUT_1, HT_NXT_SMUX_PORT_2, &sn, 0 )) {
if ( get_sensor_value( 0, sn, &val )) {
printf( "TOUCH sensor value = %d\n", val );
}
}
set_port_mode_inx( sn_port, INPUT_AUTO );

• Using keys of the EV3 brick:

uint8_t val;
do ev3_read_keys( &val ); while (( val & EV3_KEY_BACK ) == 0 );

High-level

"brick" library is a simplified interface of "ev3dev-c". We use a mask of sockets (ports) instead of sequence numbers for access to devices, it allows to set identical attributes of several devices concurrently, but extended ports are not supported.

See example of using "brick" library, based on coroutines – remote.c

A few more examples:

• Using "brick" library :

if ( tacho_is_plugged( OUTB | OUTC, LEGO_EV3_L_MOTOR )) {
tacho_set_speed_sp( OUTB | OUTC, tacho_get_max_speed( OUTB, 0 ) * 0.75 ); // 75%
tacho_run_forever( OUTB | OUTC );
sleep_ms( 3000 ); // 3 sec
tacho_stop( OUTB );
sleep_ms( 2000 ); // 2 sec
tacho_stop( OUTC );
}

• Using light module:

set_light_blink( LIT_LEFT, LIT_AMBER, 1000, 500 );

See also – light.c

Python, Ruby, Perl and other languages

The libraries for Python, Ruby and Perl have been generated using SWIG. The SWIG interface file ev3.i is generated out of ev3.yu-i.

Features of Python library:

  1. The functions return the requested value as the second element of the result tuple;
  2. Access to the descriptors of detected devices only through ev3_<class>_desc or ev3_<class>_desc_<field> functions (e.g. ev3_sensor_desc, ev3_port_desc);
  3. Access to the global variables through ev3 namespace.
1 color = [ '?', 'BLACK', 'BLUE', 'GREEN', 'YELLOW', 'RED', 'WHITE', 'BROWN' ]
2 
3 if not EV3_BRICK:
4  ev3.brick_addr = '192.168.0.244'
5 ev3_init()
7 ok, sn = ev3_search_sensor( LEGO_EV3_UART_29 )
8 if ok:
9  set_sensor_mode( sn, 'COL-COLOR' )
10 
11  ok, val = get_sensor_value( 0, sn )
12  if ok:
13  print 'COLOR =', color[ val ]
14 ev3_uninit()

Using "brick" library with Python:

2 if tacho_is_plugged( OUTB | OUTC, LEGO_EV3_L_MOTOR ):
3  tacho_set_speed_sp( OUTB | OUTC, tacho_get_max_speed( OUTB ) * 0.75 ) # 75%
4  tacho_run_forever( OUTB | OUTC )
5  sleep_ms( 3000 ) # 3 sec
6  tacho_stop( OUTB )
7  sleep_ms( 2000 ) # 2 sec
8  tacho_stop( OUTC )
9 

See also – Examples in Python

Features of Ruby library:

  1. The functions return the requested value as the second element of the result tuple, the first element has a boolean type;
  2. Access to the descriptors of detected devices only through ev3_<class>_desc or ev3_<class>_desc_<field> functions (e.g. ev3_dc_desc, ev3_dc_desc_port).
1 include Ev3
2 
3 ev3_init()
5 ok, sn = ev3_search_sensor( LEGO_EV3_TOUCH )
6 if ok
7  while get_sensor_value( 0, sn )[ 1 ] == 0 do end
8 end

See also – Examples in Ruby

Features of Perl library:

  1. The functions return the requested value as the second element of the result tuple;
  2. Access to the descriptors of detected devices only through ev3_<class>_desc_<field> functions (e.g. ev3_tacho_desc_type_inx, ev3_tacho_desc_port).
use ev3;
my ( $ok, $sn ) = ev3::ev3_search_tacho( $ev3::LEGO_EV3_M_MOTOR );
if ( $ok ) {
ev3::set_tacho_command_inx( $sn, $ev3::TACHO_RUN_FOREVER );
sleep( 2 );
ev3::set_tacho_command_inx( $sn, $ev3::TACHO_STOP );
}

See also – Examples in Perl

Similarly you can use SWIG to wrap the library in a number of other languages.