Sunday, July 17, 2016

RTOS - FreeRTOS - first look - ARMFLY tutorial

Real time operating system has been a crucial task scheduler in large scale microcontroller project.  It allows the development of project to be divided into smaller part and each part is independently develop maintain.

Furthermore, the price of microcontroller is becoming cheaper and equipped with better processing power, RTOS is an additional good feature to be implemented in microcontroller. 

The low cost development kits have ease the learning process of embedded system. For example, the STMicroelectronic series development kits are cheapest in the market (currently), the microcontroller attached with development board is equipped with a lot of peripherals like ADC, DAC, PWM, timer, usb, can, serial communication, etc. It also come with on board debugger/programmer which is helpful in debug the program. Above all, it has large memory footprint (way more that enough).

Why let the RAM and flash go wasted, when you can waste it on RTOS. (Additional RAM is required to allocate stack size for task.)

There are a lot of free RTOS in the market. Previously I have tried OSA rtos for it's low memory footprint and suitability for PIC18f. In fact, I have written three OSA learning tutorials - 1, 2 and 3.

Freertos is an another alternative for microcontroller.

It is widely used in the commercial products, but not much company acknowledge it (freertos forum). One of the notable product that had been using it and publicly acknowledge the usage of freertos is pebble watch.

The vast user base has proven the stability of freertos, but freertos has it learning curve. The source code of freertos is readily available and well organised. Despite that, the source code has low level readability and the official document requires certain fee.

Simple starting guide is desirable to get started with freertos. The best tutorial is always the official website to learn about the function of freertos.

After some googling and baidu, I found one comprehensive tutorial written in Chinese by one China company "ARMFLY" 安富莱电子.

ARMFLY is making ARM development kit particularly on STM32. the good thing about their development kits is they provide tutorial and support in forum. It is also worth mentioning, ARMFLY is selling their boards at taobao.

Beside freertos, ARMFLY had provides tutorials in UCOS, embos, USB, Lwip, and RTX.

The ARMFLY freertos tutorial has 145 examples (project files is available for download) and 1200 pages documents. Link

ARMFLY has provides 145 examples for three of it's developments board which are
STM32F429,
STM32F407 and
STM32F103.

The good thing about this tutorial is step by step guidance provided with image to show the reader exact step instead of reading line by line. ARMFLY is using IAR and MDK compiler in their tutorial, so it is the best to get started with these two compilers.

The downside of this tutorial is written in Chinese. So it is an added advantageous to the reader who know Chinese.

It is worth mentioning that tutorial given is not tied to their development boards. You can apply the example given to any STM32 development boards as long as long the microcontroller core is supported by freertos. Else you have to do the porting yourself.

For the project source code given, maybe you need to change the IO port configuration to make the project workable.

Although there are some English tutorials on web, but there are basically not even one tutorial that provides spoon feed guidance. So this Chinese version is crucial for self learner and people who has no prior experience on RTOS.

Now, let have a look at the ARMFLY board, STM32-V5
The specification also quit amazing:
MCU:
STM32F407IGT6, 1M Flash, 192KRAM
Crystal:
25MHz for main clock, 32768 for RTC
Additional Memory:
2M SRAM, 16M Nor Flash, 128M NADN Flash, 16KEEPROM,8M Flash (No idea for what purpose)
Connectors:
1 Micro SD, 2 CAN2.0, 1 RS232, 1 RS485, 1 USB device, 1 USB host, 2 LAN, Audio, PS 2
ICs:
CODEC (WM8978), AM/FM (Si4730), accelerometer and MEMS gyro (MPU6050), Magnetometer (HMC5883L), Light sensor (BH1750FVI), Barometer (BMP085)
Additional:
Infrared transmitter, Infrared receiver, 1 CR1220 battery, 4.3 inches TFT display

It also reserved some pin for modules, guess you just have to buy it. Basically, the on board ICs and connectors have provided a good learning environment as you do not need to scout for additional components and do your own wiring. Best of all, after sales technical support is available at their forum.

