Problem with PPM and LEDs

Hi all,
I hope I'm posting this in the correct forum and please excuse the fact that I'm not experienced at coding.
I am trying to control a series of led strips using 8 digital pins on an Arduino Pro mini. The input device to control these is a single PPM signal from an RC receiver.
So basically I have the PPM signal being read using pulseIn on pin 5. This channel is connected to a three position switch. This is all working fine so far.
I then want to control the output of pins 6 to 13 HIGH or LOW based on the values from pulseIn. eg. position 1 all pins HIGH, position 2 pins 11 & 13 HIGH all other pins LOW.
I can get this working for one position but if I try to add another position it behaves erraticaly.
I would appreciate it if someone could guide me as to what I should do to fix this.
Many Thanks

int ch1; 

int white_a = 13;  
int white_b = 12;  
int green_a = 11;
int green_b = 10;
int blue_a = 9;
int blue_b = 8;
int red_a = 7;
int red_b = 6;



void setup() {

  pinMode(5, INPUT); 

  Serial.begin(9600); 
  
  pinMode(white_a, OUTPUT);
  pinMode(white_b, OUTPUT);
  pinMode(green_a, OUTPUT);
  pinMode(green_b, OUTPUT);
  pinMode(blue_a, OUTPUT);
  pinMode(blue_b, OUTPUT);
  pinMode(red_a, OUTPUT);
  pinMode(red_b, OUTPUT);
   

}

