Low frequency flicker when using multiple PWM outputs and MOSFETs

I've been trying to debug this problem for hours to no avail. Finally caved and am hoping someone could offer some insight.

Description:
I have an LED panel I made using bright 3W diodes wired up in series of 3s and 4s, depending on their voltage drop, driven at 12V, and with a 6 ohm 3W resistor on each line. I wanted to be able to control not only which colors are activated, but also the intensity of the individual segments. Thus I made a driver board using logic-level MOSFETs which would be driven from PWM outputs from an Arduino Leonardo.

LED panel (old image before connectors were added to wires):

"Driver" Board:

I mistakenly soldered up the MOSFETs such that they must connect the LEDs to ground, meaning the LEDs are always held at +12V. I'm not sure if this is an issue or not.

Problem:
Each group of LEDs can be individually driven by the Arduino's PWM outputs with no visible flicker. However, the moment I drive two groups of LEDs simultaneously with two PWM pins, there's a subtle but noticeable flicker of about 1-2Hz in both groups. I've swapped about my Leonardo with another I had laying around to no avail. I've tried simplifying the circuit onto a breadboard, also to no avail.

Anyone have any ideas on what might be causing this effect? I suspect some sort of cross-interference, but I have no idea why or how.

Got a schematic & code?

The code is about as basic as it gets. I have an empty loop() function, and am using analogWrite(pin, value) for each PWM pin in the setup() function. This of course is just for debugging purposes.

As far as a schematic goes, no I don't have one, but I drew one up real quick, but left out several lines of LEDs. In total, there are 8 MOSFET drivers, for 8 strings of LEDs (there are actually more LEDs, but these are not being used currently).

I attached the .sch file. I don't have the Arduino Leonardo in my library, so I just used an ATMEGA32U4 to represent my arduino and connected the pins appropriately. I of course left out all the support/peripheral circuitry on the leonardo itself.

PWMdebug.sch (222 KB)

Upon further fiddling, I've noticed that the problem only occurs if Pin 11 is included.

Does that elucidate anything?

Nrets:
I mistakenly soldered up the MOSFETs such that they must connect the LEDs to ground, meaning the LEDs are always held at +12V. I'm not sure if this is an issue or not.

Are you saying that you have the MOSFETs "sinking" the current from the LEDs to ground? How else would you propose to connect them, and how might this be a mistake?

Nrets:
The code is about as basic as it gets. I have an empty loop() function, and am using analogWrite(pin, value) for each PWM pin in the setup() function. This of course is just for debugging purposes.

Well, it is the code that is causing the problem. You need to post it (using "code" tags) if you wish the situation to be assessed. The vast majority of actual problems brought here are the result of a mistake in code or wiring. Many or most are when the supplicant fondly believes (s)he has done something, but has actually done something quite different. :smiley:

Nrets:
I attached the .sch file. I don't have the Arduino Leonardo in my library, so I just used an ATMEGA32U4 to represent my Arduino and connected the pins appropriately. I of course left out all the support/peripheral circuitry on the Leonardo itself.

What on earth is a ".sch" file?

.sch is a file extension used by EAGLE for schematics.

The MOSFETs are shown drawn correctly.
The other 3 pins used are 32 (OC4A), 26 (OC4D/), and 18(OC0B) ?

Apologies for the unfriendly file format, and thanks CrossRoads for posting a PNG version of the schematic.

As far as the code goes, it's as simple as this:

int ledPins[] = {5, 6, 9, 10, 11, 13};

void setup()  { 
 Serial.begin(9600); 
 int pwmValue = 20;
 Serial.println(pwmValue);
 for (int i = 0; i < 6; i++) {
    Serial.println(ledPins[i]); 
    analogWrite(ledPins[i], pwmValue);
 }
} 

void loop()  { 
// nothing happens in loop
}

The PWM pins that are connected are:

Arduino -- Port/bit -- Atmega32u4 pin
D5 ------- PC6 ------ Pin 31
D6 ------- PD7 ------ Pin 27
D9 ------- PB5 ------ Pin 29
D10 ------ PB6 ------ Pin 30
D11 ------ PB7 ------ Pin 12
D13 ------ PC7 ------ Pin32