Download link for tutorials:
STM32F429: tutorial, source code
password:bs5g

STM32F407: tutorial, source code
password:8fi7

STM32F103: tutorial, source code
password: sy7f

password is required for download the source code.

Friday, July 8, 2016

Linux learning - References and some notes

Recently I just started the learning journey of Linux. I am a window person, and have been pampered by the user friendliness of window 7, window xp. Getting started in Linux - Ubuntu has been quit a challenge for me. Although Ubuntu come with GUI, but the settings and software installation must be done in command window.

Knowing some useful commands is crucial in Linux survival kits.

As always I like to take note the essential and almost important functions.
1. cd - always take note of your working directory. ~ is home. / is top level directory. .. is back on top one level.
2. ls - list out all the files.
3. sudo - work as administrator. If you have a command, that you are pretty sure it is working, but you see error. Add sudo in front of command.
4. esc - press esc to go to command part in editor.
5. :q - quit the editor.
6. :q! - quit the editor without saving any changes.
7. :x, :wq - save and exit editor.
8. tab - press tab to auto complete your folder/file name.
9. shift + insert - paste your sentences in ssh.
10. highlight - copy, double click to highlight sentences in command window.
11. mouse right click - paste your sentences in ssh.
12. mv - move the folder or change name.
13. cp - copy


Useful software:
1. tmux - terminal multiplexer, useful when ssh is in used.
2. samba - ssh with gui.
3. putty - ssh client.
4. mtputty - simpler and more convenient package of putty.

tmux tips:
- to enter tmux: tmux
- to attach a tmux session: tmux a -t 0, 0 is the tmux session
- to see tmux session: enter tmux first, then only type "tmux ls"
- to detached a tmux session: ctrl + a + d
- to split screen horizontally: (1) tmux selectp -t 0, (2) tmux splitw -h -p 50
- to split screen vertically: (1) tmux selectp -t 0, (2) tmux splitw -v -p 50

Useful links:
1. Vim Commands Cheat Sheet - Easy to understand description.
2. Unix/Linux Command Reference - List of commands printable version.
3. Linux function description -  Good explanation.



Monday, May 23, 2016

osa rtos - 3rd switch debounce

Switch debounce is a common problem faced when playing with digital circuit. It is a condition where single pressed by user would appears multiple presses.

Usual software method used to avoid this is by taking multiple samples at certain time interval.

 if (time_inverval == 10ms)          // run this function every 10ms  
 {  
      if (pin1 == HIGH)              // check the pin status  
      {  
           pin1_counter++;  
      }  
      else  
      {  
           pin1_counter--;  
      }  
      if (pin1_counter>=10)          // confirm the samples for 10 times  
      {  
           pin1_counter = 0;          // clear the pin1_counter after 10 samples  
           pin1_flag = 1;  
      }  
 } 

Or you can use extra diode and capacitor to filter out the debounce glitches as shown at labbookpages. The labbookpages actually shows solutions from A Switch Debouncer Circuit, Software Debouncing, to Digital Switch Debouncing, to Switch Debouncing ICs. Nevertheless, extra circuitry mean extra cost, it is better to settle everything in software. Only a few lines are needed.

This blog (or my osa rtos learning diary) is to show how to implement switch debounce in rtos. The solution is shown at osa rtos at "button" section but I never really understand it. So I decide to try it out.

From osa rtos website:

        //------------------------------------------------------------------------------
        //  Wait for key press (with debounce)
        //------------------------------------------------------------------------------
 
        do
        {
            OS_Cond_Wait(!pin_BUTTON);
            OS_Delay(40 ms);
        } while (pin_BUTTON);

The function use the OS_Cond_Wait to wait for button is pressed then delay it for 40ms to skip the debounce signal.

After that, wait for the key to be released.

        //------------------------------------------------------------------------------
        //  Wait for key release
        //------------------------------------------------------------------------------
 
        do
        {
            OS_Cond_Wait(pin_BUTTON);
            OS_Delay(40 ms);
        } while (!pin_BUTTON);
 
 
    }

The implementation is likely the same, so user source code should be placed in between "wait for key press" and "wait for key release" (I assume).

So I add one flag for button pressed, so my overall code for taskButton is as follow:


#ifndef TASK_BUTTON_H
#define TASK_BUTTON_H

#include <osa.h>
#include <p18cxxx.h>

#define mInitSW1()     {TRISBbits.TRISB0=1;}
#define mInitSW2()     {TRISBbits.TRISB1=1;}

#define mSW_1    PORTBbits.RB0
#define mSW_2    PORTBbits.RB1

extern unsigned char flag_button1;
extern unsigned char flag_button2;

void taskButton1(void);
void taskButton2(void);

#endif /* TASK_BUTTON_H */

The taskButton function is:


void taskButton1(void)
{
 mInitSW1();
 flag_button1 = 0;
 
    for (;;) {
 //------------------------------------------------------------------------------
 //  Wait for key press (with debounce)
 //------------------------------------------------------------------------------
        do
        {
            OS_Cond_Wait(!mSW_1);
            OS_Delay(2);   // delay 40 ms
        } while (mSW_1); 

 //------------------------------------------------------------------------------
 //  Raise a flag
 //------------------------------------------------------------------------------
  flag_button1 = 1;
 
 //------------------------------------------------------------------------------
 //  Wait for key release
 //------------------------------------------------------------------------------
 
        do
        {
            OS_Cond_Wait(mSW_1);
            OS_Delay(2);
        } while (!mSW_1);    
    }
}

I put a video to show how the whole program is working. The led blinking, 16x2 display and button.



Project file is downloadable at here.

Sunday, May 8, 2016

My Tools



For the past one year, I have been buying components, tools. It started by buying some development kits and modules, then some IC components and breadboard, when Taobao is promoting the 2rmb delivery fee to Malaysia, I bought a soldering station and multimeter. Along that, I am purchasing electronic components from Element14 and RS electronic for my design.

My room is very messy. Seeing the components boxes laying on the floor, the development kits are stacking in the drawer, and my tools are scattering here and there.

I decide to tidy up the room and just for fun I am showing current tools that I own.


TOOLS
Buy From
1.
31 in 1 electronic tool set
Taobao
2.
Test pen
Cytron
3.
Legendary PICKIT 2
Element14
4.
Tweezers
Taobao
5.
Rolson wire cutter
Ace Hardware
6.
Victor multimeter VC890C
Taobao
7.
Victor multimeter VC830L
Cytron
8.
Solder sucker
Taobao
9.
Kasadl soldering station KSD 936
Taobao

I just ordered some component boxes from Taobao, I will show my components arrangement in next post.

Friday, March 25, 2016

ADXL335 - Getting started

On the process on learning of pic18f, I like to start with existing code or hardware. So I like modules very much as my pcb design is still in the "room" of improving. I cant get the correct version until the 3rd or 4th version of pcb.

I have this three axis accelerometer breakout, bought from cytron (some time ago). It is the cheapest I can found. Since it is lying on my drawer and I am bored, I decide to test it.


Also, I have a soldering station which I bought from taobao 2 months ago, time to put it on test.

First, I align all the pin at the breadboard,

Then, I place the ADXL335 module on top the pin,


After switch on the soldering station, you need to wait until the red led indication on the soldering station went off, then the solder tip temperature is as set temperature. 
I verify it using vc890 multimeter.

My first try, it is really not bad. The soldering station really not bad, perform better than the 10 ringgit soldering iron that sold at jalan pasar. My soldering station only cost me 45 ringgit, really worth the money.

Actually I had tried popular brand of soldering station before like hakko, weller, goot, but I think this kasadi soldering station "soldering" performance is comparable to those top notch. Maybe the question lied on the robustness,  how long will it last before it break down. Last time, my 15 ringgit soldering iron from jalan pasar only been used for a few times, after leave it for few months, end of life.
Also, my lab weller soldering station is really robust, sometimes, we forgot to switch off it, leave it for two days, but it is still working great. 

I didnt dare to put test on the kasadi soldering station robustness, I handle it with cares, you should not expect much from cheap but working equipment.

