Category: Software and kits

CM-510 firmware for using as multiple sensor item updated

CM-510 firmware and post updated

 

 

XL-320 Ollo Explorer

XL-320, CM 9.04 and Ollo parts

XL-320, CM 9.04 and Ollo parts

Source code (I should clean it …)

How to start creating and programming robots

Honda Asimo

Honda Asimo

Introduction

Create robots requires a lot of different skills and, depending on how sophisticated is the behavior or the tasks that must be performed, can be really complex and extremely difficult.

The three pillars of robotics are electronics, mechanics and programming; there are others, but only with these three you can already start experimenting.

In addition to applicable knowledge you also need some others items such as motors (or other actuators), sensors, a small computer to avoid weight and power consumption (typically a SBC or microcontroller ) and a power source (battery to be autonomous) and some parts that sustain and hold together all these elements and their movements.

These elements can be acquired (some even manufactured) separately, or more easily, and probably cheaper as a kit.

.

What do I need to start?

Mainly, you need wish to enjoy creating and learning.

* Acquire a minimum and basic knowledge of:

+ Electronics or electricity (if only to distinguish voltage and current),

+ Mechanics (the minimum would be screwing and unscrewing or connect Lego type pieces)

+ Computer (at least to run a program on a computer)

* Get at least a microcontroller (Arduino, for example), a pair of motors, a distance sensor, a battery, cables, and a structure to support it. The basic set or kit.

A kit, the best option

A clear advantage of starting with a kit is that you start NOW, spending your time on where is your interest (electronic, mechanical or computer) , because the others areas are already solved, but anytime you can get to work in any of them. When you buy the kit with all the necessary set of elements together, the price is also often cheaper.

From the more expensive and complex to the cheapest and easiest

bioloid_bio_img01Bioloid : 18 powerful servo motors, 4 sensors. Ideal for humanoid, quadrupeds, hexapods and even vehicles; software to create them and behave like living beings. Includes programming software RoboPlus Tasks, you can also program in C, and create motion sequences with RoboPlus Motion.  Using other controller, like Raspberry Pi you can use any language and programming tools which generate code to it.

It costs around 1000 euros. Yes, it is somewhat expensive, but if you have enough money and programming skills or willingness to learn, I think it deserves the price.

Mindstorms_EV3Mindstorm EV3: 2 servo motors, 1 motor, 4 sensors. Ideal for mechanisms and vehicles. Very easy to use, but it also allows you to create complex robots. Includes programming software NXT-G, NXT is also possible to program in Java with Far and C / C + + with Osek, not yet available for EV3 or very early versions.

It costs around 300 euros, although it may seem expensive compared to other options, its enormous potential and flexibility in all aspects (construction, programming and electronics) make it tremendously interesting.

Mindstorms EV3 is the latest version, released in August 2013.

Arduino robot

Robot Arduino

Vehicle based on Arduino: at least 2 servomotors and all the sensors  you want to start. Is easy and cheap, for around 40€/50$70€/97$ you can have the a robot. Ideal for deepening in electronics.

It can be programmed with the friendly Arduino programming environment .

Is the cheapest option and you can go further by buying more components as you go. It not offers as much flexibility and ability to build as Mindstorms vehicles or Bioloid articulated robots, but you can really learn a lot more than it may seem.

.

.

.

And with less money or no money?

For less money, for starters, you can get an Arduino microcontroller or its clones, which cost just over 20 euros/dollars.

Or, completely free of charge, you can start learning to program in C or C + +, which will come very handy to program robots.

Free resources for learning C programming:

C introduction (pdf)

But there are a lot…

C Language Tutorial (html)
How C Programming Works (html)
Several C programming tutorials (html)
… and more from Google

And here you can find free resources for learning C++ programming.

In the next post I will write about a fast comparative between Bioloid, Mindstorms and Arduino based robots and about Arduino programming.

(I) Reading sensors connected to Robotis CM-510

This entry is part 5 of 5 in the series Bioloid C++ tutorial

cm-510 sensorsUsing the Dynamixel SDK instead of RoboPlus Tasks is not possible to query sensors connected to the CM-5xx controller. But, of course, using standard programming languages, like C++, and tools, line QT Creator or Eclipse, with its full featured IDEs and debuggers is a hugue gain.

So I created a firmware for the CM-510 which can be queried and receive commands to itself, including its sensors, or to Dynamyxel devices.

The idea is very simple:

This program running in the CM-510 receives:

