Multiple if statements "what am I missing here..." Did I create a loop ?"

Hi There,

relatively new here to Arduino and the forum, but I noticed lot's experienced user who offer help, so maybe I should just ask for help :wink:

I found some code samples here and tried to fix them together to create my own (monkey see, monkey do).
So far so good, just piece by piece and not changing to much. I use Serial.Println command to check my results (this works good)

But now I came to the point where I need some professional help from experienced users.

Below you will find some code, but let me explain what it should do.

I use a ultrasonic distance meter which is constantly measuring distance. The distance is send to Serial.Println so I can see it changing.

Furthermore we have a variable called "i" (i will be used later to set a value for DMX lightning brightness)

If the distance changes, the "i"value should change as well. This is no problem, however I would like to change it slowly by using increments.
The minimum value is 0, the maximum value is 255. Once the upper value (255) is reached, it should remain 255 unless the distance changes. If that happens, the "i" value should decrease from 255 back to 0 in steps.

In short: When distance <= 100, value "i" should start at 0 and change to 255 in steps of 1.
When distance >100, value "i" should go back from 255 to 0 in steps of 1 and stay at 0, until value changes again to <=100 ... etc.

When I execute code, the initial distance is printed but does not change anymore (like it's frozen or there is a loop ?), and value "i" remains 0.

Any clues what I'm doing wrong? I look forward to your replies :slight_smile:

#define trigPin 7 // pin for ultrasonic
#define echoPin 6
void setup()            

{
Serial.begin(9600);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
// the loop routine runs over and over again forever:
void loop() 
{
  long duration;
  int distance;
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration*0.034/2;
  int x=1;

  
if (distance <= 100)

{ 
    for (int i = 0;256> i >0 ; i=i+x)
  
  { if (i>=255)x=0;
    if (i<=0)x=1;
    Serial.println(i);
    Serial.println(distance);
    delay(10);  }
  
} 

//else 
  
  {
    for (int i = 0;256> i >0 ; i=i+x)
  
    
   {if (i>=255)x=-1;
    if (i<=0)x=0;
    Serial.println(i);
    Serial.println(distance);
    delay(10); }
}
}
/[code]
    for (int i = 0;256> i >0 ; i=i+x)

256> i >0
is not legal in C. Well, it doesn't do what you think it does...

aarg:

    for (int i = 0;256> i >0 ; i=i+x)

256> i >0
is not legal in C. Well, it doesn't do what you think it does...

But it does give me a nice count up for "i" from 0 to 255 and output "i" remains at 255
but when using this, it does not show changes in distance anymore..

Is that why you wrote it backwards, vs. the usual "0 < i < 256" when you discovered that didn't work? :slight_smile: Don't you think it might help you to look up the for statement in the reference page? Since you admit that it isn't working?

Do you read and calculate distance inside or outside the for loop(s)? :slight_smile:

Please explain what your program is supposed to do.

Nevermind... I will try to rewrite all. Apparently i'm not close with the code I provided here.

No clue where to start after the point where I have a true or false in my If statement.
So I can get the desired "0" or "255" value, but not the incremental steps towards that value :frowning:

Well, actually, you're getting close, but there are a couple of problems.

    for (int i = 0;256> i >0 ; i=i+x)

Your initializer is fine. The condition is not correct. It should be i < 256; The increment also has a problem. At this point in the code, since you passed the (distance <= 100) check, you always want i to increase. There is no need of the x, and you can just use i = i + 1, or ++i. Incidentally, I expect the reason your loop goes infinite is that x gets set to 0 somehow, and then your loop will spin with nothing changing.for (int i = 0; i < 256; ++i)

The bigger issue is that you're not checking your distance inside the loop. which means yeah, i will go from 0 to 255, but distance stays the same. If you need to be checking the distance while you're increasing the brightness of your LED, there are a few ways to do this:

  • copy and paste the distance checking code inside the loop
  • write a function that checks the distance, and call it from inside the loop
  • re-think you're entire strategy and use millis(). See Blink Without Delay

@Jimmus

That piece of code helped indeed. I've changed me old code and took out a piece of it to show.

Now when distance <= 100 the value "i" starts running up to 255 :slight_smile:

But... then it starts again at 0 (and keeps running to 255 and starts over again)

Then when distance => 100 the running stops at 255 (which is what I want when distance <= 100)

if (distance <= 100)

{ 
    Serial.println(distance);
    for (int i = 0; i < 256 ;++i)
  
    Serial.println(i);
        delay(10);  }
/[code]

So the way loop() works is that it starts at the top and runs to the bottom, executing each statement in order. Then it forgets everything it just did, and starts at the top and runs to the bottom again. Then again. And again. Forever.

Unless you put some control statements in there, like if, for, or while. Then it might skip some statements or execute some blocks more than once.

And you can make it remember some things by saving them in global variables or static variables.

There are a ton of ways to make it do what you wrote. Some are simpler than others. Some are more efficient than others. Some are easier to understand than others.

There is a very simple way to do this, if I understand it correctly, and it goes like this:

  • Read the distance.
  • If it is less than 100, fade up.
  • Keep reading the distance until it goes above 100.
  • Fade down
  • Keep reading the distance until it goes below 100.
  • Let it loop

Hi Jimmus,

I used a bit of your previous code to set the lamp

if (distance <= 100)

for (int i = 0; i < 256 ;++i)
{dmx_master.setChannelValue (4,i);

So, what happens now, that as soon as distance is lower than 100, the lamp starts fading up all the way to level 256. (which looks really nice)

But when it reached 256, it should remain there als long as distance is lower than 100. As soon as my distance is bigger than 100, the lamp (value "i") should step down from 256 to 10, and stay at 10 for as long as the distance is bigger than 100.

For some reason I can't find the solution for this :confused:

All help is appreciated !

But when it reached 256,

The code changes to invisible font, so we can only guess at the rest of it. I hate guessing games.

herbertnl:
For some reason I can't find the solution for this :confused:

You need to eliminate the for loops and move the dimming variables into the main loop because everything is forgotten in each iteration of loop() unless you specifically save it, as explained in reply #7.

loop() already loops; no need for for-loops or while-loops for what you want to achieve. And as @PaulS says, please post your full code after an update so we can place everything in perspective.

So you need to remember that the variable 'i' has reached 256. You can use a global variable (usually declared before setup()) or a static variable (in loop()). In the below I have used 'fadeValue' instead of 'i'.

void loop()
{
  // current fadeValue; static variables are (once off) initialised with 0
  static int fadeValue;

  // read distance
  ...
  ...

  // check distance
  if (distance <= 100)
  {
    // if fadeValue not at maximum
    if(fadeValue < 256)
    {
      // set current fadeValue and increment fadeValue
      dmx_master.setChannelValue (4, fadeValue++);
    }
  }
  else
  {
    // if fadeValue not at minimum
    if(fadeValue > 0)
    {
      // set current fadeValue and decrement fadeValue
      dmx_master.setChannelValue (4, fadeValue--);
    }
  }
  delay(10);
}

Because fadeValue is a static variable, it will be remembered every time loop is called. So now loop() knows what the last value was and can check for it. If the minimum or maximum values are not reached yet, it will set the value and adjust it.

@Sterretje -- I used the code as you described and it works flawless--

Looking back it is indeed much more easier to make then what I initially had in mind. For those interested, please find the (full) code below. Thanks to everyone who helped me out with this. I have several ideas in mind for the future, and lots of them can and will be made with Arduino :wink:

#include <Conceptinetics.h>
#define trigPin 7 // pin for ultrasonic
#define echoPin 6
#define DMX_MASTER_CHANNELS   100 // number of DMX channels to be used. Max 512
#define RXEN_PIN 2  // communication pin for DMX shield. Set Jumper to EN to run, 
                    // |EN when uploading to Arduino 

// Configure a DMX master controller, the master controller
// will use the RXEN_PIN to control its write operation 
// on the bus
DMX_Master dmx_master ( DMX_MASTER_CHANNELS, RXEN_PIN );

// the setup routine runs once when you press reset:
void setup()            
{
  // Enable DMX master interface and start transmitting
  dmx_master.enable ();  
  
  // Set channel 1 - 100 @ 100%
    dmx_master.setChannelRange ( 1, 100, 255);
pinMode(trigPin, OUTPUT);     // pin for ultrasonic
pinMode(echoPin, INPUT);      // pin for ultrasonic
}

// the loop routine runs over and over again forever:
void loop() 
{
  static int fadeValue;
  long duration;
  int distance;
  digitalWrite(trigPin, LOW); 
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  distance = duration*0.034/2;  // converts echo puls time to cm
  
if 
(distance <= 100)
 { if (fadeValue < 256)
 { dmx_master.setChannelValue (4,fadeValue++);}
 }
else
{
  if (fadeValue > 10) 
{ dmx_master.setChannelValue (4, fadeValue--);

}
}
delay (10);

  dmx_master.setChannelValue ( 1,0 ); //Macro (don't use) 
  dmx_master.setChannelValue ( 2,0 ); //Macro (don't use) 
  dmx_master.setChannelValue (3,0 );  //Macro (don't use)
//dmx_master.setChannelValue (4,0);   //Dim value 0 = min 255 = max is set as variable
  dmx_master.setChannelValue (5,0);   //Red
  dmx_master.setChannelValue (6,0);   //Green
  dmx_master.setChannelValue (7,255); //Blue
  dmx_master.setChannelValue (8,0);  //White
}