Running 2 pwm input/outputs

I have posted previously on the forum for the same project when I had a different problem(Pwm controlled led low frequency flicker]

The project is an Arduino controlled lights system for an rc plane which includes - navigation lights, strobe lights, beacon lights, afterburner effect and (yet to work at the same time as the previous) gun firing effect.

The new (and unrelated to previous issue) is the combination of the base sketch with the next sketch I'm adding onto the end in order to add the next functional element - which is a gun flashing effect that is called for after a switch on an external remote is triggered.

The idea of the code for the gun is to have the momentary switch start a sequence of code (by setting the bool firing to true ) then to have the sequence - zero delay flash led to start for 60 status changes then to set the bool firing back to false.

the switch input is a pwm input - so bool firing is set to true when the duty cycle is 80% (1800)

So I have been able to get this pwm gun firing sketch to work independently.
I have also got the base sketch with a pwm afterburner to work independently.

However when combined the resulting sketch does not work properly only one of the pwm controlled functions work, which one works appears to be randomly selected after the Arduino is powered up(plugged in)

Gun
input pin - 3
output pin -4
afterburner
input pin - 2
output pin - 5

gun sketch-


const char ledpingun = 4;
bool blinkinggun = true;
byte blinksgun = 0;
int ch5; //create value to keep value of switch channel
bool firing = false;

//delay stuff
unsigned long previoustimegun = 0;
int eventintervalgun = 5;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); // what does this do?
  pinMode(3, INPUT); //gunchannel
  pinMode(4, OUTPUT); //gun
}

void loop() {
  //gun
  ch5 = pulseIn(3, HIGH , 25000); //read the value of the channel on pin 3
  ch5 = constrain(ch5, 1000, 2000);
  unsigned long lasteventgun;
  unsigned long toploopgun = millis();
  unsigned long currenttimegun = millis();

if(currenttimegun - previoustimegun >= eventintervalgun){//this introduces delay to function to prevent errors
  if (ch5 >= 1800) {
    firing = true;} // this sets firing to true as soon as pulse of 1800ms is achieved and does not set to false until all following blinks have been achieved

  if (firing) { //if firing is true do following code
    if (blinkinggun) {//if blinksgun is true do following code
      if (toploopgun - lasteventgun >= 20) { //period between status change of ledpingun
        lasteventgun = toploopgun;
        digitalWrite(ledpingun, !digitalRead(ledpingun));//short for...

        if (++blinksgun >= 60) {//dtermines how many time the ledpingun will change staus x/2 gives number of light flashes
          blinkinggun = false; //tells the loop that the gun has done all flashes
          blinksgun = 0; //set number of blinks back to 0 in preperation for the next use of the gun
          firing = !firing; // resets the orional loop to false to say that the code has run its course and is ready for next activation
          //reset millis()
        }
      }
    } else if (toploopgun - lasteventgun >= 800) {
      blinkinggun = true;
    }
      previoustimegun = currenttimegun;
   }
  }
}

base sketch with afterburner and other simple led functions(strobe, nav light, beacon)

this code has the integrated gun sketch and DOES NOT WORK

//this is strobe
const char ledPinstrobe = 7;
bool blinkingstrobe = true;
byte blinksstrobe = 0;

//fade beacon
int value = 2;
int ledpin = 6;
long time=0;
int periode = 2000;

//afterburner
int ch1; // create a value to keep the rc values
int valueab = 0;
unsigned long previoustime = 0;
int eventinterval = 50;

//this is gun
const char ledpingun = 4;
bool blinkinggun = true;
byte blinksgun = 0;
int ch5; //create value to keep value of switch channel
bool firing = false;
unsigned long previoustimegun = 0;
int eventintervalgun = 5;


void setup() {
  pinMode(2,INPUT);//afterburner channel
  pinMode(3,INPUT);//gunchannel
  pinMode(4,OUTPUT);//gun
  pinMode(5,OUTPUT);//afterburner
  pinMode(6,OUTPUT);//beacon
  pinMode(7,OUTPUT);//strobe
  pinMode(8,OUTPUT);//nav light
  digitalWrite(8,HIGH);//nav lights on

    //afterburner
  Serial.begin(9600); // what does this do?
}

void loop() {

  //strobe
  static unsigned long lastEventstrobe;
  unsigned long topLoopstrobe = millis();
  if (blinkingstrobe) {
    if (topLoopstrobe - lastEventstrobe >= 50) {
      lastEventstrobe = topLoopstrobe;
      digitalWrite(ledPinstrobe, !digitalRead(ledPinstrobe));//short for "if (digitalRead(ledPin) == HIGH) { 
      //  digitalWrite(ledPin, LOW);
      //} else {
      //  digitalWrite(ledPin, HIGH);
      // }
      if (++blinksstrobe >= 4) {//if the last event was the top loop-850ms (off) it will blink on(50)-off(50)-on(50)-off(50)
        blinkingstrobe = false;
        blinksstrobe = 0;
        //reset millis()
      }
    }
  } else if (topLoopstrobe - lastEventstrobe >= 800) {//this 800 +4x50 =1000
    blinkingstrobe = true;
  }

    //beacon fade
time = millis();
  value = 128+127*cos(2*PI/periode*time);
  analogWrite(ledpin, value);           // sets the value (range from 0 to 255) 

  //afterburner
  unsigned long currenttime = millis();
  ch1 = pulseIn(2, HIGH ,25000); //read the width of each channel
  if(currenttime - previoustime >= eventinterval){
if (ch1>=1600){
  valueab = ch1;
  valueab = constrain(valueab,1600,2000);
  valueab = map(valueab, 1600,2000,0,255);
  analogWrite(5,valueab);                       //sets pwm value from 0 to 255 //led afterburner
  previoustime = currenttime;
}else{
  analogWrite(5,0);
  previoustime = currenttime;}

}
//gun
  ch5 = pulseIn(3, HIGH ,25000);//read the value of the channel on pin 3
  ch5 = constrain(ch5,1000,2000);
  unsigned long lasteventgun;
  unsigned long toploopgun = millis();
  unsigned long currenttimegun = millis();
  
  if(currenttimegun - previoustimegun >= eventintervalgun){//this introduces delay to function to prevent errors
  if(ch5 >= 1800){
   firing = true;}               // this sets firing to true as soon as pulse of 1800ms is achieved and does not set to false until all following blinks have been achieved

  if(firing){
   if (blinkinggun) {
    if (toploopgun - lasteventgun >= 20) { //period between status change of ledpingun
      lasteventgun = toploopgun;
      digitalWrite(ledpingun, !digitalRead(ledpingun));//short for...
      if (++blinksgun >= 30) {//dtermines how many time the ledpingun will change staus x/2 gives number of light flashes
        blinkinggun = false; //tells the loop that the gun has done all flashes
        blinksgun = 0; //set number of blinks back to 0 in preperation for the next use of the gun
        firing = false; // resets the orional loop to false to say that the code has run its course and is ready for next activation
        //reset millis()
      }
    }
  } else if (toploopgun - lasteventgun >= 800) {//this 800 +4x50 =1000
    blinkinggun = true;
  }
  previoustimegun = currenttimegun;
  }
  }
  }
1 Like

One problem is lasteventgun needs to be static or global.

Apologies... but I don't quite understand (please bear in mind this is actually my first 'proper' project outside of the intro book)
If you could give an example of how change to be static or global. :slight_smile:

instead of