– commands or queries to IDs of Dynamixel devices. These are not processed, only redirected to the Dynamixel bus only if it was received by serial port ( serial cable or zigbee). If it was received from the Dynamixel bus nothing is done.

– commands or queries to the CM-510 ID (I chose ID=200), like beep, or to the sensors connected to it. This commands and queries are processed in the CM-510, basically querying the sensors.

In both cases the answer is sent to the connection from which the query or command was received.

After power on the CM-510, you can select the mode with the 4 cursor keys as showed in a terminal connected to its serial port:

“For ‘Toss mode’ press (Up), for ‘Device mode’ (Down), for ‘Device debug mode’ (Left),to start press (Right)”

In the Device mode:

all the receptions and sends are through the Dynamixel bus, the CM-510 is simply another device.

In the Toss mode:

– what is received from the serial connection is sent to the Dynamixel bus or processed in the CM-510 (If sent to its ID)

-what is received from the Dynamixel bus is sent to the serial connection

Finally, the Debug mode:

is like the Device mode, but all the debug messages included in the CM-510 are sent to the serial connection.

A complete sequence with code snippets from the CM-510 program and from the code running in the other computer:

Some C++ code snippets from this example: (C# in the next post)

enum AX12Address  //and functions implemented in the CM-510 program, like
{
	ReadCM510SensorRaw = 1,
        Beep = 8,
	ReadCM510SensorFiltered = 4,
	SetSensorValuesToFilter = 5,
...
}
void doBeep()
{
    cout << "Beep" << endl;
    mySystem.dynamixelCommunication.sendOrder(100, AXS1_Buzzer, (byte) DO, (short) 500);
    usleep (200000);
    mySystem.dynamixelCommunication.sendOrder(200,MyCommunications::Beep short)5);
}

Querying sensor:

void doQuerySensor()
{
    int sensorPort=getSensorPort();
    int value=mySystem.dynamixelCommunication.readSensorValue (200,ReadCM510SensorRaw, sensorPort);
   cout << "the sensor reads: [" << value << "] " << endl << endl << endl;
}

These command and query are processed in the CM-510:

Getting the sensor value:


int executeCM510Function()
{
...
		case F_GET_SENSOR_VALUE_RAW:
			values[1] = getSensorValueRaw(parameters[1]);
			break;

		case F_GET_SENSOR_VALUE_FILTERED:
			values[1] = getSensorValueFiltered(parameters[1], sensorValuesToFilterDefined);
			break;

		case F_GET_TWO_DMS_SENSOR_VALUES:
			parametersReceived=3;
			getTwoDMSSensorsValues();
			break;

		case F_GET_MULTIPLE_SENSOR_VALUE:
			getMultipleSensorsValues();
			break;

		case F_DO_SENSOR_SCAN: 
			values[1]= sensorScan(parameters[1]);
			break;

		case F_SET_VALUE_DMS1 : //set default value DMS1
			DMS1=parameters[1];
			break;

		case F_SET_VALUE_DMS2 : //set default value DMS1
			DMS2=parameters[1];
			break;

		case F_BEEP:
			if (debugMode)
				printf("executeCM510Function beep\n");
			beep();
			break;

		case F_SET_SENSOR_VALUES_TO_FILTER:
			sensorValuesToFilterDefined=parameters[1];
			break;
	}

	return function;
}

}
...
int getSensorValueRaw(unsigned char portId)
{
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);

		setPort(portId);
		//PORTA &= ~0x80;
		//PORTA &= ~0x20;

		//_delay_us(12);				// Short Delay for rising sensor signal
		_delay_us(24);
		ADCSRA |= (1 << ADIF);		// AD-Conversion Interrupt Flag Clear
		ADCSRA |= (1 << ADSC);		// AD-Conversion Start

		while( !(ADCSRA & (1 << ADIF)) );	// Wait until AD-Conversion complete

		PORTA = 0xFC;				// IR-LED Off

		//printf( "%d\r\n", ADC); // Print Value on USART

		//_delay_ms(50);
		_delay_ms(ReadSensorDelayMS);

		return ADC;
}

 


void beep()
{
   buzzOn(100);
   buzzOff();
}

But we can do a little more with the CM-510 processor, we can do some filtering to the sensor values.

The readings from the DMS are usually somewhat erratic, so we can simply:

– discard the minimum and maximum values:

– if we take 5 more than measures, then return the average if the are more than 3, if 3 or less it

Previously we should set how many readings should be done, if not, the default number of readings are 5:

