mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-02-22 15:53:56 -04:00
Filter - added simple LowPassFilter (simple but it's possible to make errors with simple stuff too so might as well have one)
This commit is contained in:
parent
bdda74fd28
commit
2324be7e68
89
libraries/Filter/LowPassFilter.h
Normal file
89
libraries/Filter/LowPassFilter.h
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
// -*- tab-width: 4; Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
||||||
|
//
|
||||||
|
// This is free software; you can redistribute it and/or modify it under
|
||||||
|
// the terms of the GNU Lesser General Public License as published by the
|
||||||
|
// Free Software Foundation; either version 2.1 of the License, or (at
|
||||||
|
// your option) any later version.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// @file LowPassFilter.h
|
||||||
|
/// @brief A class to implement a low pass filter without losing precision even for int types
|
||||||
|
/// the downside being that it's a little slower as it internally uses a float
|
||||||
|
/// and it consumes an extra 4 bytes of memory to hold the constant gain
|
||||||
|
|
||||||
|
#ifndef LowPassFilter_h
|
||||||
|
#define LowPassFilter_h
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <Filter.h>
|
||||||
|
|
||||||
|
// 1st parameter <T> is the type of data being filtered.
|
||||||
|
template <class T>
|
||||||
|
class LowPassFilter : public Filter<T>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructor
|
||||||
|
LowPassFilter(float gain);
|
||||||
|
|
||||||
|
// apply - Add a new raw value to the filter, retrieve the filtered result
|
||||||
|
virtual T apply(T sample);
|
||||||
|
|
||||||
|
// reset - clear the filter - next sample added will become the new base value
|
||||||
|
virtual void reset() { _base_value_set = false; };
|
||||||
|
|
||||||
|
// reset - clear the filter and provide the new base value
|
||||||
|
virtual void reset( T new_base_value ) { _base_value = new_base_value; _base_value_set = true;};
|
||||||
|
|
||||||
|
private:
|
||||||
|
float _gain; // gain value (like 0.02) applied to each new value
|
||||||
|
bool _base_value_set; // true if the base value has been set
|
||||||
|
float _base_value; // the number of samples in the filter, maxes out at size of the filter
|
||||||
|
};
|
||||||
|
|
||||||
|
// Typedef for convenience (1st argument is the data type, 2nd is a larger datatype to handle overflows, 3rd is buffer size)
|
||||||
|
typedef LowPassFilter<int8_t> LowPassFilterInt8;
|
||||||
|
typedef LowPassFilter<uint8_t> LowPassFilterUInt8;
|
||||||
|
|
||||||
|
typedef LowPassFilter<int16_t> LowPassFilterInt16;
|
||||||
|
typedef LowPassFilter<uint16_t> LowPassFilterUInt16;
|
||||||
|
|
||||||
|
typedef LowPassFilter<int32_t> LowPassFilterInt32;
|
||||||
|
typedef LowPassFilter<uint32_t> LowPassFilterUInt32;
|
||||||
|
|
||||||
|
typedef LowPassFilter<float> LowPassFilterFloat;
|
||||||
|
|
||||||
|
// Constructor //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
LowPassFilter<T>::LowPassFilter(float gain) :
|
||||||
|
Filter<T>(),
|
||||||
|
_gain(gain),
|
||||||
|
_base_value_set(false)
|
||||||
|
{
|
||||||
|
// bounds checking on _gain
|
||||||
|
if( _gain > 1.0) {
|
||||||
|
_gain = 1.0;
|
||||||
|
}else if( _gain < 0.0 ) {
|
||||||
|
_gain = 0.0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Public Methods //////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
T LowPassFilter<T>::apply(T sample)
|
||||||
|
{
|
||||||
|
// initailise _base_value if required
|
||||||
|
if( ! _base_value_set ) {
|
||||||
|
_base_value = sample;
|
||||||
|
_base_value_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// do the filtering
|
||||||
|
_base_value = _gain * (float)sample + (1.0 - _gain) * _base_value;
|
||||||
|
|
||||||
|
// return the value. Should be no need to check limits
|
||||||
|
return (T)_base_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -21,6 +21,8 @@ int16_t rangevalue[] = {31000, 31000, 50, 55, 60, 55, 10, 0, 31000};
|
|||||||
ModeFilterInt16_Size5 mfilter(2); // buffer of 5 values, result will be from buffer element 2 (ie. the 3rd element which is the middle)
|
ModeFilterInt16_Size5 mfilter(2); // buffer of 5 values, result will be from buffer element 2 (ie. the 3rd element which is the middle)
|
||||||
//AverageFilterInt16_Size5 mfilter; // buffer of 5 values. result will be average of these 5
|
//AverageFilterInt16_Size5 mfilter; // buffer of 5 values. result will be average of these 5
|
||||||
|
|
||||||
|
AverageFilterUInt16_Size4 _temp_filter;
|
||||||
|
|
||||||
// Function to print contents of a filter
|
// Function to print contents of a filter
|
||||||
// we need to ues FilterWithBuffer class because we want to access the individual elements
|
// we need to ues FilterWithBuffer class because we want to access the individual elements
|
||||||
void printFilter(FilterWithBufferInt16_Size5& filter)
|
void printFilter(FilterWithBufferInt16_Size5& filter)
|
||||||
@ -44,13 +46,38 @@ void setup()
|
|||||||
delay(500);
|
delay(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read Raw Temperature values
|
||||||
|
void ReadTemp()
|
||||||
|
{
|
||||||
|
static uint8_t next_num = 0;
|
||||||
|
static int32_t RawTemp = 0;
|
||||||
|
uint8_t buf[2];
|
||||||
|
uint16_t _temp_sensor;
|
||||||
|
|
||||||
|
next_num++;
|
||||||
|
buf[0] = next_num; //next_num;
|
||||||
|
buf[1] = 0xFF;
|
||||||
|
|
||||||
|
_temp_sensor = buf[0];
|
||||||
|
_temp_sensor = (_temp_sensor << 8) | buf[1];
|
||||||
|
|
||||||
|
RawTemp = _temp_filter.apply(_temp_sensor);
|
||||||
|
|
||||||
|
Serial.printf("RT: %ld\n",RawTemp);
|
||||||
|
}
|
||||||
|
|
||||||
//Main loop where the action takes place
|
//Main loop where the action takes place
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
uint8_t i = 0;
|
uint8_t i = 0;
|
||||||
int16_t filtered_value;
|
int16_t filtered_value;
|
||||||
|
|
||||||
while( i < 9 ) {
|
int16_t j;
|
||||||
|
|
||||||
|
for(j=0; j<0xFF; j++ ) {
|
||||||
|
ReadTemp();
|
||||||
|
}
|
||||||
|
/*while( i < 9 ) {
|
||||||
|
|
||||||
// output to user
|
// output to user
|
||||||
Serial.printf("applying: %d\n",(int)rangevalue[i]);
|
Serial.printf("applying: %d\n",(int)rangevalue[i]);
|
||||||
@ -68,8 +95,8 @@ void loop()
|
|||||||
Serial.printf("The filtered value is: %d\n\n",(int)filtered_value);
|
Serial.printf("The filtered value is: %d\n\n",(int)filtered_value);
|
||||||
|
|
||||||
i++;
|
i++;
|
||||||
}
|
}*/
|
||||||
delay(100000);
|
delay(10000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
60
libraries/Filter/examples/LowPassFilter/LowPassFilter.pde
Normal file
60
libraries/Filter/examples/LowPassFilter/LowPassFilter.pde
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
Example sketch to demonstrate use of LowPassFilter library.
|
||||||
|
Code by Randy Mackay. DIYDrones.com
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <FastSerial.h>
|
||||||
|
#include <AP_Common.h>
|
||||||
|
#include <AP_Math.h> // ArduPilot Mega Vector/Matrix math Library
|
||||||
|
#include <Filter.h> // Filter library
|
||||||
|
#include <LowPassFilter.h> // LowPassFilter class (inherits from Filter class)
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Serial ports
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
FastSerialPort0(Serial); // FTDI/console
|
||||||
|
|
||||||
|
// create a global instance of the class instead of local to avoid memory fragmentation
|
||||||
|
LowPassFilterInt16 low_pass_filter(0.02); // simple low pass filter which applies 2% of new data to old data
|
||||||
|
|
||||||
|
// setup routine
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
// Open up a serial connection
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// introduction
|
||||||
|
Serial.printf("ArduPilot LowPassFilter test ver 1.0\n\n");
|
||||||
|
|
||||||
|
// Wait for the serial connection
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Main loop where the action takes place
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
int16_t i;
|
||||||
|
int16_t new_value;
|
||||||
|
int16_t filtered_value;
|
||||||
|
|
||||||
|
// reset value to 100. If not reset the filter will start at the first value entered
|
||||||
|
low_pass_filter.reset(100);
|
||||||
|
|
||||||
|
for( i=0; i<210; i++ ) {
|
||||||
|
|
||||||
|
// new data value
|
||||||
|
new_value = 105;
|
||||||
|
|
||||||
|
// output to user
|
||||||
|
Serial.printf("applying: %d",(int)new_value);
|
||||||
|
|
||||||
|
// apply new value and retrieved filtered result
|
||||||
|
filtered_value = low_pass_filter.apply(new_value);
|
||||||
|
|
||||||
|
// display results
|
||||||
|
Serial.printf("\toutput: %d\n\n",(int)filtered_value);
|
||||||
|
}
|
||||||
|
delay(10000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
1
libraries/Filter/examples/LowPassFilter/Makefile
Normal file
1
libraries/Filter/examples/LowPassFilter/Makefile
Normal file
@ -0,0 +1 @@
|
|||||||
|
include ../../../AP_Common/Arduino.mk
|
Loading…
Reference in New Issue
Block a user