From ea4cfa9046fa4dd635c25a412faa1ba9b124f70c Mon Sep 17 00:00:00 2001 From: shadowm60 Date: Thu, 2 Apr 2020 22:20:04 +0300 Subject: [PATCH] E30 M3 Tach output solution #907 (#1203) * Update tachometer.cpp Initial implementation of E30 M3 Tach output solution #907, unit_test plus debugging next * tacho unit tests First successfull unit test for tachometer * RAM adjustment so it would link * refactoring tacho, broken! * starting to make some progress...still fails after a few seconds * Rework with SW PWM * Update after code review * unit_test update * First working unit_test * Update .gitignore * Update engine_controller.cpp * Update engine_controller.cpp * Update tachometer.h * Update test_tacho.cpp Co-authored-by: rusefi --- firmware/controllers/gauges/tachometer.cpp | 75 +++++++++++++++++----- unit_tests/tests/test_tacho.cpp | 41 ++++++++++++ unit_tests/tests/tests.mk | 1 + 3 files changed, 100 insertions(+), 17 deletions(-) create mode 100644 unit_tests/tests/test_tacho.cpp diff --git a/firmware/controllers/gauges/tachometer.cpp b/firmware/controllers/gauges/tachometer.cpp index 9b65afda01..5beebc2648 100644 --- a/firmware/controllers/gauges/tachometer.cpp +++ b/firmware/controllers/gauges/tachometer.cpp @@ -12,31 +12,69 @@ #include "tachometer.h" #include "trigger_central.h" - +#include "pwm_generator.h" EXTERN_ENGINE; -static scheduling_s tachTurnSignalOff; +static SimplePwm tachControl("tach"); +static float tachFreq; +static float duty; -static void turnTachPinLow(void *) { - enginePins.tachOut.setLow(); +#if EFI_UNIT_TEST +float getTachFreq(void) { + return tachFreq; } +float getTachDuty(void) { + return duty; +} +#endif + static void tachSignalCallback(trigger_event_e ckpSignalType, uint32_t index, efitick_t edgeTimestamp DECLARE_ENGINE_PARAMETER_SUFFIX) { - UNUSED(ckpSignalType); - if (index != (uint32_t)engineConfiguration->tachPulseTriggerIndex) { + // only process at index configured to avoid too much cpu time for index 0? + if (index != (uint32_t)CONFIG(tachPulseTriggerIndex)) { return; } - enginePins.tachOut.setHigh(); - float durationMs; - if (engineConfiguration->tachPulseDurationAsDutyCycle) { - // todo: implement tachPulseDurationAsDutyCycle - durationMs = engineConfiguration->tachPulseDuractionMs; - } else { - durationMs = engineConfiguration->tachPulseDuractionMs; + +#if EFI_UNIT_TEST + printf("tachSignalCallback(%d %d)\n", ckpSignalType, index); + printf("Current RPM: %d\n",GET_RPM()); + UNUSED(edgeTimestamp); +#else + UNUSED(ckpSignalType); + UNUSED(edgeTimestamp); +#endif + + // How many tach pulse periods do we have? + int periods = CONFIG(tachPulsePerRev); + + if(periods == 0){ + warning(CUSTOM_ERR_6709,"Check Tachometer Pulse per Rev!"); + return; } - engine->executor.scheduleForLater(&tachTurnSignalOff, (int)MS2US(durationMs), &turnTachPinLow); + + // What is the angle per tach output period? + float cycleTimeMs = 60000.0 / GET_RPM(); + float periodTimeMs = cycleTimeMs / periods; + tachFreq = 1000.0 / periodTimeMs; + + if (CONFIG(tachPulseDurationAsDutyCycle)) { + // Simple case - duty explicitly set + duty = CONFIG(tachPulseDuractionMs); + } else { + // Constant high-time mode - compute the correct duty cycle + duty = CONFIG(tachPulseDuractionMs) / periodTimeMs; + } + + // In case Freq is under 1Hz, we stop pwm to avoid warnings! + if (tachFreq < 1.0) { + tachFreq = NAN; + } + + tachControl.setSimplePwmDutyCycle(duty); + tachControl.setFrequency(tachFreq); + } void initTachometer(DECLARE_ENGINE_PARAMETER_SIGNATURE) { @@ -44,11 +82,14 @@ void initTachometer(DECLARE_ENGINE_PARAMETER_SIGNATURE) { return; } - enginePins.tachOut.initPin("Tachometer", CONFIG(tachOutputPin), &CONFIG(tachOutputPinMode)); + startSimplePwmExt(&tachControl, + "Tachometer", + &engine->executor, + CONFIG(tachOutputPin), + &enginePins.tachOut, + NAN, 0.1, (pwm_gen_callback*)applyPinState); #if EFI_SHAFT_POSITION_INPUT addTriggerEventListener(tachSignalCallback, "tach", engine); #endif /* EFI_SHAFT_POSITION_INPUT */ } - - diff --git a/unit_tests/tests/test_tacho.cpp b/unit_tests/tests/test_tacho.cpp new file mode 100644 index 0000000000..96d522b2b9 --- /dev/null +++ b/unit_tests/tests/test_tacho.cpp @@ -0,0 +1,41 @@ +#include "engine_test_helper.h" + +extern WarningCodeState unitTestWarningCodeState; +extern float getTachFreq(void); +extern float getTachDuty(void); + +TEST(tachometer, testPulsePerRev) { + // This engine has a tach pin set - we need that + WITH_ENGINE_TEST_HELPER(BMW_E34); + + // We don't actually care about ign/inj at all, just tach + engineConfiguration->isInjectionEnabled = false; + engineConfiguration->isIgnitionEnabled = false; + + // Configure tach pulse count + // 5 PPR, 25% duty + engineConfiguration->tachPulsePerRev = 4; + engineConfiguration->tachPulseDuractionMs = 0.5f; + engineConfiguration->tachPulseDurationAsDutyCycle = true; + engineConfiguration->tachPulseTriggerIndex = 0; + + // Set predictable trigger settings + engineConfiguration->trigger.customTotalToothCount = 8; + engineConfiguration->trigger.customSkippedToothCount = 0; + engineConfiguration->useOnlyRisingEdgeForTrigger = false; + engineConfiguration->ambiguousOperationMode = FOUR_STROKE_CAM_SENSOR; + eth.applyTriggerWaveform(); + + // get the engine running - 6 revolutions + eth.fireTriggerEvents(48); + + // ensure engine speed and position + ASSERT_EQ(1500, GET_RPM()) << "RPM"; + ASSERT_EQ(15, engine->triggerCentral.triggerState.getCurrentIndex()) << "index #1"; + ASSERT_EQ(engine->triggerCentral.triggerState.shaft_is_synchronized, true); + ASSERT_EQ(100,getTachFreq()); + ASSERT_EQ(0.5,getTachDuty()); +std::cerr << "Tach Freq: " << getTachFreq() << "\n" << std::endl; +std::cerr << "Tach Duty: " << getTachDuty() << "\n" << std::endl; + +} diff --git a/unit_tests/tests/tests.mk b/unit_tests/tests/tests.mk index 49b93eb636..4a7c8a081c 100644 --- a/unit_tests/tests/tests.mk +++ b/unit_tests/tests/tests.mk @@ -33,6 +33,7 @@ TESTS_SRC_CPP = \ tests/test_pid_auto.cpp \ tests/test_pid.cpp \ tests/test_accel_enrichment.cpp \ + tests/test_tacho.cpp \ tests/test_gpiochip.cpp \ tests/test_multispark.cpp \ tests/sensor/basic_sensor.cpp \