int getSensorValueFiltered(unsigned char portId, int times)
{
...
	switch(function)
	{		
		case F_GET_SENSOR_VALUE_RAW:
			values[1] = getSensorValueRaw(parameters[1]);
			break;

		case F_GET_SENSOR_VALUE_FILTERED:
			values[1] = getSensorValueFiltered(parameters[1], sensorValuesToFilterDefined);
			break;

		case F_GET_TWO_DMS_SENSOR_VALUES:
			parametersReceived=3;
			getTwoDMSSensorsValues();
			break;

		case F_GET_MULTIPLE_SENSOR_VALUE:
			getMultipleSensorsValues();
			break;

		case F_DO_SENSOR_SCAN: 
			values[1]= sensorScan(parameters[1]);
			break;

		case F_SET_VALUE_DMS1 : //set default value DMS1
			DMS1=parameters[1];
			break;

		case F_SET_VALUE_DMS2 : //set default value DMS1
			DMS2=parameters[1];
			break;

		case F_BEEP:
			if (debugMode)
				printf("executeCM510Function beep\n");
			beep();
			break;

		case F_SET_SENSOR_VALUES_TO_FILTER:
			sensorValuesToFilterDefined=parameters[1];
			break;
	}
...

We also can take values from multiple sensors with one query, but It will be explained in the next post…

(I) Programming serial port communications

This entry is part 1 of 2 in the series Serial communications

250px-Serial_portConnections and operating system symbolic names

A serial port is a communication physical interface through which information  transfers in or out one bit at a time (in contrast to a parallel port) being, more or less compliant, with the RS-232 standard.

But serial port communications aren’t only useful for wired DE-9 connectors. it also allows us to use it with USB (ftdi), Bluetooth (serial profile) and Zigbee using virtual serial ports.

·

Types-usbSerial and virtual serial ports appear as  COMx in Windows operating systems (COM1, COM2, …) andin UNIX/Linux as ttySx or ttyUSBx or even ttyACMx (ttyS0, ttyS1, ttyUSB0, ttyUSB1, ttyACM0, ttyACM1,…).

For programming purposes we usually want to communicate computers with others computers, microcontrollers or other devices like GPS, LED or LCD displays.

·

Serial port programming in C/C++, Windows and Linux

Using the serial port is a lot  easier, but sometimes tricky. The basic commands are to open a connection, read and write over this connection and, finally, tom close it, better if using the C++ RAII idiom.

winWindows commands:
Here you can find a complete C++ for Windows example.

With these next two definitions (among others needed):

HANDLE
serialPortHandle
wchar_t* device

serialPortHandle = CreateFile(device, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
if (serialPortHandle!=INVALID_HANDLE_VALUE)
ReadFile(serialPortHandle, buffer, len, &read_nbr, NULL);

if (serialPortHandle!=INVALID_HANDLE_VALUE)
WriteFile(serialPortHandle, buffer, len, &result, NULL);
CloseHandle(serialPortHandle);

linuxUnix/Linux commands:
Here you can find a complete C++ for Linux example.

With these two definitions:

·
int fileDescriptor;
char *device;
·
·
  • Opening a connection, open
struct termios terminalAttributes;

fileDescriptor = open(device, O_RDWR | O_NOCTTY | O_NDELAY | O_FSYNC );

// clear terminalAttributes data
memset(&terminalAttributes, 0, sizeof(struct termios));

terminalAttributes.c_cflag = B57600 | CS8 | CLOCAL | CREAD; 
terminalAttributes.c_iflag = IGNPAR |  ONLCR;
terminalAttributes.c_oflag = OPOST;
terminalAttributes.c_cc[VTIME] = 0;
terminalAttributes.c_cc[VMIN] = 1;

tcsetattr(fileDescriptor, TCSANOW, &terminalAttributes);
int n=read(fileDescriptor, buffer, len);

int n=write(fileDescriptor, buffer, len);
  • Closing the connection, close
close(fileDescriptor);

More information:

https://en.wikipedia.org/wiki/Serial_communication
http://en.wikipedia.org/wiki/Serial_port

http://www.lvr.com/serport.htm
http://digilander.libero.it/robang/rubrica/serial.htm
http://en.wikibooks.org/wiki/Serial_Programming

http://msdn.microsoft.com/en-us/library/ff802693.aspx

(II) C++ crash examples tutorial using Robotis CM-900 board and IDE (II)

This entry is part 5 of 5 in the series Programming CM-900

In this post I will try to show one important C++ feature, virtual classes as interfaces, defining a rol that several classes can implement. Also

Here you can download the file with the source code.

_2_CM900_CPP_Interfaces


// C++ crash tutorial with Robotis CM-900.

// First example: http://softwaresouls.com/softwaresouls/

/*
Classes inheritance and interface creation in C++
*/

// Abstract class as Interface for communication device classes http://www.cplusplus.com/doc/tutorial/polymorphism/
class CommunicationDevice
{
public:
virtual void setup(int baudrate=0)=0; // baudrate=0, default parameter in case is not passed any parameter.
//...)=0; is a pure virtual method that convert the class in abstract http://www.cplusplus.com/doc/tutorial/polymorphism/
//      because is not straight usable , a derived classimpllementing the pure virtual methods must be created
virtual void send(char *message)=0;   // default parameter in case is not passed any parameter.

virtual void send(int i)=0; //Method overloading http://www.cplusplus.com/doc/tutorial/functions2/ Same method name with different parameter types

};

class Zigbee : public CommunicationDevice //inherits the interface a should define the methos to be able to create objects.
{
public:
void setup(int baudrate=0);
void send (char *message);
void send(int i);
};

class USB : public CommunicationDevice //inherits the interface a should define the methos to be able to create objects.
{
public:
void setup(int baudrate=0);
void send (char *message);
void send(int i);
};

class Debug {
CommunicationDevice &commDevice;
public:
Debug(CommunicationDevice &aCommDevice) : commDevice(aCommDevice) {}; // member object commDevice is instantiated by reference to avoid object copy
void show(char *message)
{
commDevice.send(message); // the "commDevice"  method called depends on the object passed to the constructor
}

void show(int i)
{
commDevice.send(i);
}
};

void Zigbee::setup(int baudrate)
{
if (baudrate==0)
baudrate=57600; //only changes local copy, not the variable passed as value parameter http://www.cplusplus.com/doc/tutorial/functions2/
Serial2.begin(baudrate);
}

void Zigbee::send(char *message)
{
Serial2.println(message);
}

void Zigbee::send(int i)
{
Serial2.println(i);
}

void USB::setup(int baudrate)
{
SerialUSB.begin();
}

void USB::send(char *message)
{
SerialUSB.println(message);
}

void USB::send(int i)
{
SerialUSB.println(i);
}

Zigbee zigbee;
USB usb;

const byte NumberOfCommsDevices=2;
CommunicationDevice *commsDevices[]={&usb, &zigbee};
//={usb, zigbee};

void setup()
{
//  Individually:

//  zigbee.setup();
//  usb.setup();

//  collectively. using the common Interface "CommunicationDevice"
for (int i=0;i<NumberOfCommsDevices;i++) commsDevices[i]->setup();
delay(2000); // waiting for 2 seconds, let the user activate the monitor/console window (Control+Shift+M).
}

int counter=0;
void loop()
{
++counter;
Debug debug1(usb); // Debug constructor accepts any class inhereting the Interface "CommunicationDevice", Debug(CommunicationDevice &aCommDevice)
debug1.show("Hola"); //debug object will call the method "send" implemented in the object passed to the constructor. In this case "usb.send"

//Showing the counter for each iteration until the 2000th iteration
if (counter <=2000)
debug1.show(counter);
else
{
// Showing the counter every 100 iterations and waiting for 2 seconds
if (counter%100==0) // Operator modulo http://www.cplusplus.com/doc/tutorial/operators/ (returns the remainder)
{
debug1.show(counter);
delay(2000);
}
}
}

Bioloid Workbench Windows C++ examples

This entry is part 6 of 6 in the series Bioloid Workshop

This post presents the Windows version of two examples/utilities built, this time, with MS Visual C++ and QT Creator, a great open source IDE and framework.

The first utility has a comand line user interface, being an easy example with only two DLL dependencies to the Visual C++ runtimes.

Screenshot-Terminal

The second example utility has a graphic user interface created with QT Creator.

QTWorkbench

Here you can find the bin executables and the projects with the source code.

This is the main function of the first example, the command line:

int _tmain(int argc, _TCHAR* argv[])
{
  cout << "AXControl_v2_VS_CPP test v0" << endl;

  bool quit=false;
  MyBasicSystem::BasicSystem mySystem;
  UI ui(mySystem);
  do
  {
    ui.showMenu();
    int selected=ui.selectOption();
    if (selected==ui.OptionQuit)
	quit=true;
    ui.executeSelectedOption(selected);
  }while (!quit);

  mySystem.dynamixelCommunication.close();

	return 0;
}

[Update] Yesterday I discovered a subtle but ugly bug. Can you spot it? Send an email to if you can’t find it but you want to know the danger bug.

It use two classes, the “BasicSystem” (in the library “VS_CPP_AXControl_lib.lib”) and a simple “UI” class that receives the input from the user and use the operations offered by the “BasicSystem” class.

For example:

int UI::getPosition()
{
  int position=0;

  do
  {
    cout << "Type a value between 0 and 1023 to set the AX-12 in that position" << endl;     cin>>position;

  }while(!validRange(position, 0, 1023));

  cout << "Position:" <<  position << endl;

  return position;
}
...
void UI::doSetPosition()
{
  int ax12Id=getId();
  int position=getPosition();

  mySystem.dynamixelCommunication.sendOrder(ax12Id, MyCommunications::GoalPosition,(short) position);
}

And all the cource code:

/*------------------------------------------------------------------------------*\
 * This source file is subject to the GPLv3 license that is bundled with this   *
 * package in the file COPYING.                                                 *
 * It is also available through the world-wide-web at this URL:                 *
 * http://www.gnu.org/licenses/gpl-3.0.txt                                      *
 * If you did not receive a copy of the license and are unable to obtain it     *
 * through the world-wide-web, please send an email to                          *
 * siempre.aprendiendo@gmail.com so we can send you a copy immediately.         *
 *                                                                              *
 * @category  Robotics                                                          *
 * @copyright Copyright (c) 2011 Jose Cortes (http://www.siempreaprendiendo.es) *
 * @license   http://www.gnu.org/licenses/gpl-3.0.txt GNU v3 Licence            *
 *                                                                              *
\*------------------------------------------------------------------------------*/

#include "stdafx.h"
#include
#include "BasicSystem.h"
#include "Util.h"

using namespace std;

class UI
{
public:
  static const int OptionQuit=8;

  UI(MyBasicSystem::BasicSystem& aMySystem) : mySystem(aMySystem) {}

  void showMenu();
  int selectOption();
  bool executeSelectedOption(int selected);
  void doBeep();

private:
  MyBasicSystem::BasicSystem mySystem;

  static const int OptionSetLEDOnOff=1;
  static const int OptionQueryAX12=2;
  static const int OptionMoveAX12=3;
  static const int OptionTorqueAX12=4;
  static const int OptionQuerySensor=5;
  static const int OptionShowMenu=6;
  static const int OptionBeep=7;

  static const int MinOption=OptionSetLEDOnOff;
  static const int MaxOption=OptionQuit;

  bool validRange(int value, int MinValue, int MaxValue);
  bool nonValidOption(int option);
  int getPosition();
  int getId();
  int getSensorPort();
  void doGetPosition();
  void doSetPosition();
  void doQuerySensor();
  void doSetLEDOnOff();
  void doSetTorqueOnOff();

};

void UI::showMenu()
{
  cout << "V02" << endl;

  cout << OptionSetLEDOnOff << ".- Toggle AX-12 LED" << endl;
  cout << OptionQueryAX12 << ".- Query AX-12" << endl;
  cout << OptionMoveAX12 << ".- Move AX-12" << endl;
  cout << OptionTorqueAX12 << ".- Torque AX-12" << endl;
  cout << OptionQuerySensor << ".- Query CM-510 sensor" << endl;
  cout << OptionShowMenu << ".- Show menu" << endl;
  cout << OptionBeep << ".- Beep" << endl;
  cout << OptionQuit << ".- Quit" << endl;
}

bool UI::nonValidOption(int option)
{
  return (optionMaxOption);
}

int UI::selectOption()
{
  int option=-1;

  while (nonValidOption(option))
  {
    cout << "Select option (" << MinOption << "-" << MaxOption << ")" << endl;     cin >> option;
    if (nonValidOption(option))
    {
      cout << endl;
      cout << endl;
      cout << "(" << option << ") is NOT a valid option" << endl;     }     }   return option; } bool UI::validRange(int value, int MinValue, int MaxValue) {		   return (value>=MinValue && value<=MaxValue);
}

int UI::getPosition()
{
  int position=0;

  do
  {
    cout << "Type a value between 0 and 1023 to set the AX-12 in that position" << endl;     cin>>position;

  }while(!validRange(position, 0, 1023));

  cout << "Position:" <<  position << endl;   return position; } int UI::getId() {   int ax12Id=1;        do    {	     puts ("Type the ID of the AX-12 to use, a value between 1 and 18, ");     cin >> ax12Id;

  }while(!validRange(ax12Id, 1, 18));

  cout << "AX12 Id:" << ax12Id << endl;   return ax12Id; } int UI::getSensorPort() {   int sensorPort=1;        do    {	     puts ("Type the sensor Port to read, a value between 1 and 6, ");     cin >> sensorPort;

  }while(!validRange(sensorPort, 1, 6));

  cout << "Sensor Port number:" << sensorPort << endl;

  return sensorPort;
}

void UI::doBeep()
{
  cout << "Beep" << endl;
  mySystem.dynamixelCommunication.sendOrder(100, AXS1_Buzzer, (byte) DO, (short) 500);
  Sleep (2);
  mySystem.dynamixelCommunication.sendOrder(200, MyCommunications::Beep, (byte) 5);
}

void UI::doGetPosition()
{
  int ax12Id=getId();

  int position = mySystem.dynamixelCommunication.readValue(ax12Id, MyCommunications::PresentPosition);
  cout << "the position is: [" << position << "] " << endl << endl << endl;
}

void UI::doSetPosition()
{
  int ax12Id=getId();
  int position=getPosition();

  mySystem.dynamixelCommunication.sendOrder(ax12Id, MyCommunications::GoalPosition,(short) position);
}

void UI::doQuerySensor()
{
  int sensorPort=getSensorPort();

  int value=mySystem.dynamixelCommunication.readSensorValue (200, ReadCM510SensorRaw, sensorPort);
  cout << "the sensor reads: [" << value << "] " << endl << endl << endl;
}

void UI::doSetLEDOnOff()
{
  byte lByte=0, hByte=0;
  int ledValue;

  int ax12Id=getId();

  ledValue=mySystem.dynamixelCommunication.readValue(ax12Id, MyCommunications::LED);
  Hex::toHexHLConversion(ledValue, hByte, lByte);

  bool onOff=false;
  if (lByte!=0)
    onOff=true;

  cout << "The LED is: [" << (onOff?"on":"off") << "], putting it: [" << (onOff?"Off":"on") << "] " << endl << endl << endl;
  mySystem.dynamixelCommunication.sendOrder(ax12Id, MyCommunications::LED, byte(onOff?0:1));
}

void UI::doSetTorqueOnOff()
{
  byte lByte=0, hByte=0;
  int ax12Id=getId();

  int torque=mySystem.dynamixelCommunication.readValue(ax12Id, MyCommunications::Torque);
  Hex::toHexHLConversion(torque, hByte, lByte);
  bool onOff=(lByte!=0?true:false);

  cout << "The Torque is: [" << (onOff?"on":"off") << "], putting it: [" << (onOff?"Off":"on") << "] " << endl << endl << endl;

  mySystem.dynamixelCommunication.sendOrder(ax12Id, MyCommunications::Torque,(byte) (onOff?0:1));
}

bool UI::executeSelectedOption(int option)
{
  bool isOk=true;
  cout << endl;
  cout << endl;

  cout << "Selected option: [" << option << "] " << endl;   switch(option)   {     case OptionSetLEDOnOff:          doSetLEDOnOff();           break;     case OptionQueryAX12:          doGetPosition();          break;     case OptionMoveAX12:          doSetPosition();           break;     case OptionTorqueAX12:          doSetTorqueOnOff();          break;     case OptionQuerySensor:          doQuerySensor();          break;     case OptionShowMenu: 	 showMenu(); 	 break;     case OptionBeep:          doBeep();          break;   }   return isOk; } 

The code for the Qt version is more complex, but as an example, the same operation that the example for the command line:

 int MainWindow::getAX12_1_Id() {     // Get the value from the edit control for the first AX-12     QString qStr=ui->SB_AX12_1_ID->text();
    int id=Util::convertToInt(qStr.toStdString());

    return id;
}
...
void MainWindow::on_B_AX12_1_SET_POS_clicked()
{
    int id = getAX12_1_Id();

    // Get the target position from the UI edit control as string and a convert it to int
    short position= ui->SB_AX12_1_POS->text().toInt();

    // Send the order to the AX-12 with the "id" to go to "position"
    pDynComm->sendOrder(id, MyCommunications::GoalPosition,position);
}
%d bloggers like this: