Good day!
Today I want to devote my article to programming, namely the implementation of the basic functions of a bike computer, the formulas for which we defined in the two previous articles. However, how can I program something if this is something I do not have? The answer is simple – to perform castling, in my case the king’s role is played by the FRDM-KW41Z still expected by me, and the rook’s one – by the FRDM-K64F!
My choice, I think, is obvious, FRDM-K64F is the only FRDM series board that I had available. If everything with the hardware was solved itself, as for the software it was not so simple – the main question arose before me was choosing the IDE.
Integrated Development Environment
There are many different IDEs compatible with the FRDM family, but for various reasons I only consider three of them:
- mBed is the cloud IDE I used in my previous project [link];
- NXP MCUExpresso – proprietary IDE from NXP;
- Keil uVision MDK – this environment I use in my professional work.
Initially, I planned to give preference to mBed, but there was a problem – mBed still does not officially support working with Bluetooth for the FRDM-KW41Z board [link]. It upset me a bit, because I had high hopes for it.
The brand IDE from NXP, called MCUExpresso, it seems to me I have used one, but then it had a different name, and yet it was in 2011, since then the environment has clearly changed. I view this IDE as a backup option, in case I can not solve my tasks by any other means.
The main variant of the IDE that I'm considering for the “Smart exercise bike computer project” is Keil uVision MDK. I have been using this program for several years in my professional work and I am very glad that this environment supports working with the FRDM family. Unfortunately, Keil's capabilities in conjunction with FRDM are somewhat limited, but I hope I can overcome all the difficulties associated with this.
First experiment with Keil
I want to remind you that I got a FRDM-K64F within the Road Test, held in 2015 year and it turned out that the work of the old revision of the board together with the modern Keil version and Windows 10 requires some cunning manipulations:
- it turned out that the bootloader flashed in my board was not compatible with Windows 10, this problem was solved [by this article];
- then it turned out that the restored bootloader is not compatible with Keil, and for normal operation I had to flash the board again, this time by firmware [DAPLink];
- in conclusion, it turned out that Keil needs to manually register the Programming Algorithm and only after that I finally got it working!
At this point, I was able to flash one of the demo examples (gpio_led_output) on FRDM-K64F board. The example successfully worked and for this reason I took its structure for my further experiments.
First exercise bike firmware
Taking as a basis the program gpio_led_output, I decided to start writing a program that implements the following features:
- Data processing by reed-sensor methods described in article [week 2].
- Distance and speed calculation by algorithm from [week 3].
- Indication of the distance (D) of 250 m by green LED.
- Indication of movement at speeds (V) more then 32 km/h by red LED.
- Sensor status processing and information displaying on separate RTOS threads.
As an RTOS, I chose Keil RTX for the reason that I am using this RTOS in my current commercial project. RTOS is necessary for me because the functionality of the program will gradually expand and at some point it will be impossible without RTOS to simultaneously process sensor data, transfer data via Bluetooth and display information on the display.
My program now consists of two parts:
- main program (main.cpp);
- input / output function library (gpio.cpp и gpio.h).
Let's look in detail at the file main.cpp (link to full sources will be given at the end of the article).
1. Main-function. This function performs:
- initialization of equipment (GPIO lines and clock system);
- starting RTOS threads (sensors and indication);
- empty infinity loop.
int main(void) { // system init gpio::init(); BOARD_BootClockRUN(); // starting of RTOS threads osThreadCreate (osThread(sensors), NULL); osThreadCreate (osThread(indication), NULL); // empty infinity loop for(;;) { osSignalWait(0, osWaitForever); } }
2. Sensors thread. This thread performs read-sensor processing and speed and distance calculations:
- function gpio::read(REED) read state of the sensor and is used to determine the passage of the magnet near the sensor;
- pause osDelay(10) provides protection from bouncing (thanks to neilk for the reminder!)
- variable count is used to count the number of pedal rotations;
- osKernelSysTick() function is used to determine the time required for one pedal turn;
- the clc_speed variable is used to store the measured speed value and is written to the speed variable, if the speed is within the range of acceptable values (in my example [5..80] km/h);
- function gear_to_tension used to determine Te_a(G);
- function rotation_to_distance is used to determine D(G, N);
- function wavelength_to_speed is used to determine V(G, t), where t = 60 / W.
// first thread: for work with indication static void sensors(void const *args); osThreadDef(sensors, osPriorityNormal, 1, 0); static void sensors(void const *args) { char state = 0; // current state of reed unsigned int count = 0; // count of rotations unsigned int start_time = 0; // start time for speed calculation unsigned int stop_time = 0; // stop time for speed calculation float clc_speed = 0; // calculated speed // calculation of the distance (rotation count) and wavelength for (;;) { if (!state && gpio::read(REED)) { stop_time = osKernelSysTick() - start_time; stop_time = stop_time / osKernelSysTickMicroSec(1000); osDelay(10); state = 1; count++; } else if (state && !gpio::read(REED)) { start_time = osKernelSysTick(); osDelay(10); state = 0; } // convert rotation count to distance [km] distance = rotation_to_distance(count, gear); // convert wavelength [ms] to speed [km/h] clc_speed = wavelength_to_speed(stop_time, gear); if (clc_speed >= 5.0f && clc_speed <= 80.0f) speed = wavelength_to_speed(stop_time, gear); else speed = 0; } }
Important: I assumed that the pulse duration of the reed-sensor at the time of the magnet passing is negligible compared to the wavelength, but this is not quite true. I remember this and will make the necessary corrections to the code in the near future.
3. Indication thread. This thread performs the led indication function:
- red LED lights up if rider has traveled a distance (D) more than 250 m;
- green LED lights up if rider turns pedals with speed (V) more then 32 km/h;
- blue LED lights up when the SW3 button is pressed (used for testing).
// second thread: for work with sensors static void indication(void const *args); osThreadDef(indication, osPriorityNormal, 1, 0); static void indication(void const *args) { for (;;) { gpio::write(GREEN, distance > 0.25f); // LED is turned on if we passed 250 m gpio::write(RED, speed > 32.0f); // LED is turned on if we riding on 32 km/h gpio::write(BLUE, gpio::read(SW3)); // LED is truned on and off by SW3 switch } }
While writing the program, I faced the problem of GPIO lines initialization, it turned out that NXP has a special program with a GUI, which is specially designed for the initial configuration of all lines used in the project. This program is called MCUExpresso Config and is available via [link].
Demonstration of work
After I finished writing my program, came the time to try it out. In my opinion, the best way to describe the results of the tests will be just show a short video:
Yes, I understand that pedaling, holding the camera and speaking a foreign language simultaneously is a bad idea, but unfortunately I have no assistant and I have to do everything myself
Conclusion
Today I finally managed to make sure that all the calculations performed at previous stages were not in vain! My first implementation of the bike computer showed itself from the best side.
Unfortunately, without the FRDM-KW41Z board, I will not be able to continue the project, for this reason, I temporarily stop publishing my weekly blogs until the parcel from Element14 arrives. To make sure you are not bored, I created a repository of the Smart exercise bike computer project on the Bitbucket portal where you can now track the status of my project long before the next blog is released!
Official Smart exercise bike computer repository: [link]
Thanks for reading and have a nice day!
Top Comments