Morse code detector Problems

hello there users,

I’m struggling with a project.
I’m making a morse code detector using a light sensor.
The sensor can detect light signals and makes this into letters.
I would like to make a code from 3 letters (SOS) and when the sensor detects this,
a servo motor starts turning.
How can i make this code?
Thank you in advance!

Elsa

this is the code i’m working with

#define THRESHOLD (44)
#define MAX_SAMPLES (5)
#define BAUD (100.0)
#define WAIT (5.0)
#define AVG_LONG (BAUD6.0/WAIT)
#define AVG_SHORT (BAUD3.0/WAIT)

#define AVG_NEWWORD (BAUD*7.0/WAIT)
#define MINIMUM (AVG_SHORT/4.0)
#define MAX_PATTERN (64)
#define NUM_CODES (54)

  • // 0 10 20 30 40 50*
  • // 0123456789012345678901234567890123456789012345678901234*
    static const char *letters = “ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,?’!/()&:;=±_”$@";
  • // each code represents a character.*
  • // 1 represents a dot and 0 represents a dash.*
  • // the order of these codes matches the order of the characters in*
    _ // letters._
    static const char codes[NUM_CODES] = {
    “10”, // A, codes[0]
    “0111”, // B, codes[1]
    “0101”, // C
    “011”, // D
    “1”, // E
    “1101”, // F
    “001”, // G
    “1111”, // H
    “11”, // I
    “1000”, // J
    “010”, // K
    “1011”, // L
    “00”, // M
    “01”, // N
    “000”, // O
    “1001”, // P
    “0010”, // Q
    “101”, // R
    “111”, // S
    “0”, // T
    “110”, // U
    “1110”, // V
    “100”, // w
    “0110”, // x
    “0100”, // y
    “0011”, // z
    “00000”, // 0
    “10000”, // 1
    “11000”, // 2
    “11100”, // 3
    “11110”, // 4
    “11111”, // 5
    “01111”, // 6
    “00111”, // 7
    “00011”, // 8
    “00001”, // 9
    “101010”, // .
    “001100”, // ,
    “110011”, // ?
    “100001”, // ’
    “010100”, // !
    “01101”, // /
    “01001”, // (
    “010010”, // )
    “10111”, // &
    “000111”, // :
    “010101”, // ;
    “01110”, // =
    “10101”, // +
    “01110”, // -
    “110010”, // _
    “101101”, // "
    “1110110”, // $
    “100101”, // @, codes[54]
    };
    int top=0;
    int samples[MAX_SAMPLES];
    int si=0;
    int mi=0;
    int total=0;
    int c=0;
    int is_on=0;
    char pattern[MAX_PATTERN];
    int pi=0;
    void setup() {
    Serial.begin(57600);
    for(int i=0;i<MAX_SAMPLES;++i) {
    _samples
    =0;
    _
    }
    for(int i=0;i<MAX_PATTERN;++i) {
    pattern*=0;*
    }
    }
    void loop() {
    int volume=analogRead(0);
    total -= samples[si];
    samples[si] = volume;
    total += samples[si];
    if( mi < MAX_SAMPLES ) mi++;
    si = (si+1) % MAX_SAMPLES;
    int average = total / mi;
    if( top < average ) top = average;
    int x = 10.0 * (float)(average-THRESHOLD)/(float)(top-THRESHOLD);
    if(x<0) x=0;
    if(x>10) x=10;
    if(x>1) {
    * // noise!*
    if(is_on==0) {
    * // noise has just started.*
    if( c > MINIMUM ) {
    * // Was the silence a new word or a new letter?*
    if( c > (AVG_NEWWORD+AVG_SHORT)/2.0 ) {
    pattern[pi]=0;
    findLetter();
    * // new word, extra \n*
    Serial.println();
    * // start counting - and . all over again.*
    pi=0;
    } else if( c > (AVG_LONG+AVG_SHORT)/2.0 ) {
    pattern[pi]=0;
    findLetter();
    * // start counting - and . all over again.*
    pi=0;
    }
    }
    * // remember noise started*
    is_on=1;
    c=0;
    }
    } else {
    * // silence!*
    if(is_on==1) {
    * // silence is new*
    if( c > MINIMUM ) {
    * // Was the noise a long or a short?*
    if( c > (AVG_LONG + AVG_SHORT)/2.0 ) {
    * // long*
    Serial.print(’-’);
    pattern[pi++]=‘0’;
    } else {
    * // short*
    Serial.print(’.’);
    pattern[pi++]=‘1’;
    }
    }
    * // remember silence started*
    is_on=0;
    c=0;
    }
    }
    c++;
    delay(WAIT);
    }
    * // pattern contains the received longs and shorts,*
    * // saved as 1s and 0s. Find the matching code in the list*
    * // then find the matching printable character.*
    * // print ‘?’ if nothing is found*
    void findLetter() {
    int i,j;
    * // go through all the codes*
    for(i=0;i<NUM_CODES;i++) {
    _ // check if code matches pattern exactly.
    if(strlen(pattern) == strlen(codes) && strcmp(pattern,codes*)==0) {
    // match!
    Serial.print(’ ');_

    _Serial.println(letters);
    return;
    }
    }
    Serial.print(’?’);
    }*_

How can i make this code?

You have some code that does something. You have not explained what it actually does.

You expect the code to do something. You were not really clear on what you expected.

It's hard to help you without knowing what you need help with.

this code is for a light sensor. when the light sensor receives morse codes, and turnes this into letters. I would like to make a servo motor turn when the code SOS is received by the arduino

Hi

Should these

for (int i = 0; i < MAX_SAMPLES; ++i) 
{
    samples = 0;
}
for (int i = 0; i < MAX_PATTERN; ++i) 
{
    pattern = 0;
}

…be at least something like this:

for (int i = 0; i < MAX_SAMPLES; ++i) 
{
    samples[i] = 0;
}
  for (int i = 0; i < MAX_PATTERN; ++i) 
{
    pattern[i] = 0;
}

There are some similar problems later also regarding this issue…

TommiP

Thanks tommiP,
i’m gonna try it out

Elsa123: Thanks tommiP, i'm gonna try it out

How it suppose to receive those morse codes letters by light sensor ? I'm just curious 'cos I couldn't find any inputs..

TommiP

umm i don't know actually but it works, i'm very new to arduino. i don't understand what the 'i' means

Elsa123:
umm i don’t know actually but it works,
i’m very new to arduino.
i don’t understand what the ‘i’ means

My mistake, input is in the beginning on loop() :o :slight_smile:

int volume = analogRead(0);

Elsa123:
i don’t understand what the ‘i’ means

i is variable for using single-dimensional array, you’ll find basic information for here or here

Short version about using single-dimensional array:

You could code it like this:

int variable 1 = 1;
int variable 2 = 2;
int variable 3 = 3;
int variable 4 = 4;

…or then you could use single-dimensional array for coding it:

int variable[5];

// i = 1 in the beginning, added once each loop and loop is running until i = 6
for (int i = 1; i < 5; ++i) 
{
    variable[i] = i;
 }

TommiP

PS. If you have just started to learn Arduino or C-language, i’ll give you a hint: Try to learn it by much more simple examples in the beginning. By doing that and by writing your own code, you’ll learn how it works right? :slight_smile:

Here is a small code to test it:

void setup()
{
  Serial.begin(115200);
  
  int variable[5];

  for (int i = 1; i < 5; ++i)
  {
    variable[i] = i;
    Serial.println(i);
  }
}

void loop()
{  

}

TommiP

Several things:

First, read the post at the top of the Forum by Nick Gammon on how to post here. Also, use code tags to reduce the space your code takes. It makes it easier on us who will read your code.

Second, use Ctrl-T in the IDE before you post your code. It will reformat you code in a style that also makes it easier for us to read.

Third, this for loop can be simplified with a single statement:

//for(int i=0;i<MAX_SAMPLES;++i) {
//  samples=0;
//}
  memset(samples, 0, MAX_SAMPLES);

Because you have an initializer list, this statement:

static const char *codes[NUM_CODES] = {

doesn’t need the element count specified:

_ static const char *codes = { // Let the compiler figure out how many you need_

Fourth, that array is an array of pointers to strings. With 54 elements and each pointer taking 2 bytes, just the pointers eat 108 bytes. If the average string is length 4 including the null terminator, you’re using 324 bytes just for that one array.

Suppose instead you use a byte array like:

byte letterTable[] = { // Morse coding

  • 0b101, // A*
  • 0b11000, // B*

This uses a coding algorithm that says: starting with the most significant bit, search for the first binary digit that has the value 1. You also probably know that each memory byte consists of eight binary digits, called bits.
Actually, the binary value we’ve assigned to the first element of the array is 0b00000101. Reading from left to right (i.e., most significant bit (msb) to least significant bit (lsb)), the “0b” tells the compiler that we are representing this number in binary (i.e., base 2) rather than the default representation (i.e., decimal, or base 10). Because each byte data type uses 8 bits for storage, we are assigning the next 5 bits with the value 0. However, since those bits are zero, the compiler is just as happy with 0b101 as with 0b00000101. Now, suppose we say: When you find the first 1 digit, throw it away. We are just using that first 1 bit as a marker, or sentinel, to mark the start of the “real” data. Once you’ve tossed that leading 1 bit away, interpret each 0 bit as a dit and each 1 bit as a dah.

Then the first couple of elements in the array:

0b101 becomes 01 becomes dit-dah A
0b11000 becomes 1000 becomes dah-dit-dit-dit B
ob11010 becomes 1010 becomes dah-dit-dah-dit C

and so on. This approach will only use 54 bytes of memory. Two simple for loops can do the decoding:

  int i;

  for (i = 7; i >= 0; i--)
    if (code & (1 << i))
      break;

  for (i--; i >= 0; i--) {
    if (code & (1 << i))
      dah();
    else
      dit();
  }