The code I currently have flashed is below as well, which where i first noticed the problem, and then it persisted with the debug code above:

#include <Time.h>
#include <Wire.h>

#define SLAVE_ADDRESS 0x04
const float pi = 3.1415926535897932384;
int pwmOuts[] = {5, 6, 9, 10, 11, 13};
int maxBrightness = 120; // Absolute maximum of the LEDs
int brightness = 0;     // how bright the LED is
int number = 0;
int constBrightness = 0; // no sun-cycle, constant value == maxBrightness
int statusArray[6] = {}; // status array to control settings, all zeros == program will run with defaults

void setup()  { 
  // Set the LED PWM "bus" to output
  for (int i = 0; i < 7; i++) {
    pinMode(pwmOuts[i], OUTPUT);
  }
  setTime(8, 00, 00, 30, 10, 2013);
  Serial.begin(9600);
  Wire.begin(SLAVE_ADDRESS);  // initialize i2c as slave
  // define callbacks for i2c communication
  Wire.onReceive(receiveData);
  Wire.onRequest(sendData);
} 

void loop()  { 
  // Serial Time information
  if(timeStatus() == timeNotSet)
    Serial.println("waiting for sync message");
  else
    digitalClockDisplay();
  // set the brightness
  if ( constBrightness == 1 ) {
    brightness = maxBrightness;
  } else {
    float theta = ((hour() + minute()/60.0 - 7)/(12.0)) * pi;
    
    brightness = maxBrightness * sin(theta);
  }
  
  if (brightness > maxBrightness) {
    brightness = maxBrightness;
  }
  if (brightness < 0) {
    brightness = 0;
  }
  
  //Serial.println(brightness);
  //bitBangPWM(brightness);    
  for (int i = 0; i < 7; i++) {
      Serial.print(pwmOuts[i]);
      analogWrite(pwmOuts[i], brightness);
  }  
  delay(1000); // We don't need things to update this often  
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year()); 
  Serial.println(); 
}

void parseRPI(int arr[]) {
  // byte 1 = set time yes/no
  // byte 2 = hour to set
  // byte 3 = set max brightness yes/no
  // byte 4 = max brightness
  // byte 5 = force brightness; value = max brightness; yes/no
  if ( arr[0] == 1 ) {
    setTime(arr[1], arr[2], 00, 1, 12, 2013);
  }  
  if ( arr[3] == 1 ) {
    maxBrightness = arr[4];
  }
  if ( arr[5] == 1) {
    constBrightness = 1;
  } else {
    constBrightness = 0;
  }
}
void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

// callback for received data
void receiveData(int byteCount){
    int cnt = 0;
    while(Wire.available()) {
        number = Wire.read();
        Serial.print("data received: ");
        Serial.println(number);
        statusArray[cnt] = number;
        cnt++;
        //analogWrite(13, number);
     }
     // Update the program variables
     parseRPI(statusArray);
}


// callback for sending data -- This function isn't ready for multi-byte data sets
void sendData(){
    Wire.write(number);
}

Since I'm using i2c to communicate between my RaspberryPi and Arduino, I am not using D3 as a PWM output.

You are right - the code looks simple enough.

Cannot readily find any reference or explanation by Google on how many PWMs you are allowed to use (at once) on the Leonardo - will have to leave it to the experts. :smiley:

The nearest I can guess is that it may have something to do with the millis() timer function.

Hi, a tip, when drawing circuit diagrams please avoid diagonal wires, only vert or horz, it does not look tidy and can be confusing.

Question, how heavy is the wiring to the board that you have the mosfets mounted on, in particular the gnd track that connects all the mosfet sources together.

I assume you have the gnd of arduino connected to the gnd of the driver board.

What are you using to power the LED's. Have you measured the total current flowing when the LEDs are flickering, and have you tried driving all 6 channels.
What maximum LED current have you calculated the 3.6R resisitors, and what volt drop?

Hope to help..

Tom...... :slight_smile:

Hi Nrets.

I dont know if it is still an issue, but try to have a look at this:
http://jeelabs.org/2011/11/09/fixing-the-arduinos-pwm-2/

The flicker might be due to the fact that the internal timers in the arduino are set up differently.

Hopefully this will be of use to you, or the next person who runs into this problem :slight_smile: