expr:class='"loading" + data:blog.mobileClass'>

Monday, February 25, 2013

Controller

This one is still related to the my previous posts. This time around, I have added features that I had promised in my earlier posts. The usage of the software remains mainly unchanged. What has changed is the way in which the firmware is written. The firmware now uses polymorphism to make it easier to adapt the communication frame work to different hardware platforms (The selected hardware platform should support C++ as a programming language to use this approach). The current implementation makes use of polymorphism at two different places
(a) For the implementation of the communication channel (UART/serial protocol in our case)
(b) For  implementing the functions required for accessing the digital and analog peripherals

What is polymorphism?
Let me try and explain this with a simple example that of a shoe. The coefficient of friction for a shoe on normal road is different than that on a polished smooth surface such as ice. The shoe with which you were comfortable with while walking on a normal road, changes behavior on a smooth road. It would be difficult for you walk on a icy surface with the same shoe. This happens due to variation of the coefficient of friction. Now if you were to write a simulator that uses persons using shoes and their walking behavior on different surfaces, you can use polymorphism to use this function. The gait simulator can simulate appropriate gait based on the surface with the same shoe object.
Coming back to our usage scenario, there are multiple boards that are supported, each having its own APIs for accessing the peripherals and communication channels. The functions that implement the communication protocol are generic and can be used on any platform. These functions can use objects that behave according to the hardware platform on which they are running.

How is polymorphism implemented here?
In the current implementation, the generic communication protocol frame work expects certain function to be implemented that are the bare minimum which has to be implemented by the user for a given board. Here is one such class that has be defined.

   
 class Console  
 {  
   public:  
   virtual char getCh() = 0;  
   virtual void putCh(char ch) = 0;  
   virtual void puts(char *str) = 0;  
   virtual void printf(char *fmt, ...) = 0;  
   virtual void printErr(uint err)  
   {  
    char errMsgs[][20] = {  
     "ERROR",  
     "SUCCESS",  
     "Invalid pin",  
     "Invalid arguments"  
    };  
    if (err > 4)  
    {  
      err = 0;  
    }   
    puts(&errMsgs[err][0]);  
    puts("OK");  
   }  
   virtual int available() = 0;  
 };  

This class defines a template that can be used by the generic frame work. The user has to derive this class and implement the communication methods. This class has to be derived and implemented by the user for the required hardware platform. Once the class is defined, create an object of this type and assign the pointer to the object of type "Console"(or "PerAccess" in case of peripheral access object). These methods let the protocol frame work fetch and put the data onto the communication network. These methods remain unchanged on any given platform but how they work changes from platform to platform. This is where we use polymorphism, that is, same object expected by the protocol frame work behaves differently based on the board on which the code is being implemented and run.

 extern Serial pc;  
 class MbedConsole : public Console   
 {  
   public:  
   virtual char getCh()   
   {  
     return pc.getc();  
   }  
   virtual void putCh(char ch)   
   {  
     pc.printf("%c", ch);  
   }  
   virtual void puts(char *str)  
   {  
     pc.printf("%s", str);  
   }  
   virtual void printf(char *fmt, ...);  
   virtual int available();  
 };  

This is a "concrete" class that can be used by the communication protocol. Similarly, the methods for accessing the digital pins, ADCs and DACs are implemented.

Using the software:
Now that the implementation details are out of the way, let us now see how you can use the host app to control the peripherals. The application is written in python (tested with 2.7) for GUI, wxWidgets is used along with pyserial for serial communication.  You can start the application by double clicking on "App.py" or under Linux, you could type in "sudo python App.py" to start the application. As described in the previous post, the configuration files are used to get information on communicating with the different hardware modules. On startup, the application looks for all the files in the current directory ending with '.cfg' and displays the following window


As you can see, there were two config files that were identified and are displayed in the combo box. The name that appears in the combo box is same as the config file name with '.cfg' removed. Select configuration file, connect the board and hit 'start'. In the window that appears next, select the appropriate com port and click on 'open' to start controlling the peripherals.



All the operations performed are displayed on the status bar, at the bottom as well.

 The screen shots are from the application controlling a mbed module.

The entire project is on GitHub. Please report bugs through the Git.  
Get the mbed project from here.

P.S: I am unable to upload the windows executable of the GUI app to my regular file hosting service. Please suggest a better free file hosting service so that I can upload the executable. 
You can download the per-built GUI app for windows from here.  (Thank you Grenadier Werbenjagermanjensen)

Sunday, February 24, 2013

