I’ve always wanted to have a good excuse to learn the Morse code. It’s cool to have a secret way of communicating with someone else. Morse code is now pretty much a thing of the past, and it’s good that almost no one understands it now. However, this project is not aimed at teaching how to use the Morse code; instead, it focuses more on taking the user’s Morse code input, displaying the message on a screen, and, if the message is correct, sending it to a phone as a text message. If possible, the user can also input a text message from a phone and send that message back to the PocketBeagle, where the message will be displayed. The project’s goal is to familiarize myself with Morse code through a series of practice transmission instead of merely trying to memorize the whole alphabet.
Many other projects on hackster.io use Arduino to make Morse code machines (like this Arduino Morse Code Machine and this other Morse Code Machine). However, I cannot find anyone who used a PocketBeagle, which is why I want to try to implement it on one.
FunctionsMy project includes a potentiometer which allows the user to scale up/down the pause times between letters and words. In a typical setting, the space between dots and dashes that are part of the same letter is 1 second, the space between different letters is 3 seconds, and the space between different words is 7 seconds. My project allows the user change the pause between different letters from 1.5 to 6 seconds and the pause between different words from 3.5 to 14 seconds. This functionality gives a less experienced user more time for inputting, while a more experienced user can save time and input letters faster.
If the pause between letters is 3 seconds and the pause between words is 7 seconds, the user can take up to 3 seconds to enter each dot/dash. After 3 seconds pass without getting any input from the user, the system translates the code into a letter. After this translation, the system will wait for 4 seconds (pause between words minus pause between letters = 7 - 3 = 4 seconds) before adding a space behind the letter for a new word.
My project includes three buttons. The blue arcade button is used for inputting Morse code. It will light up when the user presses it. The red pushbutton is used for deleting incorrect letters. The green pushbutton is used as a control button. After the user adjusts the pause times with the potentiometer, they can press the green button to start inputting Morse code. If they need a break in between or are done with inputting, they can press it again to stop inputting. Pressing the green pushbutton for more than 3 seconds allows the user to transmit the Morse code and reset the message string. (Note that to transmit the message, the system must be in the "stop inputting" mode. Also, the message can't be transmitted if nothing is inputted.)
When the user presses the blue arcade button, the button's built-in LED flashes either short (a dot) or long (a dash). The buzzer also buzzes accordingly. An SPI screen displays the dot/dash entered, and after the user inputs the Morse code the letter inputted shows up on the screen.
Note that the transmitting/receiving function does not work as of now. I have not yet implemented them in the project due to time constraints. A past ENGI 301 project that involves transmitting message can be found here.
Build InstructionsI built my circuit based on the system and power block diagrams below. They indicate the corresponding pins for each component on the PocketBeagle.
Preliminary Setup
The image below is a preliminary setup of the project to test out the software before the hardware components arrived. The potentiometer and buzzer are attached as they are in the final setup. The red LED and black pushbuttons correspond to the blue arcade button in the final setup. Pressing the black pushbutton lights up the LED and buzzes the buzzer. The red pushbutton in the image is the delete button. The blue pushbutton in the image is the control button (which is replaced with a green button in the final setup).
The components don't have to be placed exactly as they are in the images. I placed all the buttons on the right so that they won't be blocked by all the wires. They can be placed anywhere as long as they are connected to the right pins.
I started building the circuit from the potentiometer. Connect the middle pin to signal at AIN0 (P1_19), the left pin to power at REF+ (P1_18), and the right pin to ground at REF- (P1_17). (It is fine to switch the left and right pins.) On the Cloud9 IDE, run the file potentiometer.py in project_01 to test if it works.
Next, I attached the buzzer. Connect one end to ground and the other to PWM0 (P1_36). Run buzzer.py to test it.
Then, I attached the buttons based on the schematic below with pull-up resistors to the 3.3-V power rail. The arcade button and the two pushbuttons all have the same configuration. One end of the buttons is connected to ground. The other end has a pull-up resistor to the power rail and a wire that connects to their respective pins on the PocketBeagle (P2_02 for the blue arcade button, P2_06 for the green control button, and P2_08 for the red delete button).The arcade button also includes an LED, so I also attached an LED based on the schematic below for an LED in the active high configuration.
Final Setup
After the SPI screen and arcade button arrived, I attached them to my project. I replaced the black pushbutton and red LED in the preliminary set up with the blue arcade button. Make sure to solder wires to each of the four legs of the arcade button. Out of the four, two are for the LED (which has a cathode and an anode), and two are for the button. The LED only works if the anode is connected to ground. If the arcade button's LED does not light up on the first try, switch the two wires so that it is connected the right way around.
For the SPI screen, solder a row of headers onto the SPI side of the SPI display, as below. Also, make sure to bridge IM1, IM2, and IM3 with solder. To connect the SPI screen onto the breadboard, attach GND on the screen to GND on the PocketBeagle (P1_16), VIN to 3.3V (P1_14), CLK to CLK (P1_8), MISO to MISO (P1_10), MOSI to MOSI (P1_12), CS to GPIO5 (P1_6), D/C to GPIO89 (P1_4), and RST to GPIO87 (P1_2). After attaching the SPI screen, make sure to follow the software build instructions in my GitHub page below to install all the necessary software. Test out the screen with spi_screen.py to make sure it functions properly.
Issues with the SPI screen
After testing out the SPI screen, I notice that there is a significant delay before the image can be displayed. It only takes around 0.25 seconds for the code to open the file and scale the image to the right size. However, it takes another 3.8 seconds before the image can be displayed on the screen. If the code calls for an image to be displayed, there will be at least a 4-second delay before the image shows up. The same delay occurs with displaying text as well.
I originally planned to display the Morse code input and translated text on the SPI screen. The screen should update right after the user presses the arcade button and input something. However, due to how slowly the screen updates, it isn't possible to do so. If the screen were to display the Morse code, then the entire system would crash and not function properly (it pretty much can't translate any of the Morse code correctly).
The SPI screen can still display the images containing the welcome message and instructions. It takes quite a long time to display but does not affect the code's other functionalities. I can also display the pause times when the users configure them with the potentiometer. However, it still takes the screen a long time to update (see the Demo 1 video below).
There may be some issues with the Adafruit libraries which I installed for the SPI screen. A possible solution is to install other libraries for the SPI display (specifically, the ones used in this past ENGI 301 project). From this other project, the display does not lag at all when it uses other libraries. However, due to time constraints, I did not have the chance to try it out.
For now, the instructions of how to operate the project is displayed on the SPI screen. The Morse code input and translated texts are displayed on the Cloud9 Terminal.
Operating InstructionsFollow the following steps after building the circuit above:
- Plug the microUSB cable into the PocketBeagle and plug the other end into your laptop.
- Wait a few seconds for the PocketBeagle to power up and ping the PocketBeagle via terminal to check its connection.
- Type 192.168.6.2:3000 onto your browser to open Cloud9.
- Follow the instructions in the README.md on my GitHub page below to run the code.
The videos below demonstrate the Morse code transceiver in action. In the first video, I adjusted the pause times between letters and words with the potentiometer. In the second video, I inputted the Morse code of "ENGI 301" and demonstrated that it can delete letters and transmit the message. In the current project, transmitting the message simply means resetting the message string.
(I forgot to take videos of the message failing to be transmitted. I attached what the SPI screen would display in the "Functions" section above. In cases where the user tries to transmit message when it is still in the "start inputting" mode, a warning message will display. When the message string is still empty, another warning message will display. The videos below only demonstrate the device successfully transmitting the message.)
ImprovementsSoftware Issues
There is a tiny bug in the software which the videos do not show. The user shouldn't input anything if the time elapsed is greater than pause_between_letters. For example, let pause_between_letters = 6s and pause_between_words = 14s. 6 seconds after the user's last input, the system will translate the code into letter. It will take another 14 - 6 = 8 seconds before the system adds a space after the letter. Within these 8 seconds, the user can input letters normally, as long as they do it before 6 seconds elapsed. If they didn't input anything at first and try to input Morse code between 6 and 8 seconds, there will be a bug. Whatever they input will be translated as either an E (.) or a T (-). The system figures that another pause_between_letters duration has passed, and whatever being inputted is just the letter itself. In this case, the user can't enter the full Morse code of their intended letter. They have to press the delete button to remove the incorrectly-added E or T, then proceed with inputting again.
The check_and_translate_code(self) function needs to be modified to fix the bug above. I tried to adjust it, but it created a lot more bugs elsewhere in the code. The control button would become unresponsive, and the message transmission wouldn't work. Altering the code seemed to create more problems, so I decided to keep it as it is.
The same issue seems to occur after the red delete button is pressed. If the user waits until after pause_between_letters has elapsed before inputting anything, then the bug above will occur.
The reset_time(self) in the morse.py code file attempts to fix this bug where the system prematurely translates the letter. This function is implemented after the user switches into the "start inputting" mode. This way, if the user doesn't input anything after pause_between_letters has elapsed, the system resets the time so that the bug above won't occur.
I tried to call reset_time(self) to reset the time after a letter is deleted. However, it did not fix the issue and created more bugs. Now, the prematurely-translated letters can't be deleted. Therefore, the delete_last_character(self) function also needs to be altered slightly to fix this bug.
If the user can keep these two bugs in mind and operate the device accordingly, then these bugs can be avoided as in the video.
Other Improvements
As noted above, the transmission function of my device does not work as of now. Transmitting the message merely resets the message string and allows the user to input Morse code from scratch. My project name "Morse Code Transceiver" is therefore a bit of a misnomer. It can neither transmit not receive.
My software diagram includes another pushbutton to toggle between transmission and reception mode. In transmission mode, the device should take the translated message and send it to a phone as a text message. (Again, this project can be a good reference.) As for the reception mode, the device should receive text messages from a phone and display its Morse code on the SPI screen. However, I cannot find any similar projects online, so I'm not sure if the PocketBeagle has such a capability.
I also noted above that the SPI screen has significant delays when it displays images and texts. Alternative libraries may need to be used to fix this issue. The goal is to display all the Morse code and messages on the SPI screen (not on the Cloud9 Terminal).
AcknowledgementsI'd like to thank Professor Erik Welsh for all his help during office hours. I'd also like to thank ChatGPT for helping with debugging the code.
Comments