I have been working on a few different versions of a bicycle light control circuit which reads in various buttons and sets various outputs accordingly such as headlight, taillight, blinkers, etc.

My current design is based around an ATtiny24 (Datasheet) using the internal oscillator (8MHz), programmed in C using AVR-GCC. I would like to keep external components such as shift registers to a minimum. Resistors are OK since they are cheap and small, and I am using MOSFETs (NTD4960N: Datasheet) to drive the LED banks.

Essentially, what I am looking to do is drive the MOSFETs with a 200Hz PWM signal to control the LED brightness, but limit the duty cycle to 90%. With that in mind, I would only need a pin to be an output for a maximum of 90% of the time. In the remaining 10% of the time, I want to switch the pin to an input to read the state of a button.

I tried a lot of various configurations to allow the MOSFET to stay OFF when it is supposed to be OFF, regardless of input from the button, and this is the best I could come up with:

MCU Dual Use I/O Pin

The supply voltage (VCC) is 5V, so when the button is pressed, about 0.9V is seen at the transistor gate. This is not enough for the transistor to start conducting, but it can be read by the MCU ADC which has been enabled using the internal 1.1V reference.

So the code drives the MOSFET with a 200Hz PWM signal. The duty cycle will vary with the desired LED brightness, but will not be greater than 90%. During the last 10% of the PWM cycle, the I/O pins are set as inputs (internal pullups disabled, digital input buffers disabled) and the ADC is used to read the state of the pin. The 10k resistor keeps the MOSFET off, and if a button is pressed, 0.9V is read by the ADC. This value is still not high enough to turn the MOSFET on, so the LEDs stay off, regardless of the button press.

