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.
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
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);
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.
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!!!