Strange behavior when monitoring PWM pins

In a nutshell, and instead of using a few op-amps to boost than peak detect a signal off a current sense resistor connected to logic mosfets controlling high powered LEDs, I have analog in connected directly to the 0.1 ohm resistors connected to the mosfets sources. The mega 2560 i have has the analog 9..4 connected to these sense resistors reading direct mV. Works ok for the most part but seems to be out of sync with the analogRead to get somewhat precision measurements. I'm using adafruits precision Vref module and a 15 turn precision 10k pot to feed exactly 1.126V to Aref pin and ONLY using analogReference(EXTERNAL);

My LED's get shut off when i enter into my power monitor function only when i include the line
"if(digitalRead(c)==HIGH){ //then do analogRead while PWM pin is on.

    for (int f = 9; f >= 5; f--) {
      if(digitalRead(c)==HIGH){  //PROBLEM CHILD <----------------------???
        for(int q = 0; q<=10; q++){
          sum += analogRead(f);
          //delayMicroseconds(2);
        }
      }            
      Serial.print(sum/10);Serial.print("\t");
      voltage = (float)sum * milliVolt;
      voltage = round(voltage); //Rounds 1.5 down to 1 & 1.6 up to 2 - compensates somewhat for lack of precision in ADC
      lcd.printNumI(voltage,64, z);
      mA = voltage * 10;
      lcd.printNumF(mA, 1, 200,z);
      z += 16;
      voltage = 0.000;
      sum = 0;
      c++;
    }

Kinda stumped on how to TEST/Wait until a PWM pin comes on for a mosfet current sense resistor i'm trying to measure with a corresponding analog input. Why would adding the IF test marked "problem child" cause my LED's to shut off? Am I resetting a timer upon entry of the function to monitor current? It shouldn't shut off the PWM pins right? Or is my approach to seeing if/when a PWM pin is HIGH is wrong? Do I need a while((c) == LOW){} instead?

Any help appreciated, I could post the whole program but it's over 300 lines at this point.
Thanks, Mike

Does it matter that digitalRead() will return HIGH for any voltage over the threshold voltage ?
By the way, you are not reading all of the pins with the for loop only pins 9 to 5.

It really would be better if you posted your whole program or a cut down but working program that exhibits the problem.

As well as what @UKHeliBob said ...

Have you the analogRead()s synchronized with the PWM pulses so you are only reading when the pulse is HIGH?

What are you trying to achieve?

...R

Your readings average takes around 1.1ms ( eleven analogue readings @ 100us each) , yet you only divide "sum" by 10.
Why?

You can test the PWM pins directly with digitalRead() if you want to synchronize, but there
is the issue of analogRead() taking quite a long time (110us), thus quite a high proportion
of the PWM cycle (although the input is sampled near the start of that 110us).

You can also use the relevant timer(s) overflow interrupt handler to synchronize with
PWM controlled by that timer.

@UKHeliBob - I am trying to sync to the related PWM pins in my deign (R,G,B,W,CreeWht) that are being controlled by MOSFETs PWM'd by analogWrite 9-5. So that I'm not trying to read the mV off the current sense resistor while the PWM cycle is off.
@Robin2 - The "if" test within the for loop is supposed to sync the for loop when the PWM pin (and the LED) is on to capture a mV reading off the current sense resistor.

@Mark T - I'm only trying to sync an analog reading while the PWM pin being tested is high (LED on). Not sure how to access low level timer registers yet, would probably be faster than a digitalRead(). I don't think it matters to avg 10 readings together or not (it could be separate PWM pulses). i may need to change the Problem child IF to an while(){} becaue of the nature of an if test (will just pass through the sample loop instead of waiting for the pin to be high again).

Will try to isolate the problem loop within a quick Serial demo tonight when i get home.

rinkrides:
@Robin2 - The "if" test within the for loop is supposed to sync the for loop when the PWM pin (and the LED) is on to capture a mV reading off the current sense resistor.

