Announcement

Collapse
No announcement yet.

Announcement

Collapse
No announcement yet.

DELTA PULSE STM32F103

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • DELTA PULSE STM32F103

    PI Metal Detector Firmware Specification
    (STM32F103C8T6 "Blue Pill" + STM32CubeIDE / HAL)

    This document defines the hardware map and required functionality for a
    working reference firmware. Goal: transfer the TIMING role of a classic
    Delta Pulse analog circuit (LM556 + 2x CD4538 + CD4066) to the STM32.


    1. MCU AND ENVIRONMENT
    - MCU: STM32F103C8T6 (Blue Pill), 64KB Flash / 20KB RAM
    - Clock: HSE 8MHz crystal -> PLL x9 -> SYSCLK 72MHz
    - Toolchain: STM32CubeIDE + HAL library (NOT Arduino)
    - Programming: ST-Link V2 (SWD)
    - Display library: U8g2 (csrc, hardware I2C)


    2. PIN MAP (FIXED — the hardware is already wired to these pins)

    Outputs (GPIO Output, Push-Pull, Speed HIGH)
    | Pin | Function | Notes |
    |------|--------------|--------------------------------------------------|
    | PA8 | TX_GATE | to TC4420 driver input -> IRF740 -> search coil |
    | PB8 | D_SC_GATE | CD4066 pin13 (DISC sampling gate) |
    | PB9 | SENS_GATE | CD4066 pin12 (SENS sampling gate) |
    | PB10 | SAMPLE_GATE | CD4066 pin5,6 (AFC / ground sampling gate) |

    *** GATE LOGIC — VERY IMPORTANT (there is a BC547 INVERTER!) ***
    - The gate drivers have a BC547 transistor INVERTER in front of them.
    - GPIO LOW (RESET) = gate OPEN (the 4066 conducts)
    - GPIO HIGH (SET) = gate CLOSED
    - AT STARTUP: TX_GATE = LOW (silent), the OTHER 3 GATES = HIGH (closed).

    Analog Input
    | Pin | Function | Notes |
    |------|------------|-------------------------------------------------------|
    | PA4 | ADC1_IN4 | signal meter from TL062 output (via 560R series R) |

    - NOTE: PA4 is ONLY a display/monitoring meter. The actual detection +
    threshold + audio are done in the ANALOG circuit.
    - The TL062 stage is INVERTING (gain x10): metal -> LF357 pin6 rises ->
    PA4 FALLS.
    - With no metal present, PA4 is around 1.5V (set by a trimpot).
    - ADC clock: APB2/6 = 12MHz (max 14MHz). Sampling time: 55.5 cycles
    (the TL062 is slow / high output impedance).

    Buttons (GPIO Input, PULL-UP — buttons pull to GND, active LOW)
    | Pin | Function |
    |------|----------|
    | PB12 | UP |
    | PB13 | DOWN |
    | PB14 | SELECT |

    OLED Display (I2C1)
    | Pin | Function |
    |------|-----------|
    | PB6 | I2C1_SCL |
    | PB7 | I2C1_SDA |
    - Display: SSD1306 128x64, I2C address 0x3C (8-bit: 0x7
    - U8g2 driver: u8g2_Setup_ssd1306_i2c_128x64_noname_f
    - *** Use a TIMEOUT on the I2C transmit (e.g. 25ms) — do NOT use
    HAL_MAX_DELAY (it will hang the MCU if the display is disconnected). ***

    Timer
    - TIM2: 1us resolution (PSC=71 -> 1MHz counter). For 100Hz period, ARR=9999.
    - TIM2 interrupt (NVIC) must be ENABLED. The timing chain is generated
    inside the period-elapsed interrupt.


    3. TIMING CHAIN (the digital equivalent of the LM556 + 4538 job)

    On each 100Hz period (inside the interrupt), generate PRECISE microsecond
    timing by reading the TIM2 counter:

    t=0 : TX_GATE = HIGH (energize the coil) <- LM556 pin9 job
    t=txPulse : TX_GATE = LOW (flyback/decay begins)
    + SAMPLE_GATE(PB10) OPEN (LOW) <- LM556 pin5 / 4066 5,6
    +margin : (12us main-gate settling)
    +blank : (skip the flyback — blanking)
    : D_SC_GATE(PB OPEN (LOW) -> read ADC -> CLOSE (HIGH) <- 4538 #1 (DELAY/P1)
    +range : (delay after DISC) <- 4538 #2 (RANGE/P2)
    : SENS_GATE(PB9) OPEN (LOW) -> wait -> CLOSE (HIGH)
    : SAMPLE_GATE(PB10) CLOSE (HIGH) — end of period

    Adjustable parameters (defaults shown; changed via the button menu):
    - txPulse (TX pulse width): 150us [50–500us]
    - blank (blanking): 25us [10–300us]
    - early (DISC gate width): 40us [5–200us]
    - late (SENS gate width/delay):80us [10–500us]

    *** CRITICAL REQUEST — FREQUENCY DITHER (the most important feature!) ***
    The original Delta Pulse frequency is NOT fixed — the LM556 naturally
    WANDERS continuously between 30–100Hz. This decorrelates mains/EMI noise
    (which is BENEFICIAL). The firmware MUST EMULATE this:
    - On each period (or every few periods), change the TIM2 ARR randomly so
    the frequency wanders between 30–100Hz (e.g. ARR = 10000..33000 random).
    - This dither should be switchable ON/OFF (via menu or a flag).
    - PURPOSE: prevent a fixed frequency from accumulating noise; increase depth.


    4. SIGNAL PROCESSING (PA4 — for the on-screen meter ONLY)
    - Read the ADC (PA4) during the DISC gate window.
    - At startup, average 256 samples -> baseline (calibration).
    - Fast IIR filter (alpha ~ 1/ -> reduce noise.
    - signalOut = |filtered − baseline| (POLARITY-INDEPENDENT: take the
    ABSOLUTE deviation, because the response direction can flip depending on
    the trimpot setting; metal may push PA4 up OR down).
    - Slow baseline tracking (alpha ~ 1/4096), BUT FREEZE the baseline while
    |signal| is above a threshold (so a target is not nulled out).
    - NOTE: The detection decision / audio is in the ANALOG circuit. The
    firmware only DISPLAYS signalOut on screen.


    5. OLED LAYOUT (128x64)
    - Top line: title + a horizontal line beneath it
    - Middle (large font): "CAL %xx" during calibration, then "SIG: <value>"
    - A horizontal bar graph for SIG (fills as metal approaches)
    - Bottom: settings menu — PUL / BLK / ERL / LAT / (DITHER on/off) / BRIGHTNESS
    - The selected item shown highlighted (inverted color)
    - Refresh the screen at ~20 FPS (50ms), in the MAIN LOOP (NOT in the interrupt).

    6. BUTTON BEHAVIOR
    - SELECT: move to the next menu parameter (cyclic)
    - UP / DOWN: increase/decrease the selected parameter (auto-repeat on hold)
    - Debounce: ~25ms


    7. ROBUSTNESS / ANTI-LOCKUP RULES (MANDATORY)
    1. I2C transmit timeout = 25ms (HAL_MAX_DELAY FORBIDDEN).
    2. Any ADC wait INSIDE the interrupt (ISR) must be BOUNDED (no infinite
    loop; poll the EOC flag with a limited counter, do not rely on HAL_GetTick).
    3. Start the TIM2 interrupt BEFORE initializing the OLED (so TX still runs
    even if the display hangs).
    4. TIM2_IRQHandler must live in stm32f1xx_it.c (do NOT define it twice in main.c).
    5. At startup, gates in a safe state (TX=LOW, the others=HIGH).


    8. DELIVERABLES
    [ ] SOURCE CODE (main.c + required .h) — NOT a .hex, readable SOURCE
    [ ] CubeIDE project (incl. .ioc) or a clear list of the pin settings
    [ ] U8g2 integration (how the csrc was added)
    [ ] Short explanation: how the dither works, the sampling logic
    [ ] (If possible) a test note: what depth/result was achieved


    9. THE 3 MOST IMPORTANT THINGS (priority order)
    1. Correct TX + 3-gate TIMING (the chain above) — the foundation.
    2. FREQUENCY DITHER (30–100Hz wander) — the original's secret, critical for depth.
    3. No lockups (I2C timeout + safe ISR) — stable operation.

    NOTE: The detection threshold and AUDIO are already handled in the analog
    circuit (an NE555). The firmware does NOT generate these. The firmware only
    produces TIMING and shows PA4 on the display.
    Attached Files

  • #2
    delta pulse stm32f103
    Attached Files

    Comment


    • #3
      Hi everyone,

      I am working on an STM32F103 (BluePill) based Pulse Induction metal detector project, heavily inspired by the classic Delta Pulse analog front-end. I have successfully migrated the timing and display logic to STM32 using the STM32CubeHAL framework, and the hardware is currently up and running (OLED works, TX frequency is successfully generated).

      Hardware Architecture & Signal Path:
      • MCU: STM32F103C8T6 running at 72MHz.
      • TX Stage: Driven by PA8 (100Hz base pulse frequency).
      • Analog Switching (Gates): Managed via PB8 (DISC), PB9 (GROUND), and PB10. They control a CD4066 analog switch via BC547 inverters.
      • Analog Front-End: Coil signal is pre-amplified by an LF357. The output of LF357 (Pin 6) goes into a TL062 inverting amplifier ($x10$ gain, with a 100k resistor and 47pF capacitor in parallel).
      • ADC Input: Connected to PA4. Due to the inverting amplifier stage and damping resistor behavior on the coil, the signal at PA4 rises when a metal target is detected.
      • Threshold: Handled via an analog potentiometer on the non-inverting input of the TL062, so digital thresholding is not required in the firmware.

      Current Firmware Implementation:

      We are utilizing a hardware timer (TIM2) firing an interrupt every 10ms (100Hz). Inside the ISR, we use the Cortex-M3 DWT cycle counter (DWT->CYCCNT) for microsecond-precise gate timing.

      Here is the simplified ISR structure:

      C
      void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
      if (htim->Instance == TIM2) {
      // 1. TX Pulse
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_SET);
      DWT_Delay_us(txPulseUs);
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_8, GPIO_PIN_RESET);
      DWT_Delay_us(blankUs);

      // 2. Sample Gates (Inverted logic for BC547/CD4066)
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET); // Open DISC Gate
      DWT_Delay_us(earlyUs);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);

      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_RESET); // Open GROUND Gate
      DWT_Delay_us(lateUs);
      HAL_GPIO_WritePin(GPIOB, GPIO_PIN_9, GPIO_PIN_SET);

      // 3. Fast ADC Read
      HAL_ADC_Start(&hadc1);
      if (HAL_ADC_PollForConversion(&hadc1, 5) == HAL_OK) {
      rawDisc = HAL_ADC_GetValue(&hadc1);
      }
      HAL_ADC_Stop(&hadc1);

      // 4. Basic IIR Filtering & Baseline Tracking
      avgDiscIIR = ((avgDiscIIR * 7) + rawDisc) >> 3;
      // ... baseline tracking logic ...
      }
      }


      Where we need your expertise:
      1. Timing Stability: Is using DWT_Delay_us inside the TIM2 ISR considered safe against jitter, or should we strictly move to a timer-triggered ADC injection sequence (DMA) to free up the CPU?
      2. DSP / Filtering: What is the most effective, lightweight digital filter (e.g., an optimized exponential moving average, Median filter, or multi-stage IIR) you would recommend implementing within an STM32 ISR environment to maximize detection depth without introducing severe sweep lag?
      3. Advanced Ground Tracking / Auto-Zero: Our current implementation struggles slightly with rapid drift caused by the LF357 heating up or coil-to-ground capacitance changes. What are the best practices or code snippets used in modern PI firmware for robust background drift compensation?

      Any advice, suggestions, or firmware optimization tips would be highly appreciated!

      Thanks in advance!

      Comment


      • #4
        Additional Note for the Thread:

        "To give a bit more context on our goal: In the original Delta Pulse design, the pulse generation and sample gate delays were handled entirely in the analog domain using an NE556 dual timer and CD4538 dual monostable multivibrators.

        Our primary objective with this STM32 migration is to completely eliminate the NE556 and CD4538 chips, replacing their hardware-defined microsecond RC delay networks with pure, software-controlled digital timing.

        We are looking for open-source reference firmware designs, clean implementation patterns, or highly optimized timing state-machines specifically tailored for PI detectors on the Cortex-M3. If anyone has implemented an entirely open-source firmware that replaces these specific multivibrator/timer stages using advanced hardware timer features (like Timer PWM outputs combined with DMA or Input Capture to sample the ADC precisely), we would love to study your code structure or repository!"

        Comment


        • #5
          I'm working on a ground balancing pi project using a pic microcontroller. Mainly to see how useful AI can be in such a project. You are going to be surprised how helpful it is. Just don't use Gemini or the free module of Chat GPT because the first one is not there just yet, and the free version of Chat GPT does not have an improved memory which means you would have to "remind" it almost every time you want to resume working on your project. I've personally subscribed to the PLUS package on CHAT GPT and it sure helps me in analysing schematics, programing, and providing solutions to challenges I've been facing. I'm pretty sure that there are others AI platforms which are specialized in electronics.

          I wish you best of luck and please do not forget to eliminate the audio circuit in the original DP2. Make it sound better with the microcontroller

          Comment

          Working...
          X