for loop morse code failing

Hello again,

I am building a box that flashes a yellow LED based on a set of words programed and the user must figure out what the morse is.

I have all of the buttons and 7 segment display pieces working as intended but the flashing led for dot/dash of the morse is failing to work in 2 ways.

First I know I am doing something wrong with my "void morseBlinkWord(){" that is supposed to read an array for the morse and based on if the number in the array is a 0,1,2 it needs to either flash a "dot" or a "dash". If it is a 0 it should just "pause" for a fixed # of ms.

This ^^^ breaks everything else :slight_smile: and may be the fix for the below issue too.

Secondly the dot and dash is not the correct ms length that I have it set to use. It stays on and off for far to long when it does work at all?

morse.h:

/*
 * The Morse Code module is a module that consists of a light flashing in Morse Code, a radio with a displayed frequency and a TX button. 
 * The user must interpret the flashing Morse Light as dots and dashes to form a word in Morse Code. 
 */

#define PIN_MORSE_LED_1 3 // yellow flashing LED 
#define PIN_MORSE_LED_GREEN 12 // module complete LED
#define PIN_MORSE_BUTTON_1 4 // left button
#define PIN_MORSE_BUTTON_2 5 // right button
#define PIN_MORSE_BUTTON_3 6 // TX button

#define MORSE_BUTTON_PRESS_DELAY 50 // time required to prevent button bounce

int morseLatch=9;  // 74HC595  pin 9 STCP
int morseClock=10; // 74HC595  pin 10 SHCP
int morseData=8;   // 74HC595  pin 8 DS

int morseCurrentDisplayNumber=1; // what station is displayed
int buttonLeftState=0; // current state of the left button 
int buttonRightState=0; // current state of the right button
int buttonSubmitState=0; // current state of the submit button
int lastButtonLeftState=0; // previous state of the left button 
int lastButtonRightState=0; // previous state of the right button
int lastButtonSubmitState=0; // previous state of the submit button
int morseCorrectNumber=1;

const unsigned long morseYellowLEDDot = 100; // length of dot
const unsigned long morseYellowLEDDash = 400; // length of dash
const unsigned long morseLetterLEDDelay = 500; // length of delay between letters
const unsigned long morseDotDashLEDDelay = 200; // length of delay between dot/dash in same letter
const unsigned long morseWordLEDDelay = 1500; // delay between word repeat
unsigned long morseDelayCounter = 0; //a value that will count up while waiting for new letter/word //pointless action for while loop

unsigned long morseYellowLEDtimerOn;
unsigned long morseYellowLEDtimerOff;
unsigned long morseLetterFinishedtimer;
unsigned long morseWordFinishedtimer;

unsigned char morseTable[]=
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00}; 
// 0x3f="0",0x06="1",0x5b="2",0x4f="3",0x66="4",0x6d="5",0x7d="6",0x07="7",0x7f="8",0x6f="9",
//0x77="A",0x7c="b",0x39="C",0x5e="d",0x79="E",0x71="F",0x00="OFF"

int morseWord1[] = {1,1,1,0,1,1,1,1,0,1,0,1,2,1,1,0,1,2,1,1}; //word shell where 1=dot 2=dash, 0=new letter pause

void morseSetup()
{
  pinMode(morseLatch,OUTPUT);
  pinMode(morseClock,OUTPUT);
  pinMode(morseData,OUTPUT);
  pinMode(PIN_MORSE_LED_1,OUTPUT);
  pinMode(PIN_MORSE_LED_GREEN,OUTPUT);
  pinMode(PIN_MORSE_BUTTON_1,INPUT);
  pinMode(PIN_MORSE_BUTTON_2,INPUT);
  pinMode(PIN_MORSE_BUTTON_3,INPUT);
  morseYellowLEDtimerOn = millis ();
  morseYellowLEDtimerOff = millis ();
  morseLetterFinishedtimer = millis ();
  morseWordFinishedtimer = millis ();
}

void morseDisplay(unsigned char num)
{
  digitalWrite(morseLatch,LOW);
  shiftOut(morseData,morseClock,MSBFIRST,morseTable[num]);
  digitalWrite(morseLatch,HIGH); 
}

void morseYellowLEDOn ()
  {
  digitalWrite (PIN_MORSE_LED_1, HIGH);
  morseYellowLEDtimerOn = millis ();  
  }