Back to story, this is the soldered module
After I have finished solder all the pins, I realise that the top three pins are not necessary, just some dummy pads placed, no track connection to any component.

Now to the coding part, just the simple adc would be fine, c18 comes with some library on pic18f peripheral. However, my purpose is learning so I always look at existing code, datasheet, then start writing my own code.

It make the learning easier and your own code really suit your own need.
I go to c18 library file, copy the adc file out and start editing it for my own use.

In the end, I have only two functions 
- void ADC12_Init(void);
- int ADC12_ReadChannel(unsigned char channel);
which make it very convenient to use, but hard to modify settings (you have to edit the source code).
Overall, the settings of adc are quit general and easily applied to most conditions.

I supply the 5V to the ADXL335 module, it has on board regulator that regulate it to 3.3V. You can also supply the 3.3V to the ADXL335 module directly.

I have disassembly the connections so I have no output picture to show your guys. Nevertheless, the program have been tested and it is working fine.

In this program, the displayed value for X, Y, Z axis are adc value, I have no idea on the calibration (how to convert the adc value to angle using limited equipment). Maybe after some time of learning, trying and googling, I will post it up.

The project file is downloadable at link.



OSA rtos - 2nd

After able to run a simple led blinking using OSA rtos, I plan to integrate one display function ( lcd 16x2) and two push button (event triggered).

So I have added one additional task which is taskDisplay(), the main purpose of task display is showing the some simple words and display simple message when push button is pressed.

The OSAcfg.h file remain the same
 //------------------------------------------------------------------------------
// SYSTEM
//------------------------------------------------------------------------------
// Number of tasks that can be active at one time, two tasks for led blinking, one task for display
#define OS_TASKS               3
// Not using any fancy OS function, so "no priority" setting is set
#define OS_DISABLE_PRIORITY    


For the HD44780 driver, it is remain the same as previous tutorial, I didnt include the OS function in the HD44780 source file.
The development board I used directly ground the RW pin of HD44780, so it is only writeable (unable to implement OS_Wait() function).
I have to use the delay function to wait for HD44780 finishes the operation. The longest wait period is 2ms for HD44780 whereas the OS_Timer() interval is set to be 10ms. If I use one tick delay, it will be 10ms. Still reasonable to implement but I am lazy. After wasting 2ms out of 10ms, I still have 8ms which is a lot of time to do other stuffs, not to mention just simple led blinking.


 //------------------------------------------------------------------------------
// TASK DISPLAY header file
//------------------------------------------------------------------------------
#ifndef TASK_DISPLAY_H
#define TASK_DISPLAY_H

#include "hd44780.h"
#include <osa.h>

#define mInitSW1()   {TRISBbits.TRISB0=1;} // initialise the port direction to input
#define mInitSW2()   {TRISBbits.TRISB1=1;} // initialise the port direction to input

#define mSW_1 PORTBbits.RB0 // switch one
#define mSW_2 PORTBbits.RB1 // switch two

void taskDisplay(void);

#endif /* TASK_DISPLAY_H */

 //------------------------------------------------------------------------------
// TASK DISPLAY source file
//------------------------------------------------------------------------------
void taskDisplay(void)
{
mInitSW1();
mInitSW2();

        // initialize the LCD module is time consuming but it doesn't interfere with OS                                      // operation as OS only run the function above the forever loop on first time.                                          // After that, at each interval, it run the function inside forever loop.
        HD44780_Init();

        HD44780_GoToPoint(1,1);
        HD44780_WriteROMString("  - RTOS OSA -  ");
HD44780_GoToPoint(2,1);
        HD44780_WriteROMString("  -Simple Demo- ");

       for (;;) {
  // wait for switch to be pressed, bad implementation as I do not consider                                               // the switch debounce or noise interference.
        OS_Wait(mSW_1==0);

HD44780_GoToPoint(2,1);


         // String written when switch one is pressed, I make it to be 16 characters so                                          // that I dont have to clear any character left at display.
        HD44780_WriteROMString("Button 1 Pressed");  

  OS_Wait(mSW_2==0);
HD44780_GoToPoint(2,1);

         // String written when switch 2 is pressed.
        HD44780_WriteROMString("Button 2 Pressed");  
    }
}