That is not the sort of answer I was hoping for in reply to "What are you trying to achieve?"
I would like to know what is the purpose of the project?

...R

Are you trying to determine how much current you're pushing through the leds? Since you're using PWM instead of a constant current driver you can just look at the series resistor that you have for the leds and calculate it. They're going to draw full current when pm is HIGH and none when it is low.

Or am I misunderstanding your circuit?

Robin - Trying to limit current to 2A through high power LEDs, picking color, monitoring current. Nothing special.

Delta G - good point i suppose, but then the values on my TFT do change when switching from say red to lime green

Will try to isolate the function over the weekend and try to get it to work the way I want.

I would use the Timer interrupt to trigger the analog reading as @MarkT suggests in Reply #4. However at low duty factors the pin will not be HIGH for very long. At higher duty factors you could probably take several analog readings while the pin is HIGH.

You may be interested in this Application Note which was designed to read the voltage during the LOW part of the PWM cycle. The code is at the bottom.

...R

With the analogWrite aka PWM you're not able to limit the current. The PWM will be on or off. You can limit the average current but that's something different. If you try to blast 10A into the LED's for 1/5 of the time the average is 2A but the LED's are not happy. Certainly not at the default PWM frequency.

So I don't really get what you want. The LED current limiting should be done external of the LED's. Then the Arduino can control the brightness.

septillion:
With the analogWrite aka PWM you're not able to limit the current.

Very good point. By the time the OP has taken the measurement the damage will already be done. It's not like feeding an inductive load where the current rises gradually.

...R

Good points from everyone. Was doing some more research on pulsed LED's. Makes more sense to wind up the PWM freq to control mosfets and inductors in a Buck Converter style constant current setup and just monitor the LED heatsink temp and adjust the current accordingly.

Just strange when I add the line

if(digitalRead(c)==HIGH){...}

into the for loop that should be synced to the PWM pin, that one line either shifts the color to a primary like full red/green/blue unless the color chosen was equal amounts of color such as yellow/sky/pink. Most of the time the color just shuts off when i go into the power monitor screen. When I omit the if test the color stays the same but the readings are erroneous.

I'll modify the program to act as a buck converter constant current mode. Will figure out what value to shift delay()'s by when changing the PWM frequency to a higher value. Haven't messed with the direct port access or played with direct register settings yet, but i'll give it a go. I'd like to also tinker with some assembler on a c platform as well. I'll post back in a few days when i get the constant current mode PWM driver demo sorted.

Thank you all for the guidance and insight and valuable time. Youtube link

DS1demo.ino (11 KB)

digitalRead() turns PWM off before reading the value.

int digitalRead(uint8_t pin)
{
        uint8_t timer = digitalPinToTimer(pin);
        uint8_t bit = digitalPinToBitMask(pin);
        uint8_t port = digitalPinToPort(pin);

        if (port == NOT_A_PIN) return LOW;

        // If the pin that support PWM output, we need to turn it off
        // before getting a digital reading.
        if (timer != NOT_ON_TIMER) turnOffPWM(timer);

        if (*portInputRegister(port) & bit) return HIGH;
        return LOW;
}

oqibidipo:
digitalRead() turns PWM off before reading the value.

int digitalRead(uint8_t pin)

{
       uint8_t timer = digitalPinToTimer(pin);
       uint8_t bit = digitalPinToBitMask(pin);
       uint8_t port = digitalPinToPort(pin);

if (port == NOT_A_PIN) return LOW;

// If the pin that support PWM output, we need to turn it off
       // before getting a digital reading.
       if (timer != NOT_ON_TIMER) turnOffPWM(timer);

if (*portInputRegister(port) & bit) return HIGH;
       return LOW;
}

There's the answer to my OP. karma added, TY oqibidipo. But the other guidance pointed out that I had the wrong concept in controlling the HP LED's in the first place. 2A pulsed current but at like 1uS! Good thing I didn't hook the actual HP LED's to this design! Will try to utilize the PWM Lib for higher freq to control Constant I Buck mode from 14.4V. Thanks all, will post back.