void loop() {

  //strobe
  static unsigned long lastEventstrobe;

use

 static unsigned long lastEventstrobe; //declare outside any function
void loop() {

  //strobe

Don't know how to edit since they changed the forum...

it should really be:

unsigned long lasteventgun; //declare outside any function
void setup() {...
}
void loop() {

[/quote]

Or else make it static. It's strange that you claim not to know how to do that, since you already have declared static variables inside your function.

For simplicity and readability, I would put each effect in a separate function. That way you can use local variables and don't have to worry about name collisions.

//this is strobe
const char StrobeLEDPin = 7;
bool blinkingstrobe = true;
byte blinksstrobe = 0;

//fade beacon
int value = 2;
const byte BeaconLEDPin = 6;
long time = 0;
int periode = 2000;

const byte NavLEDPin = 8;

//afterburner
const byte AfterburnerInputPin = 2;
const byte AfterburnerLEDPin = 5;
int ch1; // create a value to keep the rc values
int valueab = 0;
unsigned long previoustime = 0;
unsigned eventinterval = 50;

//this is gun
const byte GunInputPin = 3;
const char GunLEDPin = 4;
bool firing = false;

void setup()
{
  pinMode(AfterburnerInputPin, INPUT); //afterburner channel
  pinMode(GunInputPin, INPUT); //gunchannel
  pinMode(GunLEDPin, OUTPUT); //gun
  pinMode(AfterburnerLEDPin, OUTPUT); //afterburner
  pinMode(BeaconLEDPin, OUTPUT); //beacon
  pinMode(StrobeLEDPin, OUTPUT); //strobe
  pinMode(NavLEDPin, OUTPUT); //nav light
  digitalWrite(NavLEDPin, HIGH); //nav lights on

  //afterburner
  Serial.begin(9600); // what does this do?
}

void loop()
{
  strobe();
  afterburner();
  gun();
}

void strobe()
{
  static unsigned long lastEventstrobe = 0;
  unsigned long topLoopstrobe = millis();
  if (blinkingstrobe)
  {
    if (topLoopstrobe - lastEventstrobe >= 50)
    {
      lastEventstrobe = topLoopstrobe;
      digitalWrite(StrobeLEDPin, !digitalRead(StrobeLEDPin)); //short for "if (digitalRead(ledPin) == HIGH) {
      //  digitalWrite(StrobeLEDPin, LOW);
      //} else {
      //  digitalWrite(StrobeLEDPin, HIGH);
      // }
      if (++blinksstrobe >= 4)  //if the last event was the top loop-850ms (off) it will blink on(50)-off(50)-on(50)-off(50)
      {
        blinkingstrobe = false;
        blinksstrobe = 0;
        //reset millis()
      }
    }
  }
  else if (topLoopstrobe - lastEventstrobe >= 800)    //this 800 +4x50 =1000
  {
    blinkingstrobe = true;
  }

  //beacon fade
  time = millis();
  value = 128 + 127 * cos(2 * PI / periode * time);
  analogWrite(BeaconLEDPin, value);           // sets the value (range from 0 to 255)
}

void afterburner()
{
  //afterburner
  unsigned long currenttime = millis();
  ch1 = pulseIn(AfterburnerInputPin, HIGH , 25000); //read the width of each channel
  if (currenttime - previoustime >= eventinterval)
  {
    if (ch1 >= 1600)
    {
      valueab = ch1;
      valueab = constrain(valueab, 1600, 2000);
      valueab = map(valueab, 1600, 2000, 0, 255);
      analogWrite(5, valueab);                      //sets pwm value from 0 to 255 //led afterburner
      previoustime = currenttime;
    }
    else
    {
      analogWrite(5, 0);
      previoustime = currenttime;
    }

  }
}

void gun()
{
  //gun
  unsigned long currentTime = millis();
  static unsigned long lastShotTime = 0;
  static unsigned shotsFired;

  int gunPulse = pulseIn(GunInputPin, HIGH , 25000); //read the value of the channel on pin 3
  gunPulse = constrain(gunPulse, 1000, 2000);
  if (!firing && gunPulse >= 1800)
  {
    lastShotTime = currentTime;
    digitalWrite(GunLEDPin, HIGH);
    shotsFired = 1;
    firing = true;
  }

  // Is the shot over?
  if (firing && currentTime - lastShotTime >= 5)
  {
    digitalWrite(GunLEDPin, LOW);

    // After 30 shots, stop firing
    if (shotsFired >= 30)
    {
      firing = false;
    }
  }

  // Time for a new shot?
  if (firing && currentTime - lastShotTime >= 20)
  {
    lastShotTime = currentTime;
    digitalWrite(GunLEDPin, HIGH);
    shotsFired++;
  }
}
1 Like

Thank you.
I used a lot of the principles you applied in this code and have managed to solve the problem using this code.

//this is strobe
const char STROBEledpin = 7;
bool blinkingSTROBE = true;
byte blinksSTROBE = 0;

//fade beacon
int value = 2;
const byte BEACONledpin = 6;
long time=0;
int periode = 2000;

//nav lights
const byte NAVledpin = 8;

//afterburner
const byte ABinputpin = 2;
const byte ABledpin = 5;
int ch1; // create a value to keep the rc values
int valueab = 0;
unsigned long previoustime = 0;
int eventinterval = 50;

//this is gun
const byte GUNinputpin = 3;
const char GUNledpin = 4;
bool firing = false;
bool blinkingGUN = true;
byte blinksGUN = 0;


void setup() {
  pinMode(ABinputpin,INPUT);//afterburner channel
  pinMode(GUNinputpin,INPUT);//gunchannel
  pinMode(GUNledpin,OUTPUT);//gun
  pinMode(ABledpin,OUTPUT);//afterburner
  pinMode(BEACONledpin,OUTPUT);//beacon
  pinMode(STROBEledpin,OUTPUT);//strobe
  pinMode(NAVledpin,OUTPUT);//nav light
  digitalWrite(NAVledpin,HIGH);//nav lights on

  //afterburner
  Serial.begin(9600); // what does this do?
}

void loop() {
  strobe();
  afterburner();
  gun();
}

void strobe()
{
  //strobe
  static unsigned long lasteventSTROBE;
  unsigned long toploopSTROBE = millis();
  if (blinkingSTROBE) {
    if (toploopSTROBE - lasteventSTROBE >= 50) {
      lasteventSTROBE = toploopSTROBE;
      digitalWrite(STROBEledpin, !digitalRead(STROBEledpin));//short for...
      if (++blinksSTROBE >= 4) {//if the last event was the top loop-850ms (off) it will blink on(50)-off(50)-on(50)-off(50)
        blinkingSTROBE = false;
        blinksSTROBE = 0;
      }
    }
  } else if (toploopSTROBE - lasteventSTROBE >= 800) //this 800 +4x50 =1000
  {
    blinkingSTROBE = true;
  }

  //beacon fade
  time = millis();
  value = 128+127*cos(2*PI/periode*time);
  analogWrite(BEACONledpin, value);           // sets the value (range from 0 to 255) 

}

void afterburner()
{
  //afterburner
  unsigned long currenttime = millis();
  int ABpulse = pulseIn(ABinputpin, HIGH ,25000); //read the width of each channel

  Serial.print("ABpulse");
  Serial.print(ABpulse);
  if(currenttime - previoustime >= eventinterval)
  {
   if (ABpulse>=1600)
   {
    valueab = ABpulse;
    valueab = constrain(valueab,1600,2000);
    valueab = map(valueab, 1600,2000,0,255);
    analogWrite(5,valueab);                       //sets pwm value from 0 to 255 //led afterburner
    previoustime = currenttime;
}else{
  analogWrite(5,0);
  previoustime = currenttime;}

}
}

void gun()
{
  unsigned long lasteventGUN;
  unsigned long toploopGUN = millis();
  unsigned long currenttimeGUN = millis();
  int previoustimeGUN = 0;
  unsigned eventintervalGUN = 5;
  
  int GUNpulse = pulseIn(GUNinputpin, HIGH ,25000);//read the value of the channel on pin 3
  GUNpulse = constrain(GUNpulse,1000,2000);
  
  if(currenttimeGUN - previoustimeGUN >= eventintervalGUN){//this introduces delay to function to prevent errors
  if(GUNpulse >= 1800)
  {
   firing = true;}               // this sets firing to true as soon as pulse of 1800ms is achieved and does not set to false until all following blinks have been achieved

  if(firing)
  {
   if (blinkingGUN) 
   {
    if (toploopGUN - lasteventGUN >= 20) 
    { //period between status change of ledpingun
      lasteventGUN = toploopGUN;
      digitalWrite(GUNledpin, !digitalRead(GUNledpin));//short for...
      if (++blinksGUN >= 94) //dtermines how many time the ledpingun will change staus x/2 gives number of light flashes
      {
        blinkingGUN = false; //tells the loop that the gun has done all flashes
        blinksGUN = 0; //set number of blinks back to 0 in preperation for the next use of the gun
        firing = false; // resets the orional loop to false to say that the code has run its course and is ready for next activation
      }
    }
  } else if (toploopGUN - lasteventGUN >= 800) 
  {
    blinkingGUN = true;
  }
  previoustimeGUN = currenttimeGUN;
  }
  }
  }