EvoPrimer Tutorial: ToolBars

 
This blog post is the first in series (hopefully, there will be more) of tutorials on the EvoPrimer dev kit from Raisonance. These tutorials will mainly concentrate on usage of the circle OS. This tutorial assumes that you already know how to create a simple Circle OS project. If you are not aware of the procedure to do so, you can follow this tutorial to learn about it.

For this tutorial, we will see how we can create and use a tool bar under Circle OS. Toolbars are the widgets that appear on the top of the LCD.

For this tutorial, we will build a simple game of gears, papers and scissors (I could not find a rock icon in Tango image library :p). The game logic itself is simple, the CPU makes a random selection of an object, either a rock(gears), paper or scissor and compares against the user selection, selected via the tool bar.

First we will see how the game logic is implemented and then move on to the implementation details of the game on the Circle OS.

The game:
The three game objects (gear, paper and scissor) are represented using numeric values which are defined using following '#define's:


 #define GEAR 0  
 #define PAPER 1  
 #define SIC 2  

Next up, we have defines which represent the result of a match.

 #define PLAYER_WINS 3  
 #define CPU_WINS 4  
 #define DRAW 5  

These two are used to setup the rules table. This is a two dimensional array which when accessed with column as CPU selection and row as user selection, returns the result of the match. All other parts of the application is built on this core logic. The game is “played” by the the function play() which takes as input the user choice and internally generates a random number to make a CPU selection and determines the result of the match. We'll now see how one can create tool bars and use them.

The tool bars:
You can have up to 4 tool bar items displayed at a time. The main toolbar is represented by the 'tTheToolBar' which is of type 'tToolbar' which we need to populate with our custom tool bar icons and their associated call back functions. First, we need to have icons. I got the icons from the Tango library and used “BMPTOLCD” tool to get the RGB value from the image files and store it in “C” header files.

 static const uint16_t aPaperIcn[] = {  
 #include "paper.h"  
 };  
 static const uint16_t aGearIcn[] = {  
 #include "gear.h"  
 };  
 static const uint16_t aSiccorIcn[] = {  
 #include "siccor.h"  
 };  
 static const uint16_t aExitIcn[] = {  
 #include "exit.h"  
 };  