At the main file, create the task mentioned.
 //------------------------------------------------------------------------------
// CREATE TASK
//------------------------------------------------------------------------------
// Priority zero, all task has equal priority
    OS_Task_Create(0, taskLED1);
    OS_Task_Create(0, taskLED2);
    OS_Task_Create(0, taskDisplay);

Here is the output display,

After initialisation,

After switch one is pressed,

The project file is downloaded at link.



Thursday, February 25, 2016

OSA rtos - First try

Task scheduler has been a very convenient way to manage the task flow without having multiple flags  raised at certain time interval. By optimising the timer interrupt on MCU, one can control the task at almost precise timing but as the tasks get complicated and larger, the readability and maintenance effort also significantly increased.

RTOS - real time operating system is the answer to all these hardships. 
Many people are doubt on using rtos on small mcu as the ram consumption is significantly higher and reliability/support of open source rtos has shunt most novice away.

OSA rtos is chosen for this study because it is using the cooperative scheduling and the next running task is chosen based on priority after the task before run to completion. So the ram consumption for each task is fixed and small.

I will be using PIC18f4553 and mplab c18, so the ram is 4 bytes per task which is small. Also, by enable a full rtos function - only 1214 bytes of rom and 16 bytes of ram are needed. It is small scale enough to implement an adequate system on PIC18f.

OSA rtos has stop it's development but it is still worth trying for hobby project. The OSA seem to be very popular among Russian developers and the tutorials are much complete in Russian language compared with English.

After spending much time on reading and trying to implement the OSA rtos on pic18f4553, I make some progress. I was able to make two leds blinking at different rates. It is simple but I will employ different rtos functions later.

At the introduction part, there are certain limitation on compiler that need cautions such as:
For MICROCHIP C18
-You can't use procedural abstraction optimization
-You can't use Stack Model: Multi-bank

It is not a big deal as you are not enjoying these benefits when using the free version of c18.

One thing that shunt people away is the step to step guide to implement the OSA on pic18f and very few tutorials or examples which are using c18 compiler.

So in this tutorial, I will show a step by step guide to compile in c18.
note: I am using pic18f4553, c18 version 3.47 and mplab v8.92.
1. First step is download the OSA. There are several implementation examples in this link.
2. Secondly, create a mplab project folder and copy the whole OSA folder inside the mplab project folder.

3. Add the necessary header file of OSA. 
Only osa.c is suffice but I add in osa.h for ease of troubleshooting. OSAcfg,h is the settings file which can be referred at this document. Although there is a GUI software to choose the OSA settings but it doesn't work on win 7 (or just maybe my computer).

4. Right right at the project name "osa.mcp" and choose Build Options. At the Directories, click on the "include search path" and add in the osa folder in the search path.  

5. Now, go to MPLAB C18 and type in "disable procedural abstraction optimization" -Opa- . 
If "-Opa-" instruction is at the settings there, then just maintain it as it is. (dont change anything).

6. Choose the single bank model at MPLAB C18 -> Memory Model -> Stack Model as shown below

7. To configure the OSAcfg.h, I will be blinking two leds, so OS_TASKS = 2; simple blinking cant show the task priority so OS_DISABLE_PRIORITY. The OS_ENABLE_TTIMERS and OS_ENABLE_TIMER are defined to enable OS_delay function.

8. My blinking task, led1 with 1 second blinking rate; led2 with 2 second blinking rate.

9. The OS tick increase every 10 ms. The timer interrupt setting is as follow (You can refer to my blog on setting the timer interrupt)
10. The main routine is as follow:
Actually, I havent study the OS_EI() function, I suspect that I can skip some redundant code.

11. You can check the task address using the debugger mode. You can check whether the task is switching or not.

Basically that all, this is the simple implementation.
The whole project zip file can be downloaded at here.