2

I have created a morse code input device using the following :
*Arduino Uno
*Grove Base sheild
*Grove button
*Grove light sensor
*LCD RGB Backlight

I have it so that a word is displayed on the LCD (in this case 'yellow'). That word then has to be input as morse code via the button. As it is input, the letters are translated from Morse code to English and displayed as letters on the screen. (The light sensor is used to reset the LCD).

My question is this ... How would I go about having the answer being input as morse code stored and then checked for correctness? So if my daughter inputs "Yellop" it would display a message saying "Incorrect". She would reset and try again. I am very very new to all of this and would love some help getting this up and running. Now, I am assuming I would somehow have to have each letter input stored in some sort of array and then checked for correctness. However, I have no idea how to do that. Here is my code ...

#include <Wire.h>
#include "rgb_lcd.h"

rgb_lcd lcd;

#define DOT false
#define DASH true

#define MAX_CHAR_LENGTH 6

#define BUTTON A0
#define LIGHTSENSOR A1
#define pinLED 6

#define PULSE_THRESHOLD 400
#define LETTER_SEPARATION 600
#define WORD_SEPARATION 8000

const struct MorseTree *tree = NULL;

const int colorR = 0;
const int colorG = 0;
const int colorB = 100;

int value;
int button = -1;
int pulseThreshold = 0;
int letterSeparation = 0;
int wordSeparation = 0;

void initMorse(int lbutton, int lpulseThreshold, int lletterSeparation, int 
lwordSeparation)
{
  tree = generateMorseTree();
  button = lbutton;
  pulseThreshold = lpulseThreshold;
  letterSeparation = lletterSeparation;
  wordSeparation = lwordSeparation;
}


struct MorseTree
{
  // '-' unless this is a leaf node
  char character;
  struct MorseTree *dotChild;
  struct MorseTree *dashChild;
};

struct MorseData
{
  char character;
  bool code[MAX_CHAR_LENGTH];
  byte codeLength;
};

void initMorseTree(struct MorseTree *tree)
{
  tree -> character = '-';
  tree -> dotChild = NULL;
  tree -> dashChild = NULL;
}

struct MorseTree *newMorseTree()
{
  struct MorseTree *tree = (struct MorseTree *) malloc(sizeof(struct 
MorseTree));
  initMorseTree(tree);
  return tree;
}

void addTreeMember(struct MorseTree *tree, struct MorseData &data)
{
  struct MorseTree *current = tree;
  for (byte i = 0; i < data.codeLength; i++)
  {
    boolean currentSymbol = data.code[i];
    if (currentSymbol == DOT)
    {
      if (current -> dotChild == NULL)
        current -> dotChild = newMorseTree();
      current = current -> dotChild;
    }
    else
    {
      if (current -> dashChild == NULL)
        current -> dashChild = newMorseTree();
      current = current -> dashChild;
    }
  }

  // now current must be a leaf node
  current -> character = data.character;
}

void addTreeMembers(struct MorseTree *tree, struct MorseData data[], 
byte dataLength)
{
  for (byte i = 0; i < dataLength; i++)
    addTreeMember(tree, data[i]);
}

void addAlphabet(struct MorseTree *tree)
{
  struct MorseData data[] = {
    {'A', {DOT, DASH}, 2},
    {'B', {DASH, DOT, DOT, DOT}, 4},
    {'C', {DASH, DOT, DASH, DOT}, 4},
    {'D', {DASH, DOT, DOT}, 3},
    {'E', {DOT}, 1},
    {'F', {DOT, DOT, DASH, DOT}, 4},
    {'G', {DASH, DASH, DOT}, 3},
    {'H', {DOT, DOT, DOT, DOT}, 4},
    {'I', {DOT, DOT}, 2},
    {'J', {DOT, DASH, DASH, DASH}, 4},
    {'K', {DASH, DOT, DASH}, 3},
    {'L', {DOT, DASH, DOT, DOT}, 4},
    {'M', {DASH, DASH}, 2},
    {'N', {DASH, DOT}, 2},
    {'O', {DASH, DASH, DASH}, 3},
    {'P', {DOT, DASH, DASH, DOT}, 4},
    {'Q', {DASH, DASH, DOT, DASH}, 4},
    {'R', {DOT, DASH, DOT}, 3},
    {'S', {DOT, DOT, DOT}, 3},
    {'T', {DASH}, 1},
    {'U', {DOT, DOT, DASH}, 3},
    {'V', {DOT, DOT, DOT, DASH}, 4},
    {'W', {DOT, DASH, DASH}, 3},
    {'X', {DASH, DOT, DOT, DASH}, 4},
    {'Y', {DASH, DOT, DASH, DASH}, 4},
    {'Z', {DASH, DASH, DOT, DOT}, 4},
  };

  addTreeMembers(tree, data, 26);
}

void addNumbers(struct MorseTree *tree)
{
  struct MorseData data[] = {
    {'1', {DOT, DASH, DASH, DASH, DASH}, 5},
    {'2', {DOT, DOT, DASH, DASH, DASH}, 5},
    {'3', {DOT, DOT, DOT, DASH, DASH}, 5},
    {'4', {DOT, DOT, DOT, DOT, DASH}, 5},
    {'5', {DOT, DOT, DOT, DOT, DOT}, 5},
    {'6', {DASH, DOT, DOT, DOT, DOT}, 5},
    {'7', {DASH, DASH, DOT, DOT, DOT}, 5},
    {'8', {DASH, DASH, DASH, DOT, DOT}, 5},
    {'9', {DASH, DASH, DASH, DASH, DOT}, 5},
    {'0', {DASH, DASH, DASH, DASH, DASH}, 5},
  };

  addTreeMembers(tree, data, 10);
}

void addPunctuation(struct MorseTree *tree)
{
  struct MorseData data[] = {
    {'.', {DOT, DASH, DOT, DASH, DOT, DASH}, 6},
    {',', {DASH, DASH, DOT, DOT, DASH, DASH}, 6},
    {'?', {DOT, DOT, DASH, DASH, DOT, DOT}, 6},
  };

  addTreeMembers(tree, data, 3);
}

struct MorseTree *generateMorseTree()
{

  struct MorseTree *tree = newMorseTree();
  initMorseTree(tree);

  addAlphabet(tree);
  addNumbers(tree);
  addPunctuation(tree);

  return tree;
}


void waitFor(int pin, int state)
{
  do
  {
    // spin until the pin reads the given state
    while (digitalRead(pin) != state) { }
    // delay, to verify the reading
    delay(5);
    // continue if the reading has changed
  } while (digitalRead(pin) != state);
}

boolean getNextSymbol()
{
  waitFor(button, HIGH);
  unsigned long start = millis();

  waitFor(button, LOW);
  unsigned long end = millis();

  unsigned long pulseLength = end - start;

  // Serial.println(pulseLength);
  if (pulseLength > pulseThreshold)
    return DASH;
  else
    return DOT;
}

boolean shouldTimeOut()
{
  unsigned long start = millis();
  while (digitalRead(BUTTON) == LOW)
  {
    if (millis() - start > letterSeparation)
      return true;
  }

  return false;
}

boolean shouldBeSpace()
{
  unsigned long start = millis();
  while (digitalRead(BUTTON) == LOW)
  {
    if (millis() - start > wordSeparation)
      return true;
  }

  return false;
}

char getNextChar()
{
  static boolean lastCharWasSpace = false;

  const struct MorseTree *current = tree;

  byte symbolCount = 0;

  if (!lastCharWasSpace && shouldBeSpace())
  {
    lastCharWasSpace = true;
    return ' ';
  }

  lastCharWasSpace = false;

  while (true)
  {
    symbolCount++;
    boolean currentSymbol = getNextSymbol();
    // Serial.println(currentSymbol == DOT ? "DOT" : "DASH");
    if (currentSymbol == DOT)
      current = current -> dotChild;
    else
      current = current -> dashChild;

    if (current == NULL)
      return '-';

    if (shouldTimeOut() || symbolCount >= MAX_CHAR_LENGTH)
      return current -> character;
  }

  // should never get here
  return '!';
}


void setup()
{
  pinMode(BUTTON, INPUT);
  pinMode(LIGHTSENSOR, INPUT);

  value = analogRead(LIGHTSENSOR);

  initMorse(BUTTON, PULSE_THRESHOLD, LETTER_SEPARATION, WORD_SEPARATION);

  Serial.begin(9600);
  while(! Serial);
  lcd.begin(16, 2);    
  lcd.setRGB(colorR, colorG, colorB);
  lcd.print("Input 'yellow'");
}

void loop()
{
  Serial.println(value);
  value = analogRead(LIGHTSENSOR);

  if(value<40)
  {
    lcd.clear();
  }
  static boolean firstLoop = true; //skips the first space between words.

  char c = getNextChar();

  if (firstLoop)
  {
    firstLoop = false;
    if (c == ' ')
      return;
  }

  lcd.print(c); 

}

Any help or advice would be greatly appreciated. (I deleted my last question and reposted as it was very badly worded. Hopefully this one is better!)

  • The first step would be to interpret incoming pulses as a Morse letter. Does that part work yet? Do you want to validate at the end of the word (and if so, how do you know when the sender has stopped sending?) or when the first bad letter is sent? For example, if your daughter keys "mellow" do you want the error to appear as soon as the "m" is keyed, or when "mellow" is entirely received? – Nick Gammon Mar 07 '16 at 04:25
  • Yeah, I have it so that the button presses are translated to a letter and displayed on screen. I would love a 'backspace' function for the scenario you describe, but to be honest I couldn't figure out how to do that part. Like I say, I am new to this. And I haven't figured out how I would have her submit the answer. Maybe a super long keypress could act as an 'enter' function. Again, I would have to figure all that out. Being new at this it can be a bit daunting!! – KillingJoke Mar 07 '16 at 11:10
  • `Now, I am assuming I would somehow have to have each letter input stored in some sort of array and then checked for correctness.` - not necessarily. You could maintain a position in the "correct" answer, and as each letter is received, compare it to that byte in the correct answer. If it matches, well and good. If not, error. – Nick Gammon Mar 07 '16 at 21:07

0 Answers0