Detecting varying PWM states

I have a charger which powers my arduino. On the charger is an LED which indicates these states:
1 - solid light (powers on)
2 - flashing on and off at 1 second intervals (low battery)
3 - off

When the led lit it always PWM at 1khz. I'm trying to sense this led with an input to my arduino to monitor the charger/battery status periodically without blocking my program. My program uses fast-led and other code which I can't block.

I cannot writea nice code which reliably does this. Below is an example of it flashing (state 2): This is frustrating as I've done harder projects before I'm just mentally blocked.

I would just sample periodically at some close but not equal to 1kHz rate, and look for the last time the signal went HIGH. If the difference between NOW and that time exceeds some interval, it's flashing. If the difference between NOW and that time is greater than one flash cycle time, it's OFF.

What’s the scale of the waveform you show ?

The problem is my main loop has some functions that make sampling that fast difficult. Do you suggest a routine with a periodic interrupt? Hopefully there is a simpler solution than this if I am understanding you?

@lastchancename The scale is of signal peak is HIGH (5v) and 0V. Sorry unclear.

Here are two ideas that require little software and should not interfere with your current code but you will need some hardware:

  • If you have an ADC available you can turn the signal into an analog signal using a simple RC-filter.
  • If you have a timer/counter with external input you can use that to detect the PWM signal.
1 Like

Thanks that would work but I was trying to avoid extra hardware as my project is already a bit cramped. Also I'm not quite sure how to design an RC filter that would give me clean enough analog output and I'm stuck having poll the signal still.

You need a 2-bit ADC result (ON, OFF, somewhere in between). So, the requirements for the filter are very low.

Yes, but only once a second instead of kHz sampling frequency.

How about a timer/counter with an external input? Do you have one of these? You may still need some external hardware to adapt to the voltage level.

Yeah good idea I tried this but it takes so long to detect a second high point. Maybe I should just separately monitor the battery voltage directly from the arduino?

It takes perhaps a few square millimeters if it's SMD, and if it's through-hole/old style components you'll always be able to fit an R and a C piggy-backed to each other somewhere in the space of your case. So this sounds like a bit of a poor excuse really :wink:

This sounds like performance problems with your code in general, suggesting that there just may be (I'm putting this very conservatively...) opportunities for overall performance improvements that could make your life easier.

Perhaps it's time to post a schematic and/or picture of the contraption as well as some sketch code so it becomes easier to determine which solution is appropriate. It prevents a lot of back-and forth with solutions and the "yes, but..."'s.

I am experimenting with this in a separate sketch and you're correct my code is a mess but I will clean it up and post it. I implemented an RC filter with 1uF cap and 56k resistor. I had to use a 100k pullup as the internal wasn't enough. This is what I got using analogRead. The signal has been significantly attenuated I guess I would need an op-amp if I wanted?

Yeah, but in this case even a single MOSFET may do.

Thanks. I only have a IRLZ44N with gate threshold of 1-2V. My signal peak is at 1.4V so I guess this may work.

Yeah, give it a try, it may just make it.

Otherwise an opamp or comparator (or opamp wired as comparator) or even a simple Schmitt trigger will get the job done.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.