Embedded Networking and Communications

Group Assignment

For this week the group assignment is Send a message between two projects. Two projects means needing to send a message between any combination of boards, computers and/or mobile devices.

The group assignemnt is between a microcontroller board, a smart phone and a PC. The mobile phone sends morse code by flashing the mobile flash light to a certain message, The microcontroller with a light sensor attached interprets the signals and displays them on the PC screen via serial.

morse code

Morse code is a method used in telecommunication to encode text characters as standardized sequences of two different signal durations, called dots and dashes or dits and dahs. Morse code is named after Samuel Morse, an inventor of the telegraph. Its a fascinating method of communication used historically as an easy way of encoding and sending text over long distances.

Morse Code Torch


Morse Code Torch is an app that allows you to encode your messages into morse code using your phone’s flashlight. Used on an iphone here. I tried other applications but none of them allowed me to adjust the transmission rate time or even mentioned what rate they were using. This application offers flexibility when it comes to doing that which comes in handy for writing the code.

The application is pretty easy to use, you just write a message and the phone flashlight flashes in dashes and dots cooresponding to the message.

The microcontroller

The microcontroller board used is an Arduino Mega 2560. Which is a microcontroller board based on the ATmega2560. It has 54 digital input/output pins (of which 15 can be used as PWM outputs), 16 analog inputs, 4 UARTs (hardware serial ports), a 16 MHz crystal oscillator, a USB connection, a power jack, an ICSP header, and a reset button.
The Arduino mega is frankly an overkill for this project as any attiny44 based microcontroller would easily be able to do this, but it was the microcontroller board available.

connection

A photoresistor (acronymed LDR for Light Decreasing Resistance) was used to detect the light signals. An LDR works by decreasing resistance with respect to receiving luminosity (light) on the component’s sensitive surface. The LDr can be connected to a microcontroller board via a voltage divder configuration where the voltage that appears at the analog input will vary depending on the amount of light hitting the LDR.


code

The code is largly based on krobro‘s code meant for the Duinobot board with some adjustments.

// morse code
// The value of THRESHOLD is dependent on your ambiant light ... it
// may need to be adjusted for your environment.
// original code by krobro  https://gist.github.com/krobro/4eb81265cb09cc28a8c7
//  edited by Duaa

#define DEBUG_PRINTLN(str,data)  Serial.print(F("_DEBUG: "));  Serial.print(str); Serial.println(data);
#define DEBUG_PRINTLN(str,data) // DO NOTHING

#define THRESHOLD 200
#define DOT 200
#define lightPin A1

char morse[6];
int morse_index = 0;

boolean _state;
unsigned long _millisStart;
unsigned long _millisEnd;

static char *_list[26] = {".-",       // 'a'
                          "-...",     // 'b'
                          "-.-.",     // 'c'
                          "-..",      // 'd'
                          ".",        // 'e'
                          "..-.",     // 'f'
                          "--.",      // 'g'
                          "....",     // 'h'
                          "..",       // 'i'
                          ".---",     // 'j'
                          "-.-",      // 'k'
                          ".-..",     // 'l'
                          "--",       // 'm'
                          "-.",       // 'n'
                          "---",      // 'o'
                          ".--.",     // 'p'
                          "--.-",     // 'q'
                          ".-.",      // 'r'
                          "...",      // 's'
                          "-",        // 't'
                          "..-",      // 'u'
                          "...-",     // 'v'
                          ".--",      // 'w'
                          "-..-",     // 'x'
                          "-.--",     // 'y'
                          "--..",};   // 'z'

// convert_morse
//
// convert morse code (such as "--..") to a
// letter ('z')
//
// code - the morse code to convert
//
// Returns - converted letter or '?' on failure
//
// Notes: inefficient linear search ... too slow?
//
char convert_morse(char *code)
{
  DEBUG_PRINTLN("CONVERT: ", code);

  for (int x = 0; x < 26; x++)
  {
      if (strcmp(_list[x], code) == 0)
      {
        DEBUG_PRINTLN("GOT: ", (char)(x+'a'));
          return (char)(x + 'a');
      }
  }

  // could not decode what was read
  return '?';
}

void setup() {
  Serial.begin(115200);
  delay(2000);

  _millisStart = _millisEnd = 0;
  _state = LOW;


  Serial.println (" ");
  Serial.println ("Finished setup ...");
}

void loop() {
  /* uncomment the line below to test and find the light threashold in your enviorment.
   *  comment it again after adjusting the threashold value
   */
 // Serial.println (analogRead(A1));
  boolean  state;

  // read the light sensor ; sensor can be HIGH or LOW
  if (analogRead(lightPin) <= THRESHOLD)
  {
    state = LOW;
  }
  else
  {
    state = HIGH;
  }

  // check to see if the current state of the sensor
  // matches the last state of the sensor.
  if (state != _state)
  {
    _millisEnd = millis();

    if (_state == HIGH)
    {
        // Just finished a HIGH state and transitioned to a low state
        // did we just process a dot or a dash?
        if (_millisEnd - _millisStart < DOT + DOT/10 )
        {
          morse[morse_index] = '.';
          Serial.print(".");
        }
        else
        {
          morse[morse_index] = '-';
          Serial.print("-");
        }

        // just finished reading another dot or dash
        // append the dot or dash to the morse to decode
        morse_index++;
        morse[morse_index] = '/0';
    }
    else
    {
      // just finished a low state and transitioned to a high state
      //  Was a character, letter or word just finished?
      if ( _millisEnd - _millisStart < DOT + DOT/10 )
      {
        // single dot low state ... finished a dot or a dash
      }
      else if ( _millisEnd - _millisStart > DOT*3 - DOT/10 )
      {
        // 3 dot low state or 7 dot low state ... finished a letter
        char c = convert_morse(morse);
        if (c =='?') {
          Serial.println(" *** Failed to decode properly ... retrying ...");
        }
        else
        {

          Serial.println(c);
        }
        morse_index = 0;

        if ( _millisEnd - _millisStart > DOT*7 - DOT/10 )
        {
            // 7 dot low state ... finished a word
            Serial.print(' ');
        }
      }
    }

    // set the current state
    _state = state;
    _millisStart = _millisEnd;
  }
}

The first step is to check the light thrashold for normal room lighting vs flashlight pointed at the LDR. This value changes from enviornment to enviornment. A quick test showed at at normal condition the value is around 90, and with the flashlight pointed it was around 300. So the thrashold was set at 200.

results

With that, the microcontroller was ready to decode morse code. Here is a video of the microcontroller decoding “hello world” in morse code.