PWM over 2N2222 not fading a LED

Hello, fairly new to transistors and not sure why this isn't working. I have code that is fading LEDs in and out via PWM. It works. I now need to drive 4 LEDs off each PWM pin, so that means transistors. I have a 5V outside source that goes through a 1K resistor to the LED anode and the cathode is connected to the emitter. PWM signal comes in from the Arduino via base through another 1K resistor. Collector goes to ground. I'm using this layout, which looks backwards:
Switching Using Transistor - Arduino Project Hub.

SO...while the other LEDs are breathing, the transistor LED is steady on. AND, to prove i don't know what I'm doing, I reversed the transistor and it didn't appear to change anything. I do know that ain't right. Help.

The LED is a generic low voltage type that came with an electronics kit, 3V I think.

Follow the schematic below.

R1&2 can be 220R

Let’s see a good image of your circuit.

What is the writing on the transistor ?


In the Arduino IDE, use Ctrl T or CMD T to format your code then copy the complete sketch.

Use the </> icon from the ‘reply menu’ to attach the copied sketch.

Unfortunately that means rotating the transistor, which I've already tried and it doesn't change the LED output. It is equally bright and steady regardless of which way the flat side is facing. Hence my confusion as to 1) why that works at all and 2) why PWM isn't working at all.

The transistor has 2N2222 A331 stamped on it. So this is interesting...when taking a picture, I noted the LED is pulsing ever so slightly, not visible to the eye, but my cell phone cam picked up the pulse. In the picture, green to right is the PWM input. Goes to center pin via resistor. Yellow is ground. Red is the higher current 5V line, again, connected via resistor to the LED.

int ledPin[] = { 3, 5, 6, 9}; // LED pins to use.
//int ledPin[] = { 9, 6, 5, 3}; // LED pins to use.
int brightness[] = {97, 148, 199, 251};
int fadeAmount[] = {5, 5, 5, 5};
int MaxB = 220; 
int MinB = 80;
long interval = 1.5;
long previousMillis = 0;        // will store last time LED was updated
int i = 0;

void setup() {
 for(int j = 0; j<4; j++){
   pinMode(ledPin[j],OUTPUT);
   digitalWrite(ledPin[j], LOW); // all LEDs off
 }
}

void loop() {
  unsigned long currentMillis = millis();   
  if(currentMillis - previousMillis > interval) {             // Arduino run time - changeTime value greater then ledDelay variable? Yes then
    previousMillis = currentMillis; 
    i = ++i % 4;       //i is either 0, 1 , 2 or 3
    changeLED();       // Go to changeLED routine.       
  }
}  
  
void changeLED(){
  if (i == 0){
    analogWrite(ledPin[i], brightness[i]);
    brightness[i] = brightness[i] + fadeAmount[i];
      if (brightness[i] <= MinB || brightness[i] >= MaxB) {
    fadeAmount[i] = -fadeAmount[i];}
  }
else if (i == 1){
    analogWrite(ledPin[i], brightness[i]);
    brightness[i] = brightness[i] + fadeAmount[i];
      if (brightness[i] <= MinB || brightness[i] >= MaxB) {
    fadeAmount[i] = -fadeAmount[i];}
 }
else if (i == 2){   
      analogWrite(ledPin[i], brightness[i]);
    brightness[i] = brightness[i] + fadeAmount[i];
      if (brightness[i] <= MinB || brightness[i] >= MaxB) {
    fadeAmount[i] = -fadeAmount[i];}         
}
else if (i == 3){            //This failed in previous versions due to using "else" v "else if"
      analogWrite(ledPin[i], brightness[i]);
    brightness[i] = brightness[i] + fadeAmount[i];
      if (brightness[i] <= MinB || brightness[i] >= MaxB) {
    fadeAmount[i] = -fadeAmount[i];}         
  }
}

The code is for a 4 LED chaser that fades vs blinks.

long interval = 1.5;

controls the speed of the chaser and fade. If I set it to 1.5, nice fade, transistor LED stays steady. If I make it 10 or higher, the transistor LED rapidly blinks while the other LEDS just fade a little slower.

That is a float :wink:


Try:
unsigned long previousMillis = 0;
. . .
if(currentMillis - previousMillis > 100)

Try the "Fading" example from the Arduino IDE...

To quote Bernie Mac, summamabtch. The fading example works just fine. Except, fading uses delay(), which I can't have in this code for the chaser to work. I also need other pins to do stuff on their own schedule, and delay() is a no no.

Thanks for that idea, I've now isolated it is NOT the wiring, it is the code. How do I fix that? Or, why is it messed up?

The circuit is correct:

$ 1 0.000005 285.9303473255704 88 2 50 5e-11
w 352 256 352 304 1
w 352 224 352 176 1
g 352 304 352 320 0 0
t 304 240 352 240 0 1 0.6309666440652523 0.6579516458358551 100 default
r 272 176 192 176 0 1000
R 192 176 128 176 0 0 40 5 0 0 0.5
r 304 240 192 240 0 1000
R 192 240 144 240 4 5 5 4.7 0 0 0.1
162 272 176 352 176 2 default-led 1 0 0 0.01

http://falstad.com/circuit/

Say what ? :thinking:


1.5 does not fit in ‘type’ long


Slow things down.

if(currentMillis - previousMillis > 100)

That was the plan.

I changed "interval" to a float, and then 100. The chaser doesn't chase, and the transistor LEDs blink at about half a second or so.

image

image

Barely any difference in brightness here.

byte MaxB = 220; 
byte MinB = 80;

As a test, try

byte MaxB = 100; 
byte MinB = 0;

and try

unsigned long interval = 100;

This version should fade UP/DOWN all LEDs, change as needed.

int ledPin[] = { 3, 5, 6, 9}; 
int brightness[] = {0, 0, 0, 0};
//int brightness[] = {97, 148, 199, 251};
int fadeAmount[] = {5, 5, 5, 5};

//int MaxB = 220;
//int MinB = 80;
int MaxB = 255;
int MinB = 0;

unsigned long interval = 10;
unsigned long previousMillis = 0;

int i;

//**********************************************************************
void setup()
{
  Serial.begin(115200);

  for (int j = 0; j < 4; j++)
  {
    pinMode(ledPin[j], OUTPUT);
    digitalWrite(ledPin[j], LOW); 
  }

} //END of   setup()

//**********************************************************************
void loop()
{
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;

    i = ++i;

    if ( i == 4)
    {
      i = 0;
    }

    changeLED();       
  }

} //END of    loop()

//**********************************************************************
void changeLED()
{
  //*****************************
  if (i == 0)
  {
    analogWrite(ledPin[i], brightness[i]);

    brightness[i] = brightness[i] + fadeAmount[i];

    if (brightness[i] <= MinB || brightness[i] >= MaxB)
    {
      fadeAmount[i] = -fadeAmount[i];
    }
  }

  //*****************************
  else if (i == 1)
  {
    analogWrite(ledPin[i], brightness[i]);

    brightness[i] = brightness[i] + fadeAmount[i];

    if (brightness[i] <= MinB || brightness[i] >= MaxB)
    {
      fadeAmount[i] = -fadeAmount[i];
    }
  }

  //*****************************
  else if (i == 2)
  {
    analogWrite(ledPin[i], brightness[i]);
    brightness[i] = brightness[i] + fadeAmount[i];

    if (brightness[i] <= MinB || brightness[i] >= MaxB)
    {
      fadeAmount[i] = -fadeAmount[i];
    }
  }

  //*****************************
  else if (i == 3)             
  {
    analogWrite(ledPin[i], brightness[i]);

    brightness[i] = brightness[i] + fadeAmount[i];

    if (brightness[i] <= MinB || brightness[i] >= MaxB)
    {
      fadeAmount[i] = -fadeAmount[i];
    }
  }

} //END of   changeLED()

SOLVED!! OK, so this is a chaser, which means they do the wave. I had to initialize each LED at some offset value. If they are all

int brightness[] = {0, 0, 0, 0};

then they all go up and down exactly the same--no chase. I had been testing with the lead off Pin 9, which had an initial brightness of 251.

I started trying the other leads--and the transistor LEDs started fading as desired. It was only pin 9 that looked basically steady. I then realized pin 9 was set to 251, yet the max brightness was set at 220.

Now, this code is supposed to flip the sign if brightness goes too high or too low--above MaxB, below MinB. But 251 is so far from 220, it just kept flipping the sign of the fade amount so pin 9 was oscillating from 255 to 250 back to 255. I dropped Pin 9 down to 219, and now it goes up to 224, flips sign on the fade amount, and decrements back down to MinB.

Thanks a ton for all the help. I would never had looked at the code if not for @ZX80 , and @dlloyd and @LarryD got me to look closer at my parameters which is how I caught it.

And yeah, I know the min and max numbers are odd, but there is a reason for it. It is a ring chaser, and having the MinB value go to 0 is too stark, which is why I limit it to 80 or so. So here is my automated way to avoid that mistake again and evenly bound the brightness values (I know, they are still saturated at the higher end but I can tweak it later):

int ledPin[] = { 3, 5, 6, 9}; // LED pins to use.
//int ledPin[] = { 9, 6, 5, 3}; // LED pins to use.
//int brightness[] = {97, 148, 199, 219};
//int brightness[] = {0, 0, 0, 0};
int fadeAmount[] = {5, 5, 5, 5};
int MaxB = 220; 
int MinB = 80;
int brightness[] = {MinB+1, MinB +(MaxB-MinB)/3, MaxB-(MaxB-MinB)/3, MaxB-1};
unsigned long interval = 1.5;
unsigned long  previousMillis = 0;        // will store last time LED was updated
int i = 0;

It is a little known fact that if you swap the collector and emitter in the circuit you have it will continue to work as a transistor. All that happens is that the gain is reduced. As those resistors used just require a gain of one to work then you will not see any difference. This was one of my favourite questions for me to ask when interviewing hardware engineers.

When driving more than one LED each LED needs its own current limiting resistor, you can't use just one because the LEDs would be in parallel and they don't share current evenly.

And breakdown voltage is reduced. Works well when you try the circuit with low voltage current limited power source, goes bang when you connect it to the full power.

IIRC switching speed suffers too.