Recent changes
Slingshot user guide
tag Guide, user
NFCLamp user guide
tag Guide, user
Homepage
MPL115A2
Compiler Error 42
From the mbed microcontroller Cookbook.  

RPC Interface Library

The RPC interface can be really useful because it makes it possible to interface with mbed without having to worry about the communication method. However, Many projects require more than just Digital and Analog I/O and want to make use of the mbeds interfaces or work with many of the libraries which have already been written for various sensors and actuators. This library provides a method of adding RPC functionality without you having to write any of the communication or RPC code. It is made up of 3 parts:

» Import this library into a programRPCInterface

Library to provide a mechanism to make it easier to add RPC to custom code by using RPCFunction and RPCVariable objects. Also includes a class to receive and process RPC over serial.

The mbedRPC software libraries such as for Java, Matlab and LABVIEW also support the RPCFunction and RPCVariable so as to simplify the connection on both the mbed and computer software.

RPCFunction

The RPCFunction object makes it possible to call a custom function over RPC. The function must be of the form void foo(char * input, char * output). To use you first create the function, you then create the RPCFunction object when you attach the function and give it a name by which it will be called over RPC. You might use the input and ouput strings to pass several numeric values by using sscanf and sprintf to read and write the input and output strings. Alternativly you might not need the strings and instead just call the function.

Code

//Create a function of the required format
void foo(char * input, char * output);
//Attach it to an RPC object
RPCFunction rpc_foo(&foo, "foo");

void foo(char * input, char * output){
   int x,y;
   sscanf(input, "%i, %i", &x, &y);

   //Do something here......

   sprintf(output, "%i, %i", x, y );
}

To run this function over RPC you then call the run method on the RPCFunction object. The function you define can be used to wrap the common interactions with class methods that you wish to call over RPC.

Here is an example of it being used to return the value from an I2C Range finder. Using the RPCFunction has made the Rangefinder avaliable over RPC as its library doesn't include support for RPC.

» Import this program

00001 #include "mbed.h"
00002 #include "SerialRPCInterface.h"
00003 #include "SRF08.h"
00004 
00005 using namespace mbed;
00006 
00007 //Create the interface on the USB Serial Port
00008 SerialRPCInterface RPC(USBTX, USBRX);
00009 void ReadRange(char * input, char * output);
00010 RPCFunction RangeFinder(&ReadRange, "RangeFinder");
00011 SRF08 srf08(p9, p10, 0xE0);      // Define SDA, SCL pin and I2C address 
00012 DigitalOut myled(LED1);
00013 
00014 int main() {
00015 //The range finder demo also uses 2 servos but these will be handled entirly over the RPC
00016 
00017     while(1) {
00018         myled = 1;
00019         wait(0.2);
00020         myled = 0;
00021         wait(0.2);
00022     }
00023 }
00024 
00025 //As neither I2C nor the SRF08 library is avalible directly over RPC we create a Custom Function which we make RPCable by attaching to an RPCFunction
00026 void ReadRange(char * input, char * output){
00027     //Format the output of the srf08 into the output string
00028     sprintf(output, "%f", srf08.read());
00029 }

Information

RPC command to read the range: /RangeFinder/run

A complete example using the range finder and software on a computer will be written up soon

» Import this library into a program

Public Member Functions

  RPCFunction (void(*f)(char *, char *), const char *=NULL)
  Constructor.
char *  run (char *str)
  run
char *  read ()
  Reads the value of the output string.

RPC variable

RPCVariable allows you to read and write the value of any variable on mbed. You do this by creating an RPCVariable object and then attaching the variable you want to access over RPC.

Code

//First create the variables you wish to use
float f;
int i;
char c;
//Then attach them to an RPCVariable Object
RPCVariable<float> rpc_f(&f, "f");
RPCVariable<int> rpc_i(&i, "i");
RPCVariable<char> rpc_c(&c, "c");

Information

