Motors

Lego_Ev3_small_motor

All the programs that interact with the EV3 hardware use the following three include files that are part of the EV3 source code (lms2012.h, bytecodes.h and lmstypes.h). The files can be copied and pasted from the links. They must be placed in the same work directory as the program that is being compiled.

The EV3 motors can be accessed using simple write file operations. Internally the program interacts with the kernel module d_pwm. More details about the use of motors can be found in the d_pwm.c file, inside the function Device1Write. The following programs show how to initialize, and use the motors in open and close loop as well as how to read the encoders.
Open loop control

The following program sets the the motor power to a specified level. This is done by means of setting the power level (PWM signal duty cycle). The motor is running in open loop. It can be slowed down or stopped without the system trying to compensate for this variation. Before running this program, make sure you have a motor connected to port A.

/*
* Robot Navigation Program
* www.robotnav.com
*
* (C) Copyright 2013 Lauro Ojeda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
#include "lms2012.h"

// Motor power 0..100
const int MOTOR_POWER = 10;
// The motor operations use a single bit (or a combination of them)
// to determine which motor(s) will be used
// A = 0x01, B = 0x02, C = 0x04, D = 0x08
// AC = 0x05
const char MOTOR_PORT = 0x01;

int main()
{
//DEFINE VARIABLES
char motor_command[3];
int motor_file;

//INITIALIZE DEVICE
//Open the device file asscoiated to the motor controlers
if((motor_file = open(PWM_DEVICE_NAME, O_WRONLY)) == -1)
return -1; //Failed to open device

//ACTUATE MOTORS
// All motor operations use the first command byte to indicate the type of operation
// and the second one to indicate the motor(s) port(s)
motor_command[0] = opOUTPUT_POWER;
motor_command[1] = MOTOR_PORT;
motor_command[2] = MOTOR_POWER;
write(motor_file,motor_command,3);
// Start the motor
motor_command[0] = opOUTPUT_START;
write(motor_file,motor_command,2);
// Run the motor for a couple of seconds
sleep(2);
// Stops the motor
motor_command[0] = opOUTPUT_STOP;
write(motor_file,motor_command,2);

//CLOSE DEVICE
close(motor_file);
return 0;
}

Closed loop control

The following program sets the the motor speed and runs the motor in closed loop. The speed units are counts per second divided by ten (count/sec/10). If the motor is slowed down the system will try to compensate for it by increasing the motor power (PWM duty cycle)

/*
* Robot Navigation Program
* www.robotnav.com
*
* (C) Copyright 2013 Lauro Ojeda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
#include "lms2012.h"

// Motor speed 0..100
const int MOTOR_SPEED = 10; //[count/s]/10
// The motor operations use a single bit (or a combination of them)
// to determine which motor(s) will be used
// A = 0x01, B = 0x02, C = 0x04, D = 0x08
// AC = 0x05
const char MOTOR_PORT = 0x1;

int main()
{
//DEFINE VARIABLES
char motor_command[3];
int motor_file;

//INITIALIZE DEVICE
//Open the device file asscoiated to the motor controlers
if((motor_file = open(PWM_DEVICE_NAME, O_WRONLY)) == -1)
return -1; //Failed to open device

//ACTUATE MOTORS
// All motor operations use the first command byte to indicate the type of operation
// and the second one to indicate the motor(s) port(s)
motor_command[1] = MOTOR_PORT;
// Set the motor desired power 0 to 100
motor_command[0] = opOUTPUT_SPEED;
motor_command[2] = MOTOR_SPEED;
write(motor_file,motor_command,3);
// Start the motor
motor_command[0] = opOUTPUT_START;
write(motor_file,motor_command,2);
// Run the motor for a couple of seconds
sleep(2);
// Stop the motor
motor_command[0] = opOUTPUT_STOP;
write(motor_file,motor_command,2);

//CLOSE DEVICE
close(motor_file);
return 0;
}

Encoder Reading

The motor encoders can be read as any other EV3 sensor. The following code shows how to setup and access the encoder readings. The motor is controlled in closed loop.

/*
* Robot Navigation Program
* www.robotnav.com
*
* (C) Copyright 2013 Lauro Ojeda
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include
#include
#include <sys/mman.h>
#include "lms2012.h"
// Motor power 0..100
const int MOTOR_SPEED= 10;
// The motor operations use a single bit (or a combination of them)
// to determine which motor(s) will be used
// A = 0x01, B = 0x02, C = 0x04, D = 0x08
// AC = 0x05
const char MOTOR_PORT_A = 0x01;
const char MOTOR_PORT_D = 0x08;
const int MAX_READINGS = 10000;
int main()
{
MOTORDATA *pMotorData;

char motor_command[4];
int motor_file;
int encoder_file;
int i;
//Open the device file asscoiated to the motor controlers
if((motor_file = open(PWM_DEVICE_NAME, O_WRONLY)) == -1)
{
printf("Failed to open device\n");
return -1; //Failed to open device
}
//Open the device file asscoiated to the motor encoders
if((encoder_file = open(MOTOR_DEVICE_NAME, O_RDWR | O_SYNC)) == -1)
return -1; //Failed to open device
pMotorData = (MOTORDATA*)mmap(0, sizeof(MOTORDATA)*vmOUTPUTS, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, encoder_file, 0);
if (pMotorData == MAP_FAILED)
{
printf("Map failed\n");
return -1;
}
// All motor operations use the first command byte to indicate the type of operation
// and the second one to indicate the motor(s) port(s)
motor_command[0] = opOUTPUT_SPEED;
motor_command[1] = MOTOR_PORT_A;
motor_command[2] = MOTOR_SPEED;

motor_command[0] = opOUTPUT_SPEED;
motor_command[1] = MOTOR_PORT_D;
motor_command[2] = MOTOR_SPEED*2;
write(motor_file,motor_command,3);
// Start the motor
motor_command[0] = opOUTPUT_START;
motor_command[1] = MOTOR_PORT_A | MOTOR_PORT_D;
write(motor_file,motor_command,2);
// Read encoders while running the motor
for(i=1;i<MAX_READINGS;i++)
printf("Spd/Cnt/Snr: A=%d/%d/%d D=%d/%d/%d\n",\
pMotorData[0].Speed,pMotorData[0].TachoCounts,pMotorData[0].TachoSensor,\
pMotorData[3].Speed,pMotorData[3].TachoCounts,pMotorData[3].TachoSensor);
// Stop the motor
motor_command[0] = opOUTPUT_STOP;
write(motor_file,motor_command,2);
// Close device files
close(encoder_file);
close(motor_file);
return 0;
}

Prev >> Sensors
Next >> Hardware Interaction