Hi everyone! I'm still really new to coding and Arduino, but I have a school project which is essentially to build a morse code decoder. For my design, I'm thinking of coding a long/short press button that will register as either dots (short press) or dashes (long press) and then save in that order on a SD card. A "space" button will separate the letters from one another. Once the "enter" button is pressed, the arduino should be able to retrieve an already there file on the SD card which has the translations from morse code to english. I have the basics of retrieving files down, but I don't know how to translate from the file on the SD card. I'm also not sure how to record the dots and dashes and spaces on the SD card. And another small thing is I have a longpress and shortpress code, but it isn't working for some reason. Sorry if this is confusing, but I'd really appreciate if someone could help! The button code should be down below
int inPin = 8; //dot dash button
int val = 0;
long buttonTimer = 0;
long longPressTime = 250; //can be changed: time we want for dash to activate
void setup() {
pinMode(inPin, INPUT); // declare button as input
}
void loop() {
if (digitalRead(inPin) == HIGH) { //Button pressed
buttonTimer = millis(); //records time
if ((millis() - buttonTimer > longPressTime) { //Button pressed long enough
//record as a dash
} else { //Button not pressed long enough
//record as a dot
}
}
How is there ever going to be more than 1 microsecond difference between these two lines?
Not only do you need to know what the button input is now, you need to know what it was before to decides if it was just pressed or it's being held down.
Their is no need to have an SD card, the data recieved by mores code is very small and will fit into the Arduino's memory.
You do not have an extra button for space, you decide if it is a letter break or a word break by simply timing the gap between the dot and dash.
Morse code does not work at fixed rates but with ratios of time. A dot being one unit of time and a dash being three units of time. So the strategy to lock onto a morse stream is to assume that the timing of the first press is a dash. Then make the dot / dash time threshold half this value. If you then receive something less than this threshold call it a dot and make the threshold twice the time just received. In that way you will always lock on to the correct timing.
This threshold is adjusted for the key down times, the key up events, the spaces between the dots and dashes are treated the same way except the threshold is not adjusted. So less than the threshold is still the same letter, greater than the threshold but less than 2.5 times the threshold is a space between letters and greater than 2.5 times the threshold is a space between words.
The timing code should detect then the button is first pressed down and a note of the millis time made in a variable. Then it should detect when the button is released and note of the millis time made in an other variable. Subtract the two times to get the length of time it was held down. Look at the "State Change" example in the IDE to see how to detect when the button becomes pressed, not just when it is pressed.
Thank you for your input! How would the morse code be stored on the arduino's memory though? I was told by my teacher that I would need an SD card for the translation file and to store the dots and dashes, etc. I don't know if it makes any difference but I will be using an arduino uno board connected to a battery pack.
How would the morse code be stored on the arduino's memory though?
You could store a morse character in a byte, a zero for a dot and a one for a dash. However that gives you a leading zero problem for characters that start with dots. So a byte with nothing in it would start with a value of one, in binary that is
0000 0001
Then when a new element comes along you shift this byte one place to the left and if it is a dash put a one in the least significant bit and if it is a dot do nothing. So from that start suppose you have a dot:-
Byte after receiving a dot
0000 0010
Next say we have another dot we get
0000 0100
finally say we have a dash we get
0000 1001
So that byte finish up with a value of 9 for dot dot dash
This is morse code for a U
Take the byte and apply it to a look up table, which is an array consisting of two byte integers. The most significant byte consisting of the ASCII code and the least significant byte your morse code byte as received in the method above. Search this array looking for your received byte in the least significant byte of the int array and when you find it the ASCII character is in the most significant byte. You can then store that in a char array or better simply write it ( not print ) to the serial output for display on your monitor.
In the case of the above example the entry in your look up table will be
ASCII for U = 0x55
Received morse for U = 0x09
entry = 0x5509
I don't know if it makes any difference but I will be using an arduino uno board connected to a battery pack.
Makes no difference
I was told by my teacher that I would need an SD card for the translation file and to store the dots and dashes,
No that look up table will easily fit into the SRAM for 26 letters and 10 numbers that is only 72 bytes for your translation table.
I guess that on the SD card, you would store the translated morse code ie letters and numbers etc., not invent some translation of the dots and dashes.
That is, if you enter dot dot dot dash dash dash dot dot dot through the keys, you would translate that as you are entering it and write the letters "SOS" to the SD card.