By Sydney Lim and Brian Lee
The goal of this project is to create a vision test inspired by a tumbling E chart. A user will choose the difficulty (easy/hard) and mode (practice/test) on Termite, which is connected through the Bluetooth module. They must then stand a certain distance away from an 8x8 LED matrix. This distance is gauged using the Ultrasonic Distance Sensor. The 8x8 matrix will stop blinking when the user is at the proper distance. The LED matrix will show an “E” rotated in random directions, similar to a tumbling E chart. The user has to indicate the orientation of the branches of the “E” using the joystick on a Wii Nunchuk. The user can choose to take the test again with a prompt on Termite.
To ensure the basic functionality of our project, we will first meet these checkpoints:
Program the 8x8 LED matrix to display E's in different directions
Connect the Wii Nunchuk and read its joystick inputs to correspond them to different directions
Implement the distance sensor to ensure the user is at an appropriate distance
Connect to Termite via the Bluetooth Module to communicate with the user
To improve the functionality, we will then:
Program the 8x8 LED matrix to display E's in different sizes
Given extra time, we will:
Add a way for the user to visually know when they are at the correct distance
Connect a 7-segment display to show the user's current score during the test
Implement a random number generator for choosing the directions of the E's and add different test modes to increase replay value
Here is the block diagram of our vision test.
The HC-SR04 Distance Sensor is activated by a PWM signal. A free-run counter of a timer is used. When an overflow or underflow occurs, the timer will generate a time interrupt. The interrupt service routine of the timer can tell you what events were generated in the timer interrupt. The update interrupt flag (UIF) is set when counter overflow/underflow occurs.
A valid transition of an external signal can also trigger the timer interrupt. When a transition is detected, the timer hardware generates an interrupt and copies the free-run counter value into the capture/compare register. By keeping track of the CCR values from two consecutive interrupts, we can compute the amount of time that has passed between the two transitions. This value can be converted into a distance.
The timer interrupt service routine must clear these flags to prevent it from being immediately called again by the processor.
Pin PE11 is used for the trigger (TIM1_CH2) and pin PA5 is used for the echo (TIM2_CH1).
The system timer (SysTick) is used for implementing a delay function, seeding a random number generator, as well as implementing the time-out feature of test mode. Interrupts are generated with a period of 1ms.
The delay function gets the current SysTick value and waits for a certain number of ticks. The delay function is occasionally used to indicate certain events. For example, when a user times out in test mode, we flash the 8x8 LED Matrix for 1.5 seconds by turning on the LED, waiting with delay(1500), and then turning off the LED.
The RNG for the E directions are also implemented with SysTick. The SysTick value is taken after the user inputs their chosen options (difficulty and test mode) and moves to the correct distance away from the display. This time is variable, as the user is not going to take the same amount of time, down to the millisecond, to do this every time. Thus, we use this value to seed srand(). Then, we call rand() and use that value, modulo 4, to determine which direction to display the E in.
Lastly, SysTick is used for the time-out feature of test mode. In test mode, the user has 5 seconds to input a direction. The SysTick value is taken after the E is displayed. If the difference between the current SysTick value and that value is over 5000 ticks, or 5 seconds, we flash the 8x8 LED Matrix and move onto the next E.
The I2C serial interface is used to communicate with the 8x8 LED Matrix and the Wii Nunchuk. We configure PB6 for serial clock (SCL) and PB7 for serial data (SDA).
For the 8x8 LED Matrix, we simply send a command byte to start the oscillation. After this initialization, we can send a buffer of data bytes that correspond to the LEDs that we want to light up, followed by another command byte to display it to the LED. This last command byte can be changed to instead make the LED blink.
For the Wii Nunchuk, we initialize it by sending a series of command bytes and reading the device ident data. Then, we read a series of 6 bytes, the first two of which correspond to the X- and Y-axes of the joystick. We continuously read this data and divide it into quadrants to determine the direction that the user input.
The user communicates with the program through Termite, which is connected to via the Bluetooth Module and USART. Bidirectional communication with USART requires a minimum of two pins:
RX for receiving data (PA3)
TX for transmitting data (PA2)
The functions printf() and scanf() are retargeted to transmit and receive data to Termite.
The 7-segment display is controlled by 7 GPIO pins (PE10, PE12, PE13, PE14, PE15, PH0, PH1). Each segment is turned on by setting the corresponding bit in the output data register, and turned off by clearing this bit. We wrote functions for turning on the corresponding segments to display digits from 0 through 8.
Here is the demo video for the Vision Test: https://youtu.be/Bk0X0REsdyE
Here is photo of the hardware connections. The white wire on the left connects to an external 5V power source. The white wire on the right connects to the Wii Nunchuk.