Изменить стиль страницы

The sketch uses the Ardiuno’s built-in EEPROM library. The Morse code message is stored in EEPROM memory every time a change is made, meaning that the beacon can remember the message even if power to the Arduino is interrupted. The sketch also makes use of a library from the Arduino community called EEPROMAnything, which makes saving to and reading from EEPROM easier. The code for EEPROMAnything is included in the download for this project, so there is nothing to download separately.

First, we load both the official Arduino EEPROM library and EEPROMAnything:

#include <EEPROM.h>

#include "EEPROMAnything.h"

A number of constants are used to control the project:

const int ledPin = 13;

const int dotDelay = 100; // milliseconds

const int gapBetweenRepeats = 10; // seconds

const int maxMessageLen = 255;

The pin that controls the LEDs is specified in ledPin. The constant dotDelay defines in milliseconds the duration of a dot flash. Dashes are always three times the duration of a dot.

The constant gapBetweenRepeats specifies in seconds the time that will elapse between each repetition of the message, and maxMessageLen specifies the maximum length, in letters rather than dots and dashes, of the message. A maximum size is specified because in Arduino code, you have to declare the size of arrays.

Two global variables are used:

char message[maxMessageLen];

long lastFlashTime = 0;

The message variable will contain the text of the message to be flashed, and lastFlashTime keeps track of when the message was last flashed, to allow a break between the repeats.

Two global char arrays are used to contain the dot and dash sequences for Morse code. The program will only flash characters that it knows how to send, that is letters, digits, or a space character. All other characters in the message are ignored.

char* letters[] = {

  ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..",   // A-I

  ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", // J-R

  "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."         // S-Z

};

char* numbers[] = {"-----", ".----", "..---", "...--", "....-", ".....",

"-....", "--...", "---..", "----."};

The setup function sets the ledPin as an output and then starts serial communication at Serial.begin:

void setup()

{

  pinMode(ledPin, OUTPUT);

  Serial.begin(9600);

  Serial.println("Ready");

  EEPROM_readAnything(0, message);

  if (! isalnum(message[0]))

  {

    strcpy(message, "SOS");

  }

  flashMessage();

}

Serial communication is used to set a new message, either using the serial monitor of the Arduino IDE or, as you will see in “Using the Morse Beacon” on page 205, a terminal program running on a Raspberry Pi.

Every time the message is changed, it is saved in EEPROM, so during the setup process, the sketch reads any stored message from EEPROM. If no message has been set, the if statement in setup sets the default message to “SOS.” Finally, at flashmessage, the setup function flashes the message for the first time.

The loop function first checks whether a new message has been sent over the serial connection:

void loop()

{

  if (Serial.available())      // Is there anything to be read from USB?

  {

    int n = Serial.readBytesUntil('\n', message, maxMessageLen-1);

    message[n] = '\0';

    EEPROM_writeAnything(0, message);

    Serial.println(message);

    flashMessage();

  }

  if (millis() > lastFlashTime + gapBetweenRepeats * 1000L)

  {

    flashMessage();

  }

}

Any new message is read into the message character array until the newline character (\n) is read. The null character ’\0’ is added to the end of the message. This is the Arduino’s way of indicating the end of a string of characters. Once the whole message has been read through, it is saved into EEPROM (EEPROM_writeAnything), and then the new message begins flashing immediately.

The remainder of the loop function checks whether enough time has passed before it can repeat the message. This could be done more simply using delay, but we would be unable to interrupt the loop if a new message arrived during the delay.

The flashMessage function is the most complex function in the sketch.

void flashMessage()

{

  Serial.print("Sending: ");

  Serial.println(message);

  int i = 0;

  while (message[i] != '\0' && i < maxMessageLen)

  {

    if (Serial.available()) return; // new message

    char ch = message[i];

    i++;

    if (ch >= 'a' && ch <= 'z')

    {

      flashSequence(letters[ch - 'a']);

    }

    else if (ch >= 'A' && ch <= 'Z')

    {

      flashSequence(letters[ch - 'A']);

    }

    else if (ch >= '0' && ch <= '9')

    {

      flashSequence(numbers[ch - '0']);

    }

    else if (ch == ' ')

    {

     delay(dotDelay * 4);      // gap between words

    }

  }

  lastFlashTime = millis();

}