void loop() {

  ch1 = pulseIn(5, HIGH, 20000); // Read the pulse width of channel 5
  

  //Sequence 1 
  
 if (ch1 >= 900 && ch1 <= 990)
  
  {digitalWrite(white_a, HIGH);}
  else
  {digitalWrite(white_a, LOW);}
  
   if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(white_b, HIGH);}
   else
   {digitalWrite(white_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(green_a, HIGH);}
   else
   {digitalWrite(green_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(green_b, HIGH);}
   else
   {digitalWrite(green_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(blue_a, HIGH);}
   else
   {digitalWrite(blue_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(blue_b, HIGH);}
   else
   {digitalWrite(blue_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(red_a, HIGH);}
   else
   {digitalWrite(red_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(red_b, HIGH);}
   else
   {digitalWrite(red_b, LOW);}
  

  
  // Sequence 2
  
  if (ch1 >= 1000 && ch1 <= 1800)
  
  {digitalWrite(white_a, HIGH);}
  else
  {digitalWrite(white_a, LOW);}
  
   if(ch1>1000)
   {digitalWrite(white_b, HIGH);}
   else
   {digitalWrite(white_b, LOW);}
   
    if(ch1>1000)
   {digitalWrite(green_a, HIGH);}
   else
   {digitalWrite(green_a, LOW);}
   
    if(ch1>1000)
   {digitalWrite(green_b, HIGH);}
   else
   {digitalWrite(green_b, LOW);}
   
    if(ch1>1000)
   {digitalWrite(blue_a, HIGH);}
   else
   {digitalWrite(blue_a, LOW);}
   
    if(ch1>1000)
   {digitalWrite(blue_b, HIGH);}
   else
   {digitalWrite(blue_b, LOW);}
   
    if(ch1>1000)
   {digitalWrite(red_a, LOW);}
   else
   {digitalWrite(red_a, LOW);}
   
    if(ch1>1000)
   {digitalWrite(red_b, LOW);}
   else
   {digitalWrite(red_b, LOW);}
  
  
  Serial.print("PWM:"); 
  Serial.println(ch1);        

  

  delay(100); 
}

I don't see why you keep testing if(ch1>1000)

Why not just one single "if..else.." ?

Actually I did mean to do that. It's a result of copy and paste.
I was going to get it working and then go through the code and get rid of anything unnecessary :blush:

Well, give it a try, and repost if you've still got problems.

And try to describe what

it behaves erraticaly

means

  Serial.print("PWM:"); 
  Serial.println(ch1);

Don't you want to tell us what gets printed? You do, if you really want help.

Sorry. By erratic I meant that the leds are flashing extremely fast on and off as if the values on the pins are floating between high and low.
What I dont understand is that this piece of code works perfectly (I've removed sequence two for the moment),

int ch1; 

int white_a = 13;  
int white_b = 12;  
int green_a = 11;
int green_b = 10;
int blue_a = 9;
int blue_b = 8;
int red_a = 7;
int red_b = 6;



void setup() {

  pinMode(5, INPUT); 

  Serial.begin(9600); 
  
  pinMode(white_a, OUTPUT);
  pinMode(white_b, OUTPUT);
  pinMode(green_a, OUTPUT);
  pinMode(green_b, OUTPUT);
  pinMode(blue_a, OUTPUT);
  pinMode(blue_b, OUTPUT);
  pinMode(red_a, OUTPUT);
  pinMode(red_b, OUTPUT);
   

}

void loop() {

  ch1 = pulseIn(5, HIGH, 20000); // Read the pulse width of channel 5
  

  //Sequence 1 
  
 if (ch1 >= 900 && ch1 <= 990)
  
  {digitalWrite(white_a, HIGH);}
  else
  {digitalWrite(white_a, LOW);}
  
   if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(white_b, HIGH);}
   else
   {digitalWrite(white_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(green_a, HIGH);}
   else
   {digitalWrite(green_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(green_b, HIGH);}
   else
   {digitalWrite(green_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(blue_a, HIGH);}
   else
   {digitalWrite(blue_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(blue_b, HIGH);}
   else
   {digitalWrite(blue_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(red_a, HIGH);}
   else
   {digitalWrite(red_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(red_b, HIGH);}
   else
   {digitalWrite(red_b, LOW);}
  

  
  // Sequence 2
  
  
  Serial.print("PWM:"); 
  Serial.println(ch1);        

  

  delay(100); 
}

But as soon as I change the if (ch1 >= 900 && ch1 <= 990) to if (ch1 >= 1000 && ch1 <= 1800) to correspond with the PPM input the flashing behavior starts.
Hi PaulS
The serial window is giving my a value fluctuating between 960 and 967 in switch position one, 1507 and 1514 in switch position 2 and 2056 and 2061 in switch position 3
Thanks for the help guys

if (ch1 >= 900 && ch1 <= 990)
  
  {digitalWrite(white_a, HIGH);}
  else
  {digitalWrite(white_a, LOW);}
  
   if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(white_b, HIGH);}
   else
   {digitalWrite(white_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(green_a, HIGH);}
   else
   {digitalWrite(green_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(green_b, HIGH);}
   else
   {digitalWrite(green_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(blue_a, HIGH);}
   else
   {digitalWrite(blue_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(blue_b, HIGH);}
   else
   {digitalWrite(blue_b, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(red_a, HIGH);}
   else
   {digitalWrite(red_a, LOW);}
   
    if (ch1 >= 900 && ch1 <= 990)
   {digitalWrite(red_b, HIGH);}
   else
   {digitalWrite(red_b, LOW);}

would be a lot easier to read as:

if (ch1 >= 900 && ch1 <= 990)
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
else
{
  digitalWrite(white_a, LOW);
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW)
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);
}

Making that change would then make it patently obvious that an array of pin numbers would be a great idea. A for loop could then be used to set all the pins HIGH or LOW in a loop.

Printing the value right after you read it, not many lines of code later is also a good idea.

Thanks PaulS,
I've had to step out for an hour but as soon as I get back I'll make the changes and see where I am.
Will post back.

HI all,
Sorry I didn't get a chance to get back to this last night.
I've just changed the code to reflect the method you mentioned PaulS but unfortunately the problem remains the same.
The pulseIn works perfectly. If I have just one sequence the entire sketch will work perfectly. When I add a second sequence the second will work perfectly but the first sequence will just flash on and off rapidly.
I've just added a third sequence and now I find that in sequence 1 green and blue will stay on but red and white flash rapidly, in sequence 2 green and blue stay on, white flashes rapidly and red turns off. Sequence 3 works as expected.
I should have mentioned that I am using the pins to activate a ULN2803 transistor as my led strips are a 12v source. Perhaps this is involved in the problem ?
In regard to arrays I am new to them and while I think I understand them after seeing some sample code, I can't really get my head around how I would use them to light particular strips while leaving others off. All of the examples I have seen involve flashing sequences which I'm not really after.
Again any guidance is much appreciated.
Many thanks
Current code below,

int ch1; 

 

  int white_a = 13;  
  int white_b = 12;  
  int green_a = 11;
  int green_b = 10;
  int blue_a = 9;
  int blue_b = 8;
  int red_a = 7;
  int red_b = 6;



  void setup() {

  pinMode(5, INPUT); 

  Serial.begin(9600); 
  
  pinMode(white_a, OUTPUT);
  pinMode(white_b, OUTPUT);
  pinMode(green_a, OUTPUT);
  pinMode(green_b, OUTPUT);
  pinMode(blue_a, OUTPUT);
  pinMode(blue_b, OUTPUT);
  pinMode(red_a, OUTPUT);
  pinMode(red_b, OUTPUT);
   

  }

  void loop() {

  ch1 = pulseIn(5, HIGH, 20000); 
  
   Serial.print("PPM:"); 
   Serial.println(ch1); 
   delay(100); 
   
   //Sequence 1
  
 if (ch1 >= 900 && ch1 <= 990)
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
else
{
  digitalWrite(white_a, LOW);
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW);
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);
}
  
  
  // Sequence 2
  
  if (ch1 >= 1000 && ch1 <= 1800)
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);
}
else
{
  digitalWrite(white_a, LOW);
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW);
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
  
  
  // Sequence 3
  
  if (ch1 >= 2000 && ch1 <= 3000)
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW);
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
else
{
  digitalWrite(white_a, LOW);
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);
}

  

  
}

I should have mentioned that I am using the pins to activate a ULN2803 transistor as my led strips are a 12v source. Perhaps this is involved in the problem ?

I think the first thing you need to do is to acquire some regular LEDs and resistors, and see whether the problem is hardware or software. If the regular LEDs and resistors exhibit the same behavior, then the problem is software. If not, the problem is hardware.

Worry about the hardware side, first. Then, when you know where the problem is, and have corrected it (if possible), worry about simplifying the code by using arrays.

The number of "sequences" should have no impact on the situation. You can test this, of course, by reducing the number of instructions in each "sequence". Just turn one pin on or off in each "sequence".

If one pin works, then the problem with multiple pins is that you are drawing too much current, resetting the Arduino.

Thanks PaulS
Working on it now. I'll post back when I have some results.

Apologies all,
I got called away to work and didn't get near this since the last night I was on.
Tonight I tested with single leds and they exhibit the same problem.
I'm sure it's something simple but I have absolutely no idea !
Any further thoughts ?

Yes, I think I see the issue. It is in your code not hardware.

The problem is in your else statements. Remember you have 3 if else statements back to back, with 3 separate conditions. So logically one condition will have to be true and run that code, and the other two will be false so the code in their else statements will also run.

For example when the signal is between 900 and 990, sequence 1 is true. But the else statements of the other two sequences also run. So this is the effective code that is executing over and over very rapidly.

 if (ch1 >= 900 && ch1 <= 990) //sequence 1 true
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
else // from sequence 2
{
  digitalWrite(white_a, LOW);
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW);
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
else // from sequence 3
{
  digitalWrite(white_a, LOW);
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);
}

That is basically what the program is doing, it's flashing LEDs like crazy.

Try this instead:

int ch1; 

 

  int white_a = 13;  
  int white_b = 12;  
  int green_a = 11;
  int green_b = 10;
  int blue_a = 9;
  int blue_b = 8;
  int red_a = 7;
  int red_b = 6;



  void setup() {

  pinMode(5, INPUT); 

  Serial.begin(9600); 
  
  pinMode(white_a, OUTPUT);
  pinMode(white_b, OUTPUT);
  pinMode(green_a, OUTPUT);
  pinMode(green_b, OUTPUT);
  pinMode(blue_a, OUTPUT);
  pinMode(blue_b, OUTPUT);
  pinMode(red_a, OUTPUT);
  pinMode(red_b, OUTPUT);
   

  }

  void loop() {

  ch1 = pulseIn(5, HIGH, 20000); 
  
   Serial.print("PPM:"); 
   Serial.println(ch1); 
                             //  I moved the delay after the if statements so the LEDs are lit during the delay
   
  
 if (ch1 >= 900 && ch1 <= 990)   //Sequence 1
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
else if (ch1 >= 1000 && ch1 <= 1800) // Sequence 2
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
}
else if (ch1 >= 2000 && ch1 <= 3000) // Sequence 3
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}

  delay(100); // keep the LEDs on for a moment

  digitalWrite(white_a, LOW);  //turn them all off and read the ch1 again
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW);
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);

}

I hope that helps.

-Tony

Hi Tony,
Thank you very much for this. After reading your code it makes a lot of sense to me. Definitely getting somewhere now, but not quite there yet. The flashing is still occurring but at a different rate.
I noticed that it seems to match the delay value so I changed this value and sure enough it changed the rate of flashing. So the delay value appears to be the key but I'm not sure why.
In code is there a way to isolate the else values from each other ? I'm afraid I'm not very experienced at this but what I had visualised in trying to write this was that each 'sequence' would exist in a separate 'container', eg. If my PPM values are within a certain range then sequence 1 has x true value and x false value. Now when I flick my switch, changing the PPM input value, the code should divert to sequence 2 (container 2) and execute the codes true and false values in this container, ignoring the code in all other containers. I wonder how one could isolate these values ?
Again thanks for the help !

In code is there a way to isolate the else values from each other ?

Yes, using if/else if/else, as Tony showed.

Yes I get what you're saying. The problem is the pulsein function takes time and the code and only do one thing at a time. So having the code shut all of them off, then read the pulse, the turn the right ones on again every time it loops will always yield flashing. Maybe we can ditch the LOW sequence.

Try this, I think it'll work.

  int ch1; 
  int white_a = 13;  
  int white_b = 12;  
  int green_a = 11;
  int green_b = 10;
  int blue_a = 9;
  int blue_b = 8;
  int red_a = 7;
  int red_b = 6;



  void setup() {
  pinMode(5, INPUT); 
  pinMode(white_a, OUTPUT);
  pinMode(white_b, OUTPUT);
  pinMode(green_a, OUTPUT);
  pinMode(green_b, OUTPUT);
  pinMode(blue_a, OUTPUT);
  pinMode(blue_b, OUTPUT);
  pinMode(red_a, OUTPUT);
  pinMode(red_b, OUTPUT);
  digitalWrite(white_a, LOW); //start with all LEDs off
  digitalWrite(white_b, LOW);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW);
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);
  }

  void loop() {

  ch1 = pulseIn(5, HIGH, 20000); 


 if (ch1 >= 900 && ch1 <= 990)   //Sequence 1
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
else if (ch1 >= 1000 && ch1 <= 1800) // Sequence 2
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, HIGH);
  digitalWrite(green_b, HIGH);
  digitalWrite(blue_a, HIGH);
  digitalWrite(blue_b, HIGH);
  digitalWrite(red_a, LOW);
  digitalWrite(red_b, LOW);
}
else if (ch1 >= 2000 && ch1 <= 3000) // Sequence 3
{
  digitalWrite(white_a, HIGH);
  digitalWrite(white_b, HIGH);
  digitalWrite(green_a, LOW);
  digitalWrite(green_b, LOW);
  digitalWrite(blue_a, LOW);
  digitalWrite(blue_b, LOW);
  digitalWrite(red_a, HIGH);
  digitalWrite(red_b, HIGH);
}
}

Another approach is to use interrupts to read the RC signal. Rather than the code having to constantly re-check the pulse, if the RC signal instead triggers an interrupt subroutine the ch1 value can be change at any moment in the loop. So in that case you could use while loops instead of if statements.

Thanks Tony ! This is working perfectly now.
I'm going to look into using interupts instead of IF statements, but for the moment it's doing exactly what I need.
Thanks again.

I'm going to look into using interupts instead of IF statements, but for the moment it's doing exactly what I need.

That would be something like buying cat litter instead of new shoes. Interrupts and if statements are two completely different things,

An interrupt is like a phone ringer. It means that there is something you need to respond to. You can choose to respond to it, or not, but the ringing gets your attention.

What exactly would replace the code in the if statement that would get your (the Arduino's actually) attention in the same way?

I'm glad to hear it's working!

Paul, I think he means that if he uses interrups instead of pulsein he can use while loops instead of if statements.

There is nothing wrong with if statements. But in some cases a while loop and interrupts is a more efficient solution rather than having the code cycle over the whole loop and constantly checking the variable and condition for the if statement.

PaulS:
That would be something like buying cat litter instead of new shoes.

True.