What's up with this.. erratic LED brightness

OK, I was testing some stepper motor code, and the LED’s don’t keep the same brightness…

There’s a LED attached to each pin 3 through 7, and with the delay() line commented out, they all suddenly increase in brightness together for about 2 seconds, then dim for 2 seconds. If you have a very short delay, it takes about 10 seconds for this to occur… I tried longer intervals but I don’t notice it, perhaps it just takes too long to happen, and by that point the LED’s are visibly blinking in sequence… with no delay they should just maintain what appears to be a constant brightness since they have about a 25% duty cycle

The blink order for LED1, LED2, LED3, LED4 goes like this

  1. T F F F
  2. T T F F
  3. F T F F
  4. F T T F
  5. F F T F
  6. F F T T
  7. F F F T
  8. T F F T

Here’s the code

int pinA = 3;
int pinB = 4;
int pinC = 5;
int pinD = 6;

void setup() {
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(pinD, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

  blink();
 // delay(2);
}

void blink() {
  //Halfstep stepper control
  static int i;
  i++;
  digitalWrite(pinA, (i + 7) % 8 < 3);
  digitalWrite(pinB, (i + 5) % 8 < 3);
  digitalWrite(pinC, (i + 3) % 8 < 3);
  digitalWrite(pinD, (i + 1) % 8 < 3);
}

Forgot to mention, this happens on both a Sparkfun Redboard (Uno) and a genuine Mega 2560.. Haven't tried it on my Leonardo... will do that perhaps

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

How have you got the LEDs connected, do you have current limiting resistors in series with each one?

digitalWrite(pin, HIGH or LOW)

(i + 7) % 8 < 3) is what?

What happens when i > 32,767 ?

Tom… :slight_smile:

there’s a 220 ohm resistor in line with each LED, one side of it goes to ground, the other to the output pin, for each of the 4 outputs

So the best diagram I can do is

PIN------>|---------////-------GND

Haven’t really worried about integer overflow (yet) though that will come evidently… I’ll probably reset the variable it before it gets there

(i + 7) % 8 < 3) is a boolean test, the formula leads to the correct sequencing through a series of steps…

Thanks, I’d like to find out what’s causing this

Hi,
I think any test has to be done with an IF statement.

(i+7)%8<3

As explained to you in

You can do some form of test in a digitalWrite statement, but it is not documented.

Have you done a truth table of the expression you are using?

(value of i plus 7) modulo 8 less than 3
Please explain your logic expression?

How will it return a HIGH or LOW?

Tom… :slight_smile:

I think any test has to be done with an IF statement

Any change to program flow will require an "if", but a simple logical true/false can be evaluated in a single expression zero/non-zero

I understood that something that evaluates to true or false is going to be interpreted as High and Low respectively. That is what I gathered from my thread of Conditional in digitalWrite.

The truth table to the equation is listed in the first post, and that part of it works fine... it seems to work fine without going into If statements and breaking it down.

I will try converting everything first and using IF statements with HIGH and LOW, and see if that makes a difference, and also put a timer in to see the relative speed changes much or at all..

Thanks for the help so far, I'll try and rewrite it tonight and test.

Rx7man:
OK, I was testing some stepper motor code, and the LED’s don’t keep the same brightness…

There’s a LED attached to each pin 3 through 7, and with the delay() line commented out, they all suddenly increase in brightness together for about 2 seconds, then dim for 2 seconds. If you have a very short delay, it takes about 10 seconds for this to occur… I tried longer intervals but I don’t notice it, perhaps it just takes too long to happen, and by that point the LED’s are visibly blinking in sequence… with no delay they should just maintain what appears to be a constant brightness since they have about a 25% duty cycle

The blink order for LED1, LED2, LED3, LED4 goes like this

  1. T F F F
  2. T T F F
  3. F T F F
  4. F T T F
  5. F F T F
  6. F F T T
  7. F F F T
  8. T F F T

Here’s the code

int pinA = 3;

int pinB = 4;
int pinC = 5;
int pinD = 6;