Since the ADC is turned off and on, I discard the first reading and keep the second. This is done in plenty of time before the pin needs to be reset as an output to start the next PWM cycle. Since I am reading multiple buttons, I only read one each duty cycle, then update the ADC multiplxer to read the next button at the end of the next duty cycle - hence, each button is read once every [(# of buttons) * (200Hz)^-1]. The PWM and button reads are handled entirely by interrupts while MAIN determines what to do with the state of any particular button.

I have built and tested this circuit, and it seems to work perfectly, but I wanted to present the description here with the following questions:

  1. First, is this a bad idea? If so, then why?
  2. Is there an obviously better way to do this besides GPIO expanders/shift registers?

I can post some (or all) of the code if you want. I just thought the description might be enough, and I didn't want to make this any longer than it already was.


I should have said this the first time, but the MCU supply voltage (VCC) is 5V, the battery voltage (V_bat) is 12V (could be more like 14 on a fully charged battery), and the total LED current (as in the amount going through the FET) will be close to 2A. The LED bank will consist of numerous parallel strings of 3 series LEDs (white, V_LED = 3.3V) and a series resistor in each string. The pulsed current is around 50mA per string. With 40 or so strings equaling about 2A total.

I have tested and verified my ADC version of the circuit as well as the "digital" version presented by DrFriedParts below with a small current (50mA total), but have not yet tested either circuit with the larger current load.

This is the original project that I am redesigning. When I first built this bike light controller, I was new to microconctollers, so it was more of a learning experience than anything else.

  • \$\begingroup\$ How are you geting from 12VDC battery to 5VDC MCU source? \$\endgroup\$ Commented Apr 23, 2013 at 1:21
  • \$\begingroup\$ @DrFriedParts - Voltage regulation... The MCU current is so small, I don't really care about the tiny loss in a linear regulator compared to the larger power consumption of the LEDs. \$\endgroup\$ Commented Apr 23, 2013 at 1:29
  • 1
    \$\begingroup\$ Sure. The reason I asked is that a regulated source makes playing the threshold game (as I do in my answer) much easier (since the voltage is stabilized). It makes everything less of a moving target. =) \$\endgroup\$ Commented Apr 23, 2013 at 1:30
  • \$\begingroup\$ @DrFriedParts - I get what you are saying. I need to test this circuit with the full LED load to see what is really happening with the FET. Calculations can only take you so far before you just have to do it and see what happens. \$\endgroup\$ Commented Apr 23, 2013 at 1:36

1 Answer 1


That's perfectly fine...

The short answer is that there is nothing wrong with this approach. It presumes, of course, that you have time to switch and do an ADC conversion (which at 200Hz) you do.

You might want a series current-limiting resistor in line with the gate to protect your MCU driver (if the total gate charge of the N-FET is in the tens of nC, didn't read the datasheet).

If you want a completely "digital" solution:


simulate this circuit – Schematic created using CircuitLab

The component choices are (CircuitLab defaults) approximates, a wide range of parts will work, but it's a balancing act between R3 and R4.

  • You need to make the R3/R4 ratio big enough that V(R4) < M1's Vth
  • You need to make the R3/R4 ratio small enough that Vsrc-V(R3) > MCU V_IH

...for SW1 "on", MCU Hi-Z


Here's a specific configuration that should work (5V source):


See "documents" at these links:


enter image description here

enter image description here


Start with the (GPIO: Hi-Z; SW1: Closed) case:

  1. Vsrc -> R3 -> D3 -> R4 -> GND, must yield V(R4) < Vth,M1,min = 2V
  2. We need V(gpio) > V_IH = 2.6V
  3. This spread determines the minimum Vf,diode (Vfd) we need

Now, look at the (GPIO: Logic-1; SW1: Open) case:

  1. We need V(R4) > Vth,M1,min = 1.8V (ideally with some comfortable margin)
  2. This determines the upper-bound of the required Vfd

Now, look at the (GPIO: Logic-1; SW1: Closed) case:

  1. We need I(R3) < I(OH),max
  2. This determines the minimum size of R3 (go bigger for reliability)


  • R3 = 15k
  • D3 = 1.6V (forward) = approx 3x 1N4148 in series
  • R4 = 10k

Control the FET/LED:

V(gpio) = 5V; V(g) = 3.4V

  • PASS: 3.4V > 2V -- FET turns "on"

Read the state of an "on" switch:

V(gpio) = 2.9V; V(g) = 1.4V

  • PASS: 1.4V < 1.8V -- FET turns "off"
  • PASS: 2.9V > 2.6V -- MCU reads logic 1

Avoid damaging contention:

Switch is "on" AND MCU is driving the GPIO "low"

  • PASS: 5V / R3 = 500uA

Power dissipation in the FET

The issue of power dissipation in the FET has been raised by a few commenters. It isn't a problem in this circuit due to the highly non-linear behavior of the LED.

Let's ignore the LED to bound the problem, by considering a worst-case impossible D4 with I(D4) = 20mA but Vled = 0 and R5 = 0 (impossible!). Now all of the power dissipation happens in the FET.

Under these conditions, the power dissipation in the FET can be maximally 100mW or ~1/5 of the maximum tolerable power of the suggested part. So we're safe.

However, you won't see dissipation near that level for any appreciable length of time. The transition time from R4 = 10k is approximately (RQV) = 10k * 1.1n * 3.4 = 37uS overall, but since we only need to move from 3.4V to below 1.8V we can finish in less than half that time.

At 200Hz, that translates into a mere 0.75% to 1.5% duty-cycle or less than 1mW in aggregate.

...and remember we ignored the real power consumers in the path -- the LED and current-limiting resistor (R5). In practice, it is impossible to deliver Vds = 5V to the FET, while Iled = 20mA, and the power dissipation in the FET will be negligible.

  • \$\begingroup\$ I thought about using a series resistor, but I didn't think it would be a problem: with V_GS being 5V, the gate charge is around 4-8 nC. I guess it wouldn't hurt - just trying to keep the parts to a minimum. \$\endgroup\$ Commented Apr 21, 2013 at 23:32
  • \$\begingroup\$ Are you suggesting that I could use the digital input (not the ADC) with this circuit? Wouldn't the HI voltage from the button press go back through D3 and turn the FET on? I would prefer to keep the ADC out of it, just hadn't come up with anything yet. \$\endgroup\$ Commented Apr 21, 2013 at 23:50
  • \$\begingroup\$ Thanks to @Mark for pointing out the redundant pull-down (removed) \$\endgroup\$ Commented Apr 21, 2013 at 23:55
  • \$\begingroup\$ @Kurt -- No. The switch presents too weak of a drive to the gate. It's Vsrc -> R3 -> D3 -> R4 -> Gnd tapped at the node between D3 and R4. That's only Vsrc/10 - Vdf (approx). \$\endgroup\$ Commented Apr 21, 2013 at 23:56
  • \$\begingroup\$ @DrFriedParts I'm struggling to understand why D2 is necessary, could you explain that a little bit? \$\endgroup\$
    – NickHalden
    Commented Apr 22, 2013 at 0:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.