void morseYellowLEDOff ()
  {
  digitalWrite (PIN_MORSE_LED_1, LOW);
  morseYellowLEDtimerOff = millis ();  
  }

void morseDot(){
  if ((digitalRead (PIN_MORSE_LED_1) == LOW) && ((millis () - morseYellowLEDtimerOff) >= morseDotDashLEDDelay)) {
    morseYellowLEDOn ();
  }
  else if ( (millis () - morseYellowLEDtimerOn) >= morseYellowLEDDot) {
     morseYellowLEDOff ();
  }
}

void morseDash(){
  if ((digitalRead (PIN_MORSE_LED_1) == LOW) && ((millis () - morseYellowLEDtimerOff) >= morseDotDashLEDDelay)) {
    morseYellowLEDOn ();
  }
  else if ( (millis () - morseYellowLEDtimerOn) >= morseYellowLEDDash) {
     morseYellowLEDOff ();
  }
}

void morseBlinkWord(){ // not expanded for other words as only 1 word array is built for testing
  if (morseCorrectNumber==1) {
    for (int i = 0; i < 20; i = i + 1) {
      if(i == 1){
        morseDot();
      }
      else if(i == 2){
        morseDash();
      }
      else if(i == 0){ 
        morseLetterFinishedtimer = millis () ;
        Serial.print(morseLetterFinishedtimer);
        while (millis () - morseLetterFinishedtimer < morseLetterLEDDelay){
        Serial.print(millis () - morseWordFinishedtimer);
        morseDelayCounter+1 ;
        }
      }
      morseWordFinishedtimer = millis () ;
      while (millis () - morseWordFinishedtimer < morseWordFinishedtimer){
      Serial.print(millis () - morseWordFinishedtimer);
      morseDelayCounter+1 ;
      }
    }
  }
}

void morseLeftButtonPressed(){
  if (morseCurrentDisplayNumber > 0)  {
    morseCurrentDisplayNumber=morseCurrentDisplayNumber-1;
    morseDisplay(morseCurrentDisplayNumber);
    delay(MORSE_BUTTON_PRESS_DELAY);
  } else {
    morseDisplay(morseCurrentDisplayNumber);
    }
}
void morseRightButtonPressed(){
  if  (morseCurrentDisplayNumber < 15)  {
    morseCurrentDisplayNumber=morseCurrentDisplayNumber+1;
    morseDisplay(morseCurrentDisplayNumber);
    delay(MORSE_BUTTON_PRESS_DELAY);
  } else {
    morseDisplay(morseCurrentDisplayNumber);
    }
}
void morseSubmitButtonPressed(){
  Serial.println(morseCurrentDisplayNumber);
  Serial.println(morseCorrectNumber);
  if (morseCurrentDisplayNumber==morseCorrectNumber) {
  morseModuleDefused = true;
  digitalWrite(PIN_MORSE_LED_GREEN,HIGH);
  }
  else { //if (morseCurrentDisplayNumber!=morseCorrectNumber) {
  addStrike();
  morseDisplay(0);
  delay(500);
  morseDisplay(morseCurrentDisplayNumber);
  }
}

void morseLoop()
{
  // read the pushbutton input pins:
  buttonLeftState = digitalRead(PIN_MORSE_BUTTON_1);
  buttonRightState = digitalRead(PIN_MORSE_BUTTON_2);
  buttonSubmitState = digitalRead(PIN_MORSE_BUTTON_3);

  // compare the buttonLeftState to its previous state
  if (buttonLeftState != lastButtonLeftState) {
    // if the state has changed, increment the counter
    if (buttonLeftState == HIGH) {
      Serial.println("leftOn");
      morseLeftButtonPressed();
    } else {
      Serial.println("leftOff");
    }
    // Delay to avoid bouncing
    delay(MORSE_BUTTON_PRESS_DELAY);
  }
  // save current state as last state
  lastButtonLeftState = buttonLeftState;

  if (buttonRightState != lastButtonRightState) {
    if (buttonRightState == HIGH) {
      Serial.println("rightOn");
      morseRightButtonPressed();
    } else {
      Serial.println("rightOff");
    }
    // Delay to avoid bouncing
    delay(MORSE_BUTTON_PRESS_DELAY);
  }
  lastButtonRightState = buttonRightState;

  if (buttonSubmitState != lastButtonSubmitState) {
    if (buttonSubmitState == HIGH) {
      Serial.println("submitOn");
      morseSubmitButtonPressed();
    } else {
      Serial.println("submitOff");
    }
    delay(MORSE_BUTTON_PRESS_DELAY);
  }
  lastButtonSubmitState = buttonSubmitState;
  
  // display starting number (always fixed lowest # in array)
  morseDisplay(morseCurrentDisplayNumber);
  
// IF THIS STATEMENT IS ENABLED I CAN NO LONGER PRESS BUTTONS AND THE FLASHING DOES NOT WORK AS INTENDED CURRENTLY
  if (!morseModuleDefused) morseBlinkWord();
  
}