The RPC commands to read and write the float f would be:

  • /f/write 0.123
  • /f/read

Here is an example of this being used to control a Motor taking feedback from a QEI. None of the control is implemented on mbed, this must be done on the computer however this method has qucikly given the computer access to the Motor and QEI class neither of which are otherwise not avaliable over RPC

» Import this program

00001 /**
00002 * Copyright (c)2010 ARM Ltd.
00003 * Released under the MIT License: http://mbed.org/license/mit
00004 */
00005 
00006 #include "mbed.h"
00007 #include "QEI.h"
00008 #include "Motor.h"
00009 #include "SerialRPCInterface.h"
00010 
00011 //Create the interface on the USB Serial Port
00012 SerialRPCInterface SerialInterface(USBTX, USBRX);
00013 
00014 QEI Encoder(p29 ,p30, NC, 48);
00015 Motor Wheel(p23, p21, p22);
00016 
00017 //Create float variables
00018 float MotorOutput = 50;
00019 float Percentage = 0;
00020 
00021 //Make these variables accessible over RPC by attaching them to an RPCVariable
00022 RPCVariable<float> RPCMotorOut(&MotorOutput, "MotorOutput");
00023 RPCVariable<float> RPCPercentage(&Percentage, "Percentage");
00024 
00025 int main(){
00026 
00027     Encoder.reset();
00028     float NoPulses;
00029     
00030     while(1){ 
00031          NoPulses = Encoder.getPulses();
00032         Percentage = ((NoPulses / 48) * 100);
00033         //RPC will be used to set the value of MotorOutput.
00034         Wheel.speed((MotorOutput - 50) * 2 / 100);
00035         wait(0.005);
00036     }
00037 }

Information

  • rpc command to get the position: /percentage/read
  • rpc command to set the motor speed: /MotorOutput/write 0.8

A complete example of closed loop motor control using the code above and a computer running a software package will be written up soon.

Note that this is entirly asynchronous and so you could get unexpected results if the code on mbed and an interupt driven RPC handler both try to write different values to the variable at the same time.It won't be possible to predict which value has been written into the variable. As such it would be advisable to consider some variables as only written to over RPC and only read by mbed code and other variables the opposite.

The RPCVariable is well suited to the motor and QEI which can be updated whenever however the I2C Range Finder is better suited to the RPCFunction as every reading has to be requested from the device.

These two classes should help you to add RPC to projects which go beyond just reading and writing to mbed's pins. RPCFunction and RPCVariable interfaces are included in the software libraries so as with the rest of the RPC interface you can communicate with mbed without having to design and implement the communication protocol etc.

To avoid having to format your data into and out of strings both on mbed and in your software on the computer, but still have synchronous communication you could combine the RPCvariables and RPCFunctions. Here is the Range finder example using this approach:

Code

float Range = 0;
RPCVariable rpc_range(&Range, "Range");

void RangeFinder(char * input, char * output){
 Range = srf08.read();
}

RPCFunction rpc_GetRange(&RangeFinder, "RangeFinder");

Information

To get the Range now requires 2 RPC commands:

  • /RangeFinder/run
  • /Range/read

This does mean that you have to make a few more RPC requests (and so your communication will be slower) but it could be useful if you want to avoid parsing strings either on mbed or in the software you are working with.

» Import this library into a program

Public Member Functions

template<class A >
  RPCVariable (A *ptr, const char *name)
  Constructor.
read ()
  Read the variable over RPC.
void  write (T value)
  Write a value to the variable over RPC.

SerialRPCInterface

SerialRPCInterface will set up RPC for serial by registering all the base classes and setting up the serial port on an intterupt. When a serial communication is recevied it will pass the commands to the RPC and return the response. This leaves your own code to run on mbed.

To use all you have to do is create it at the top of your program

Code

SerialRPCInterface SerialInterface(USBTX, USBRX);

You can then write the rest of your code as required.

