Good day!
In my [first article about the exercise bike I wrote that I was planning to display the data of my computer on the screen of my smartphone However due to the temporary absence of FRDM-KW41ZFRDM-KW41Z board equipped with Bluetooth module which is necessary for transferring information to a smartphone I can't do it In order to temporarily solve this problem I made a strategic decision until I get a board equipped with Bluetooth I will use the LCD display as a data output device which we will talk about in today's article
At work, we usually use graphic displays, for example [MT-1286J], but I do not need such a display for the exercise bike. Best I'd be suited with a display with a built-in character generator, for example [MT-16S2H]. In my home workshop I found a display of the kind (though made in China, but more on that later) and I will use it.
Connection of the LCD
The display I chose is equipped with a chip-driver HD44780, well-known to all embedded software developers. There are many "classic" schemes of its connection to the microcontroller. Let's onsider the two most interesting.
1. The standard scheme with 4-bit data bus. This connection option does not require any additional components except the resistor to adjust contrast. Let's take a look at the assignments of our display lines:
- A, K – anode and cathode of the LCD back-light;
- V0 – contrast calibration;
- DB4 – DB7 – 4-bit data bus;
- RS – selection between data and command mode;
- E – strob signal.
As you can see, 6 lines are connected to the microcontroller. If instead of a 4-bit data bus we would use a faster 8-bit data bus, it would require 10 lines.
2. Scheme with additional driver and I2C interface. To reduce the number of lines coming to the microcontroller, you can use the I/O expander IC. When using the I2C interface, you can connect the display to the MCU with just two wires!
In 2011, I have [already experimented] with a similar scheme, then I used the NXP chip [PCA9675PW The solution mentioned had a number of minor drawbacks so I updated the scheme a little bit and now it is great to use it with FRDM-K64FFRDM-K64F
Simple LCD driver
For the display, I've written a small library that includes three functions:
- lcd::init() – initialization of the LCD;
- lcd:send_two_bytes(one, two) – send data/command to the LCD;
- lcd::write(pos, value) – write text or value on the LCD.
Display initialization function lcd::init performs the following actions:
- setting the I2C interface to work in the default master-mode;
- initial display setting (backlight on, cursor off, etc.)
To send data to the display, a tricky function lcd::send_two_bytes is used, which transmits to the I2C driver the data intended for the display, and the transfer is carried out in two stages: first, the data is transmitted with the installed strobe signal, and then the same data, but with the strobe signal removed, this is necessary in order to write the data frame to the memory of the chip HD44780.
The function lcd::write has two options: one for text output and the second for display of float type variable. In addition, I have provided the ability to output data to different "sectors" of the display. I did this to:
- write the name of the parameter #1 (for example, speed) in the upper left corner;
- write the value of the parameter #1 in the lower left corner;
- write the name of the parameter #2 (for example, distance) in the upper right corner;
- write the value of the parameter #2 in the lower right corner;
In today's article I will mention only a small piece of code that describes an example of using my driver. The driver itself can be found in the [official project repository].
// definitions #define EXPERIMENT 1 // main function of the program int main(void) { // system init gpio::init(); #if (TENSION_MODE == 2) adc::init(); #endif BOARD_BootClockRUN(); // LCD init lcd::init(); // write text to LCD lcd::write(TEXT_UP_LEFT, "Speed"); lcd::write(TEXT_UP_RIGHT, "Distance"); lcd::write(TEXT_DOWN_CENTER, "Hello Element14!"); // exit from the program (if it's an experiment) #if (EXPERIMENT != 0) return 0; #endif // if it isn't an experiment then - start RTOS threads osThreadCreate (osThread(sensors), NULL); osThreadCreate (osThread(indication), NULL); // empty infinity loop for(;;) { osSignalWait(0, osWaitForever); } }
The result of the program is presented in the photo:
Using of the LCD in exercise bike computer firmware
Now when we have the display driver, it's time to use it for its intended purpose! I added the function call lcd::write to the indication RTOS thread: now I put to the display values of speed and distance. During the experiments it was found out that the lcd::write function works rather slowly, for this reason I decided to call it not every RTOS clock cycle (10ms), but every 100 clock cycles. After all improvements, the code of the indication thread looks as follows:
static void indication(void const *args); osThreadDef(indication, osPriorityNormal, 1, 0); static void indication(void const *args) { static int counts = 0; 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 counts++; if (counts > 10) { // output data to LCD lcd::write(TEXT_DOWN_LEFT, (float)speed); lcd::write(TEXT_DOWN_RIGHT, (float)distance); counts = 0; } } }
As a demonstration of the results, I offer a photo of my computer installed on the bike (photo taken during training).
Conclusion
Today I made an important strategic decision to continue the project despite the lack of key components And as you can see even without FRDM-KW41ZFRDM-KW41Z my project looks more and more like a real bike computer
Before I finish my today's post, I'd like to address the community: during the experiments I had a little problem with the LCD display based on the HD44780 controller, if you have such a display — please take part in [voting] it will help me a lot in the project!
Thanks for reading and have a nice day!
Top Comments