Sensing during PWM

I hope this is the right forum, I'm having a bit of a problem.

I'm powering a funduino pro mini using a 3S LiPo battery. I'm using the same battery to power a low resistance load and I need to measure the resistance of the load.

To provide the power to the load I'm using PWM (pin 9) to switch a mosfet via a gate driver. This works well and I can vary the power the load receives.

In order to measure the resistance I'm using a hall effect current sensor (ACS713) with the output of the sensor going straight to an ADC pin. I'm also measuring the voltage across the load using a differential amplifier, the output from this also goes to an ADC pin. As I know V and I it's easy to get R.

Now this works really well so long as the PWM duty cycle is 255. The resistance measured is consistent to within about .005 ohms which is excellent and agrees with my multimeter (same ballpark, my multimeter isn't that good :)).

However as the duty cycle of the PWM drops the voltage measured by the differential amplifier varies more and more wildly.

I'm measuring the battery voltage too using a basic divider.

I take 32 measurements of each, battery V, differential amplifier output and current sensor in turn in a loop then average them and subtract any offset before using them in my calculations. I have set the PWM frequency to ~32KHz. I don't have a scope :(.

Any ideas? I hope my explanation is clear enough.

can you clarify what you mean by "varies more and more wildly"? If you set the PWM duty cycle to a constant lower value (eg 127) do you get stable readings or not?

I’ve taken the relevant parts of my sketch and put them into a test sketch which takes a reading every second with the duty cycle incrementing by 1 each time.

Here’s the sketch:

float zeroVolts;
float zeroAmps;
float currentResistance;
int firePin = 9;
int powerPin = 6;

void setup() {
  
  TCCR1B = TCCR1B & B11111000 | B00000001;    // set timer 1 divisor to     1 for PWM frequency of 31372.55 Hz
  Serial.begin(9600);
  pinMode(firePin, OUTPUT);
  pinMode(powerPin, OUTPUT);
  digitalWrite(powerPin, HIGH);
}

void loop() {
  
  delay(1000);
  
  Serial.print("dutyCycle\t");
  Serial.print("avgVolts\t");
  Serial.print("avgAmps\t");
  Serial.print("avgbVolts\t");
  Serial.print("currentResistance/measured");
  Serial.print("\n");
  
  measureResistance();

}

void measureResistance(void)
{
  unsigned long totalAmps = 0;
  unsigned long totalVolts = 0;
  unsigned long totalbVolts = 0;
  int dutyCycle;
  
  float avgAmps;
  float avgVolts;
  float avgbVolts;
  
  //
  
  for ( dutyCycle = 0; dutyCycle < 256; dutyCycle++)
  { 
    totalVolts = 0;
    totalbVolts = 0;
    totalAmps = 0;
    analogWrite(firePin, dutyCycle);
  
    for (int i = 0; i < 32 ; i++)
    {
      // read voltage across the coil
      totalVolts += analogRead(A3);
      // read battery voltage
      totalbVolts += analogRead(A1);
      // read amps
      totalAmps += analogRead(A2);
    }
    
    analogWrite(firePin, 0);
    
    if (dutyCycle == 0)
    {
      zeroVolts = ((totalVolts / 32.0) * (5.0 / 1023.0));
      zeroAmps = (((totalAmps / 32.0) * (5.0 / 1023.0))/0.133);
      avgbVolts = ((totalbVolts / 32.0) * (5.0 / 1023.0))/ (51.0/133.0) ;
      
      Serial.print(dutyCycle);
      Serial.print("\t");
      Serial.print(zeroVolts);
      Serial.print("\t");
      Serial.print(zeroAmps);
      Serial.print("\t");
      Serial.print(avgbVolts);    
      Serial.print("\t");
      //Serial.print("");
      Serial.print("\n");
      
    }
    else
    {    
      avgVolts = ((totalVolts / 32.0) * (5.0 / 1023.0)) - zeroVolts ;
      avgAmps = (((totalAmps / 32.0) * (5.0 / 1023.0))/0.133) - zeroAmps;
      avgbVolts = ((totalbVolts / 32.0) * (5.0 / 1023.0))/ (51.0/133.0) ;
      
      currentResistance = (avgbVolts - ((270.0/100.0) * avgVolts))/avgAmps;
      
      
      Serial.print(dutyCycle);
      Serial.print("\t");
      Serial.print(avgVolts);
      Serial.print("\t");
      Serial.print(avgAmps);
      Serial.print("\t");
      Serial.print(avgbVolts);    
      Serial.print("\t");
      Serial.print(currentResistance);
      Serial.print("\n");
      
    }
    delay(1000);
  }  
}

I’ve attached the output of two cycles. I notice an anomaly as it gets to full duty cycle too which I’ve not had before…?

duty cycle vs measured resistance.pdf (32.4 KB)

I've gotten rid of the anomaly at full duty cycle by removing the noise filter capacitor from the current sensor, although the output is definitely noisier it's still the same pattern.

I'm an idiot.

I needed to multiply by duty cycle/255.