» Import this library into a program

Public Member Functions

  SerialRPCInterface (PinName tx, PinName rx, int baud=9600)
  Constructor.
void  Disable (void)
  Disable the RPC.
void  Enable (void)
  Enable the RPC.



calendar Page history
Last modified 10 Dec 2011, by   user Michael Walker   tag No tags | 19 comments  

19 comments on RPC Interface Library:

02 Oct 2010

this sounds like what i need: amethod to communicate with my MBED over ethernet - wiggle pins etc, but how can i get my PC to send / recive messages?

i REALY want to use DELPHI to do the clever stuff

how do i communicate with MBED,

Cheers CERI

04 Oct 2010

Is it me or are the library files listed here currently unavaiable?

04 Oct 2010

Hi Joe,

If you hit 'enable beta' at the top of the page, this page will make a lot more sense! Libraries as discussed here are only available in beta right now. The beta version will become 'live' very soon now - in the next couple of days hopefully.

Dan

04 Oct 2010

Hi Dan,

Cheers. I thought I'd seen the libraries appear on this page correctly before, just forgot that beta mode resets on new sessions. I'll just have to remember for the next few days until the beta goes 'live'.

Joe

17 Oct 2010

I can't work out what to #include to be able to use RPCFunction in my code. "SerialRPCInterface.h" can't be found. There's no "enable beta" at the top of the page, so I assume the beta is now live?

I tried clicking on the RPCInterface link and then the "Import into Compiler" button, and that opens the Import pane in the Compiler with http://mbed.org/users/MichaelW/libraries/RPCInterface/lfctbw in the Source URL box, but the Import button is greyed-out.

Help!

Rob.

29 Dec 2010

You have to click on the library button or whatevery you call where it says import as

15 Jan 2011

This is what the first code snippet should look like to actually work:

Code

//Create a function of the required format
void foo(char * input, char * output);
//Attach it to an RPC object
RPCFunction rpc_foo(&foo, "foo");

void foo(char * input, char * output){
   int x,y;
   sscanf(input, "%i, %i", &x, &y);

   //Do something here......

   sprintf(ouput, "%i, %i", x, y );
}

One semicolon was missing, and the asterisk after the name of the actual foo function implementation has no business being there.

23 Jun 2011

This is cool!!

04 Jul 2011

Hiya

Attached is a link to a simple program where the required RPC command length seems to affect the stability of the program. If the last custom command is changed from:

"LED4_Off_LONG_NAME" to "LED4_Off_LONG" then the program seems to work in a stable manner. However, if this is not changed then the mbed will hang if there are multiple non-ideal inputs i.e. multiple backslashes. Is there any reason for this and if so can some find a way around this. I do realise that the program attached can use shorter commands, however this bug seems to affect other programs with long command names which are required. Any help will be appreciated.

http://mbed.org/users/NathanWhitaker/programs/TestRPC/ltrx2p

A last note, I am using Tera Term to connect to the mbed with CR+LW forced.

Nathan

11 Aug 2011

Hi Michael,

Thanks for the RPC library. It has become my favorite channel for controlling and getting data off the mbed. There are times, though, that the serial and timer interrupts will clash, especially if you have really frequent Tickers in your code. The symptom is that the code just hangs in the middle of an RPC transaction, especially if an RPCFunction is returning a large string.

The solution is quite simple give the serial interrupt a low priority and the timer a higher one. So, wherever I've used SerialRPCInterface, I also add the following lines to my main:

Code

    NVIC_SetPriority(UART0_IRQn, 2);
    NVIC_SetPriority(TIMER3_IRQn, 0);

Hope this helps someone.

Zainul.

11 Aug 2011

My mbed regularly easily hangs somewhere in the webserver since I'm using RPC. When I request a log file for example http://ip_of_my_mbed/log.txt my mbed also easily hangs. It helps a bit to use little and short RPC commands and to use fast code. Because my mbed hangs so easy in the webserver library, I am using a watchdogtimer to restart the mbed. This helps often but not always.

