Reliable if statement switching with sin()

Hello,

I’m writing a basic DMX controller which has a few simple colour animations. One animation I’m working on currently uses a sin() function to oscillate the brightness value. When the brightness is 0 I want the hue to increment or decrement by certain amount (basically just creating a pulsing colour change).

The code is almost working fine, although my if statement which tries to trigger when brightness == 0 isn’t reliable. It seems as it doesn’t register sin() reaching the minimum every time. I’ve tried the value being set to float or int and it doesn’t make a difference.

Here’s the relevant code with comments:

  // Use sin to cycle brightness from min-max with variable speed
   int x = int(map(sin(a), -1, 1, 0, 100)); 
   a = a + speed; 
   Bright = x;
 
  // Switch to increment or decrement
   if (Bright == 0){
     if (swaphue == true) {
       Hue += HUE_SWAP_AMT;  // adjust by controlP5 specified amount
       swaphue = false;
     }
     else if (swaphue == false){
      Hue -= HUE_SWAP_AMT; 
      swaphue = true;
     }
   }

   //Wrap around Hue value.. Keep in range 0-255
   if (Hue > 255) {
     Hue = 0 + HUE_SWAP_AMT;
   }
   else if (Hue < 0) {
     Hue = 255 - HUE_SWAP_AMT; 
   }

I feel like I’m probably missing something quite obvious… but please let me know how I might be able to make the switch trigger consistently.

Thanks for your help!!

1 Like

not understand above concept, where the sin val only is used for switching??

color cb;
float a;

void setup() {
 size(200,200);
 colorMode(HSB,100,100,100,100);
}

void draw() {
 mycolor();
 background(cb); 
}

void mycolor() {
 a += 0.01;
 int hue = int(map(sin(a),-1,1,0,100));
 cb = color(hue,100,100); 
}

Thanks for your response - sorry it’s not that clear!

the if (Bright == 0){ is the ‘switch’ I’m talking about… that value is taken from the int x in the section above which is mapped using sin().

I’ve combined your code with mine into a working example to demonstrate better. You’ll notice that while it oscillates it doesn’t just go red-green-red-green etc… but sometime’s it’ll go red-red-green-red-green-green for example.

color cb;
float a;
boolean swaphue = true;
float HUE_SWAP_AMT = 75;
float speed = 0.09;
float hue = 0;

void setup() {
 size(200,200);
  colorMode(HSB, 255, 100, 100);
}

void draw() {
 mycolor();
 background(cb); 
}

void mycolor() {
    // Use sin to cycle brightness from min-max with variable speed
   int bright = int(map(sin(a), -1, 1, 0, 100)); 
   a = a + speed; 
 
  // Switch to incrememnt or decrememnt
   if (bright == 0){
     if (swaphue == true) {
       hue += HUE_SWAP_AMT;  // adjust by controlP5 amount
       swaphue = false;
     }
     else if (swaphue == false){
      hue -= HUE_SWAP_AMT; 
      swaphue = true;
     }
   }

   //Wrap around Hue value.. Keep in range 0-255
   if (hue > 255) {
     hue = 0 + HUE_SWAP_AMT;
   }
   else if (hue < 0) {
     hue = 255 - HUE_SWAP_AMT; 
   }
 
 cb = color(hue,100,bright); 
}

Please let me know if there is a better way to achieve a reliable red/green oscillation.

Thanks again!

i would just use that, if a RED GREEN oscillation is needed??

sorry i still not go into your code logic.

color cb;
float a;

void setup() {
 size(200,200);
 colorMode(RGB,100,100,100,100);
}

void draw() {
 mycolor();
 background(cb); 
}

void mycolor() {
 a += 0.01;
 int red = int(map(sin(a),-1,1,0,100));
 cb = color(red,100-red,0); 
}

Okay so I’ll explain in words to maybe help clarify.

The sin() is oscillating the brightness from 100 to 0.

When the brightness is 0, I want the if statement to change the hue by a specified amount (HUE_SWAP_AMT;).

Everything is working fine, aside from the fact that the hue swap, controlled by if (bright == 0){doesn’t seem to engage reliably every phase…

So in this case with the HUE_SWAP_AMT set to 75 (which swaps from 0 (RED) to 75 (GREEN))… what we see is something like:

RED_BLACK_RED_BLACK_GREEN_BLACK_GREEN_BLACK_RED_BLACK_GREEN etc… a non-reliable switching between hues which isn’t predicable.

whereas what I’m after is a normal switching back and forth like so:

RED_BLACK_GREEN_BLACK_RED_BLACK_GREEN… and so on…

Put differently… I’m looking to have a fading in-out of 2 cycling colours… say colour x and colour y… so that it goes:

x-y-x-y-x-y-x-y-x-y-x-y-x-y-x

but my code seems to produce something more like:

x-x-y-y-x-y-x-y-y-y-x-x-y-x-y-y-x

Please let me know if you have any ideas after that explanation.

Thanks!

Floating-point numbers are only very rarely exactly equal to a given value or to each other. It’s safe to compare < or > for floats, but almost never safe to compare ==.

sin(a) is only exactly equal to -1.0 when a is exactly equal to pi*3/2 (plus multiples of 2pi). If you are feeding in values of a that you are computing by adding up floating-point numbers, it’s extremely unlikely that you would ever hit the precise value that the computer would store for pi*3/2. Your speed step is more likely to go from just less than that amount to just greater than it, so your map(sin()) will never hit 0 exactly. The only reason you’re hitting 0 at all is that you are mapping to integers and occasionally a sufficiently small value rounds down to 0.

A better approach would be to look at the value a and consider when it will be near multiples of pi*3/2. Again, though, you can’t exactly compare floats, but you CAN compare integers. So increment an integer instead or just use the built-in frameCount. Decide how many frames you want per cycle. Set a as a multiple of the frameCount and swap your hue when the integer frameCount hits the exact values for which your map(sin()) would hit 0.

2 Likes
void setup() { size( 200, 200 ); }
void draw() {
  float steps = 120.0;
  colorMode( HSB, 3, 1, 1 );
  background( floor((frameCount/steps)%2.), 
              1, 
              -cos(frameCount*TAU/steps)*0.5+0.5 );
}

3 Likes

i look again at your logic and the 2 uncontrolled swings

  • bright sin
  • hue ramp
    and see no way to make

whereas what I’m after is a normal switching back and forth like so:
RED_BLACK_GREEN_BLACK_RED_BLACK_GREEN…

that would be like a sinus for bright,
but a switch for red // green
and for the logic needed one more memory

add the usual tip:

to know what is going on: PRINT IT

// https://discourse.processing.org/t/reliable-if-statement-switching-with-sin/8399/3

color cb;
float a, speed = 0.01, hue = 0;
boolean highedge=false,swaphue = true;
//float HUE_SWAP_AMT = 1;


void setup() {
  size(200, 200);
  colorMode(HSB, 255, 100, 100);
}

void draw() {
  mycolor();
  background(cb);
}

void mycolor() {    // Use sin to cycle brightness from min-max with variable speed
  int bright = int(map(sin(a), -1, 1, 0, 100)); 
  a = a + speed; 

  if ( bright == 0 && highedge )  { highedge = false; swaphue = ! swaphue; }
  if ( bright > 98 ) highedge = true;
  if ( swaphue )     hue = 75;                                      // green at 0 .. 255 range 
  else               hue =  0;                                      // red
  //println(" swaphue "+swaphue+" highedge "+highedge+" bright "+bright+" hue "+hue);
/*
  // Switch to incrememnt or decrememnt
  if (bright == 0) {
    if (swaphue == true) {
      hue += HUE_SWAP_AMT;  // adjust by controlP5 amount
      swaphue = false;
    } else if (swaphue == false) {
      hue -= HUE_SWAP_AMT; 
      swaphue = true;
    }
  }

  //Wrap around Hue value.. Keep in range 0-255
  if (hue > 255) {
    hue = 0 + HUE_SWAP_AMT;
  } else if (hue < 0) {
    hue = 255 - HUE_SWAP_AMT;
  }
*/
  cb = color(hue, 100, bright);
}

1 Like