void setup() {
  pinMode(pinA, OUTPUT);
  pinMode(pinB, OUTPUT);
  pinMode(pinC, OUTPUT);
  pinMode(pinD, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:

blink();
// delay(2);
}

void blink() {
  //Halfstep stepper control
  static int i;
  i++;
  digitalWrite(pinA, (i + 7) % 8 < 3);
  digitalWrite(pinB, (i + 5) % 8 < 3);
  digitalWrite(pinC, (i + 3) % 8 < 3);
  digitalWrite(pinD, (i + 1) % 8 < 3);
}

Your eyes could never hope to see how fast those leds blink.

And you could make i an unsigned int to avoid the time when all the leds stay on due to negative values being < 3.

OK, TomGeorge gets the star on this one… it is something to do with the integer overflow… HOW it’s happening and why it’s dimming the LED’s I don’t know, perhaps it’s something to do with the modulus and negative numbers that is inverting my truth table so they’re on 75% duty… which sounds like the most likely culprit (will do the testing later)

So, I rewrote the code as suggested for ‘readability’ to this

int pinA = 3;
int pinB = 4;
int pinC = 5;
int pinD = 6;

void setup() {
 pinMode(pinA, OUTPUT);
 pinMode(pinB, OUTPUT);
 pinMode(pinC, OUTPUT);
 pinMode(pinD, OUTPUT);
}

void loop() {
 // put your main code here, to run repeatedly:

 blink();
// delay(2);
}

void blink() {
 //Halfstep stepper control
 static int i;
 i++;
 
// if (i == (pow(2,15)-1)){i=0;}
 
 boolean pinAon = (i + 7) % 8 < 3;
 boolean pinBon = (i + 5) % 8 < 3;
 boolean pinCon = (i + 3) % 8 < 3;
 boolean pinDon = (i + 1) % 8 < 3;
 
 
 
 if (pinAon) {
     digitalWrite(pinA, HIGH);
 }
 else{
   digitalWrite(pinA, LOW);
 }
 if (pinBon) {
     digitalWrite(pinB, HIGH);
 }
 else{
   digitalWrite(pinB, LOW);
 }
 if (pinCon) {
     digitalWrite(pinC, HIGH);
 }
 else{
   digitalWrite(pinC, LOW);
 }
 
 if (pinDon) {
     digitalWrite(pinD, HIGH);
 }
 else{
   digitalWrite(pinD, LOW);
 }
}

Sketch uses 1,574 bytes (0%) of program storage space. Maximum is 253,952 bytes.
Global variables use 19 bytes (0%) of dynamic memory, leaving 8,173 bytes for local variables. Maximum is 8,192 bytes.
That code does 30,000 iterations in about 1401-1432ms

the previous (original) sketch was

Sketch uses 1,614 bytes (0%) of program storage space. Maximum is 253,952 bytes.
Global variables use 19 bytes (0%) of dynamic memory, leaving 8,173 bytes for local variables. Maximum is 8,192 bytes.
And that does 30,000 iterations in about 2500ms… what a difference…

However, this was the same speed as using the IF statements, meaning the compiler is doing it all behind the scenes anyhow…

  boolean pinAon = (i + 7) % 8 < 3;
  boolean pinBon = (i + 5) % 8 < 3;
  boolean pinCon = (i + 3) % 8 < 3;
  boolean pinDon = (i + 1) % 8 < 3;
 

  digitalWrite(pinA, pinAon);
  digitalWrite(pinB, pinBon);
  digitalWrite(pinC, pinCon);
  digitalWrite(pinD, pinDon);

So my code doesn’t like negative values for i, and that was the cause of my problem… also, I may be going out on a limb here, but the compiler seems to get confused about conditional tests in the digitalWrite statement, and goes about figuring it out the long way, taking a long time.

Thanks for the help folks :slight_smile:

Oh, and GoForSmoke, you’re completely correct, you’d never see how fast they blink, but if they mess up and somehow their duty cycle changes, you’d notice that in the brightness.
And yes, I think I will make i an unsigned int, if nothing else to remind me negatives are not good!

I must have had some differences in my program when I checked the speeds...

the one using the if statements is a running at 1080ms, the one directly writing is at 1040.. .so it's a 2% difference...

However, using the modulus with a signed integer is MUCH MUCH slower than with an unsigned int.. I picked up a lot of speed there as well as getting rid of the overflow problems. Thanks GoForSmoke!

A little more tweaking got me down to 1000 ms for 30,000 loops with this, by removing the number of times I need to calculate a modulus... This is what I was trying for from the get-go, but the logic just wasn't coming to me.

  static unsigned int stepNumber;
  stepNumber++;  
  
  byte mod = stepNumber%8;
  mod /=2;
    
  digitalWrite(pinA, mod == 0);
  digitalWrite(pinB, mod == 1);
  digitalWrite(pinC, mod == 2);
  digitalWrite(pinD, mod == 3);

So that's 2.7 times faster than originally

  static unsigned int stepNumber;

  stepNumber = stepNumber++ & 3;  
  
  digitalWrite(pinA, stepNumber == 0);
  digitalWrite(pinB, stepNumber == 1);
  digitalWrite(pinC, stepNumber == 2);
  digitalWrite(pinD, stepNumber == 3);

I tested that, and it does full steps only.. it is also not any quicker from my tests (1004 ms per 30,000 iterations)