topic=642475.0
First things first
1)
Use decent names for your variables. The letter 'l' does not mean anything at all; neither does the letter 'x' or any of the others. Searching for the variable named 'l' is a disaster; the letter 'l' occured 330 times in the code in reply #9 and not all of them refer to the variable.
2)
To solve your issue, get rid of for-loops (and the likes) and delays. It makes your code unresponsive.
3)
Get rid of goto.
Below a rewrite of sound2_5. My understanding of your code is that variables 'x' and 'y' represent the minimum and maximum frequency of the siren and that variable 'l' represents a frequency.
Your current variable 'j' represents the number of times that you want the siren to cycle.
Note in advance:
static variables are remembered just like global variables when the function finishes; they however have local scope (only known in the function where they are used).
At the top of your code, rename the variables 'x' and 'y' to reflect their real meaning; I've also renamed t2 (based on how I understand your code). The below assumes that these variables never change (I did not look too much at the rest of your code).
// siren constants
const uint16_t minSirenFrequency = 400;
const uint16_t maxSirenFrequency = 1000;
const uint32_t sirenToneDuration = 500;
Next the sound2_5
/*
sound2_5
In:
stop; if true, forces the stop state
Returns:
true when siren has cycled 10 times or is stopped, else false
*/
bool sound2_5(bool reset)
{
// count the cycles
static uint8_t numCycles;
// the current frequency
static uint16_t frequency;
}
Variable 'n' is a variable that indicates if you want to increase the frequency or decrease the frequency. We will implement a simple state machine with three steps reflecting the three states (increase, decrease, off)
// indicate if we want to increase (0) or decrease (1) the frequency or switch the buzzer off (2)
static uint8_t state = 0;
Next you can implement the states; each state will do one step of the increase or decrease or switches the buzzer off. Below the framework.
/*
sound2_5
In:
stop; if true, forces the stop state
Returns:
true when siren has cycled 10 times or is stopped, else false
*/
bool sound2_5(bool stop)
// count the cycles
static uint8_t numCycles;
// the current frequency; initial value minSirenFrequency
static uint16_t frequency = minSirenFrequency;
// indicate if we want to increase (0) or decrease (1) the frequency or switch the buzzer off (2); initial value increase (0)
static uint8_t state;
delayMicroseconds(sirenToneDuration);
switch (state)
{
// increase siren frequency
case 0:
// do whatever needs to be done
// stop when you reach maxSirenFrequency and go to decrease state
break;
// decrease siren frequency
case 1:
// do whatever needs to be done
// stop when you reach minSirenFrequency, increment number of cycles and go to off state when all cycles done or to the increase state when not
break;
// buzzer off
case 2:
// do whatever needs to be done
// cleanup
break;
}
}
Before we do the real implementation, we will give the numbers 0, 1 and 2 meaningful names. Place the below near the top of your code.
// sound states
enum SOUND_STATES
{
SOUND_INCREASE,
SOUND_DECREASE,
SOUND_STOP,
};
/*
sound2_5
In:
stop; if true, forces the stop state
Returns:
true when siren has cycled 10 times, else false
*/
bool sound2_5(bool stop)
{
// count the cycles
static uint8_t numCycles;
// the current frequency; initial value minSirenFrequency
static uint16_t frequency = minSirenFrequency;
// indicate if we want to increase or decrease the frequency or switch the buzzer off; initial value increase
static SOUND_STATES state = SOUND_INCREASE;
if (stop == true)
{
Serial.println("stop");
state = SOUND_STOP;
}
delayMicroseconds(sirenToneDuration);
switch (state)
{
case SOUND_INCREASE:
//Serial.print("frequency = ");
//Serial.println(frequency);
tone(buzzer, frequency);
frequency += 2;
// if we've reached the maximum frequency
if (frequency >= maxSirenFrequency)
{
// go to the next state
state = SOUND_DECREASE;
}
return false;
case SOUND_DECREASE:
//Serial.print("frequency = ");
//Serial.println(frequency);
tone(buzzer, frequency);
frequency -= 2;
if (frequency <= minSirenFrequency)
{
numCycles++;
Serial.println(numCycles);
if (numCycles < 10)
{
state = SOUND_INCREASE;
}
else
{
state = SOUND_STOP;
}
}
return false;
case SOUND_STOP:
Serial.println("off");
noTone(buzzer);
numCycles = 0;
state = SOUND_INCREASE;
return true;
default:
return false;
}
}
The SOUND_INCREASE state stops when the maximum frequency is reached by changing the state variable to SOUND_DICREASE. The next time that you call the sound2_5 function, it will do the decrease of the frequency
The default case was added to keep the compiler happy.
You need to call this function as often as possible from e.g. loop(); directly or indirectly (from your siren() function).
Below demonstrates the use of the function in loop(). The code uses the Serial input to start (and optionally) stop the siren.
void loop()
{
static bool runIt = false;
if (Serial.available() > 0)
{
char ch = Serial.read();
Serial.println(ch);
if (ch == 'A')
{
runIt = true;
}
else if (ch == 'B')
{
sound2_5(true);
runIt = false;
}
}
if (runIt == true)
{
if (sound2_5(false) == true)
{
sound2_5(true);
runIt = false;
}
}
}
If you press A in a terminal program, the siren starts. You can interrupt it by pressing be or let it run till completion.
The sound2_5() function now no longer uses a for-loop which makes it more responsive but it still uses a delay. To get rid of that, you will have to use a micros() based approach.
Add two variables to the function.
// keep track of startTime of delay
static uint32_t delayStartTime;
// keep track if the siren was already started or not
static bool sirenInProgress = false;
And add an else to the if(stop == true).
if (stop == true)
{
Serial.println("stop");
state = SOUND_STOP;
}
else
{
// do timing here; replace delayMicroseconds
}
And the implementation with explanation
else
{
// if this is the first time that the function is called for the sequence
if (sirenInProgress == false)
{
delayStartTime = micros();
sirenInProgress = true;
}
// if it's not time yet
if (micros() - delayStartTime < sirenToneDuration)
{
// nothing to do yet
return false;
}
delayStartTime = micros();
}
Once you have modified all your sound functions, you can implement the above in a state machine in siren(). If all your sound functions are implemented as shown, siren can look like (not tested)
bool siren()
{
static uint8_t state;
switch (state)
{
case 0:
if (sound2_1(false) == true)
state++;
break;
case 1:
if (sound2_1(false) == true)
state++;
break;
case 2:
delay(300);
state++;
break;
case 3:
if (sound2_3(false) == true)
state++;
break;
case 4:
if (sound2_2(false) == true)
state++;
break;
case 5:
delay(300);
state++;
break;
// other case here
...
...
default:
noTone(buzzer);
delay(1000);
state = 0;
return true;
//break;
}
return false;
}