MASARYK U N I V E R S I T Y FACULTY OF INFORMATICS loT Display Technologies Bachelor's Thesis KRISTIÁN ORAVEC Brno, Spring 2024 MASARYK U N I V E R S I T Y FACULTY OF INFORMATICS loT Display Technologies Bachelor's Thesis KRISTIÁN ORAVEC Advisor: doc. Mgr. Karel Slavíček, Ph.D. Department of Computer Systems and Communications Brno, Spring 2024 Declaration Hereby I declare that this paper is my original authorial work, which I have worked out on my own. A l l sources, references, and literature used or excerpted during elaboration of this work are properly cited and listed in complete reference to the due source. Kristián Oravec Advisor: doc. Mgr. Karel Slavíček, Ph.D. iii Acknowledgements I want to thank my supervisor, doc. Mgr. Karel Slavíček, Ph.D., for his valuable advice, hours spent on consultations, and, most importantly, the opportunity to learn about hardware. I also want to thank my family and friends for their mental support and me for not giving up and finishing (hopefully) the bachelor thesis successfully. iv Abstract The bachelor thesis aims to create materials for the expansion of teaching in the field of IoT at the Faculty of Informatics of Masaryk University in the area of display devices for IoT. The theoretical part contains explanations and descriptions of individual displays, their respective drivers, and the principle of operation. The main benefit of this work is laboratory tasks, where students can use the acquired theoretical knowledge. The tasks are diverse, with an effort to use as few libraries as possible so the student can try embedded development. Part of the attachment is a ZIP file with sample solutions of laboratory exercises. Keywords IoT, display methods, Arduino IDE, display methods, STM32 Blue Pill v Contents Introduction 1 1 Laboratory exercises using STM32 Blue Pill with Arduino interface 2 1.1 Terms 2 1.1.1 Platform 2 1.1.2 Development board 2 1.2 Comparison of STM32 and Arduino 3 1.2.1 Advantages and disadvantages of the STM32F103 board 4 1.2.2 ArduinoIDE vs STM32CubeIDE 5 1.3 Project examples available on the Internet 6 2 STM32F103C8T6 "Blue Pill" overview" 7 2.1 STM32F103C8T6 "Blue Pill" 7 2.2 Cores 9 2.3 Upload methods 10 2.3.1 ST-Link V2 10 2.3.2 USB 11 2.3.3 UART 12 2.4 The most frequent errors 13 3 Displays used in lab exercises 14 3.1 Displays overview 14 3.2 L E D diode 14 3.3 NEOPIXEL WS2812 15 3.4 LED 4 7-SEGMENT DISPLAY 17 3.5 L E D MATRIX M A X 7219 18 3.6 L C D 16x2 18 3.7 OLED 0.96 SHI 106 19 3.8 Open-Smart 2.4" 320x240 TFT Touchscreen SPFD5408 . 21 3.9 Waveshare 1.54" 200x200 ePaper 22 4 Laboratory exercises 24 4.1 L E D 24 4.2 LED with P W M 28 vi 4.3 Neopixel 31 4.4 4-7 segment display 34 4.5 Hitachi HD44780 L C D 16x2 I2C 38 4.6 Hitachi HD44780 42 4.7 OLED SPISH1106 48 4.8 OLED SH110612C 55 4.9 L E D MATRIX M A X 7219 57 4.10 Waveshare E-paper 200x200 1.54 inch 60 4.11 Open-Smart 2.4" 320x240 TFT Touchscreen SPFD5408 . 63 5 Conclusion 65 Bibliography 66 vii List of Tables 1.1 STM32 Blue Pill vs Arduino Nano [2] 5 4.1 Hitachi HD44780 pinout [37] 43 viii List of Figures 1.1 STM32 Blue Pill development board [1] 3 2.1 BluePill pinout [2] 8 2.2 The config of ST-Link V2 should be more or less same . . 12 2.3 Steps to get Serial Number 14 3.1 LED and it's inner working parts [6] 15 3.2 Neopixel stripe [8] 16 3.3 Data transmission method in cascade mode [10] 16 3.4 4-7 segment display and its pinout [11] 17 3.5 Matrix LED [12] 18 3.6 L C D 16x2 with I2C controller [14] 19 3.7 OLED with I2C controller. Notice 4 pins[16] 20 3.8 OLED with SPI controller. Notice 6 pins [17] 20 3.9 TFT [19] 21 3.10 1.54 inch e-paper model [11] 22 4.1 Serial monitor overview 26 4.2 Trimmer [31] 29 4.3 Potentiometer 30 4.4 Thermometer at 27 °C 33 4.5 4-7 segment display and its pinout [11] 35 4.6 Number 2 with its common cathode segments [35] . . . . 36 4.7 Dinosaur game 40 4.8 Hitachi HD44780 commands [38] 45 4.9 Rotary encoder principle of working [42] 51 4.10 Alarm countdown timer 54 4.11 Matrix 8x8 display smiley face [44] 58 4.12 Pong 60 ix Introduction Almost every device in the computer industry uses a display device whether it's L E D diodes indicating disk writing or huge advertising displays. The IoT segment is no different: it provides various display devices. The problem is that at the time of writing this thesis, I could not find any overview of commonly used display devices. There is no description of the principles of how to operate individual display devices or laboratory exercises where one would try out different options and generally learn to work with various display programming interfaces. M y goal was to take display devices, find functional libraries for operating the devices, and possibly modify them. Based on that, I prepared laboratory exercises interesting for newcomers to IoT and simultaneously, complex enough that even a more experienced programmer would learn something new. Various display devices of varying complexity are used: L E D diodes, Matrix L E D display, 7-segment display, Hitachi clone L C D 16x2, OLED, and TFT display. In Chapter 1, the platform and development board choice are explained. Chapter 2 discusses the development board, the description of the most essential functionality, and the selection of a suitable core for programming the board. Finally, this chapter presents the most common development problems and their solutions. Chapter 3 includes a short description and principle of operation of the display devices used in the thesis. This knowledge should help when working on laboratory exercises, which is the content of Chapter 4. The Arduino IDE and the C language were used during the laboratory exercise development. The Appendix lab_exercises_solution.zip contains a sample solution of laboratory works. The secondary product of the thesis is the testing and modification of drivers for display devices and a summary of solutions to problems with the development board. This result should facilitate the further creation of laboratory exercises and the expansion of the university's IoT courses. 1 1 Development of laboratory exercises using STM32 Blue Pill with Arduino interface In this chapter, I present the basic terms used throughout the thesis (see 1.1), the platforms on which the laboratory exercises were developed (see 1.2), and the current state of laboratory exercises available for free on the Internet (see 1.3). 1.1 Terms In this section, I explain the key terms used throughout the thesis: platform and development board. 1.1.1 Platform The most general term that includes everything related to a product line is platform. For the STM32 product line, the platform is: • an integrated STM32CubeIDE development environment designed for professional development of STM32 software • a software interface for STM32 • STM32 series M C U , such as the STM32F103C8T6 (used in the development board "Blue Pill", also used in the thesis) or STM32F411CEU6 (used in the development board "Black Pill"). The platform provides mutual compatibility of the development board's software interface. The solution - software interface - is integrated into some common integrated environment - drivers. The term platform is sometimes substituted by ecosystem; the terms are used interchangeably. 1.1.2 Development board Development board is a piece of hardware - usually a board fitted with a microcontroller with output pins for communication with the outside world. Its purpose is primarily educational, to learn how to work with a microprocessor. 2 i . LABORATORY EXERCISES USING S T M 3 2 BLUE PILL WITH ARDUINO INTERFACE The development boards have no display. Usually, the only display element is an LED that indicates basic states. For Blue Pill, these basic states are loading of the program or its failure. The board is not hidden in any packaging; it is intended for work in laboratory conditions. The physical interface of the development board usually provides various ports for peripheral communication with the program on the chip and a micro USB port for programming the Blue Pill. At the same time, the USB port can be used for debugging. The Blue Pill development board (shown in Figure 1.1) is an example of a powerful and cheap development board. Laboratory exercises were also developed and tested using this board. Figure 1.1: STM32 Blue Pill development board [1] 1.2 Comparison of STM32 and Arduino Arduino is a platform that offers software support - mainly Arduino IDE (Integrated Development Environment), libraries, and software interface for working with hardware peripherals and development 3 i . LABORATORY EXERCISES USING S T M 3 2 BLUE PILL WITH ARDUINO INTERFACE boards, for example, Arduino U N O or Arduino MEGA. Boards from Arduino use M C U s made by Atmel - Atmega. Arduino U N O use Atmega328, Arduino M E G A use Atmega2560. Both of them use 8-bit architecture. Arduino IDE provides a simple code editor and environment for writing and launching code on the development board. Using the Arduino IDE is simple enough for a complete beginner and, at the same time, provides the most important functionality for development on a development board. Thanks to a large and active Arduino open-source community and due to the widespread use of STM32 in industry, the popularity of STM32 development boards has resulted in many implementations of the Arduino software interface on various STM32 development boards. 1.2.1 Advantages and disadvantages of the STM32F103 board The fundamental advantage of the STM32F103 platform is its performance and low price. There are many development boards with an STM32F103 microcontroller - from cheap clones to professional variants. The Arduino development boards are more expensive than STM32F103. There are cheap clones of the Arduino boards but the processors on Arduino boards are significantly slower than the price equivalent from the STM32 family. Table 1.1 compares Blue Pill and Arduino Nano. The cost is more or less the same, but the hardware capabilities of Blue Pill are much more impressive. The size of the boards also plays a significant role. As a rule, a smaller board is better since built-in devices (such as cameras, printers, or routers) usually do not have much space available. In some cases, a device may not utilize all of the pins on the board, resulting in wasted space and increased costs. One disadvantage of the STM32 platform is its problematic compatibility with the Arduino platform. The open-source community and STMicroelectronics1 itself officially support a wide range of development boards, but the support of peripherals lags; this problem is also manifested when working with display devices. 1. the company developing of STM32 4 i . LABORATORY EXERCISES USING S T M 3 2 BLUE PILL WITH ARDUINO INTERFACE Table 1.1: STM32 Blue Pill vs Arduino Nano [2] SPECS/BOARD Blue Pill ARDUINO Nano Number of cores 1 1 Architecture 32 Bit 8 Bit C P U Frequency 72 M H z 16 M H z WiFi N O N O BLUETOOTH N O N O R A M 20 KB 2 K B F L A S H 64KB 32KB GPIO Pins 37 14 Busses SPI, I2C, UART, C A N SPI, I2C, UART A D C Pins 10 6 DAC Pins 0 0 The current state of STM32 platform is that with some effort, one can find a working driver for most display devices. When a driver is not available, it is possible to create it. This approach can be even faster than searching for an existing driver. Moreover, some of the existing drivers do not work out-of-the-box and need to be modified. Due to lack of easy-to-use drivers, STM32 is not a good platform for beginners in programming, unlike Arduino. 1.2.2 ArduinoIDE vs STM32CubeIDE Like Arduino, STM32 has an integrated development environment. It is called STM32CubeIDE, and it's an enterprise editor. It has many more options and works significantly better in cooperation with STM32 boards than Arduino IDE. (Note that the cooperation is seamless only with the original boards, clones of the STM32 boards refuse to cooperate with STM32CubeIDE.) Still, it has the typical disadvantages of professional editors - it is complicated, complex, and rather highly hardware demanding, unlike Arduino IDE. The Arduino IDE provides a code editor, an Arduino library, an integrated third-party library installer, and a serial connection to the board for possible code debugging. 5 i . LABORATORY EXERCISES USING S T M 3 2 BLUE PILL WITH ARDUINO INTERFACE Due to the simplicity of the Arduino IDE and the available tutorials on the official Arduino site, a student will learn to work with the Arduino IDE much faster than with the STM32CubeIDE. I decided to combine STM32 and Arduino because STM32 offers development boards with a better price-performance ratio, but Arduino has a more suitable IDE for learning purposes. 1.3 Project examples available on the Internet Project examples available online for free are of poor quality. These project examples often use libraries and are programmed with doubtful code quality: the entire program logic in one function is no exception. The code usually lacks documentation. Another issue with higher-quality project examples is that those on the internet are mostly processed as an article, not an assignment. The authors explain the principle of the code in detail but do not give much space for the reader to process the work themselves. There are no sub-tasks, explanations of basic concepts, and space for the reader's creativity. What I tried to create are laboratory exercises. Laboratory exercises in imaging devices are tasks that explain the issue and subtasks intended to practice working with the selected imaging device. Each exercise presents the relevant driver functionalities and device operation principles, or at least references the relevant documentation. 6 2 STM32F103C8T6 "Blue Pill" overview" This chapter aims to present the STM32F103C8T6 device (hereinafter referred to as Blue Pill), for which the tasks, presentation of "Cores" used in tasks, and drivers for uploading and debugging source code. The chapter closes with the problems I encountered during development and their solutions. 2.1 STM32F103C8T6 "Blue Pill" One of the many boards equipped with an M C U1 , STM32F103C8 is a very affordable chip with a processor based on the architecture. A R M Cortex-M3 [3]. I cannot forget its professional use in the development of embedded systems. Its integration with the Arduino IDE is not without problems; sometimes, finding a suitable driver for a peripheral is impossible. Then, it is appropriate to consider whether writing your driver for the peripheral is easier. The next chapter will introduce the board and its most important functionality. Pinout Now, I introduce the most essential information regarding the Blue Pill pinout. A l l input and output are handled through the so-called GPIO pin. It has no specific function. Its function can be reprogrammed by software. Here is a list of most common pins. • Input/output pins - (PA0-PA15), (PB0-PB15), (PC13-PC15) GPIO pins • Analog pins - orange ones ADCO-9 (PA0-PA7, PBO-1) are socalled analog pins. So they have an A D C - Analog Digital Converter and can distinguish up to 4096 states, which means that it can convert an analog signal, i.e., distribute the voltage to 4096 discrete values. For example, 3V3 / 4096 = 0.805 mV, so the smallest distinguishable analog step is 0.805 m V [4] 1. Microcontroller unit 7 2. S T M 3 2 F 1 0 3 C 8 T 6 "BLUE PILL" OVERVIEW" RESET button PC13 LED P W R LED Figure 2.1: BluePill pinout [2] • PWM pins - Pins marked with a tilde (~) are so-called P W M pins (e.g., PAO, PA1 ..). Pulse Width Modulation mimics an analog signal by being able to modify the width of the signal. • I2C pins - SCL and SDA are I2C pins - serial data transfer protocol. Pair of 212C pins - I2C1 f.e. can hold up to 127 devices. • Peripheral pin power supplies - 5V provides 5V power for peripherals, 3V3 3.3v power. G N D is the OV reference level for the input voltage 8 2. S T M 3 2 F 1 0 3 C 8 T 6 "BLUE PILL" OVERVIEW" • ST-Link V2 pins - Provides an interface for the ST-Link V2 programmer. You already know 3V3 and GND, but in this case, the 3V3 pin powers the entire board with the programmer. But the new pins are SWDIO and SWCLK. They are used for serials. ST-Link V2 communication. Loads the program into the Flash memory of the Blue Pill. • SPI pins - 2 SPI interfaces are available, SPI2: PB12-PB15 and SPI 1: PA15, PB3-5 and PA4-PA7. SCK1 pin determines the agreed frequency based on which the Master, which in our case is the Blue Pill, sends data to the Slave (e.g., OLED display with SPI support). It sends itself to the MOSI pin (Master out(put) slave in(put)). data. • PWR LED - lights up red when the Blue Pill is connected to the electricity • PC13 LED - You will most often encounter it when testing the upload of a program to flash memory. The program switches the diode on and off at regular intervals, which causes flashing. Less commonly, this serves as a run-time error indicator. For example, the L E D flashes quickly in case of heap overflow Blue Pill runs out of flash memory. • USB - for debugging via Serial monitor and board programming. It has a huge advantage in the ease of connection. It also provides power for the entire Blue Pill. The disadvantage is that the Blue Pill does not come with an Arduino Ready bootloader, and it will be necessary to upload a suitable bootloader. • Reset button - restarts the Blue Pill • Boot pins - By setting the Boot pins, you can set what type of memory the Blue Pill should boot from. 2.2 Cores They are implementations of the system libraries for the Arduino interface and are necessary for programming in the Arduino IDE. During development, I came across these 2 Cores for Blue Pill: 9 2. S T M 3 2 F 1 0 3 C 8 T 6 "BLUE PILL" OVERVIEW" • Arduino Core STM32 - official core, supports a wide range of STM32 development boards. Its launch settings are more customizable and less foolproof, so I don't recommend it for beginners unless necessary. There is one laboratory exercise that requires this core. 2 • Arduino STM32 - unofficial core, also known as "Roger Clark's core," I recommend using when solving tasks (unless I warn you otherwise). It does not support a wide range of STM32 development boards as the official core, but it's less complicated to work with than the official core.3 2.3 Upload methods You have two options for uploading the code: USB or ST-Link V2. Unfortunately, only USB can debug via Serial Monitor. I strongly recommend first installing ST-Link V2 and trying to use it to upload some example programs provided by Arduino IDE. This will make sure that both the Blue Pill and the programmer work. You can then try to install USB support. 2.3.1 ST-Link V2 It is a clone of the original ST-Link V2 from STMicroelectronics. Powering the Blue Pill with 3.3V energy is possible, but the problem arises with peripherals that need more energy, such as LCD. The L E D light signals the status. A steady red light means it communicates with the computer, and everything is fine. A blinking red light means no established communication - a missing driver or ST-Link is not connected to the PC. I only came across an alternation of flashing blue and red lights. While flashing the bootloader. Blue Pill, unfortunately, 2. More information about the official STM32 core can be found here: h t t p s : //github.com/stm32duino/Arduino_Core_STM32 3. More information about Roger Clark's core can be found here: https: //github .com/rogerclarkmelbourne/Arduino_STM32 10 2. S T M 3 2 F 1 0 3 C 8 T 6 "BLUE PILL" OVERVIEW" only provides program uploading to flash memory via STLINK V2; debugging is impossible. 4 2.3.2 USB It is the most convenient option but also the least reliable. Connecting a USB cable to a computer allows you to upload data and debug while simultaneously providing enough power for various peripheral devices. Its installation is a bit longer than ST-Link V2.1 assume you have familiarized yourself with the ST-Link V2 programmer, installed Roger Clark Core, and tried uploading the example code from the Arduino IDE. Unfortunately, the instructions included in the documentation were not the most suitable and I am attaching a tried-and-tested guide. Install guide 1. Download the appropriate bootloader to the development board, in our case generic_boot_20_pcl3.bin 5 2. it is necessary to flash the Blue Pill using ST-Link V2 and STM32CubeProg 6 3. set BOOTO jumper to 1 and BOOT1 jumper to 0. This will set booting from System Memory. At the same time, it allows us to flash the bootloader [5] 4. Connect ST-Link V2 to Blue Pill and P C and open the bin file generic_boot_20_pcl3.bin. The ST-Link V2 configuration should roughly match. Ensure that the starting address is 0x08000000, the size is 0x400, and the data width is 32 bits. These are the default values. 5. Click on generic_boot_20_pcl3.bin tab and Press Download 4. a link to the driver: https://www.st.com/en/development-tools/stsw-lin k009.html 5. a link to the bootloader: https: //github. com/rogerclarkmelbourne/STM32 duino-bootloader/tree/master/binaries 6. further information can be found here: https: //www. st. com/en/developmen t-tools/stm32cubeprog.html 11 2. S T M 3 2 F 1 0 3 C 8 T 6 "BLUE PILL" OVERVIEW" il MJtLubeHrccji'em ner 0 Data Information Notice UiSM | Memory & File editing generic_boot20_pc13.bin Address I OkDGOOOOOO » I Size 0x400 a width 32-bit • Find Data Ox No data to display Log 15:19:03 Time elapsed during download operation: 00:00:01.355 15:19:15 Erroi: Unable to jet tore ID 15:19:15 Error Unable to gettort ID 15:19:15 Error: Unable to gettöre-ID 1519:15 Warning Connect to device J.i414 s lo:t 15:19:15 Disconnected from device, 13:53:40 URccnn=ctb" nc:e is dein:d ",ith :h= HWrst reset moc 19:5540 Error; Mo debug probe detected. [ ] Live Update Verbosity level • 1 1 3 Target information Board Device Type Device ID Revision ID Flash size CPU Izz: Cr:?' Version Figure 2.2: The config of ST-Link V2 should be more or less same 6. after successful download, disconnect Blue Pill, set BOOTO jumper to 0, i.e., to default mode - it boots from User flash [5] 7. connect the USB to the Blue Pill and the PC. You should see a new USB Serial Device under Ports (COM & LPT) in Windows Device Manager. The name should be Maple Serial 2.3.3 UART The third option for communicating and programming the Blue Pill is via UART. Realized most commonly by UART-to-USB cable. Both cores support this communication method, but I use it as an emergency option when uploading via USB or ST-Link has failed. However, nothing stops you from using the UART as your main upload method. 12 2. S T M 3 2 F 1 0 3 C 8 T 6 "BLUE PILL" OVERVIEW" 2.4 The most frequent errors Let's finish the chapter with the most common errors I've encountered during the first steps with Blue Pill. However, this is not a definite list of errors and its solutions! • Couldn't find the DFU device: [1EAF:0003] - Check if you set the BOOT jumpers correctly during flashing. With some copies, I have discovered that the BOOT jumpers have the other way around: BOOT1 to 1 and BOOTO to 0. Try flashing the bootloader again. • PC13 LED flashes frantically - the program may have crashed. In this case, the reset did not help me, but only through Full chip erase through STM32CubeProgrammer and flash bootloader again. • STM32CubeProgrammer ST-Link config missing serial number - It's not a bug, but I spent quite a lot of time on it before I accidentally figured out how to read the serial number. The steps are described in the figure 2.3 • USB device not recognized - When the device is in an error state: incorrectly connected ground and voltage peripheral to Blue Pill, heap overflow, it can happen that Windows cannot recognize the device. Try to unplug the USB cable from the PC, and even if that doesn't solve the issue, flash the bootloader according to the steps mentioned in the USB Install guide. 13 Not connected Figure 2.3: Steps to get Serial Number 3 Displays used in lab exercises The content of this chapter is an overview of imaging devices used when working on laboratory tasks. To begin with, I introduce the term "electronic display" and then continue with a more detailed description of display devices used in laboratory tasks. I end the chapter with Blue Pill's communication methods with individual display devices. 3.1 Displays overview This section deals with a short technical description of the individual display devices used in the laboratory tasks with the Blue Pill development board. 3.2 LED diode It is a semiconductor electronic component that emits light when an electric current passes through it. The pinout is very simple and 14 3- DISPLAYS USED IN LAB EXERCISES consists of two pins: the longer pin is the anode to which the positive voltage travels and the shorter pin is the cathode connected to the ground. Connecting a resistor to work with the Blue Pill and the LED will be necessary. O n the manufacturer's website, you will usually come across a description that describes in more detail how many Ohm resistors are needed for different types of voltage. In the case of a strong enough resistor, there is a risk of significantly shortening the lifetime of the LED, even destroying the diode itself. This is because Blue Pill works with 3.3V, and the L E D is structurally adapted to a maximum of 1.79V [7] It is an Intelligent control L E D integrated light source. A part of each LED is an RGB chip that allows you to set a color combination that will remain saved even after the electricity is disconnected. Up to 256 brightness levels, 16777216 colors can be set. [9] Its protocol is fairly simple. Protocol encodes bits based on pulse length, with off time between bits. The pulse length is quite short, only 1.25 us. Therefore, it requires fairly fast pin toggling rates [9]. Doing it with only interrupts would consume a lot of C P U resources. That's why D M A is used. It limits the count of used interrupts; therefore C P U consumes much less resources. Figure 3.1: L E D and it's inner working parts [6] 3.3 NEOPIXEL WS2812 15 3- DISPLAYS USED IN LAB EXERCISES Figure 3.2: Neopixel stripe [8] D l reset code >=50us -Data refresh cycle 1- first24bit second 24bit third 24bit «-Data refresh cycle 2- reset code first 24bi second 24bit third 24bii D2 second 24L.it third 24b. second 24bit thrrd 24b. D3 third 2 4 hit third 24bii D4 Figure 3.3: Data transmission method in cascade mode [10] It also enables cascade mode, where 24-bit data packets are sent serially. For example, you have three LEDs; you send 72 bits. The first LED takes 24 bits, sets the color, and sends the rest of the message to the next LED. The next L E D takes another 24 bits, sets the color, 16 3- DISPLAYS USED IN LAB EXERCISES and sends the rest. The third L E D has the last 24 bits and repeats the operation of the previous LEDs. 3.4 LED 4 7-SEGMENT DISPLAY The 7-segment display uses 7 L E D segments to illuminate. You can display individual numbers by lighting specific segments to resemble numbers. Dl A F D2 D3 B I I I I I I 0 ffi 0 u . I I I I I I E D DP C G D Figure 3.4: 4-7 segment display and its pinout [11] • D1-D4 send current to individual digits. Thus, to display, for example, the number three on the second digit, it is necessary to turn on pin D2, and then it is possible to light up the corresponding segments to resemble the number three. • A - G lights up given segment on turned on D1-D4 cipher. Unfortunately, as in the picture, you may encounter displays from other manufacturers that have D1-D4 pins stored reversely. Also, a significant source of errors is whether the given display uses a common anode or a common cathode. For a common anode, the pin must be grounded for the segment or digit to light up. On the contrary, in the case of a common cathode, the logic is reversed. 17 3- DISPLAYS USED IN LAB EXERCISES Figure 3.5: Matrix LED [12] 3.5 LED MATRIX MAX 7219 It is an L E D matrix module with L E D Display Driver M A X 7219. It allows persistent storage of the state of up to 64 LEDs. The chip itself provides various interfaces for communication, i.e., SPI, QSPI, and MICROWAVE. Allows multiple modules to be connected in a cascade. Consumption depends very much on the number of illuminated LEDs; the chip enables Low-power Shutdown, which preserves data with minimal electricity consumption. When controlling 7-segment displays, the MAX7219 controller enables BCD decoding. In that case, only 4 bits are enough instead of eight to display the characters 0-9, E, H , L, P, and -) [13] 3.6 LCD 16x2 It is an L C D capable of holding 16 characters on two lines. It is controlled by a Hitachi HD44780 LCD controller or its clone. It is produced in various variants, for example, the one already mentioned 16x2 or 20x4. 18 3- DISPLAYS USED IN LAB EXERCISES Figure 3.6: LCD 16x2 with I2C controller [14] It contains R O M memory capable of holding up to 240 characters, Of which 208 are 5x8 and 32 are 5x10 (source: 1 page Hitachi datasheet). It also contains a Character generator about the size. Sixtyfour bytes and is capable of holding eight custom characters of size 5x8. The problem is that it is a volatile memory; therefore, custom characters will not be saved after the display is turned off. The most common communication with Blue Pill is through parallel or I2C interfaces. [15] Don't forget to set the contrast with a screwdriver for the I2C variant. In the case of the I2C variant, it is necessary to find the appropriate address. I encountered only 212C addresses; you can find the address simply by the chip name on the I2C converter or by software - I2C address detector. The parallel variant contains a large number of pins. But it is possible to send data in 4-bit mode instead of 8-bit mode and thus eliminate four cables. A l l known libraries support this mode. 3.7 OLED 0.96 SH1106 It is a small display using O L E D technology - a thin organic film between the anode and the cathode. OLED, unlike LCD, does not 19 3- DISPLAYS USED IN LAB EXERCISES need a backlight and provides low consumption, fast response, and a wide viewing angle. Figure 3.7: OLED with I2C controller. Notice 4 pins[16] Figure 3.8: OLED with SPI controller. Notice 6 pins [17] In this size, they have a resolution of 132x64, and the driver is usually of two types: SHI 106 or SSD1306. There are drivers for both displays, even the Adafruit GFX library, which provides the basic 20 3- DISPLAYS USED IN LAB EXERCISES graphic primitives - points, lines, circles... for building graphic interfaces. [18] Blue Pill can communicate with OLED displays in two ways: either via SPI or I2C. For the average user, it doesn't matter; I2C uses four cables, but SPI uses seven. For both variants, a variety of libraries exists. 3.8 Open-Smart 2.4" 320x240 TFT Touchscreen SPFD5408 Inexpensive, large, colorful TFT display with touch control support. It works natively with almost no problems with Arduino Uno or Mega. Figure 3.9: TFT [19] The board includes an SD card slot. It serves as a potential storage for various bitmap images. You can also find an LM75 thermometer on the board communicating via I2C. The package also includes a stylus. [19] Applications do not occupy the display with much memory because the display driver has many graphic operations and memory. I worked with SPFD5408. There aren't many libraries that are com- 21 3- DISPLAYS USED IN LAB EXERCISES patible with Blue Pill. I therefore recommend using it with Arduino Uno/Mega or choosing a display with a different driver 3.9 Waveshare 1.54" 200x200 ePaper E-Ink is the so-called electrophoretic display. The display contains white particles in microcapsules dispersed in a thin layer of dark, viscous solution. By applying a short pulse these white particles move; in some cases, they turn towards the front of the display, which causes the given pixel to appear white by introducing a pulse of the opposite polarity, again as black. The high viscosity of the solution causes the changes to assemble even after disconnection from the electricity. But after a long time, you need to clean the screen again so the changes don't stay engraved on display. [20] $23—29°C Monday 18:00 May 8th Figure 3.10:1.54 inch e-paper model [11] This model communicates with Blue Pill via three or 4-pin SPI. It provides a resolution of 200x200. Here, you can encounter the problem of memory requirements since the display itself does not store any data: all bitmap data must be kept on Blue Pill or another development board. With 3-color display variants, this problem is even more acute 22 3- DISPLAYS USED IN LAB EXERCISES because it is also necessary to remember the bitmap for the third color. It is not able to handle this at a resolution of 200x200 any board. Therefore, I recommend using STM32 boards or a powerful Arduino Mega. The libraries are officially available from the manufacturer Waveshare. 23 4 Laboratory exercises 4.1 LED The first laboratory exercise focuses on working with L E D and A r duino IDE: Serial monitor, delays, sending current to individual pins, and writing code that's easy to read. Libraries: none Equipment: LED, 220 Ohm resistor Approach: You need to determine which pin the LED is connected to. For example, it is pin PB7. For clarity, define a macro for a pin. The code will, therefore, be much more readable and modular. This way, you define each constant or pin: #define LED_PIN PB7 \\ Replace with your desired LED pin First, test whether you have the LED connected correctly. Code for LED function test: #define LED_PIN PB7 void setupO { // put your setup code here, to run once: pinMode(LED_PIN, OUTPUT); digitalWrite(LED_PIN, HIGH); } void loopO { // put your main code here, to run repeatedly: } If the LED lights up, you can start working. Warm up Assignment: Write a program that light up for led Is, and then 24 4. LABORATORY EXERCISES turns it off again for Is. At the same time, write the message to the serial monitor "Every 2 seconds, a new line in the Serial monitor will arrive!" and write any input you write to the Serial monitor back to the serial monitor in the format: "My input: ". Approach: As with the program that tested the L E D connection, you should also define a macro for the pin and another for the terminator. I will explain its meaning later; for now, create and define it as '\n'. Let's start with the Setup () function. In this function, you just set the Baud rate of the Serial monitor to 9600 bauds and start the serial communication keyword "Serial". void setupO { // Starts s e r i a l communication Serial.begin(9600); pinMode(LED_PIN, OUTPUT); } Key commands for the task: • pinMode(pin, mode) - function accepts GPIO pin, and it's mod as input. The vast majority of the time, you encounter two mods [21] OUTPUT - the peripheral on the P I N serves as an output; in this case, the LED presents the output: you send a signal, and it lights up [21] INPUT - a peripheral on a pin serves as an input. For example, a button represents an input. • Serial.begin(speed): Starts serial communication via the serial monitor. [22] speed - It's the speed of serial data transmission in a unit called Baud rate. Most of the time, you can use the 9600 Baud rate through a full course of these lab assignments. It means that the frequency of the serial monitor can be changed a maximum of 9600 times per second. [22] 1 1. you are interested in a closer history, or why the number 9600 is used, I recommend this link:https://www.sparkfun.com/news/2231 25 4. LABORATORY EXERCISES • Serial.println(data) - prints data to the serial monitor and puts a delimiter - a new line at the end of data. [23] • Serial.print(data) - same but without delimeter. [24] • Serial.available() - find out whether the input from the user has arrived on the serial monitor; if so, the return value is non-zero; if not, it is zero [25]. It is often used with the Serial.readStringUntil command • Serial.readStringUntil (terminator) - reads letters from the serial buffer into a String. He reads until he hits the terminator. [26] • delay(ms) - pauses the program. [27] ms: duration of pause in ms • digitalWrite(pin, value) - writes a HIGH or L O W value to digital pin. [28] Serial monitor: ® COM10(Map eMini) m — • X | My input 2| Send Every 2 seconds a new 1 ine i n S e r i a l monitor w i l l a r r i v e ! Every 2 seconds a new 1 ir.e i n S e r i a l monitor w i l l a r r i v e '. Every 2 seconds a new l i n e ir. S e r i a l monitor w i l l a r r i v e ! Every 2 seconds a new l i n e ir. S e r i a l monitor w i l l a r r i v e ! Every 2 seconds a new l i n e ir. S e r i a l monitor w i l l a r r i v e '. Every 2 seconds a new 1 ine i n S e r i a l monitor w i l l a r r i v e ! Every 2 seconds a new 1 ine ir. S e r i a l monitor w i l l a r r i v e '. Every 2 seconds a new 1 ir.e ir. S e r i a l monitor w i l l a r r i v e ! Every 2 seconds a new l i n e ir. S e r i a l monitor w i l l a r r i v e ! Every 2 seconds a new l i n e ir. S e r i a l monitor w i l l a r r i v e ! My input:My p r e t t y input Every 2 seconds a new 1 ine ir. S e r i a l monitor w i l l a r r i v e ! Every 2 seconds a new 1 ir.e i n S e r i a l monitor w i l l a r r i v e '. Every 2 seconds a new 1 ir.e i n S e r i a l monitor w i l l l~2~ a r r i v e '. 0 Autnscroll Newline v 9600 baud v | | d o r output | Figure 4.1: Serial monitor overview 26 4. LABORATORY EXERCISES 1. Terminator: Let it be selected to Newline. It's separates sentences: command Serial.readStringUntil uses it 2. Baud rate: A speed of serial monitor, set it to the same value as you use in Serial.begin command 3. Input tab: This is where you put your input. String to Morse code Assignment: The first laboratory exercise's goal will be converting characters into Morse code. The output is a flashing LED expressing the individual characters of Morse code. Approach: As I mentioned, you should define macros for constants. In our case, it will be useful to define a delay - that is, how many ms will the LED light up at a certain character. I defined the smallest delay unit - let's call it DELAY_UNIT - at 300ms. Morse code consists of 2 types of characters, i.e., dot"." and dash I recommend defining these characters as macro. Each of these signs should lit for a different amount of time In our case, the dot should light for 300ms and the dash for 900ms. A dash takes three times as long as a period. Don't forget about spaces, and there are three types of them: • Each dot of the dash is followed by the blank period, which equals the DELAYJJNIT. • Space between letters is 3 * DELAY_UNIT. • Space between words is 7 * DELAYJJNIT. [29] Define the remaining macros according to these rules. I recommend limiting the alphabet to a global character array, as this minimizes the number of lines of code, and the case can be approached elegantly. Also, it is a global field for numbers. HINT: Check the ASCII table. The program's main functionality is in the loop() function, where we find out if any input from the Serial monitor has run out. After 27 4. LABORATORY EXERCISES that, you must go through the entire entry, translate each letter into Morse code and signal accordingly. You have all the standard features in C/C++, and you shouldn't need anything extra. 4.2 LED with PWM The goal of the second laboratory exercise is to create a program that allows you to adjust the brightness of an LED with a potentiometer. Libraries: none Equipment: LED, 220 Ohm resistor, rotary potentiometer Potentiometer: It is a simple tool that adjusts the electrical resistance by rotary or linear movement. It has a vast range of uses, from adjusting the volume of the HI-FI system to controlling a large cargo ship (Source: https://sound-au.com/pots.htm ) There are many types of potentiometers, and their knowledge is beyond the scope of this bachelor's thesis. There are two most basic potentiometer parameters you should be concerned with. 1. Resistance: This is the maximum resistance to set. It is often referred to as 100k W or 100k Q. Surprisingly, one does not often come across the correct designation f2for the unit ohms. Various websites or stamping presses do not have the in-character set symbol ^available. 2. Type: There are different types, but the most common is met with • Rotary: Adjust the amount of voltage by turning the knob. • Trimmer: It is usually attached to the circuit board, hidden from the user in the cover. A screwdriver is used for adjustment. Its advantage is a meager price, but the disadvantage is that it is not very resistant to frequent use and lasts only 100-200 cycles on average [30]. One can find it on the L C D I2C display; it sets the display's contrast. 28 4. LABORATORY EXERCISES Figure 4.2: Trimmer [31] Warm up Assignment: Write a program that allows you to change the brightness of the L E D using a potentiometer. Approach: Connect the L E D to the P W M pin (see Chapter 1.) and the potentiometer to the Analog pin. The potentiometer generates an analog signal, and the P W M pin can convert it to a digital one. But you use slightly different commands than usual since you are working with P W M and analog pins: • analogRead(pin): reads an analog value from an analog pin. The function returns values between <0,1023>. The default reference voltage on Blue Pill is 3V. [32] • analogWrite (pin, value): writes the analog value to the P W M pin. The parameter value is an 8-bit long duty cycle. (255 = 100%, 127 = 50% ...) [33] • map (value, original_low, original_high, map_low, map_high) : the function which maps the values between "originallow" and "original_high" to values in the range "map_low" and "map_high". For example, the number 1023 maps to the value 255. The resulting program is highly trivial, so with the pre- 29 4. LABORATORY EXERCISES Figure 4.3: Potentiometer viously mentioned commands, you should be able to create a program without significant problems. [34] Question: When I connect the ground and the voltage vice versa, I have to turn the knob in the opposite direction. Why? Answer: When you connect the potentiometer the other way around, the length of the potentiometer changes as well: the most considerable resistance is suddenly at the leftmost point. LED fading Assignment: Create the program so that the L E D will decrease the brightness until it goes out and, vice versa, increase the brightness to full intensity. There is no need for a potentiometer. Approach: The entire program will be in the "loop()" function, 30 4. LABORATORY EXERCISES where there will be two cycles and a numerical variable that represents an analog value. In one cycle, the value written analogically will be incremented and, in the second, incremented into the LED. Thus, it will create the effect of decreasing and increasing the brightness. A d d a delay with a short delay for a better effect. 4.3 Neopixel The second laboratory work aims to create a thermometer using a Neopixel. Based on the temperature recorded with the sensor, express the height of the temperature with lighted LEDs on the Neopixel. Libraries: bluepill_ws28122 , my thermometer library Equipment: Neopixel, DS18B20 (or another temperature measuring device, another library must be used) Warm up Assignment: Light all the LEDs on the Neopixel to green and send the current temperature to the Serial monitor every second. I want the temperatures to always be on a new line in the format: "Temperature: °C." Approach: Initially, insert all necessary libraries, define macros, and create instances of Neopixel and temperature sensor: #include #include #define NUM_PIXELS 8 #define string_port GPIOA #define string_pin 7 pixel string[NUM_PIXELS]; bluepill_neopixel PIX; Temp_sensor_dsl8b20 sensor(PB3); 2. https://github.com/FearlessNight/bluepill_ws2812 31 4. LABORATORY EXERCISES On the 4th and 5th lines, are defined instances of peripherals. Most libraries are written in C++; hence, you can create an instance of a class of a specific library of some peripherals. There are different types of neopixels with different lengths and shapes of LED placement (e.g., circles). I worked with Neopixel, which has 8 LEDs. Count the number of LEDs per to your Neopixel and adjust accordingly This is one of the libraries where port and pin are defined separately. Usually, a pin is described together with a port (f.e. PA7). The last line defines a chain of LEDs where you can set a specific color for each of the individual elements of the field. Initialize the peripheral in the "SetupO" function. void setupO { Serial.begin(9600); PIX.begin(string_port, string_pin); // set p i n to output clear_pixels(); } The 2nd line initializes the Neopixel, taking as arguments the defined pin and the port where the DATA pin is connected. The 3rd line is a custom-defined function. It is a good practice to run the socalled cleaning function, which erases the data from the previous program run from the display. Sometimes, this is an unnecessary step because some libraries do this during initialization, and they will do the step for us, but in this case, the library does not have such an option. The implementation is up to you. Let's take a closer look at the last three functions that will be necessary to complete the warm-up and subsequent laboratory work: • set_pixel(&string[i], 0, 0, 0); - sets the i.th L E D to RGB color. 0, 0, 0 means the L E D will turn off. // You can use this function definition void set_pixel( pixel *p, i n t r , i n t g, i n t b) { // this i s intentional (grb) p->rgb.r = g; p->rgb.g = r p->rgb.b = b 32 4. LABORATORY EXERCISES It's not a mistake. The library has a bug where you assign the green part of RGB to red and vice versa. • PIX.paint( string [0].bytes, NUM_PIXELS, string_port, string_pin); - sets the colors on the Neopixel itself, as the input wants the colors of the first led, the number of pixels/LEDs and again the pin and port. • sensor.get_temp(); - returns the measured temperature from the sensor. Your task is to use the acquired knowledge to complete the task to define clear_pixels() and loop(). Neopixel thermometer Figure 4.4: Thermometer at 27 °C Assignment: Based on the temperature recorded with the sensor, express the height of the temperature with lighted LEDs on the Neopixel. 33 4. LABORATORY EXERCISES Approach: Use the functions you defined during the warm-up. The core of the task is to define the temperature ranges and assign a corresponding color to each range. As a guide, I used this page to define colors in RGB: https: //www. rapidtables . com/web/color/RG B_Color.html Color ranges can be controlled in different ways. A naive solution is through a series of if-else. But if you want your code to be compact, fast, and readable, I recommend considering the struct keyword. I defined a struct where I saved the lower temperature limit and the corresponding color in RGB. 4.4 4-7 segment display This laboratory work aims to create a driver for a 4-7-segment display. Then, create simple programs, namely a button press counter and a timer. Libraries: None Equipment: 4-7 segment display, button Warm up Assignment: Program a button press counter. After each press, the number on the display increases by 1. Approach: Since you do not use any library, you have to make everything from scratch. A 7-segment display contains 8 pins - 1 pin for the dot and the remaining 7 pins for the number itself. Each of the given pins: pins A - G lights up the corresponding segment on the display, and pin DP lights up the dot segment. Thus, it is necessary to send H I G H (or LOW) to the individual segments so that they represent the number. In this case, you must determine if you have a 7-segment display with a common anode or cathode. To light up the cathode, send a H I G H signal to the segment. On the other hand, to light up the segments of the anode, send a LOW signal. 34 4. LABORATORY EXERCISES D1 A F D2 D3 B J HE D DP C G D4 Figure 4.5: 4-7 segment display and its pinout [11] A 4-7-segment display is four 7-segment displays connected together. In addition to the segment control pins, four more are available: Dl-4. They are used to control the individual digits and determine which signals pass through the LED blocks. I recommend defining macros for pins D1-D4 and pin A-G (or DP if you plan to use it), buttons, and other constants that you use in the code (number of digits, number of segments). I put the pins for the numbers and the pins for the segments in separate arrays. I save the 8-bit numbers that represent the numbers 0-9 on the 7-segment display in a separate array in hexadecimal form. I initialize the button press counter to 0 and define variables that hold the previous and current button press status. In the setup () function, set the pinMode for all the pins on display to OUTPUT and the button to INPUT_PULLUP In the loop() function, read the state of the button, and when it is pressed, increment the counter by one. The program's core functionality is the print_number function, which is responsible for obtaining individual digits from the counter variable. By the division operation (dividing by 1000,100,10, and 1), you get individual digits that I send to the corresponding digit pin on the display. I send the division result to the display_number function, which has two arguments: the digit of the number and the digit itself to be displayed. I call the function four times (for each number digit). 35 4. LABORATORY EXERCISES c a 1 b i c 0 d i e i f 0 g 1 Figure 4.6: Number 2 with its common cathode segments [35] void print_number(int num) { i f (num < 0) { num = 0; } i f (num > 9999) { num = 9999; } display_number(0, num / 1000); num = num % 1000; display_number(1, num / 100); num = num % 100; display_number(2, num / 10); num = num % 10; display_number(3, num / 1); } In the display_number function, I call the cipher_enable function, which sends a signal to one of the D pins. But before that I recommend sending L O W to each D pin to avoid undefined states and bugs. Next, send a HIGH to the selected D pin and ideally turn off each segment: 36 4. LABORATORY EXERCISES some segments could remain under voltage, and the numbers would be displayed incorrectly. After executing the cipher_enable function, a digit can be displayed. A for loop's body sends bits of the input digit to different pins. The zero bit is sent to pinA, the first bit to pinB, the second bit to pinC, and so on. A d d a 5 ms delay at the end of the function to make the number on the display easier to read. It prevents an annoying blinking effect. Try experimenting with a longer delay. void clear_segments() { for (int i = 0; i < SEGMENTS; i++) { d i g i t a l W r i t e ( p i n s [ i ] , HIGH); } } void cipher_enable(int id) { for (int j = 0; j < 4; digitalWrite(dPins[j], LOW); digitalWrite(dPins[id], HIGH); clear_segments(); } void display_number(int i d , unsigned char num) { cipher_enable(id); for (int i = 0; i < SEGMENTS; i++) { d i g i t a l W r i t e ( p i n s [ i ] , (numbers[num]>>i)&0x01); } delay(5); } Countdown timer Assignment: Program a countdown timer. After pressing the button, the countdown should start over again. Approach: If you succeeded in the previous task, this one is very simple. The easiest way to achieve this is to create an integer variable that you decrease by one every 1000 ms. Use already defined functions from warm up to display numbers. 3 7 4. LABORATORY EXERCISES 4.5 Hitachi HD44780 LCD 16x2 I2C The goal of this lab assignment is to create a copy of Dinosaur Game from a popular web browser. The scoring system is up to you, the Dinosaurs's jumping is controlled by a button. The Dinosaur only moves in the Y direction: up and down. It doesn't move in the X direction (it doesn't go forward or backward). The game's final version contains obstacles - a cactus that can kill Dinosaur and thus end the game. In addition to obstacles, there is also a bonus in the game that Dinosaur can get to improve his score. Obstacles and bonuses come from the right side of the screen, just like in the original Dinosaur game. Libraries: LiquidCrystal_I2C 3 Equipment: Hitachi HD44780 L C D 16x2 I2C, button Warm up Assignment: Program a simplified version of the Dinosaur game. Obstacles do not need to be implemented yet. Just implement the movement of the Dinosaur. The score increases for Dinosaur only when he is in the bottom position. A jump is performed by clicking a button. The score is displayed in the upper right corner. Approach: As mentioned in the third chapter, the HITACHI HD44780 enables to save eight custom characters to its internal memory. This online tool serves as a helper: https://omerk.github.io/lcdchargen/ . Thanks to this, you can upload your own character, Dinosaur (later also obstacles), to the display memory. In the global space, in addition to defining macros and global variables, I also defined the Dinosaur bitmap and initialized an instance of the LiquidCrystal_I2C class: #include #define Dinosaur 0 #define BUTTON PB11 int score = 0; 3. https://github.com/j ohnrickman/LiquidCrystal_I2C 38 4. LABORATORY EXERCISES bool Dinosaur_LOWER_POS = false; LiquidCrystal_I2C lcd(0x27, 16, 2); byte Dinosaur [8] { B00000, B00111, B00101, B10111, B11100, B l l l l l , B01101, B01100, }; The initialization function of the LiquidCrystal_I2C class takes the I2C device address, display width, and display height as input arguments. The majority of displays have an I2C address of 0x27, but it may happen that the given display does not have such an address. In that case, you need an I2C scanner. More on this page: https://www.instructables.com/How-to-Use-LCD-HD44780-I2c/ H i tachi HD44780 is made in different sizes, for example, with a width of 20 characters and a height of 4 characters. Therefore, display width and height are specified as parameters in the initialization of the LiquidCrystal_I2C class. Necessary functions that are needed to complete the laboratory work: • lcd.init() - initialize the display. Without calling this function, the display is non-functional • lcd.backlight() - turn on the backlight of the display • lcd.createChar(index, charmap) - place a byte array on the index, for example, lcd.createChar(Dinosaur, Dinosaur) stores the byte map "Dinosaur" on the Dinosaur index representing the number 0. It is possible to add up to 8 characters, otherwise, the maximum index should be 7. • lcd.setCursor(col, row) - set the display cursor to the corresponding column and row. 39 4. LABORATORY EXERCISES • lcd.print(string) - display the string on the corresponding column and row set, e.g. function lcd.setCursor(col, row) • led.write (index) - very similar to the print function, it only displays custom characters based on the index you set with the function lcd.createChar (index, charmap) • lcd.clearQ - clear display, set cursor position to zero Dinosaur game Assignment: Expand the game. A d d obstacles. A n obstacle can be a cactus, as in the original game. You can also add some rewards. A bomb will instantly add 50 score points. The choice is up to you. Approach: Compared to the warm up, new mechanics have been added, namely obstacles. I use a simple 16-element byte array to generate and display obstacles (the display is 16 characters wide). In the case of a 20x4 display, you can expand the byte array to 20 elements. The core of the program is the game() function, which is in charge of the game itself, i.e., calling the graphic () function, scoring system, and "death" Dinosaur. void gameO { graphic(); Figure 4.7: Dinosaur game 40 4. LABORATORY EXERCISES i f (Dinosaur_LOWER_POS) { i f (terrain[0] == CACTUS) { game_over(); delay(5000); init_game(); } i f (terrain[0] == BOMB) { score += 50; } score++; } } The graphic () function handles graphics: moving Dinosaur on the screen, generating obstacles, and showing the score. I skip the explanation Dinosaur_move() and score_board() functions since they are simple and unimportant. void graphicO { dino_move(); score_board(); for ( i n t i = 0; i <= WIDTH - 2; { i f ((DIN0_L0WER_P0S && i == 0) && t e r r a i n [ i + 1] == WHITESPACE) { continue; } terrain[i] = t e r r a i n [ i + 1]; } delay(300); terrain[15] = new_block(); for ( i n t i = 0; i <= WIDTH - 1; i++) { lcd.setCursor(i, 1); lcd.write(terrain[i]); } } The movement of obstacles to the Dinosaur from right to left solves the first for cycle by shifting the element in the terrain field to the left. 41 4. LABORATORY EXERCISES The if condition in the body guarantees that the Dinosaur character does not shift off the screen if it is in the bottom position. In the case of obstacles and bonuses, shifting off the screen is required. Delay is added there to slow down the movement of obstacles and bonuses. Place a new randomly selected obstacle on the last place of the terrain field. The last for loop just displays the individual elements of the terrain field on the screen. 4.6 Hitachi HD44780 The aim of this laboratory work is to create a driver for Hitachi HD44780. Get used to working with datasheet and creating rudimentary driver. Libraries: None Equipment: Hitachi HD44780 Warm up Assignment: driver for Hitachi HD44780. It should display strings using 8-bit mode. Approach: Display with HD44780 controller communicate via four or eight data links. In the case of four data links, the data is written twice - first the upper four bits and then the lower four bits. Data is send to DB7-DB4. The communication is controlled by the R/W (Read/Write) link and the enable input E (enable/disable input) The display has two types of memory: • DD R A M - contains characters that appear on the display. It can store up to 80 characters (display can be up to 20 characters per line, 4 lines, in total 80 characters). [36] • C G R A M - contains up to 8 user defined characters. The address for these custom characters spans from 0x00 to 0x07. For 5x8 dots, eight character patterns can be written, and for 5 x 10 dots, four character patterns can be written [36] 42 4. LABORATORY EXERCISES Table 4.1: Hitachi HD44780 pinout [37] er of pin Pin Description 1 vss Ground 2 VDD 5V 3 VE Contrast of display 4 RS Command (0), data (1) 5 R/W Read (1), write (0) commands or data 6 Enable Starts data read/write 7 DBO Data/Command (least significant bit) 8 DB1 Data/Command 9 DB2 Data/Command 10 DB3 Data/Command 11 DB4 Data/Command 12 DB5 Data/Command 13 DB6 Data/Command 14 DB7 Data/Command (most significant bit) 15 A Backlight anode 16 K Backlight cathode As usual, you need to create an initialization sequence for display No library does the initialization for us this time, you have to create it based on the instructions from the datasheet. void l c d _ i n i t ( ) { i n i t _ p i n s ( ) ; delay(50); lcd_send_command(LCD_FUNCTIONSET I LCD_8BITM0DE); delay(5); lcd_send_command(LCD_FUNCTIONSET I LCD_8BITM0DE); delay(1); lcd_send_command(LCD_FUNCTIONSET I LCD_8BITM0DE); 1cd_send_ command(LCD_FUNCTIONSET I LCD_8BITM0DE I LCD_2LINE I LCD_5x8F0NT); 43 4. LABORATORY EXERCISES delayMicroseconds(50); lcd_send_command(LCD_CLEAR); delay(3); 1cd_ send_ command(LCD_ENTRYMODESET I LCD_ENTRYLEFT I LCD_ENTRYSHIFTDECREMENT); delayMicroseconds(50); lcd_send_command(LCD_DISPLAYCONTROL I LCD_DISPLAY0N I LCD_CURS0R0N I LCD_BLINK0N); delayMicroseconds(50); } Let's start with the first function init_pins(). This function sets pinMode to RS, EN, and data pins. The function set_rs sends 0 or 1 to the RS pin. As I mentioned earlier 4.1, if you want to send commands to HD44780, you must set the RS pin to 0. O n the other hand, you have to set the RS pin to 1 if you want to send data [37]. In lcd_init() I used macro LCD_CMD - 0 for commands and LCD_DATA -1 for data. It makes sense to send LCD_CMD to RS pin because lcd_init function sends only commands to HD44780. // RS b i t #define LCD_CMD 0 #define LCD_DATA 1 void init_pins() { pinMode(RS, OUTPUT); pinMode(EN, OUTPUT); int pin_count = 8; for (int i = 0; i < pin_count; i++) { pinMode(data_pins[i], OUTPUT); } set_rs(LCD_CMD); } lcd_send_command function takes as argument command. In our case, commands are just bits specified by the datasheet. 44 4. LABORATORY EXERCISES R S R W DB7 D5Ě DB5 j B ^ DB3 DB2 JB1 DBO Clear display Code 0 0 0 0 0 D D 0 0 1 RS R/W DB7 Die DBi J E 3 DB2 DB1 DBO Return home Code 0 0 0 0 0 0 0 D 1 * Note: * Don't care. RS RJW DB7 D3Ě DBS DB4 J B 3 DB2 DB1 DBO Entry mode set Code 0 0 0 0 0 D D 1 |.'D S R S R W DB7 D5Ě DB5 j B ^ DB3 DB2 JB1 DBO Display on/off control Code 0 0 0 0 0 0 1 D C E R S R.'W DB7 DBĚ JB4 DB3 DB2 DE' DBO Cursor or display shift Code 0 0 0 0 0 1 S/C R/L * Note: * Don't care. RS R'W DB7 DBĚ J B 5 JB4 J B 3 DB2 DB' DBO Function set Code 0 0 0 0 1 DL N F « * RS DB7 DBĚ j E s j B 4 DB3 DB2 DB' DBO Set CG RAM address Code 0 0 0 1 A A A A A A Higher Lower order bit order bit Figure 11 Instruction (1) Figure 4.8: Hitachi HD44780 commands [38] Let's review some of the commands and explain how to use them. • clear display command - for example, define it as "LCD_CLE AR". The only bit set to 1 is LSB (Least significant bit). So set a macro to 0x01 (you can use binary, decimal, or hexadecimal number system). • Return home - for example, define it as LCD_SETTOHOME. The second least significant bit is set to 1. Set macro to 0x02 • Function set - default function with all flags set to 0 has only one pin set to 1: DB5. Macro, let's call it LCD_FUNCTIONSET 45 4. LABORATORY EXERCISES is set to 0x20. Notice the arguments on DB4 (DL) DB3 (N), and DB2(F) 1. DL - Sets the interface data length. Data is sent or received in 8-bit lengths (DB7 to DBO) when D L is 1, and in 4-bit lengths (DB7 to DB4) when DL is 0. When 4-bit length is selected, data must be sent or received twice. [39] 2. N - sets the number of display lines. The display is set to 2-line mode when N is 1. Set N to 1 if you have a display with 2 lines. [39] 3. F - sets the character font. 5x10 dots are the size of the character when F is 1, and 5x8 dots are the size of the character when F is 0. [39] There are two choices: hardcode the commands or make it modular like in my function lcd_init. I definitely recommend making it modular, using bitwise OR. Function set and its flags: #define LCD_FUNCTIONSET 0x20 // FunctionSet flags #define LCD_5x8F0NT 0x00 #define LCD_2LINE 0x08 #define LCD_8BITM0DE 0x10 #define LCD_4BITM0DE 0x00 Sending command or data to HD44780 is fairly uncomplicated: I created two separate functions, one for sending the command and another one for sending data. The only difference is in the setting of RS pin. 0 for commands and 1 for data. void lcd_send_command(char cmd) { send_to_lcd(cmd, LCD_CMD); } void lcd_send_data(char data) { send_to_lcd(data, LCD_DATA); } 46 4. LABORATORY EXERCISES void send_to_lcd(char data, i n t rs) { set_rs(rs); send_byte(data); digitalWrite(EN, LOW); delay(2); digitalWrite(EN, HIGH); delay(50); } Notice that in the function send_to_lcd, besides sending 0 or 1 to RS pin, E N pin is set to 0 and then after a delay to 1. The E N pin is triggered by a rising edge (rising voltage level from zero) [40]. These commands are necessary to initialize the driver. I recommend defining each of these functions and their flags as a macro. Check page 26 in the Hitachi HD44780 datasheet. • Display clear - clears the content of the display and sets the cursor on the position of the first character and first line • Function set - sets the size of characters, bit mode, and count of lines • Display control - sets display on/off, curson on/off, and cursor blinking on/off • Entry mode - sets cursor direction, writing from left to right or vice versa • Return home - sets cursor on the position of the first character and first line. It does not clear the content of the display. Driver in 4-bit mode Assignment: In the previous task, you made a driver communicating with HD44780 via eight data links. Extend the driver implementation by adding 4-bit communication with HD44780. Afterward, try to add 47 4. LABORATORY EXERCISES a function that sets the position of the string within the display by row and column. Approach: In the case of four data links, the data is written twice first the upper four bits and then the lower four bits. It means two calls of a function send_to_lcd are needed. Data is send to DB7-DB4. Four bits are also called nibble. You need to create a mask to filter out the lower (or upper) four bits. Also, you need to create a function, which sets the cursor on a specified row and column. Check pages 29,30, and 43 of the datasheet for further information. 4.7 OLED SPI SH1106 The goal of this laboratory assignment is to create a simple countdown timer. The rotary encoder is used to set the time, the button is used to confirm the action. Libraries: Adafruit_SH1106_STM32 4 dsl8b20_temp_sensor 5 Equipment: Neopixel, DS18B20 temperature sensor, O L E D SPI SHI 106, Rotary encoder, Button Warm up Assignment: Program the countdown timer. Selection and setting of time units - a rotary encoder controls hour/minute/second. Time units - select seconds/minutes/hours by clicking the rotary encoder push button. Approach: As in almost every assignment, it will be necessary to create an instance of the library that controls the display, in our case Adafruit_SH1106. // hardware SPI1 (the default case): SDA(M0SI)=PA7, SCK=PA5 #define SPI_P0RT 1 // 1:SPI1, 2:SPI2 4. https://github.com/wonho-maker/Adafruit_SHl106 5. https://github.com/f41crum/DS18B20-temp-driver/tree/main/dsl8b20 48 4. LABORATORY EXERCISES // oled pins #define 0LED_DC PB15 #define 0LED_CS PB12 #define OLED_RESET PB14 Adafruit_SH1106 display(0LED_DC, OLED_RESET, 0LED_CS, SPI_P0RT); The initialization function of the Adafruit_SH1106 class takes as an input argument the SPI pins of the O L E D and the SPI port you want to use. Initialization functions of the Adafruit_SH1106 library include: • display.begin(SH1106_SWITCHCAPVCC) - initializes the display, without calling this function, the display is inactive • display.display() - displays the contents of the display mem- ory • display.clearDisplay() - clear display memory I recommend defining the function init_oled(), which will do all these necessary steps. This function also serves as a test of the correct connection of the display. In the initial state, the display shows the Adafruit logo. A delay with a length of 2000 ms is there so that you have enough time to notice the logo on the display. void init_oled() { display.begin(SH1106_SWITCHCAPVCC); display.display(); delay(2000); display.clearDisplay(); } The necessary step is an initialization of the rotary encoder. The rotary encoder contains 3 pins (not including G N D and VCC) - CLK, DT, and SW. Thanks to the CLK and DT pins, you can find out which direction the rotary encoder knob is turning. SW is the push button of the rotary encoder. 49 4. LABORATORY EXERCISES I recommend creating a separate function that initializes the rotary encoder. Interrupts are used to process the movement of the rotary encoder. The principle is simple: pause the program run and call ISR: Interrupt Service Routine. This is a function that is always executed when the program is interrupted. After all the ISR instructions of the function have been executed, the run returns the program to the place where it was interrupted and continues the execution of instructions. void init_encoder() { pinMode(CLK, INPUT); pinMode(DT, INPUT); pinMode(SW, INPUT_PULLUP); lastStateCLK = digitalRead(CLK); attachInterrupt(digitalPinToInterrupt(DT), read_encoder, CHANGE); } attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) • pin, in our case DT • ISR, a pointer to a function that is called at every interrupt • mode defines the circumstances under which the interrupt should be performed, in this scenario, I recommend using CHANGE - it is activated when there is any change in the value on the pin The most important part is the ISR itself. It is defined as any other function. However, there are differences compared to the normal func- tions. • it cannot have any input parameters • must return void Having variables shared between ISR functions and normal functions declared as "volatile" is highly recommended. This tells the compiler that such variables might change at any time, and thus, the compiler must reload the variable whenever you reference it rather than relying upon a copy it might have in a processor register. [41] 50 4. LABORATORY EXERCISES ISR function read_encoder is in charge of setting the time according to the rotation of the encoder's knob. Initially, set a limit for hours, minutes, and seconds. The function's main task is determining whether to rotate left-right or right-left. Subtract or add values accordingly. Let's explain how it works. Common Pin C Figure 4.9: Rotary encoder principle of working [42] The principle of the rotary encoder is tricky. By turning the encoder knob from left to right, the contact zone will come into contact first CLK pin. If the CLK pin is active (it touches the contact zone), then by finding out if the DT pin is active, you can determine the direction. DT pin is active when you turn from left to right - po touching the C L K pin is also near the DT pin, which must be touched when approaching it. DT pin is inactive when turning from right to left - po contact with the C L K pin is moving away from the DT pin, and thus, no contact will occur. Connected the interrupt to a change in the value on the DT pin. Because of this, when turning right-to-left, decrement the time, and when turning left-to-left, increment it. v o l a t i l e i n t currentStateCLK; v o l a t i l e i n t lastStateCLK; v o l a t i l e i n t encoder_pos = 0; 51 4. LABORATORY EXERCISES void read_encoder() { display.clearDisplay0; int lower_bound; int upper_bound; i f (setTimeMode == HOURS){ lower_bound = 0; upper_bound = 23; } else { lower_bound = 0; upper_bound = 59; } currentStateCLK = digitalRead(CLK); i f (currentStateCLK != lastStateCLK && currentStateCLK == 1) { i f (digitalRead(DT) != HIGH) { i f (encoder_pos > lower_bound){ encoder_pos-; } } else { i f (encoder_pos < upper_bound) encoder_pos++; } } lastStateCLK = currentStateCLK; } Question: Is linking an interrupt to a value change on the C L K pin instead of the DT pin incorrect? Answer: It's a good idea! I recommend trying both pins. Has something changed? A n d if so, why? In addition to turning the knob of the rotary encoder, you should also use the push button of the rotary encoder. Click the push button to choose between time units - hours, minutes, and seconds. Each click changes the timemode. 52 4. LABORATORY EXERCISES enum SetMode { HOURS, MINUTES, SECONDS >; void read_button() { setTimeMode = static_cast( (setTimeMode + 1) °/„ 3); encoder_pos = setTimeMode == HOURS ? _hours : setTimeMode == MINUTES ? _minutes : _seconds ; refresh_display(); } Functions of the Adafruit_GFX library (this library is included in Adafruit_SH1106_STM32 library) - that are necessary to complete the laboratory task: • display.setTextSize(size) - set the text size • display.setTextColor(uint8_t s) - set the text color • display.setCursor(x, y) - set the cursor to the x and y coordi- nates • display.println(string) - display the text on the display Use the display.display() function to display the content from the OLED display's memory. Therefore, it is necessary, for example, to call the function after calling the display.println() function in order to show the changes on the display. Be careful not to use long delays. The Blue Pill does not respond to interruptions during the delay function, and thus, the setting using the rotary encoder works imprecisely. Alarm countdown timer Assignment: Expand the countdown time version from warm up. Add a button. The countdown starts by pressing the button. Approach: If you can use the rotary encoder to set the hours, minutes, 53 4. LABORATORY EXERCISES o f GND VOC DO Dl RES DC CS SB-03=51 M i n u t e s J o Figure 4.10: Alarm countdown timer and seconds, then the assembly can only be simulated by decrementing the seconds, minutes, and hours countdown timer. Since the purpose of this laboratory work is not to create a GUI, I decided to provide functions responsible for displaying data to the display. void print_settings() { char* mode; i f (setTimeMode == HOURS) { mode = "Hours"; } else i f (setTimeMode == MINUTES) { mode = "Minutes"; } else { mode = "Seconds"; } display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(24, 32); display.println(mode); display.display(); } void print_time() { char time_str[9] = "XX:YY:ZZ"; snprintf(time_str, sizeof(time_str), •7„02d:°/„02d:°/„02d", 54 4. LABORATORY EXERCISES _hours, _minutes, _seconds); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(18, 14); display.println(time_str); } 4.8 OLED SH1106 I2C This laboratory work aims to create a "not-so-smart" watch. You get experience working with RTC - Real time clock, temperature sensor, and finally, creating simple GUI to show data from mentioned devices. Libraries: RTClib 6 , dsl8b20_temp_sensor7 , Adafruit_SH1106_STM32 8 Equipment: O L E D I2C SHI 106, DS18B20 temperature sensor, RTC DS3231 Warm up Assignment: Create a basic "not-so-smart" watch. Display the current time and temperature. Approach: As usual, you need to create instances of the class of every device used in laboratory work. // SCL and SDA pins both of OLED and RTC to PB6 and PB7 RTC_DS3231 r t c ; Adafruit_SH1106 display(0LED_RESET); Temp_sensor_dsl8b20 sensor(TEMP_SENSOR_PIN); The initialization process of O L E D I2C is almost the same as for OLED SPI, just add a parameter to begin the procedure. SH1106_I2C_ADDRESS is already defined in the SHI 106 library. No need to redefine it. 6. https://github.com/adafruit/RTClib/tree/master/src 7. https://github.com/f41crum/DS18B20-temp-driver/tree/main/dsl8b20 8. https://github.com/wonho-maker/Adafruit_SHl106 55 4. LABORATORY EXERCISES void init_oled() { // i n i t i a l i z e with the I2C addr 0x3C (for the 128x64) display.begin(SH1106_SWITCHCAPVCC, SH1106_I2C_ADDRESS); display.display(); delay(2000); display.clearDisplay(); } The initialization process of RTC is something new. As usual, create a separate method for the whole initialization process: void i n i t _ r t c ( ) { rtc.begin(); i f (rtc. lostPowerO) { rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); } // we don't need the 32K Pin, so disable i t rtc.disable32K(); } • rtc.beginQ - initialize the RTC • rtc.lostPower() - returns TRUE if rtc lost power. • r t c . a d j u s t ( D a t e T i m e ( F ( _ D A T E _ ) , F ( _ T I M E _ ) ) ) - when RTC lost power, clock stop. This command resets the clock and sets it to the operating system's time. • rtc.disable32K() - due to power saving, disables 32K pin. Smart watch Assignment: Extend functionality. Add three buttons - powerjbiitton, units_change_button, and show_date button. Powerjbutton turns on/off OLED screen, units_change switch temperature unit between Celsius/Fahrenheit, and show_date switch between current date/time. Approach: This task is just an extension of the previous task. For simple formatting of date, use the function snprintf: 56 4. LABORATORY EXERCISES DateTime today = rtc.nowO; char today_str[ll] = "XX:YY:ZZZZ"; snprintf(today_str, sizeof (today_str) , "yo02d.%02d.%02d", today.dayO, today.monthO, today.year()); I used a 50 ms delay for buttons. Experiment with the length of the delay. 4.9 LED MATRIX MAX 7219 The goal of this laboratory work is to create a clone of the game PONG. Libraries: LedControl9 Equipment: 2 rotary encoders, L E D MATRIX M A X 7219 Warm up Assignment: Program a movement of 2 paddles. The paddle should be 3 pixels wide and move up and down, just like in the original game. Approach: The matrix display initialization sequence is a little different than usual. LedControl lc=LedControl(DIN_MATRIX, CLK_MATRIX, CS_MATRIX, 1); void setupO { lc.shutdown(0,false); lc.setlntensity(0,8); lc.clearDisplay(0); } The fourth argument of LedControl is the number of cascaded MAX72XX devices you're using with this LedControl. The library can address up to 8 devices from a single LedControl-variable. [43] 9. https://github.com/wayoda/LedControl 57 4. LABORATORY EXERCISES • lc.If the status is true, shutdown(n, status) - Shutdown the nth display. If the status is false, the display works in normal mode. [43] • lc.setlntensity(n, intensity) - Set the brightness of the nth display (0..15) [43] • lc.clearDisplay(n) - Clears content of the nth display [43] For both paddles, I created a struct. This struct holds the most important values, the current and previous state of the C L K pin, C L K pin, DT pin, and position of the paddle within the matrix display. When processing the movement of the rotary encoder, I recommend using interrupts. Therefore, member variables of struct should be volatile. The matrix display used in this laboratory exercise has eight rows with eight columns. To control each LED, you must create a byte array of length 8. Each of these bytes represents a row - the first row is the first byte, the second row is the second byte, etc.. O rH = p->y_pos - 1 && y <= p->y_pos + 1; } void paddle_move(Paddle *p) { for (int y = 0; y < 8; y++) { i f (paddle_range(p, y)) { put_val_playground(p->x_pos, y ) ; } else { del_val_playground(p->x_pos, y ) ; } } } PONG Assignment: Implement the ball logic into the game. When the ball touches the paddle, it should bounce off randomly. Approach: I suggest creating another struct, this time for a ball. In my case, the struct for ball contains member variables, such as two integers X and Y - current position, and Y_Velocity and X_Velocity. The velocity member variables can be only -1 or 1 - in the case of 59 4. LABORATORY EXERCISES X_Velocity if 1, the ball is going from left to right and vice versa if -1. In the case of Y_Velocity, the ball goes up and down. Adjust a score accordingly when the ball hits the last or first column. When the ball hits the paddle, bounce the opposite way. Do the same when the ball hits the "ceiling" - first row or last row. Figure 4.12: Pong 4.10 Waveshare E-paper 200x200 1.54 inch The goal of this laboratory work is to write an E-paper notes program. Libraries: epdlin54_V2, imagedate, epdpaint1 0 Equipment: 1.54inche-Paper (B) (200x200), HC-05 Bluetooth module Warm up Assignment: Program the E-paper notes program. Send a note via Bluetooth to the Seriall connection and retrieve it. Afterwards, display it on E-paper. Approach: As usual, you must create an instance of the device driver's classes. This time, however, you need to create an instance for the E- 10. all from https://github.com/waveshareteam/e-Paper/tree/master/Ardui no/epdlin54_V2 60 4. LABORATORY EXERCISES paper and the Paint driver. The e-paper hardware capabilities are somewhat limited; it can just turn pixels on the screen on or off, nothing else. Therefore, I need another piece of software - Paint, to create necessary graphics, like characters or geometric shapes. It is also necessary to define macros for colors. #include #include #include #include #include #define COLORED 0 #define UNCOLORED 1 Epd epd; unsigned char image[10000]; Paint paint(image, 0, 0); I recommend defining the functions that take care of reloading the content of the E-paper display. void reloadO { epd.SetFrameMemory(paint.GetImage(), 0, 0, paint.GetWidthO , paint.GetHeight ()); epd.DisplayPartFrameO ; } • epd.SetFrameMemory(image_buffer, x, y, image_width, image_height) - sets E-paper's pixels to content of imagejbuffer, starting from x, y to x + image_witdh and y + image_height. • epd.DisplayPartFramerQ - displays content of memory. Because of the limited hardware capabilities of the E-paper, Blue Pill needs to keep track of the image - the content to display on the E-paper. Even a single-color low-resolution display takes up too much scarce memory out of Blue Pill. Therefore, use an array with a length of 10000 for this laboratory task. However, if you work with larger 61 4. LABORATORY EXERCISES displays with greater resolutions or multiple colors, you can quickly run out of memory. The commands necessary to complete this laboratory exercise: • epd.LDirInit() - display initialization • epd.ClearQ - clears content from the display, to call this function right after LDirInit() call. • paint.SetWidth(width) -set width for paint, put the resolution width of the e-paper (in our case, 200) • paint.SetHeight(height) - set height for paint, put the resolution height of the e-paper (in our case, 200) • paint.Clear(COLORED) - put as a background color. Use macros COLORED macro for a black background or U N C O L ORED macro for a white background. • paint.DrawStringAt(x, y, text, font, colored) - puts string on beginning of x and y, font could be only &Font8, &Fontl2, &Fontl6, &Font20 or &Font24 I recommend using a black background with white text for better readability. You need to send data via the Bluetooth module. If a module is properly connected, you should be able to see 2 new C O M ports in Device Manager. Then, via PuTTY, you can send data to one of the ports. Notes program Assignment: You should be able to put multiple notes on display. Add functionality that adds every new note on a new line. Approach: If you don't have any lines left on display, clear the display's memory. The width of every sentence depends on the font used. Font8 is 8 pixels wide, Fontl6 is 16 pixels wide, etc. 62 4. LABORATORY EXERCISES 4.11 Open-Smart 2.4" 320x240 TFT Touchscreen SPFD5408 This laboratory exercise aims to create a GUI for the fingerprint sensor. This exercise is different. Use a file with a skeleton code provided by your tutor. Use the provided functions to finish this laboratory exercise. For seminar tutors: this exercise and its libraries work rather well with a different core used most of the time. Use HID Bootloader 1 1 Libraries: Arduino-STM32-8bitTFT 1 2 , Adafruit_Fingerprint 1 3 , Adafruit_GFX 1 4 Equipment: Open-Smart 2.4" 320x240 TFT Touchscreen SPFD5408, Fingerprint sensor R307 Warm up Assignment: Use function getFingerprintEnroll from skeleton source code and TFT API functions to create a GUI menu for fingerprint. Use a serial monitor to send commands. For example, for enrolling a new fingerprint via a sensor, send enroll to the serial monitor. In this part, implement only the enroll function. Approach: To change the size or color of a string, use the Adafruit_GFX library. These functions were explained in previous laboratory exercises 4.7. Instead of a display, use an instance of your TFT display (f .e. tft.setTextColor()). For a better immersion, create something like a booting sequence. In setup function is verified if the fingerprint sensor is detected so you can print some messages like "Sensor is detected". I suggest creating a help menu that lists all commands and their descriptions (in warm up stage, only enroll) Fingerprint GUI 11. For further information visit https: //mischianti . org/stm32-programming -stm32fl-stm32f4-via-usb-with-hid-boot-loader-3/ 12. https : //github.com/nopnop2002/Arduino-STM32-8bitTFT 13. https://github.com/adafruit/Adafruit-Fingerprint-Sensor-Library 14. https://github.com/adafruit/Adafruit-GFX-Library 63 4. LABORATORY EXERCISES Assignment: Finish the GUI by adding command options for fingerprint sensor: identification of fingerprint and erasing fingerprints from fingerprint's database. Approach: Use function get_id() from skeleton's source code and fingerprint's function finger.emptyDatabase() to clear all entries from fingerprint's database 64 5 Conclusion I worked with various displays, from the simplest (and historically first) - LEDs, RGB LEDs (neopixel), L E D 7-segment display, L C D Hitachi HD44780, OLED, TFT, and finally, E-paper. Each of the display devices used in this thesis is still used in real world nowadays: L E D for reading/writing disk indication, Hitachi HD44780 can be found as a display on vending machines, and 7-segment displays are used where good readability at a distance is necessary. I learned to work with display devices from scratch; therefore, I remember problems and pitfalls throughout the learning process. I tried to project these experiences into the creation of the laboratory exercises. In the laboratory exercises, I indicate the principle of operation of the display device and describe the problem the students have to solve with the particular display device. The result of the work is a set of laboratory exercises for IoT display devices. The idea was to give the students an insight into embedded development, and the laboratory tasks were designed with this in mind. By successfully completing the laboratory tasks, the student should acquire the basics of embedded development and the ability to build further knowledge on these basics or apply them as an embedded developer. I've learned a great lesson during the lab exercises development. Experience gained working on my bachelor thesis will help to develop my future professional live. 65 Bibliography 1. LASKAKIT. BluePill ARM STM32 STM32F103C8 Vývojová deska [online], [visited on 2023-10-31]. Available from: https: //www .laskakit.cz/bluepill-arm-stm32-stm32f103c8-vyvojova- deska/. 2. MISCHIANTI, Renzo. STM32F103C8T6 Blue Pill: high resolution pinout and specs [online]. 2022-05-15. [visited on 2023-10-07]. Available from: https : //mischianti . org/2022/05/15/stm32f 103c8t6-blue-pill-high-resolution-pinout-and-specs/. 3. STMICROELECTRONICS. STM32F103C8 [online]. STMicroelectronics [visited on 2023-10-06]. Available from: https: //www. st .com/en/microcontrollers-microprocessors/stm32f103c8.h tml. 4. How to use ADC in STM32F103C8T6? STM32 ADC Tutorial [online]. Electronicshub, 2020-03-30 [visited on 2023-09-07]. Available from: https : //www. electronicshub. org/how-to-use-ad c-in-stm32f103c8t6/. 5. CARRASCO, Daniel. STM32F103 Bootloader and programming [online]. Electrosoftcloud, 2020-12-06 [visited on 2023-09-07]. Available from: https://www.electrosoftcloud.com/en/stm32f103 -bootloader-and-programming/. 6. POOLE, Nick; BBOYHO. Light-Emitting Diodes (LEDs) [online], sparkfun [visited on 2023-10-12]. Available from: https : //lear n.sparkfun.com/tutorials/light-emitting-diodes-leds/a 11. 7. LED dioda červená 5mm [online]. Dratek [visited on 2023-10-08]. Available from: https: //dratek.cz/arduino/1031-led-dioda- cervena-5mm.html. 8. LASKAKIT. 8x inteligentní RGB LED NeoPixel pásek, WS2812B, 5050, 5V [online], [visited on 2023-10-12]. Available from: https ://www.laskakit.cz/8x-inteligentni-rgb-led-neopixel-p asek--ws2812b—5050--5v/?variantId=11621¤cy=eur &gclid=Cj0KCQjwsp6pBhCfARIsAD3GZuaa4HTR_5cJ5T-2YP8TtYz WNC9u0TmryH0M0MrVMa0UJIIiC0VftwwaAvX3EALw_wcB. 66 BIBLIOGRAPHY 9. WORLDSEMI. WS2812B Intelligent control LED integrated light source [online], [visited on 2023-10-08]. Available from: https: //cdri-shop. adaf r u i t . com/datasheets/WS2812B. pdf. 10. WORLDSEMI. WS2812B Intelligent control LED integrated light source [online], [visited on 2023-10-08]. Available from: https: //cdri-shop. adaf r u i t . com/datasheets/WS2812B. pdf. 11. KOKKINOS, Dimitris. Learn How a 4-Digit 7-Segment LED Display Works and how to control it using an Arduino - Software Particles [online]. Softwareparticles [visited on 2023-10-12]. Available from: https : //sof twareparticles . com/learn-how-a-4-digi t-7-segment-led-display-works-and-how-to-control-it-u sing-an-arduino/. 12. LASKAKIT. 8x8 LED matice s MAX7219 3mm [online], [visited on 2023-10-17]. Available from: https: //www. laskakit. cz/8x8 -led-matice-s-max7219-3mm-červena/. 13. INTERGRATED, Maxim. MAX72I9/MAX722I Serially Interfaced, 8- Digit LED Display Drivers" [online]. Maxim Integrated [visited on 2023-10-08]. Available from: https: //www. analog. com/medi a/en/technical-documentation/data-sheets/max7219-max7 221.pdf. 14. O D U N L A D E , Emmanuel. Using a 16x2 I2C LCD display with ESP32 [online]. Electronics-lab [visited on 2023-10-17]. Available from: https://www.electronics-lab.com/project/using-16 x2-i2c-lcd-display-esp32/. 15. HITACHI. HD44780U {LCD-IT) (Dot Matrix Liquid Crystal Display Controller/Driver) [online], [visited on 2023-10-08]. Available from: https://www.sparkfun.com/datasheets/LCD/HD44780.p df. 16. LASKAKIT. 0.96 "128x64 OLED displej, I2C, modroIžlutý [online]. [visited on 2023-10-17]. Available from: https : //www. laskakit .cz/oled-displej-modry-a-zluty-128x64-0-96--i2c/. 17. LASKAKIT. 0.96 "128x64 OLED displej, SPI, modro/žlutý [online]. [visited on 2023-10-17]. Available from: https : //www. laskakit .cz/oled-displej-modry-a-zluty-128x64-0-96--spi/. 67 BIBLIOGRAPHY 18. ADAFRUIT. Adafruit GFX Library [online]. Github [visited on 2023-10-08]. Available from: https ://github. com/adaf ruit/Ad afruit-GFX-Library#adafruit-gfx-library-. 19. L A S K A K I T . Open-Smart 2.4"320x240 TFT displej, dotykový, Arduino shield [online], [visited on 2023-10-17]. Available from: https://www.laskakit.cz/open-smart-320x240-barevny-lc d-tft-displej-2-4-shield-arduino/. 20. WAVESHARE. 1.54inch e-Paper Module Manual - Waveshare Wiki [online], [visited on 2023-10-08]. Available from: https: //www .waveshare.com/wiki/1.54inch_e-Paper_Module_Manual#Int roduction. 21. A R D U I N O . pinModeQ [online], [visited on 2023-09-14]. Available from: https://www.arduino.cc/reference/en/language /functions/digital-io/pinmode/. 22. ARDUINO. Serial.begin() [online]. [visited on 2023-09-17]. Available from: https://www.arduino.cc/reference/en/language /functions/communication/serial/begin/. 23. A R D U I N O . Serial.printing, [online], [visited on 2023-09-17]. Available from: https : //www. arduino. cc/ref erence/en/lang uage/functions/communication/serial/println/. 24. ARDUINO. Serial..print() [online], [visited on 2023-09-17]. Available from: https://www.arduino.cc/reference/en/language /functions/communication/serial/print/. 25. ARDUINO. Serial.readStringUntilQ [online], [visited on 2023-09- 18]. Available from: https://www.arduino.cc/reference/en/l anguage/functions/communication/serial/available/. 26. ARDUINO. Serial.readStringUntilQ [online], [visited on 2023-09- 17]. Available from: https://www.arduino.cc/reference/en/l anguage/functions/communication/serial/readstringuntil /. 27. A R D U I N O . delayQ [online], [visited on 2023-09-18]. Available from: https://www.arduino.cc/reference/en/language/func tions/time/delay/. 68 BIBLIOGRAPHY 28. ARDUINO. digitalWrite() [online]. [visited on 2023-09-18]. Available from: https://www.arduino.cc/reference/en/language /functions/digital-io/digitalwrite/. 29. What is Morse Code? [online]. U C L Computer Science [visited on 2023-09-19]. Available from: http: //students . cs . ucl. ac. uk/s choolslab/proj ects/PY2/introduction.html. 30. ETECHNOPHILES. 10 Types of Potentiometer: How to choose & Applications [online], [visited on 2023-09-17]. Available from: https : //www. etechnophiles . com/types-of-potentiometer- applications/. 31. BOURNS. Multiturn Trimpot® Trimming Potentiometers [online], [visited on 2023-09-17]. Available from: https : //www. bourns . c om/products/trimpot-trimming-potentiometers/trimpot-t rimming-potentiometers-multiturn. 32. ARDUINO. analogRead() [online]. [visited on 2023-09-19]. Available from: https://www.arduino.cc/reference/en/language /functions/analog-io/analogread/. 33. ARDUINO. analogWrite() [online]. [visited on 2023-09-19]. Available from: https://www.arduino.cc/reference/en/language /functions/analog-io/analogwrite/. 34. A R D U I N O . map() [online], [visited on 2023-09-19]. Available from: https://www.arduino.cc/reference/en/language/func t i ons/math/map/. 35. NICHOLLS, Paul. 7 Segment Displays [online]. [visited on 2024- 01-31]. Available from: https : //pf nicholls . com/Electronics /LEDDisplays.html. 36. HITACHI. HD44780U {LCD-U) (Dot Matrix Liquid Crystal Display Controller/Driver) [online], [visited on 2024-02-11]. Available from: https://www.sparkfun.com/datasheets/LCD/HD44780.p df. 37. HITACHI. HD44780U (LCD-IT) (Dot Matrix Liquid Crystal Display Controller/Driver) [online], [visited on 2024-02-11]. Available from: https://www.sparkfun.com/datasheets/LCD/HD44780.p df. 69 BIBLIOGRAPHY 38. HITACHI. HD44780U {LCD-U) (Dot Matrix Liquid Crystal Display Controller/Driver) [online], [visited on 2024-02-11]. Available from: https://www.sparkfun.com/datasheets/LCD/HD44780.p df. 39. HITACHI. HD44780U (LCD-IT) (Dot Matrix Liquid Crystal Display Controller/Driver) [online], [visited on 2024-02-11]. Available from: https://www.sparkfun.com/datasheets/LCD/HD44780.p df. 40. HITACHI. HD44780U (LCD-IT) (Dot Matrix Liquid Crystal Display Controller/Driver) [online], [visited on 2024-02-11]. Available from: https://www.sparkfun.com/datasheets/LCD/HD44780.p df. 41. A R D U I N O . attachlnterrupt() [online], [visited on 2024-02-04]. Available from: https : //www. arduino. cc/ref erence/en/lang uage/functions/external-interrupts/attachinterrupt/. 42. HOW2ELECTRONICS. How to use Rotary Encoder with Arduino - Tull Guide [online], [visited on 2024-02-04]. Available from: https://how2electronics.com/how-to-use-rotary-encoder- with-arduino/. 43. FAHLE, Eberhard. LedControl. Available also from: http: //wayo da.github.io/LedControl/index.html. 44. SANTOS, Rui. Guidefor 8x8 Dot Matrix MAX7219 with Arduino \ Random Nerd Tutorials [online], [visited on 2024-02-20]. Available from: https://randomnerdtutorials.com/guide-for-8x8-do t-matrix-max7219-with-arduino-pong-game/. 70