14 Aug 2011

Hi, Just a question : would it be possible to have an example of adding a RPC command with RPC Interface Library working with the HTTPServer ? The RPC "classic" library works perfect with HTTP but it's very complicated to add a command. Whith RPC Interface Library, simple to add command, but no example with HTTP !

I'm a bit lost within all of this, so it could be very helpfull ! ^^

Thanks a lot.

FX

04 Sep 2011

Hello, How would you declare a string RPC-Variable? I have tried the following but it returns an error indicating that the type is not valid :

char SomeString[20] = "this is a string"; .. RPCVariable<char *> rpc_String(SomeString, "MyString");

Thanks, Louis

23 Sep 2011

Jasper Sikken,

I am also a victim of the hanging problem you mentioned above. My mbed regularly easily hangs somewhere in the webserver. I'm using RPC to control the Digital outs and Digital ins. I can't use watchdogtimer also as it is critical system. Jasper, Do you think RPC variables inside mbed program can make it hang? Have you solved this issue? If yes, please share with me. I am ready to send you my code if it is ok. I use HTTPServer in static ip mode. pl. reply. Thanks joby jobyiuac@gmail.com

30 Sep 2011

joby antony, did disabling interrupts help to solve the hanging problem?

Code

__disable_irq(); 	// Disable Interrupts
// do something that can't be interrupted
__enable_irq(); 	// Enable Interrupts

Did you disable interrupts for the webserver part?

24 Nov 2011

Hi,

I´m new to c++ and so on I´m the best in coding ;-) but I need a bit help. My problem is:

I would like to use the rpc funktion to send command to the mbed. BUT the mbed should look if the ip or mac is one I stored in programm. Cause I don´t want that anyone else could gibve the commands to the mbed rather than me :-( Is there any way to check Mac or ip adress within a RPCFuntion call like the one in eth.read(buf, size); printf("Destination: %02X:%02X:%02X:%02X:%02X:%02X\n",buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); printf("Source: %02X:%02X:%02X:%02X:%02X:%02X\n",buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);

???????????? I mean this way.....

mymac="00:01:02:03:04:05"; myip="192.168.178.33"; Create a function of the required format void foo(char * input, char * output); Attach it to an RPC object RPCFunction rpc_foo(&foo, "foo"); void foo(char * input, char * output){ int x,y; sscanf(input, "%i, %i", &x, &y);

get MACadress from sender and test against mymac or get IPadress from sender and test against myip if same then set variable else do nothing sprintf(ouput, "%i, %i", x, y ); }

Please help me, regards, Thomas

27 Mar 2012

Hello!

Thanks for the library, but I need some clarification.

I can use this only on SerialRPC?

There is no way of using this over HTTP???

28 Mar 2012

Hi Ernesto,

The RPCFuntion and RPCVariable classes can be used with RPC over HTTP, or RPC over any other transport method. They can both be used without using the serialRPCInterface class. Theres a demo using RPCFunctions over HTTP on this page (remote sensing demo at the bottom) which uses this code (see main.cpp)

» Import this programRPC_RemoteSensing

Remote Sensing demo. This is the code that runs on mbed to interface with the Remote Sensing Applet Demo

The SerialRPCInterface class just handles RPC commands received over serial. For more information on how RPC works go here

The RPCVariable and RPCFunctions will work over HTTP in the same way as any other object that can be used over RPC; though you cannot create new instances of them over RPC, ie you can only call ones which are created in code.

Hope this helps

Michael

28 Mar 2012

@Michael Walker

Thanks a lot for the quick response!

Maybe you should include this example in the cookbook page, it would really help newbies like myself.

I'm working in some interesting code to interface with LabVIEW over HTTP, once I'm done I'll also publish it here. Thanks again!!

Please login to post comments.