If you were to add the above lines and copy the header files into current working directory you would encounter following error message
 undefined symbol `!!!!!!!!! FLASH IS FULL !!!!!!!!!' referenced in expression   

This is due to the fact that each circle OS application by default is allocated 8K of program memory and by including all the header files of icons (which also consumes program memory), we have exceeded the memory allocated to us. Solution is to modify the linker script, “Circle_App_OP4.ld” (or “Circle_App.ld” in case of primer 1 or 2) to allow us to use more program memory. The linker script is located in the same directory as the project files are located. Open the file “Circle_App_OP4.ld” in RIDE ( or your favorite editor) and scroll down to line number 198 and change “16K” to “64K” now that the linker knows the program memory available (flash), we also need to set the higher address for the flash. According to the linker script our program memory starts from “0x800C000” and the higher address would be 0x800C000 + 64K – 1. Modify line 206 as well with the similar changes that you made to line 198 that is, replace 16K with 64K. Save the modifications and now the application should compile.

Now that we have icons for the tools bar, we need to create the toolbar items that can be used by the circle OS.

 const tToolbarItem tItem1 = { aGearIcn, ToolBar_Handle_Gear};  
 const tToolbarItem tItem2 = { aPaperIcn, ToolBar_Handle_Paper};  
 const tToolbarItem tItem3 = { aSiccorIcn, ToolBar_Handle_Siccor};  
 const tToolbarItem tItem4 = { aExitIcn, ToolBar_Handle_Exit};  

The above structure initializations has two parts, the first part is the starting address of the image data (which has to be 60x60 pixels for proper drawing on the LCD). The second part is the callback function that will be executed when the user clicks on the corresponding tool bar item.

 enum MENU_code  
 ToolBar_Handle_Gear (void)  
 {  
 Play(GEAR);  
 return MENU_CONTINUE_COMMAND;  
 }  
 enum MENU_code  
 ToolBar_Handle_Siccor (void)  
 {  
 Play(SIC);  
 return MENU_CONTINUE_COMMAND;  
 }  
 enum MENU_code  
 ToolBar_Handle_Paper (void)  
 {  
 Play(PAPER);  
 return MENU_CONTINUE_COMMAND;  
 }  
 enum MENU_code  
 ToolBar_Handle_Exit (void)  
 {  
 MENU_RestoreAppliDivider();  
 return MENU_Quit();  
 }  

All the toolbar handlers (except for exit) use the Play() function to play the game. Finally, we register our toolbar items with the circle OS using the following steps in the Application_Ini().

 tTheToolBar.NbItems = 4;  
 tTheToolBar.FirstDispItem = 0;  
 tTheToolBar.Items[0] = tItem1;  
 tTheToolBar.Items[1] = tItem2;  
 tTheToolBar.Items[2] = tItem3;  
 tTheToolBar.Items[3] = tItem4;  
 TOOLBAR_Set (&tTheToolBar);  

Above, we populate the main toolbar ('tTheToolBar') with the information of our tool bar items. First statement sets the number of tool bar items, which is 4 in our case. The next statement sets the first tool bar item to be displayed which we have set to zero since we want 'gears' toolbar item to be displayed first. This parameter can be useful if tool bar items are greater than 4. In that case you can cycle through your multiple tool bar items to be displayed. The tool bar for our application is set using the function “TOOLBAR_Set()”. When you start your application, you should see the toolbar in the top and should be able to play the game.

You can download the project and related files from here.
You need to have an account at stm32circle.com to download the files.

I've kept out description of other circle OS features used (such as LCD_Draw()). These can be part of future tutorials. You can post any questions you might have in the comments section. I'll try my best to answer. Please do leave your feed back as well. Would help me to better these tutorials.

P.S.: Toolbars events are actually triggered through the LCD touch screen, hence you need to calibrate the touch screen (if you are restarting the EvoPrimer and have not calibrated the touch screen). Bottom line is, Without calibration, the tool bars won't work. 

Monday, October 29, 2012

Arduino controller - 2

 This blog post is continuation of the previous post. I have made some changes to the software on the host side. Most important among them is that now you can a have a configuration file that describes what ports on the board are available. One more change is that, as opposed to earlier, now you can select the serial port directly from the GUI rather than specifying it within a configuration file.
Here is a sample configuration file (for Arduino Duemilanove):

 [Digital]  
 p0=0  
 P1=1  
 P2=2  
 P3=3  
 P4=4  
 P5=5  
 P6=6  
 P7=7  
 P8=8  
 P9=9  
 P10=10  
 P11=11  
 P12=12  
 P13=13  
 [Settings]  
 Board=Arduino Dumilanove 
 vref=5  
 res=1024  
 AoutMax=256 
 [AnIn]  
 p0=0  
 p1=1  
 p2=2  
 p3=3  
 p4=4  
 p5=5  
 [AnOut]  
 p3=3  
 p5=5  
 p6=6  
 p9=9  
 p10=10  
 p11=11  

As you can see, it follows syntax of ini files. The first section describes the digital pins. The first part of entries in this section is the name of the port, that will appear in the GUI controls (in the combo boxes). The second part (one after =) dictates what value will be sent to the board as part of the command frame. Similarly the analog input (AnIn) and analog output (PWM in case of Arduino) are filled up. The special section here is the "Settings" section. Here you can specify general settings such are board name, reference voltage(vref), the resolution of ADC(res) and also the maximum digital value that can be output by the DAC(/PWM) unit on the micro controller(AoutMax). The program then reads these config files and then populates the GUI controls appropriately at startup.

Using it:
Download the Arduino sketch from here.Connect the Arduino and start the download. Once downloading is done, start the GUI app by double clicking on "controller.exe" (or type in "python App.py" under linux, assuming that you have installed all the python dependencies required by this app which are pyserial and wxPython-2.8). If the Arduino is already connected, the serial port name should appear in the combo box:

Select serial port

Select a digital pin and set a logic level

Select a digital pin and read logic level

Enter a digital value representing analog voltage and set it at pin of your choice

Read analog voltage at selected pin



Open the port and now you are ready to toggle GPIOs, read voltage level on GPIOs as well as read and output analog voltages.

With a different config file and matching code running on the hardware, one should be able to use any of the hardware modules available with the same GUI.
I'll soon upload code for mega(I have chipkit MAX32) which should be trival and also one more version compatible with the mbed module.
Please leave suggestions and feedbacks in the comments section below.

The project on MCU side has been modified click on this link to know more.

Note1: In case of PWM output (AnalogOut) the GUI accepts voltages in range 0-255 and not direct representation of analog voltage. These are not analog values.

Note2: The default config file here is named as conf.txt.

Note3:  In case of linux, the GUI needs some tweaking so will not render properly. Will fix the issue shortly and upload the code when it is done.
  

Tuesday, October 9, 2012

Arduino controller


This project is based on Arduino Platform.
This current project implements a software architecture which eases the Arduino related peripheral operations such as Analog out(pwm), digital read/write and analog read operations. The core of the project is implemented in “trans_layer.cpp”. The central object in this project is “TransLayer” which has following methods:
TransLayer ()(constructor)
AddService()
SeeServices()
LookForService()
MainLoop()

Services here I am referring to are actually functions that accomplish certain task such as turning on an LED or reading Analog voltage at a given pin. The list of services are maintained within a linked list. The construct in this project (TransLayer()) initializes the head and tail pointers for the linked list. The linked list is list of data object of type service_list whose deceleration is:

struct service_list /**< Struct for holding service list */
{
call_back_ptr service_function; /**< call back function pointer */
char service_flag; /**< Packet service flag for which this service responds*/ service_ptr next_service;
};

call_back_ptr is the function pointer to the call back function. The service_flag is a char which uniquely represents the service. To add a service, AddService() should be used. It accepts a function pointer, to be used as call back function when the character which corresponds to the second argument to this function is received.

All the packets start with character 'S' followed by, the character which represents the given service. This is followed by any extra data required by the service. The generic structure of the packet is:

 

In the MainLoop() method, within an infinite loop, the incoming packets are examined. As soon as character 'S' is received, the next character in the packet is examined and if a match is found, the corresponding call back function is executed. These functions extract their input arguments from the input buffer and perform the required action.
On host side, to ease things, I have developed a Python script to transmit commands and receive responses from the Arduino. This script requires wx python and py serial to be installed on your system. The GUI was designed using visual wx tool.There are few bug fixes and more improvements required. I plan to fix bugs and make improvements shortly.

Some screen shots:
 


 
The central part of the application is 'TransLayer' object which has various methods that forms packets and transmits them over the serial port. It also has methods which receive incoming data over serial port and parse the response coming from Arduino and pass it to the upper layer.

Note: You need to specify serial port name in "ser.cfg" file as the first string. 

Download Arduino code
Download Python code

P.S: Improved GUI app here

Sunday, July 3, 2011

Smith chart plotter

This was my first ever major project. So this is going to be first blog pot. So what actually does is, plots the network characteristics on a smith chart. What is Smith chart you ask, it is a graphical tool that RF engineers use to evaluate the characteristics of a network more. For more info, head onto wikipedia  http://en.wikipedia.org/wiki/Smith_chart.

So why did I do it? Well at the time, I was UG engineering student and had just finished with TLWG (Transmission line and wave guides) and at about the same time, there was an EFY article explaining about the software that plotted Smith chart. It was based on the BGI libaray that came with the turbo C and I wanted to do something that was windows based and had a modern look and feel.

The language, environment that I choose to develop with was just BASIC(JB). which is a flavor of basic language and free version of commercial software called liberty BASIC. They are written in small talk. They are/were windows only software that is why I abandoned the platform.

So let us get on with the implementation of the software. The first few lines in the code  set up the GUI interface for us which is marked by "windows creation" section . The labels that you see within square brackets are actually event handlers. The flow jumps to these labels whenever event with which they are associated occurs. For example, you will find a label called new ([new]) which is the event handler for button named new. Each label ends with "wait" which reactivates the event handling loop. All the action happens when you click on the "plot" button. The event handler for this button first reads the input from the text boxes and then looks if they are valid data. If it sees that user has entered a valid data then it proceeds with the calculations. First it normalizes the impedance and then calculates the voltage standing wave ratio (VSWR).  With all this data, the next step is to plot the smith chart.

Before we get into the plotting logic, let us have a look at the drawing system used by JB. JB uses what is called as turtle graphics to draw stuffs. Conceptually, turtle (a turtle shaped object was used in some toy to draw pictures) has a pen and you can ask the turtle to move from (x1, y1) to (x2, y2) with pen up or pen down. If pen is down, it joins (x1, y1) with (x2, y2) else nothing appears. Additionally, this turtle also knows methods to draw graphics primitives such as circles, triangles etc.

First the program draws r-circles with predetermined radii. Then imaginary circles of the Smith chart are drawn just to give a smith chart kind of look. The subroutine that does this is "drawGraph". It also labels various parts in the graph. This sub routine calculates both radius and 'x' position for the center of the circle to be drawn. These calculations are made using the posx=(rl/(rl+1));  posR = (1.0/(rl+1)); where posx is the variable that holds the position for circle along x axis and posR is the radius of the circle and rl is the variable which is incremented within a for loop to get the concentric circles.  Similarly, the imaginary circles are drawn using the equation posix= = (1/rl) ; posR = (1/rl).

 
Once these circles are in place, the required circles that represent the network are drawn. First, the network impedance is normalized, then the VSWR is calculated  the equations used for calculations are those similar to the equations that appear in the wiki entry. All the above said calculations are scaled internally to suit the drawing area. Along with drawing the circle, the program also displays parameters such as normalized impedance, admittance of the network and VSWR.

You can download the software from here. I'll soon find and upload the source as well. I have uploaded the code to github.

Smith chart plotter software