Hi, I'm trying to make a program that writes out three letters in morse code on three separate LEDs when a button is pressed. I also want the button to be able to stop the LEDs from flashing, and then restart from the first letter on an additional button press.
// Work in progress - stop and start with button does not work yet
//Initials: TRB
int buttonState = 0;
int ledState = 0;
unsigned long timeUnit = 500; // Morse code unit in milliseconds
int cycle = 0; // 0 or 1 depending on if lights should be on or not
const int buttonCheckInterval = 250; // how long program waits to check if button is pressed in milliseconds
unsigned long previousTimeSequence = 0;
unsigned long previousTimeChecker = 0;
unsigned long currentTime = 0;
void dot(int pinNumber) {
currentTime = millis();
if(currentTime - previousTimeSequence >= timeUnit) {
previousTimeSequence = currentTime;
if(cycle >= 1) {
if(ledState == LOW) {
ledState = HIGH;
}
else {
ledState = LOW;
}
digitalWrite(pinNumber, ledState);
}
}
}
void dash (int pinNumber) {
currentTime = millis();
if(currentTime - previousTimeSequence >= 3*timeUnit) {
previousTimeSequence = currentTime;
if(cycle >= 1) {
if(ledState == LOW) {
ledState = HIGH;
}
else {
ledState = LOW;
}
digitalWrite(pinNumber, ledState);
}
}
}
void T(int inputNumber) {
dot(inputNumber);
Serial.println("T");
}
void R(int inputNumber) {
dot(inputNumber);
dash(inputNumber);
dot(inputNumber);
Serial.println("R");
}
void B(int inputNumber) {
dash(inputNumber);
dot(inputNumber);
dot(inputNumber);
dot(inputNumber);
Serial.println("B");
}
void circuitCheck() {
currentTime = previousTimeChecker;
buttonState = digitalRead(5);
if(buttonState == HIGH) {
cycle++;
}
if(currentTime - previousTimeChecker >= timeUnit) {
if(cycle > 1) {
cycle = 0;
}
}
}
void setup() {
pinMode(2, OUTPUT);
digitalWrite(2, LOW);
pinMode(3, OUTPUT);
digitalWrite(3, LOW);
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
pinMode(5, INPUT);
Serial.begin(9600);
}
void loop() {
currentTime = millis();
circuitCheck();
if (cycle == 1) {
T(4);
R(3);
B(2);
}
}
welcome to the Arduino-Community.
What you code does really good is beeing divided into functions.
First of all I have a question of HOW the code should work.
Do you want to blink each LED independent from the two other LEDs repeating his letter continously?
Thtat's what your code (almost) does right now
or do you want the three LEDs to act this way:
first LED blink letter "T "and then stop blinking
second LED blink letter "R" and then stop blinking
third LED blink letter "B" and then stop blinking
The non-delayed code-execution with millis() and if-conditions that check if an interval of time has passed
means that all code inside your loop runs through thousands of times per seconds.
The if-conditions
if(currentTime - previousTimeSequence >= timeUnit
are only true if the defined time stored into variable timeunit has passed by
true
because the dot-condition is always faster to update variable previousTimeSequence
to get your code checking for a buttonpress every 250 milliseconds and make your code blink the LEDs in the right sequence you need a functionality called statemashine. There is another variable that is assigned different values
to and you have if-conditions or a "switch-case statement.
a statemashine brings together:
executing parts of your code in a defined sequence
delayed execution of parts of your code
while other parts of your code (the checkbutton) are executed much faster
I don't have an example for a statemachine handy so I call @The Community: who does know a link to a well explained example of a statemachine?
The hardest part is not necessarily understanding them, it’s changing your programming style away from linear (which is how your brain naturally thinks when you can only really do one task at once)....
i.e. Do this, wait, do this, do this, wait....
To responding to stimulus events and current state....
Constantly check:
If stimulus A and state X, perform action 1, set state Y.
If stimulus B and state Y, perform action 2, set state Z.
etc.
A stimulus can be anything from a button press, to a certain amount of time having passed since you last did an action, to a byte of data arriving from the serial port or elsewhere.