Project updated to beta 6.4 (released on May 30th, 2022)
This project is going to show you how easy is to make a Morse Code trainer using a Push Button, a Display using MicroGraphics and a Piezo speaker to make a buzzing sound when pushing the button. We'll write our application using all the peripheral drivers included in Meadow.Foundation.
Meadow.Foundation a platform for quickly and easily building connected things using.NET on Meadow. Created by Wilderness Labs, it's completely open source and maintained by the Wilderness Labs community.
If you're new working with Meadow, I suggest you go to the Getting Started w/ Meadow by Controlling the Onboard RGB LEDproject to properly set up your development environment.
Step 1 - Assemble the circuitWire your project like this:
Create a new Meadow Application project in Visual Studio 2022 for Windows or macOS and name it MorseCodeTrainer.
Step 3 - Add the required NuGet packagesFor this project, search and install the following NuGet packages:
Step 4 - Write the code for MorseCodeTrainerDisplayControllers.cs
Copy the following code below:
public class DisplayControllers
{
MicroGraphics graphics;
public DisplayControllers()
{
Initialize();
DrawTitleAndFrame();
}
void Initialize()
{
var config = new SpiClockConfiguration(
new Frequency(48000, Frequency.UnitType.Kilohertz),
SpiClockConfiguration.Mode.Mode3);
var spiBus = MeadowApp.Device.CreateSpiBus(
clock: MeadowApp.Device.Pins.SCK,
copi: MeadowApp.Device.Pins.MOSI,
cipo: MeadowApp.Device.Pins.MISO,
config: config);
var display = new St7789
(
device: MeadowApp.Device,
spiBus: spiBus,
chipSelectPin: null,
dcPin: MeadowApp.Device.Pins.D01,
resetPin: MeadowApp.Device.Pins.D00,
width: 240, height: 240,
displayColorMode: ColorType.Format16bppRgb565
);
graphics = new MicroGraphics(display)
{
Stroke = 1,
CurrentFont = new Font12x20(),
Rotation = RotationType._270Degrees
};
graphics.Clear();
graphics.Show();
}
void DrawTitleAndFrame()
{
graphics.Clear();
graphics.DrawRectangle(0, 0, 240, 240);
graphics.DrawText(24, 15, "Morse Code Coach");
graphics.DrawHorizontalLine(24, 41, 196, Color.White);
graphics.Show();
}
public void DrawCorrectIncorrectMessage(string question, string answer, bool isCorrect)
{
Color color = isCorrect ? Color.GreenYellow : Color.Red;
graphics.DrawText(120, 65, question, color, ScaleFactor.X3, TextAlignment.Center);
UpdateAnswer(answer, color);
graphics.DrawText(120, 190, isCorrect ? "Correct!" : "Try again!", color, ScaleFactor.X1, TextAlignment.Center);
graphics.Show();
}
public void ShowLetterQuestion(string question)
{
graphics.DrawRectangle(2, 65, 236, 60, Color.Black, true);
graphics.DrawText(120, 65, question, Color.White, ScaleFactor.X3,
TextAlignment.Center);
graphics.DrawRectangle(5, 120, 230, 110, Color.Black, true);
graphics.Show();
}
public void UpdateAnswer(string answer, Color color)
{
int x = 0;
int y = 143;
switch (answer.Length)
{
case 1: x = 109; break;
case 2: x = 96; break;
case 3: x = 83; break;
case 4: x = 71; break;
case 5: x = 57; break;
default: return;
}
graphics.DrawRectangle(24, y, 200, 30, Color.Black, true);
foreach (var ch in answer)
{
DrawDashOrDot(x, y, ch == '-', color);
x += 26;
}
graphics.Show();
}
void DrawDashOrDot(int x, int y, bool isDash, Color color)
{
if (isDash)
{
graphics.DrawRectangle(x + 3, y + 6, 20, 8, color, true);
}
else
{
graphics.DrawCircle(x + 11, y + 10, 10, color, true);
}
graphics.Show();
}
}
- Initialize - Initializes the ST7789 display along with MicroGraphics to easily draw shapes and text.
- DrawTitleAndFrame - Draws a rectangle around the display and the title Morse Code Coach.
- DrawCorrectIncorrectMessage - Shows a message to indicate if the user's answer is either right or wrong.
- ShowLetterQuestion - Clears the previous character and answer, and shows a new character.
- UpdateAnswer - Arranges the dash and dots as the user enters them as well as draws them at the given color which could be green or red depending if the answer is right or wrong.
- DrawDashOrDot - Draws dashes and dots depending of what the user enters.
MeadowApp.cs
Copy the following code below:
// public class MeadowApp : App<F7FeatherV1, MeadowApp> <- If you have a Meadow F7v1.*
public class MeadowApp : App<F7FeatherV2, MeadowApp>
{
Dictionary<string, string> morseCode;
PushButton button;
PiezoSpeaker piezo;
DisplayControllers displayController;
Timer timer;
Stopwatch stopWatch;
string answer;
string question;
public MeadowApp()
{
Initialize();
}
void Initialize()
{
var onboardLed = new RgbPwmLed(device: Device,
redPwmPin: Device.Pins.OnboardLedRed,
greenPwmPin: Device.Pins.OnboardLedGreen,
bluePwmPin: Device.Pins.OnboardLedBlue);
onboardLed.SetColor(Color.Red);
displayController = new DisplayControllers();
piezo = new PiezoSpeaker(Device, Device.Pins.D09);
button = new PushButton(device: Device, Device.Pins.D04);
button.PressStarted += ButtonPressStarted;
button.PressEnded += ButtonPressEnded;
stopWatch = new Stopwatch();
timer = new Timer(2000);
timer.Elapsed += TimerElapsed;
LoadMorseCode();
ShowLetterQuestion();
onboardLed.SetColor(Color.Green);
}
void LoadMorseCode()
{
morseCode = new Dictionary<string, string>();
morseCode.Add("O-" , "A");
morseCode.Add("-OOO" , "B");
morseCode.Add("-O-O" , "C");
morseCode.Add("-OO" , "D");
morseCode.Add("O" , "E");
morseCode.Add( "OO-O", "F");
morseCode.Add("--O" , "G");
morseCode.Add("OOOO" , "H");
morseCode.Add("OO" , "I");
morseCode.Add("O---" , "J");
morseCode.Add("-O-" , "K");
morseCode.Add("O-OO" , "L");
morseCode.Add("--" , "M");
morseCode.Add("-O" , "N");
morseCode.Add("---" , "O");
morseCode.Add("O--O" , "P");
morseCode.Add("--O-" , "Q");
morseCode.Add("O-O" , "R");
morseCode.Add("OOO" , "S");
morseCode.Add("-" , "T");
morseCode.Add("OO-" , "U");
morseCode.Add("OOO-" , "V");
morseCode.Add("O--" , "W");
morseCode.Add("-OO-" , "X");
morseCode.Add("-O--" , "Y");
morseCode.Add("--OO" , "Z");
morseCode.Add("-----", "0");
morseCode.Add("O----", "1");
morseCode.Add("OO---", "2");
morseCode.Add("OOO--", "3");
morseCode.Add("OOOO-", "4");
morseCode.Add("OOOOO", "5");
morseCode.Add("-OOOO", "6");
morseCode.Add("--OOO", "7");
morseCode.Add("---OO", "8");
morseCode.Add("----O", "9");
}
async void TimerElapsed(object sender, ElapsedEventArgs e)
{
if (!morseCode.ContainsKey(answer)) { return; }
timer.Stop();
bool isCorrect = morseCode[answer] == question;
displayController.DrawCorrectIncorrectMessage(question, answer, isCorrect);
await Task.Delay(2000);
if (isCorrect)
{
ShowLetterQuestion();
}
else
{
answer = string.Empty;
displayController.ShowLetterQuestion(question);
}
timer.Start();
}
void ButtonPressStarted(object sender, EventArgs e)
{
piezo.PlayTone(440);
stopWatch.Reset();
stopWatch.Start();
timer.Stop();
}
void ButtonPressEnded(object sender, EventArgs e)
{
piezo.StopTone();
stopWatch.Stop();
if (stopWatch.ElapsedMilliseconds < 200)
{
answer += "O";
}
else
{
answer += "-";
}
displayController.UpdateAnswer(answer, Color.White);
timer.Start();
}
void ShowLetterQuestion()
{
answer = string.Empty;
question = morseCode.ElementAt(new Random().Next(0, morseCode.Count)).Value;
displayController.ShowLetterQuestion(question);
}
}
- Initialize - Initializes the DisplayController, the Piezo speaker and the PushButton. For the button we register the PressStarted and PressEnded event handlers to monitor the user's input and determine if its a dot or dash.
- LoadMorseCode - Loads a Dictionary of the alphabets and numbers with its corresponding morse code combination as '-' as dashes and '0' as dots.
- TimerElapsed - We use a Timer to check when the user has finished entering his/her answer, so when this event is fired, the app determines if its the right or wrong morse code combination for the character shown.If its right, the character and answer is show in green with a message saying "Correct" and shows another character, otherwise, the letter and answer is shown in red with a message saying "Try again!", clearing the user's answer to try entering a new morse code combination.
- ButtonPressStarted - It plays a tone on the Piezo, starts a Stopwatch and stops the timer.
- ButtonPressEnded - Stops the Piezo from playing a tone, stops the stopwatch and depending on the elapsed time it determines if its a dash and dot to then draws it on the display, and finally starts the timer to see if the user will enter another dash or dot or it completes its answer, firing the TimerElapsed event.
- ShowLetterQuestion - Picks a character from the dictionary at random and calls
ShowLetterQuestion
method on the DisplayController.
Click the Run button in Visual Studio. It should look like to the following GIF:
This project is only the tip of the iceberg in terms of the extensive exciting things you can do with Meadow.Foundation.
- It comes with a huge peripheral driver library with drivers for the most common sensors and peripherals.
- The peripheral drivers encapsulate the core logic and expose a simple, clean, modern API.
- This project is backed by a growing community that is constantly working on building cool connected things and are always excited to help new-comers and discuss new projects.
Comments