void morseModuleBoom()
{
  // if the WRONG ANSWER is input the display with the frequency should clear and the flashing led should stop
  digitalWrite(PIN_MORSE_LED_1,LOW); // stop flashing yellow morse
  digitalWrite(PIN_MORSE_LED_GREEN,LOW); // turn off green module complete LED
  morseDisplay(16); //shows "    " on module tx display
}
 if (morseCorrectNumber=1) {

you ment "=="

i always put the constant on the left hand side because this type of error, which occurs often, then results in a compiler error

gcjr:

 if (morseCorrectNumber=1) {

you ment "=="

i always put the constant on the left hand side because this type of error, which occurs often, then results in a compiler error

Thank you for pointing that out. I corrected that but still have the exact same problem as before. The lights do what appears to be a single dot then a single dash (both way longer than it should be) then never flash again. I am also unable to press the buttons at all unless I comment out the part of my loop that runs the flashing lights.

Any other errors? I updated the above code with that fix for consistency sake.

[quote author=cwegrecki link=msg=4567119 date=1587309959Any other errors? I updated the above code with that fix for consistency sake.
[/quote]

Altering code that you have already posted is a bad idea. It makes the responses seem wrong, so confuses readers. In future, just post updated code in another message.

it would have helped if you had explained how your code was expected to work rather than explain what it didn't do.

i tried running your code. that gave me some idea of what it does, but i'm still very confused

you basically said executing morseWordBlink() trapped the code. you have several loops in that code. I believe the following has the error

i put serial prints to try to follow what the code was doing in order to debug it.

     morseWordFinishedtimer = millis () ;
      while (millis () - morseWordFinishedtimer < morseWordFinishedtimer){

i see you subtracting morseWordFinishedtimer from a value and comparing it to the same variable.

aarg:
[quote author=cwegrecki link=msg=4567119 date=1587309959Any other errors? I updated the above code with that fix for consistency sake.

Altering code that you have already posted is a bad idea. It makes the responses seem wrong, so confuses readers. In future, just post updated code in another message.

Good point. My apologies. I will keep that in mind in the future.

gcjr:
it would have helped if you had explained how your code was expected to work rather than explain what it didn't do.

i tried running your code. that gave me some idea of what it does, but i'm still very confused

you basically said executing morseWordBlink() trapped the code. you have several loops in that code. I believe the following has the error

i put serial prints to try to follow what the code was doing in order to debug it.

i see you subtracting morseWordFinishedtimer from a value and comparing it to the same variable.

This was another great catch. I can't believe I missed that too... It should have been

     morseWordFinishedtimer = millis () ;
      while (millis () - morseWordFinishedtimer < morseWordLEDDelay){

Updated that too and no luck still..

You make a good point about explaining what it should do not what is wrong. I thought I had enough comments to explain in the code but I see your point.

The goal is that the buttons left and right will move the 7 segment display numbers up and down. This works.
The submit button will verify if the correct entry is made. This works.
The flashing led should take an array and flash either a dot or dash with padding to prevent it from just being on off so fast you can't read it. Then upon ending flashing the Morse code repeat with delay between end of word and starting again.

All without an actual delay command to allow "multitasking" of buttons and Morse code flashing led.

cwegrecki:
The goal is that the buttons left and right will move the 7 segment display numbers up and down. This works.
The submit button will verify if the correct entry is made. This works.
The flashing led should take an array and flash either a dot or dash with padding to prevent it from just being on off so fast you can't read it. Then upon ending flashing the Morse code repeat with delay between end of word and starting again.

i still don't understand and I played with the code for a while

if you can't explain the problem succinctly

it would help to explain things completely, correctly and unambiguously

what is the purpose of the number displayed?
why do you need a submit button? what is being submitted?
what does the array represent?
what does the array have to do with timing?

you code does something with morse code.
how would a user use it?
now, how to you implement that behavior in the code?

Seems inefficient to store morse code in and array of "int". Try to look at this older topic which may give you a way to simplify the morse part of your code.

gcjr:
i still don't understand and I played with the code for a while

if you can't explain the problem succinctly

it would help to explain things completely, correctly and unambiguously

what is the purpose of the number displayed?
why do you need a submit button? what is being submitted?
what does the array represent?
what does the array have to do with timing?

you code does something with morse code.
how would a user use it?
now, how to you implement that behavior in the code?

I am building a "physical adaptation" of the game called Keep Talking and Nobody Explodes.
Here is a github repo with a lot of broken things. GitHub - AziDesigns/IRLKTANE: A real life (but not really real) version of the game Keep Talking and Nobody Explodes
I am however focusing on getting just one module built and working (morse code module).
This is a game where the user is presented with bomb of random modules and random rules for each module.
It is played with 2 people a Defuser and an Expert. The Defuser would hold this physical version of the game in their hand and the Expert would have a manual with steps to help them defuse the module.

The module that you have the code for above is one of 12 and is called morse code. This module is explained in full detail on how it should work here and even shows an image almost identical to my physical recreation: Morse Code | Keep Talking and Nobody Explodes Wiki | Fandom

There are a fixed number of "radio stations" that the Defuser must scroll through and select the correct one based on the information given by the Expert. So for this code I want to have a few things happening.

  1. The module needs to start up/ turn on.
  • Turning on consists of the morse code LED to start flashing a random word from an array and the 7 segment display showing a starting radio station that the user can later scroll through.
  • I do not have the full list of words built as I wanted to start with a single word to test and make sure I could get it to properly flash and accept button input.
  1. The user will communicate with the expert and tell them what morse code is flashing in front of them. Once they determine what word is flashing the expert will tell the defuser what station they should input and submit.
    3 The defuser will hit the right/left buttons to get to the correct radio station and then hit submit.
  2. If submitted correctly the module will turn on a green led showing module complete and stop flashing the morse.
  3. if submitted incorrectly the module will "Add a strike" which can end the game if to many are accumulated.

I really hope that giving those links and that description are more through. I am sorry for not including more. I am just jumping into learning how to do this and feeling unsure about what is relevant when asking for help.

a lot is still unclear.

another thing that doesn't seem to make sense is morseModuleDefused. it's not defined in this file (i added it. when ! true, morseBlinkWord is called. It's set to true in morseSubmitButtonPressed() which would inhibit BlinkWord() from being called. But where is it set to false?

it seems that the left and right buttons inc/decrement some number. what is suppose to happen when Submit() is called? should is allow Blink() to run or not run?

gcjr:
a lot is still unclear.

another thing that doesn't seem to make sense is morseModuleDefused. it's not defined in this file (i added it. when ! true, morseBlinkWord is called. It's set to true in morseSubmitButtonPressed() which would inhibit BlinkWord() from being called. But where is it set to false?

it seems that the left and right buttons inc/decrement some number. what is suppose to happen when Submit() is called? should is allow Blink() to run or not run?

Ok I will try to clarify that specific question/concern.
In the github I linked to there are all of my files. Including the buzzer that goes off when you fail, the overall timer for completion of all modules, etc.
The main ino file is what declares that variable morseModuleDefused and sets it to false.

For the second question, yes the left and right buttons inc/decrement a number which is then displayed on the 7 segment display. That is the "radio frequency" that they are trying to get right to win the module. When they press the submit button it should do one of two things. Either update the value to show that it is defused=true and green led is HIGH to show the user that it is now successfully defused OR add a strike to the total counter from the .ino which then if to many of these strikes are accumulated (over 3 right now) it will make the void morseModuleBoom() function be called which shuts off all modules.

If there are other things unclear please ask. I REALLY am appreciating the help.

.ino file:

#include <LiquidCrystal.h>
#include <LiquidCrystal_I2C.h>
#include <LedControl.h>
#include <SevenSegmentExtended.h>

#define BOMB_TIMER_MINUTES 7 // total bomb starting time min
#define BOMB_TIMER_SECONDS 0 // total bomb starting time sec

#define PIN_STRIKE_LED_1 50 // strike 1 LED
#define PIN_STRIKE_LED_2 48 // strike 2 LED
#define PIN_STRIKE_LED_3 46  // strike 3 LED

bool defused = false, exploded = false; // is bomb defused or exploded default values false

// on new bomb all modules start with default "is difused" state of False, set to true if you dont want to have to do the modules for testing
bool 
//buttonModuleDefused = false, 
//mazeModuleDefused = false,
//memoryModuleDefused = false, 
morseModuleDefused = false;
//passwordModuleDefused = false,
//simonModuleDefused = false, 
//whoModuleDefused= false;

bool explodedFromStrikes = false; // is bomb exploded from strikes default value false
int nrStrikes = 0; // number of strikes default starting is 0 (could be changed in future to allow only 1 strike, etc)

char serialCode[10];

void generateSerialCode() // function that generates the serial number for the bomb
{
  char alphanumeric[50] = {'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', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
  for ( int i = 0; i < 7; i++)
    serialCode[i] = alphanumeric[random(0, 35)];
}

// list all modules/ header files that should be included 
// ** buzzer.h and time.h must be at the top as they are called by other functions

#include "buzzer.h"
#include "time.h"
//#include "button.h"
//#include "discharge.h"
//#include "knob.h"
//#include "maze.h"
//#include "memory.h"
#include "morse.h"
//#include "password.h"
//#include "simon.h"
//#include "venting.h"
//#include "who.h"

void setup() // this section includes all setups for all modules to define INPUTS/OUTPUTS/DEFAULT VALUES/ ETC
{
  Serial.begin(9600);
  randomSeed(analogRead(0));

  pinMode(PIN_STRIKE_LED_1, OUTPUT);
  pinMode(PIN_STRIKE_LED_2, OUTPUT);
  pinMode(PIN_STRIKE_LED_3, OUTPUT);

  digitalWrite(PIN_STRIKE_LED_1, LOW);
  digitalWrite(PIN_STRIKE_LED_2, LOW);
  digitalWrite(PIN_STRIKE_LED_3, LOW);

  generateSerialCode();

  //buttonSetup();
  //dischargeSetup();
  //knobSetup();
  //mazeSetup();
  //memorySetup();
  morseSetup();
  //passwordSetup();
  //simonSetup();
  timeSetup();
  //ventingSetup();
  //whoSetup();

}

void bombExploded() // what should each module do when exploded
{
  exploded = true;
  boomBuzzer();
  //buttonModuleBoom();
  //dischargeModuleBoom();
  //knobModuleBoom();
  //mazeModuleBoom();
  //memoryModuleBoom();
  morseModuleBoom();
  //passwordModuleBoom();
  //simonModuleBoom();
  timeModuleBoom();
  //ventingModuleBoom();
  //whoModuleBoom();
}

void addStrike() // function that adds a strike
{
  nrStrikes++;
  strikeBuzzer();

  if (nrStrikes == 1) digitalWrite(PIN_STRIKE_LED_1, HIGH);
  else if (nrStrikes == 2) digitalWrite(PIN_STRIKE_LED_2, HIGH);
  else if (nrStrikes == 3) // the maximum number of strikes is reached
  {
    digitalWrite(PIN_STRIKE_LED_3, HIGH);
    explodedFromStrikes = true;
    bombExploded();
  }
}

void loop()
{

  timeLoop();
//    buzzerLoop(); //dont need a loop as it only goes off if true?

  if (!defused && !exploded)
  {
    //buttonLoop();
    //dischargeLoop();
    //knobLoop();
    //mazeLoop();
    //memoryLoop();
    morseLoop();
    //passwordLoop();
    //simonLoop();
    //ventingLoop();
    //whoLoop();
  }

  if (!exploded && (
   //buttonModuleDefused && 
   //mazeModuleDefused &&
   //memoryModuleDefused && 
   morseModuleDefused //&&
   //passwordModuleDefused &&
   //simonModuleDefused && 
   //whoModuleDefused
   ))
  {
    victoryBuzzer();
    defused = true;
  }
}

so it seems that BlinkWord() is allowed to run if ! morseModuleDefused and Submit() stops it from running by setting Defused to true.

it's still not clear to me what Blink() does. Besides case i == 0, each iteration it also looks like it wants to increment morseDelayCounter but incorrectly does morseDelayCounter+ 1 in instead of either += 1 or simply ++

it's also not clear why it has two loops incrementing DelayCounter.

gcjr:
so it seems that BlinkWord() is allowed to run if ! morseModuleDefused and Submit() stops it from running by setting Defused to true.

That is correct!

gcjr:
it's still not clear to me what Blink() does. Besides case i == 0, each iteration it also looks like it wants to increment morseDelayCounter but incorrectly does morseDelayCounter+ 1 in instead of either += 1 or simply ++

it's also not clear why it has two loops incrementing DelayCounter.

I would assume that I built that completely wrong then. This is what I want / am trying to do with the blinking.

I wanted to define an array with the word or morse code for all possible words from the manual. There are 16 words possible. I then want the Blink() function to simply blink out the morse code that corresponds to that predefined word that was selected. In the code above I only have one of the 16 words defined because I wanted to test the logic before I added more mess to the file.

So at the end of the day. Blink() should cause the PIN_MORSE_LED_1 to blink out the word.

I thought I was doing this by looping through the array with the for loop and based on what number was returned performing a blink of different lenghts for dot/ dash.

The weird DelayCounter was just a stupid attempt to make the system wait a predefined amount of time before moving to the next letter/ word.. It means nothing and can be removed.

still confusing.

because Submit() suspends calls to Blink() by setting Defused to true, it seems that purpose of Blink() is to display a morse sequence until the DisplayNumber matches the CorrectNumber.

but Blink() unnecessarily tests for CorrectNumber ==1 which seems to limit when the that code runs

and Blink() determines whether to display dot or dashed based on the index, "i" rather than using "i" as the index to an array and using the array value to determine dot, dash or space.

it also seems that the morse sequence array should be determined from another array (of 16), an array and pointers to arrays.

while newbies seem reluctant to use sub-functions, i think you have too many. I think you can display a dot or dash with a single function given the duration. Blink() would call the same function with a DotDelay or a DashDelay. Similarly there's no need for a YellowOn() and YellowOff(). a dotDash() would turn on the LED, wait the specified delay, turn off the LED and then wait the fixed delay between a dot/dash.

you said there are 16 morse sequences. looks like morseWord1 [] with 0,1 or 2 is an example, but I don't know what morseTable [] is

here's what I think Blink() should be and demonstrates what I said above.

This version of Blink() doesn't run thru the entire sequence each time it's called. It just displays one morse letter. This allows buttons to be scanned before the sequence completes

// -----------------------------------------------------------------------------
void morseDotDash (
    unsigned long  duration )
{
    digitalWrite  (PIN_MORSE_LED_1, LOW);
    delay (duration);
    digitalWrite  (PIN_MORSE_LED_1, HIGH);
    delay (morseDotDashLEDDelay);
}

// -----------------------------------------------------------------------------

void
morseBlinkWord ()
{
    Serial.println (__func__);

    static unsigned i = 0;

    switch (morseWord1 [i])  {
    case 2:
        morseDotDash (morseYellowLEDDash);
        break;

    case 1:
        morseDotDash (morseYellowLEDDot);
        break;

    case 0:
    default:
        delay (morseLetterLEDDelay);
        break;
    }

    i = i < (sizeof(morseWord1)/sizeof(int))-1 ? i+1 : 0;
}

i'm also sure the button code can be made smaller

gcjr:
here's what I think Blink() should be and demonstrates what I said above.

This version of Blink() doesn't run thru the entire sequence each time it's called. It just displays one morse letter. This allows buttons to be scanned before the sequence completes

// -----------------------------------------------------------------------------

void morseDotDash (
    unsigned long  duration )
{
    digitalWrite  (PIN_MORSE_LED_1, LOW);
    delay (duration);
    digitalWrite  (PIN_MORSE_LED_1, HIGH);
    delay (morseDotDashLEDDelay);
}

// -----------------------------------------------------------------------------

void
morseBlinkWord ()
{
    Serial.println (func);

static unsigned i = 0;

switch (morseWord1 [i])  {
    case 2:
        morseDotDash (morseYellowLEDDash);
        break;

case 1:
        morseDotDash (morseYellowLEDDot);
        break;

case 0:
    default:
        delay (morseLetterLEDDelay);
        break;
    }

i = i < (sizeof(morseWord1)/sizeof(int))-1 ? i+1 : 0;
}




i'm also sure the button code can be made smaller

This is fantastic. I simply had to swap the HIGH and LOW values in order to get it blink the morse code instead of the time where LED is off being the code, I also added another case 3 that I added to the array that does a long delay before the word repeats.

I do want to understand though why I would want to go back to using delay() instead of following the setup similar to BlinkWithoutDelay that measures the time since change as that would NEVER overlap with button presses.

I replaced my code with what you provided and the blinking worked perfectly except I could not press the buttons any time a delay was occurring. that is why I thought I should change it back to something like that sample code that came with the IDE.

Would doing that break the logic in some way I am not seeing.

Also THANK YOU. I appreciate that you have stuck this out. I know you are not obligated to do so and this has helped me learn a lot about the importance of many things.

I replaced my code with what you provided and the blinking worked perfectly except I could not press the buttons any time a delay was occurring. that is why I thought I should change it back to something like that sample code that came with the IDE.

not sure i understand what you're saying

in your code, Blink() ran thru the entire sequence before returning and allowing loop() to repeat where button presses were checked. in my version of Blink(), it returns after displaying each morse letter. this allow a button press to be detected in the gap between letters. this mean the button has to be held down during the the display of the letter.

Are you questioning that a button press is not detected during the display of a morse letter, while your code doesn't detect a button press during the display of the entire sequence?

i see no advantage in these cases of using millis() to implement a delay over simply using delay() for short periods of time. your code has several delay()s including one for 500 msec

gcjr:
not sure i understand what you're saying

in your code, Blink() ran thru the entire sequence before returning and allowing loop() to repeat where button presses were checked. in my version of Blink(), it returns after displaying each morse letter. this allow a button press to be detected in the gap between letters. this mean the button has to be held down during the the display of the letter.

Are you questioning that a button press is not detected during the display of a morse letter, while your code doesn't detect a button press during the display of the entire sequence?

i see no advantage in these cases of using millis() to implement a delay over simply using delay() for short periods of time. your code has several delay()s including one for 500 msec

You are right, I thought the first version I posted here was an older version that I was working on where the logic
was much simpler but not expandable, where I had a dot & dash function that used this type of logic and were manually called the number of times needed for my test word.

blinkwithoutdealy style:

if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

The problem is that the time that the LED is off is very small (200ms roughly) and since this game relies heavily on timing any input delays could mean the game is failed and would make the experience much worse in the long run as it compounds from one module to the next.

I will try writing these types of delays back in and if I have issues I will make a post about it as it would be a different issue completely from the original post issue.

the code i posted (again below) uses the delays value from your code. why do you need to add additional delay instead of simply adjusting those values?

const unsigned long morseYellowLEDDot = 100; // length of dot
const unsigned long morseYellowLEDDash = 400; // length of dash
const unsigned long morseLetterLEDDelay = 500; // length of delay between letters
const unsigned long morseDotDashLEDDelay = 200;
// -----------------------------------------------------------------------------
void morseDotDash (
    unsigned long  duration )
{
    digitalWrite  (PIN_MORSE_LED_1, LOW);
    delay (duration);
    digitalWrite  (PIN_MORSE_LED_1, HIGH);
    delay (morseDotDashLEDDelay);
}

// -----------------------------------------------------------------------------
// not expanded for other words as only 1 word array is built for testing

void
morseBlinkWord ()
{
    Serial.println (__func__);

    static unsigned i = 0;

    switch (morseWord1 [i])  {
    case 2:
        morseDotDash (morseYellowLEDDash);
        break;

    case 1:
        morseDotDash (morseYellowLEDDot);
        break;

    case 0:
    default:
        delay (morseLetterLEDDelay);
        break;
    }

    i = i < (sizeof(morseWord1)/sizeof(int))-1 ? i+1 : 0;
}