INA260 shunt current sensor [change sampling counts to average]

Hi. I am a student working on a project about DC motor current PI control.
For doing so, I want to use a current sensor.
But as my corrected current data obtains so much noise, I try to find a good way to come over this.
(The noise I guess comes from PWM signal in the motor driver and it seems to oscillate a lot.)

and I think one of good ways is sampling a few number of data and averaging.(and INA260 module has this function by setting its register)

But as a newbie of MCU world, It is hard for me to get through its code (especially header file) and manufulate its function.

How can I set averaging Mode from 1 to 4?

Below are INA260 datasheet, header file and cpp file.

ina260.pdf (1.2 MB)
Adafruit_INA260.h (5.9 KB)
Adafruit_INA260.cpp (12.0 KB)

I would be so much appreciated if you could give me its solution!!

This is the Adafruit INA260 library: https://github.com/adafruit/Adafruit_INA260.
There is a function "setAveragingCount()" and there are defines such as "INA260_COUNT_1024".

The INA260 can measure a DC current.
A RC filter would turn a PWM signal into a normal analog signal. A PWM signal into a RC filter keeps the accuracy of the average value.

There is probably a application note that shows how to measure the current of a PWM signal (but I can not find it yet). Some current sensor chips have an internal PWM rejection filter. I don't know if the INA260 has that.
The INA240 has it: https://www.ti.com/product/INA240

Please show us your sketch.

My sketch is this. But here, I am not programming its register.

#include <Wire.h>               
#include <Adafruit_INA260.h>

Adafruit_INA260 ina260 = Adafruit_INA260();

float Current_data;
float offset = 2.5;
float count1;
float duty = 665;  //duty rate set// range = 0~666  

void setup(){
 currentsetup();
 Timer1_setup();
 pinMode(9, OUTPUT);// PWM output
}

ISR(TIMER1_OVF_vect)        // interrupt service routine that wraps a user-defined function supplied by attachInterrupt
{
  digitalWrite(2, HIGH);        // Motor direction (HIGH or LOW)
 OCR1A = duty*0.5; //   50% dutyrate
 count1 ++;
}

void loop()
{ 
 Currentloop();
 }

void Timer1_setup() {
   //Fast PWM 3000Hz overflow setting start for motordriver
 noInterrupts();           // disable all interrupts
 TCCR1A = 0;
 TCCR1B = 0;
 TCNT1 = 0;            
 TCCR1A=bit(COM1A1)|bit(COM1B1); //set none-inverted mode
 TCCR1A|=bit(WGM11);
 TCCR1B=bit(WGM12)|bit(WGM13); //set Fast PWMmode using ICR1 as TOP
 TCCR1B|=bit(CS11); //start the timer with  prescaler=8
 ICR1 = 666; //16Mhz/8/3000hz = 666/    
 TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
 interrupts();             // enable all interrupts 
 //Fast PWM 3000Hz setting finish 
}

void currentsetup() {
   Serial.begin(115200);
  // Wait until serial port is opened
  while (!Serial) { delay(10); }
  Serial.println("Adafruit INA260 Test");
  if (!ina260.begin()) 
  {
    Serial.println("Couldn't find INA260 chip");
    while (1);
  }
  Serial.println("Found INA260 chip");
}

void Currentloop(){
  if (count1 > 10)      // slower sammping frequency
  {
  Current_data = ina260.readCurrent() + offset;
  Current_data = Current_data/1000;     // mA -> A
  Serial.print("Current: ");
  Serial.print(Current_data);
  Serial.println(" A");
    if (Current_data > 14*1000)   // Current saturation (ina260 is up to 15A)   
    { 
      duty = 0;       // when closed to max, operating stop
    } 
    count1 = 0;    
  }
}

And on your recommendation, I look over the header and cpp files. I found some code that you said


> Adafruit_INA260.h
typedef enum _alert_type {
  INA260_ALERT_CONVERSION_READY = 0x1, ///< Trigger on conversion ready
  INA260_ALERT_OVERPOWER = 0x2,        ///< Trigger on power over limit
  INA260_ALERT_UNDERVOLTAGE = 0x4,     ///< Trigger on bus voltage under limit
  INA260_ALERT_OVERVOLTAGE = 0x8,      ///< Trigger on bus voltage over limit
  INA260_ALERT_UNDERCURRENT = 0x10,    ///< Trigger on current under limit
  INA260_ALERT_OVERCURRENT = 0x20,     ///< Trigger on current over limit
  INA260_ALERT_NONE = 0x0,             ///< Do not trigger alert pin (Default)
} INA260_AlertType;
/**************************************************************************/
  INA260_AveragingCount getAveragingCount(void);
  void setAveragingCount(INA260_AveragingCount count);

Adafruit_INA260.cpp

void Adafruit_INA260::setCurrentConversionTime(INA260_ConversionTime time) {
  Adafruit_I2CRegisterBits current_conversion_time =
      Adafruit_I2CRegisterBits(Config, 3, 3);
  current_conversion_time.write(time);
}

I am sorry to say but I am ignorant about which part should I modify...

Could you be kind to post the few lines I have to put on..??

Thank you indeed by heart

The "ina260.begin()" sets a certain default configuration. You can add your own settings after that.

  if (!ina260.begin()) 
  {
    Serial.println("Couldn't find INA260 chip");
    while (1);
  }
  Serial.println("Found INA260 chip");

  // Set your own configuration
  setAveragingCount( INA260_COUNT_1024);

There is a big difference between floating point numbers and integers. That big difference does not show in the sketch.

I think that 'count1' can be 'unsigned int' or 'unsigned long' and 'duty' can be 'unsigned int'.

Then do the integer calculations with integers. And do the float calculations with float.

OCR1A = duty / 2;       // *0.5  =>  /2

Current_data = Current_data/1000.0;     // 1000 => 1000.0

if (Current_data > 14000.0)      // 14*1000 => 14000.0

Here is such a RC filter: https://www.onsemi.com/blog/industrial-cloud-power/current-sense-amplifiers-input-and-output-filtering.
It is two resistors and a capacitor. I don't understand why the resistors are only 10Ω, maybe someone else knows more about this.

Awesome!!! I appreciate your help from bottom of my heart!!!!
it's incredulously what I am eager to know about...!
Thanks a ton. so much!!
I will work hard by this!!!