HF-MAX22200 Driver 0.1.0-dev
HF-MAX22200 C++ Driver
Loading...
Searching...
No Matches
c21_dpm_tuning_test.cpp File Reference

DPM (Detection of Plunger Movement) tuning + CSV-logging cycle test. More...

#include <cinttypes>
#include <cstdio>
#include <memory>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp32_max22200_bus.hpp"
#include "esp32_max22200_test_config.hpp"
#include "max22200.hpp"
#include "max22200_registers.hpp"
#include "max22200_types.hpp"
Include dependency graph for c21_dpm_tuning_test.cpp:

Namespaces

namespace  cfg
 

Functions

void app_main ()
 

Variables

constexpr bool cfg::kEnableSlewRate = true
 
constexpr float cfg::kDpmStartCurrent_mA = 20.0f
 
constexpr float cfg::kDpmThreshold_mA = 4.0f
 
constexpr float cfg::kDpmDebounce_ms = 0.05f
 
constexpr uint32_t cfg::kPollPeriod_us = 1000
 
constexpr uint32_t cfg::kEnergisePoll_ms = 200
 
constexpr uint32_t cfg::kReleasePoll_ms = 50
 

Detailed Description

DPM (Detection of Plunger Movement) tuning + CSV-logging cycle test.

Cycles a Parker C21 24V solenoid on MAX22200 channel 0, with DPM enabled and configured via the parameters at the top of this file. During every ENERGISE phase the FAULT register is polled at high rate (~1 kHz) for the first ~200 ms so we can capture exactly when (and whether) DPM fires within the HIT window.

The MAX22200 does NOT expose continuous current measurements over SPI — DPM is a binary "did we see a current dip" flag handled by the chip's analogue front-end. So instead of plotting the actual current waveform we plot the DPM event timing across many cycles.

Per the datasheet (CFG_DPM section):

  • ISTART (7-bit, 0-127): current above which the chip starts monitoring for a dip. ISTART = value × IFS/127. With IFS=1000mA, value=15 → ISTART ≈ 118 mA. Must be < HIT current.
  • IPTH (4-bit, 0-15): minimum dip amplitude to count as valid. IPTH = value × IFS/127. With IFS=1000mA, value=1 → 7.87 mA dip. Lower = more sensitive.
  • TDEB (4-bit, 0-15): minimum dip duration in chopping periods. Lower = more sensitive but also more false positives.

Recommended starting tune for C21 (102 mA hit / 51 mA hold):

  • ISTART_MA = 30 (start monitoring well below HIT)
  • IPTH_MA = 8 (catch ~10% dips, typical plunger BEMF)
  • TDEB_MS = 0.5 (filter out noise, allow short dips)

CSV output format on every cycle: cycle,phase,t_us,fault_byte,status_byte,dpm_fired

  • phase: ENERGISE | RELEASE
  • t_us: microseconds since the ENERGISE / RELEASE banner
  • fault_byte: lower 8 bits of FAULT register
  • status_byte: lower 8 bits of STATUS register (fault flags)
  • dpm_fired: 1 if FAULT.DPM[0] is set this sample, else 0

Pipe the serial output through a logger and grep for CSV, lines to plot in your tool of choice (matplotlib, Excel, octave, etc.).

At the end of N cycles a summary prints the DPM hit-rate and the distribution of "time-to-fire" so you can see whether your ISTART/IPTH/TDEB tune is catching real plunger movements.

DPM polarity (datasheet §"Detection of Plunger Movement")
FAULT.DPM[ch] = 0  →  current dip seen → plunger MOVED (healthy)
FAULT.DPM[ch] = 1  →  drop NOT revealed → plunger STUCK (fault)
A free-moving valve should produce zero DPM fires across many cycles. To validate the DPM logic, hold the plunger still by hand during a cycle — then DPM should fire (DPM=1) for that cycle.
Tuning workflow
  1. Run with the C21 plunger free. Expect 0 DPM fires per cycle — confirms healthy operation and that the tune isn't false- positive on noise.
  2. Hold the plunger physically still and run again. DPM SHOULD fire on every cycle — confirms the algorithm catches the "no-movement" condition.
  3. If step 2 doesn't fire DPM, lower IPTH (catch smaller dips → easier for chip to "miss" them when no real movement) or raise ISTART (start monitoring later in the rise).
  4. If step 1 produces false positives, raise IPTH (need bigger dips to count).
  5. Adjust ISTART so monitoring starts before the BEMF dip but doesn't trigger on the inrush slope.
Author
HardFOC
Date
2026

Function Documentation

◆ app_main()

void app_main ( void )