mirror of https://github.com/rusefi/rusefi-1.git
knock sensing peak detect (#2910)
* knock peak detect * comments * comment * initialize * test * fix warnings while we're here * those are functions, not values * ram
This commit is contained in:
parent
df98194106
commit
5e08907590
|
@ -11,7 +11,7 @@
|
||||||
#include "closed_loop_controller.h"
|
#include "closed_loop_controller.h"
|
||||||
#include "pid.h"
|
#include "pid.h"
|
||||||
|
|
||||||
class IPwm;
|
struct IPwm;
|
||||||
|
|
||||||
class BoostController : public ClosedLoopController<float, percent_t> {
|
class BoostController : public ClosedLoopController<float, percent_t> {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
struct gppwm_channel;
|
struct gppwm_channel;
|
||||||
class OutputPin;
|
class OutputPin;
|
||||||
class IPwm;
|
struct IPwm;
|
||||||
class ValueProvider3D;
|
class ValueProvider3D;
|
||||||
|
|
||||||
class GppwmChannel {
|
class GppwmChannel {
|
||||||
|
|
|
@ -698,7 +698,7 @@ void initEngineContoller(DECLARE_ENGINE_PARAMETER_SUFFIX) {
|
||||||
* UNUSED_SIZE constants.
|
* UNUSED_SIZE constants.
|
||||||
*/
|
*/
|
||||||
#ifndef RAM_UNUSED_SIZE
|
#ifndef RAM_UNUSED_SIZE
|
||||||
#define RAM_UNUSED_SIZE 1500
|
#define RAM_UNUSED_SIZE 1400
|
||||||
#endif
|
#endif
|
||||||
#ifndef CCM_UNUSED_SIZE
|
#ifndef CCM_UNUSED_SIZE
|
||||||
#define CCM_UNUSED_SIZE 300
|
#define CCM_UNUSED_SIZE 300
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
#include "biquad.h"
|
#include "biquad.h"
|
||||||
|
@ -7,6 +6,7 @@
|
||||||
#include "knock_logic.h"
|
#include "knock_logic.h"
|
||||||
#include "software_knock.h"
|
#include "software_knock.h"
|
||||||
#include "thread_priority.h"
|
#include "thread_priority.h"
|
||||||
|
#include "peak_detect.h"
|
||||||
|
|
||||||
#if EFI_SOFTWARE_KNOCK
|
#if EFI_SOFTWARE_KNOCK
|
||||||
|
|
||||||
|
@ -15,9 +15,10 @@ EXTERN_ENGINE;
|
||||||
#include "knock_config.h"
|
#include "knock_config.h"
|
||||||
#include "ch.hpp"
|
#include "ch.hpp"
|
||||||
|
|
||||||
NO_CACHE adcsample_t sampleBuffer[2000];
|
static NO_CACHE adcsample_t sampleBuffer[2000];
|
||||||
int8_t currentCylinderIndex = 0;
|
static int8_t currentCylinderIndex = 0;
|
||||||
Biquad knockFilter;
|
static efitick_t lastKnockSampleTime = 0;
|
||||||
|
static Biquad knockFilter;
|
||||||
|
|
||||||
static volatile bool knockIsSampling = false;
|
static volatile bool knockIsSampling = false;
|
||||||
static volatile bool knockNeedsProcess = false;
|
static volatile bool knockNeedsProcess = false;
|
||||||
|
@ -141,6 +142,7 @@ void startKnockSampling(uint8_t cylinderIndex) {
|
||||||
currentCylinderIndex = cylinderIndex;
|
currentCylinderIndex = cylinderIndex;
|
||||||
|
|
||||||
adcStartConversionI(&KNOCK_ADC, conversionGroup, sampleBuffer, sampleCount);
|
adcStartConversionI(&KNOCK_ADC, conversionGroup, sampleBuffer, sampleCount);
|
||||||
|
lastKnockSampleTime = getTimeNowNt();
|
||||||
}
|
}
|
||||||
|
|
||||||
class KnockThread : public ThreadController<256> {
|
class KnockThread : public ThreadController<256> {
|
||||||
|
@ -164,6 +166,10 @@ void initSoftwareKnock() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using PD = PeakDetect<float, MS2NT(100)>;
|
||||||
|
static PD peakDetectors[12];
|
||||||
|
static PD allCylinderPeakDetector;
|
||||||
|
|
||||||
void processLastKnockEvent() {
|
void processLastKnockEvent() {
|
||||||
if (!knockNeedsProcess) {
|
if (!knockNeedsProcess) {
|
||||||
return;
|
return;
|
||||||
|
@ -190,16 +196,27 @@ void processLastKnockEvent() {
|
||||||
sumSq += filtered * filtered;
|
sumSq += filtered * filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// take a local copy
|
||||||
|
auto lastKnockTime = lastKnockSampleTime;
|
||||||
|
|
||||||
|
// We're done with inspecting the buffer, another sample can be taken
|
||||||
|
knockNeedsProcess = false;
|
||||||
|
|
||||||
// mean of squares (not yet root)
|
// mean of squares (not yet root)
|
||||||
float meanSquares = sumSq / localCount;
|
float meanSquares = sumSq / localCount;
|
||||||
|
|
||||||
// RMS
|
// RMS
|
||||||
float db = 10 * log10(meanSquares);
|
float db = 10 * log10(meanSquares);
|
||||||
|
|
||||||
tsOutputChannels.knockLevels[currentCylinderIndex] = roundf(clampF(-100, db, 100));
|
// clamp to reasonable range
|
||||||
tsOutputChannels.knockLevel = db;
|
db = clampF(-100, db, 100);
|
||||||
|
|
||||||
|
// Pass through peak detector
|
||||||
|
float cylPeak = peakDetectors[currentCylinderIndex].detect(db, lastKnockTime);
|
||||||
|
|
||||||
|
tsOutputChannels.knockLevels[currentCylinderIndex] = roundf(cylPeak);
|
||||||
|
tsOutputChannels.knockLevel = allCylinderPeakDetector.detect(db, lastKnockTime);
|
||||||
|
|
||||||
knockNeedsProcess = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KnockThread::ThreadTask() {
|
void KnockThread::ThreadTask() {
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "rusefi_types.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the recent peak value, preventing loss of intermittent peaks in a signal.
|
||||||
|
*/
|
||||||
|
template <typename TValue, efitick_t TTimeoutPeriod>
|
||||||
|
class PeakDetect {
|
||||||
|
public:
|
||||||
|
TValue detect(TValue currentValue, efitick_t nowNt) {
|
||||||
|
if ((nowNt > m_lastPeakTime + TTimeoutPeriod) || // if timed out
|
||||||
|
(currentValue > m_peak)) { // or current is higher than the previous peak
|
||||||
|
// store new peak and time
|
||||||
|
m_peak = currentValue;
|
||||||
|
m_lastPeakTime = nowNt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_peak;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
TValue m_peak = std::numeric_limits<TValue>::min();
|
||||||
|
efitick_t m_lastPeakTime = std::numeric_limits<efitick_t>::min();
|
||||||
|
};
|
|
@ -24,6 +24,7 @@
|
||||||
#include "io_pins.h"
|
#include "io_pins.h"
|
||||||
#include "efi_gpio.h"
|
#include "efi_gpio.h"
|
||||||
#include "efilib.h"
|
#include "efilib.h"
|
||||||
|
#include "peak_detect.h"
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
@ -490,3 +491,24 @@ TEST(util, datalogging) {
|
||||||
// printf("Got [%s]\r\n", LOGGING_BUFFER);
|
// printf("Got [%s]\r\n", LOGGING_BUFFER);
|
||||||
// ASSERT_STREQ("rusEfiVersion,776655@321ID DEFAULT_FRANKENSO 239,", LOGGING_BUFFER);
|
// ASSERT_STREQ("rusEfiVersion,776655@321ID DEFAULT_FRANKENSO 239,", LOGGING_BUFFER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(util, PeakDetect) {
|
||||||
|
constexpr int startTime = 50;
|
||||||
|
constexpr int timeout = 100;
|
||||||
|
PeakDetect<int, timeout> dut;
|
||||||
|
|
||||||
|
// Set a peak
|
||||||
|
EXPECT_EQ(dut.detect(1000, startTime), 1000);
|
||||||
|
|
||||||
|
// Smaller value at the same time is ignored
|
||||||
|
EXPECT_EQ(dut.detect(500, startTime), 1000);
|
||||||
|
|
||||||
|
// Larger value at the same time raises the peak
|
||||||
|
EXPECT_EQ(dut.detect(1500, startTime), 1500);
|
||||||
|
|
||||||
|
// Small value at almost the timeout is ignored
|
||||||
|
EXPECT_EQ(dut.detect(500, startTime + timeout - 1), 1500);
|
||||||
|
|
||||||
|
// Small value past the timeout is used
|
||||||
|
EXPECT_EQ(dut.detect(500, startTime + timeout + 1), 500);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue