Announcement

Collapse
No announcement yet.

VLF MD with digital signal processing : Bee-Buzz 1

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

  • Originally posted by moodz View Post
    Try the nano_vlf as a starting point .... however it uses two processors for some reason that I dont know. But you should be able to see there is fair bit of work in this project to achieve what it does.
    https://www.geotech1.com/forums/foru...d-january-2024

    However if you are going to get into developmental DSP you will need more powerful hardware than a blue pill for development work because there will be insufficient processing overhead for debugging code etc.
    The rule of thumb is go hard or go home.
    Once you have understood what the signal chain looks like and you have coded a working system or simulation ... then and only then should you try to port it to the blue Pill which may or may not be capable
    In commercial development the only reason to use less powerful chips is to save money ( for the manufacturer ) however engineers usually hate this reason because it just creates headaches.

    moodz
    can you analyse my design for all the points above?

    I dont want to 'port' the nano vlf, thats not my idea of a direct sampling md. its some one elses idea, and nano vlf is working and its technically pointless to reengineer it to a diffetent platform. our philosophies are different and so are the aims.

    from your comments, I understand that you are suggesting that I should shut down thid project, because the processor does not have sufficient processing power !

    can you send me your basis of this assessment, and the calvulations there of?

    I fully understand the process flow and the msthematics and logic of the design I've put forth.

    so if you can, pick holes in this design / suggest improvements etc. instead of asking me to shut down the project or use the processor suggested by you !

    from your statements, it seems that you arent happy with my design, processor and objectives. it may be a good idea for you to put forth your design, which I can then follow.

    Comment


    • See post #113 again above.
      The complete project along with my pictures of the built device.
      I forgot to emphasize that that detector works pretty well WITH SLOW COIL SWINGING (ADC&DSP capabilities).
      But I think what you would find very useful and welcome now Atul Asthana is the book ITMD3 which I am currently reading these days.
      I just came to (the most interesting part for me) today, which is:


      Click image for larger version  Name:	20250104_010345.jpg Views:	0 Size:	147.6 KB ID:	432383Click image for larger version  Name:	20250104_010352.jpg Views:	0 Size:	207.0 KB ID:	432384​​

      Comment


      • I really like the clear and unambiguous division on "baseband" and "direct" sampling.
        First you have to decide on one of those two approaches.
        It is obvious that you have chosen a platform for development, so it is recommended that you choose baseband sampling.
        STM32 bluepill will give you much more with this choice.
        You can find reasons and detailed explanations for this in the book.

        Comment


        • Without the risk of copying directly from the book and thereby infringing our friend's copyright... I will try to explain these two approaches to you using the example of radio applications.

          Baseband Sampling:
          1. Uses downconversion before sampling
          2. Signal is mixed with a local oscillator to shift high frequencies down to baseband
          3. Requires analog mixing components (mixers, filters, oscillators)
          4. Lower sampling rate needed since you're only sampling the downconverted baseband signal
          5. Typically used in traditional radio receivers

          Direct Sampling:
          1. Samples RF signal directly at high frequencies without downconversion
          2. No analog mixing stage needed
          3. Requires faster/higher performance ADCs
          4. Higher sampling rates required (must meet Nyquist criteria for highest frequency) ... (When we talk about metal detectors, this criterion is stricter)
          5. More modern approach used in Software Defined Radio (SDR)... (Ha! Gotcha Paul!)

          Main Tradeoffs:
          - Direct sampling offers simpler hardware design but requires more expensive, higher-speed ADCs
          - Baseband sampling uses slower/cheaper ADCs but needs more analog components
          - Direct sampling can capture wider bandwidth but generates more data to process
          - Baseband sampling is more established but has more potential points of signal degradation


          ...

          Originally posted by moodz View Post
          ...The rule of thumb is go hard or go home...
          Sounds harsh but it is true and take it as extremely friendly advice from Moodz.

          Comment


          • Ok I can see I am upsetting you .. and I apologise for that. But there have been many projects started and not finished on this forum ( dont worry me included ... but I am easily distracted and procrastination so I have at least 60 or 70 projects . not all metaldetectors on the go ) The goals were set out in a very clear way and you asked for advice ... so I gave you some. Obviously not everyone thinks the same way but one thing is that if you research then you will find quite a few VLF detector projects and the one you propose is really not aspiring to any new "breakthrough" so its a YAVLF project ... Yet Another VLF project and since you already nominated the hardware before knowing the "system solution" ie if the system ( ie code ) that will eliminate most people on this forum as they will not have the hardware / development environment and so the commentary will be less informed than you as the project lead / director would like. Some would call this armchair commentary.
            For instance I use LTSPICE to simulate analogue ccts before I build them in most cases ... and this saves time .. but also if you publish the simulation on forums like this then others can also run the simulation and comment more effectively as they can easily run the sim and provide more meaningful commentary.
            So I was essentially trying to advise you that if you want a fully digital VLF detector then just develop the code ( signal flow solution ) that does that unconstrained by any hardware consideration THEN select the appropriate hardware that MATCHES the requirements set by your code. So that was my advice not trying to shut you down or anything. If you choose to go the other way its a free world.

            PS ... the blue pill uses its VDD as the ADC reference voltage rather than a bandgap reference so its a poor choice for frontend ADC if noise is a concern.

            Comment


            • Ok, the "scenario" is slowly folding itself, I don't know if you understand all this Atul?
              Let's agree on the STM32 bluepill, ok?
              You chose STM32 and that's ok. But you have to follow the conditions as they are.

              1) The chosen platform is STM32 bluepill
              2) The only sensible choice is baseband sampling with this platform.
              3) Use an external voltage reference.
              a) cheapest choise is LM336.
              b) very good choice is LT1461.
              ...

              Look!
              The code is written by itself!


              Code:
              // Configure ADC to use external VREF with two analog inputs
              // Hardware setup:
              // - VREF chip (like LM336-2.5) output connected to PA0 (ADC1_IN0)
              // - First analog input on PA1 (ADC1_IN1) - "X"
              // - Second analog input on PA2 (ADC1_IN2) -"R"
              // - VREF GND to Blue Pill GND
              // - VREF VDD through current limiting 2.2kΩ resistor to Blue Pill 3.3V
              // - VREF Out to PA0
              // - 0.1µF bypass cap between positive and negative​
              
              void adc_init_external_vref(void) {
                  // Enable GPIOA and ADC1 clocks
                  RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_ADC1EN;
                  
                  // Configure PA0 (VREF), PA1 (analog1), PA2 (analog2) as analog inputs
                  GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0 |
                                  GPIO_CRL_MODE1 | GPIO_CRL_CNF1 |
                                  GPIO_CRL_MODE2 | GPIO_CRL_CNF2);
                  
                  // ADC configuration
                  ADC1->CR2 = 0;                   // Reset CR2 register
                  ADC1->CR2 |= ADC_CR2_ADON;       // Enable ADC
                  
                  // Wait for ADC to stabilize
                  delay_ms(1);
                  
                  // Calibrate ADC
                  ADC1->CR2 |= ADC_CR2_CAL;        // Start calibration
                  while(ADC1->CR2 & ADC_CR2_CAL);  // Wait for calibration
              }
              
              // Structure to hold both readings
              typedef struct {
                  float voltage1;
                  float voltage2;
              } analog_readings_t;
              
              analog_readings_t read_dual_voltages(void) {
                  uint16_t vref_reading, signal1_reading, signal2_reading;
                  analog_readings_t results;
                  
                  // Read VREF on PA0
                  ADC1->SQR3 = 0;                  // Select channel 0 (PA0)
                  ADC1->CR2 |= ADC_CR2_ADON;       // Start conversion
                  while(!(ADC1->SR & ADC_SR_EOC)); // Wait for conversion
                  vref_reading = ADC1->DR;
                  
                  // Read first analog input on PA1
                  ADC1->SQR3 = 1;                  // Select channel 1 (PA1)
                  ADC1->CR2 |= ADC_CR2_ADON;       // Start conversion
                  while(!(ADC1->SR & ADC_SR_EOC)); // Wait for conversion
                  signal1_reading = ADC1->DR;
                  
                  // Read second analog input on PA2
                  ADC1->SQR3 = 2;                  // Select channel 2 (PA2)
                  ADC1->CR2 |= ADC_CR2_ADON;       // Start conversion
                  while(!(ADC1->SR & ADC_SR_EOC)); // Wait for conversion
                  signal2_reading = ADC1->DR;
                  
                  // Calculate actual voltages using VREF reading
                  // Assuming VREF chip outputs 2.5V (for LM336-2.5)
                  results.voltage1 = (signal1_reading * 2.5f) / vref_reading;
                  results.voltage2 = (signal2_reading * 2.5f) / vref_reading;
                  
                  return results;
              }
              
              // Example usage in main
              void main(void) {
                  analog_readings_t readings;
                  
                  // Initialize ADC with external reference
                  adc_init_external_vref();
                  
                  while(1) {
                      readings = read_dual_voltages();
                      
                      // Use the readings
                      printf("Voltage 1: %.3fV\n", readings.voltage1);
                      printf("Voltage 2: %.3fV\n", readings.voltage2);
                      
                      delay_ms(1000);  // Read every second
                  }
              }


              "X" and "R" are derivative from both channels.
              As a result in the code you have "readings.voltage1" and "readings.voltage2" variables that contain samples from both channels.
              What will you do with them; it's up to you and your ideas about the filters you will apply.

              "delay_ms(1000); // Read every second"
              of course this is too slow and serves only as an example.
              You will adjust the sampling rate according to your needs.
              ...

              ​A much faster and better approach is analog readings using DMA.
              Among us Serbs, there is an old saying: "As much money - as much music"!

              ​​

              Comment


              • My natural born altruism (lol-Paul) dictates that I see the job through.
                So here is a ready solution for STM32.
                That's all from me for now.
                I'm going to continue reading the book... much to learn yet.


                Code:
                // Piece of code for metal detector with adjustable TX frequency (6-18kHz, - lets make this more interesing !!!) and synchronized dual ADC
                // Fast dual analog reading with DMA and continuous scan mode
                // Hardware:
                // - VREF (LM336-2.5) on PA0 (ADC1_IN0) // - VREF Out to PA0
                // - RX processed baseband sampled signal 1 on PA1 (ADC1_IN1) - "X" derivative
                // - RX processed baseband sampled signal 2 on PA2 (ADC1_IN2) - "R" derivative
                // - TX output on PA8 (TIM1_CH1) - TX clock, goes to TX driver
                // - VREF GND to Blue Pill GND
                // - VREF VDD through current limiting 2.2kΩ resistor to Blue Pill 3.3V
                // - 0.1µF bypass cap between positive and negative​
                
                #define ADC_BUFFER_SIZE 3
                #define PWM_FREQ_MIN 6000   // 6kHz  - lets make this more interesing !!!
                #define PWM_FREQ_MAX 18000  // 18kHz - lets make this more interesing !!!
                
                volatile uint16_t adc_values[ADC_BUFFER_SIZE];
                volatile uint32_t current_freq = 10000; // Start at 10kHz
                
                void timer_pwm_init(uint32_t frequency) {
                    // Enable TIM1 and GPIOA clocks
                    RCC->APB2ENR |= RCC_APB2ENR_TIM1EN | RCC_APB2ENR_IOPAEN;
                    
                    // Configure PA8 as alternate function output (TIM1_CH1)
                    GPIOA->CRH &= ~(GPIO_CRH_MODE8 | GPIO_CRH_CNF8);
                    GPIOA->CRH |= GPIO_CRH_MODE8_1 | GPIO_CRH_MODE8_0 | GPIO_CRH_CNF8_1;
                    
                    // Calculate PWM parameters for 72MHz clock
                    uint32_t period = (72000000 / frequency) - 1;
                    
                    TIM1->PSC = 0;            // No prescaler
                    TIM1->ARR = period;       // Auto-reload value
                    TIM1->CCR1 = period / 2;  // 50% duty cycle
                    
                    // PWM mode 1, preload enable
                    TIM1->CCMR1 = TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1PE;
                    
                    // Enable output compare
                    TIM1->CCER = TIM_CCER_CC1E;
                    
                    // Enable counter and main output
                    TIM1->CR1 = TIM_CR1_CEN;
                    TIM1->BDTR = TIM_BDTR_MOE;
                }
                
                void adc_dma_init(void) {
                    // Enable clocks
                    RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_ADC1EN;
                    RCC->AHBENR |= RCC_AHBENR_DMA1EN;
                    
                    // Configure analog pins
                    GPIOA->CRL &= ~(GPIO_CRL_MODE0 | GPIO_CRL_CNF0 |
                                    GPIO_CRL_MODE1 | GPIO_CRL_CNF1 |
                                    GPIO_CRL_MODE2 | GPIO_CRL_CNF2);
                    
                    // DMA configuration
                    DMA1_Channel1->CCR = 0;
                    DMA1_Channel1->CPAR = (uint32_t)&ADC1->DR;
                    DMA1_Channel1->CMAR = (uint32_t)adc_values;
                    DMA1_Channel1->CNDTR = ADC_BUFFER_SIZE;
                    DMA1_Channel1->CCR |= DMA_CCR_CIRC | DMA_CCR_MINC |
                                         DMA_CCR_PSIZE_0 | DMA_CCR_MSIZE_0;
                    
                    // Enable DMA
                    DMA1_Channel1->CCR |= DMA_CCR_EN;
                    
                    // ADC configuration
                    ADC1->CR1 = 0;
                    ADC1->CR2 = 0;
                    
                    // Configure for external trigger from Timer1
                    ADC1->CR2 |= ADC_CR2_EXTTRIG |    // External trigger enable
                                 (4 << 17) |          // Timer1 CC1 event as trigger
                                 ADC_CR2_DMA |        // Enable DMA
                                 ADC_CR2_ADON;        // Enable ADC
                    
                    // Scan mode configuration
                    ADC1->CR1 |= ADC_CR1_SCAN;
                    ADC1->SQR1 = ((ADC_BUFFER_SIZE - 1) << 20);
                    ADC1->SQR3 = 0 | (1 << 5) | (2 << 10);
                    
                    // Sample times
                    ADC1->SMPR2 = (7 << 0) |   // VREF: 239.5 cycles
                                  (4 << 3) |   // AN1: 41.5 cycles
                                  (4 << 6);    // AN2: 41.5 cycles
                    
                    // Calibrate
                    delay_ms(1);
                    ADC1->CR2 |= ADC_CR2_CAL;
                    while(ADC1->CR2 & ADC_CR2_CAL);
                    
                    // Start ADC
                    ADC1->CR2 |= ADC_CR2_ADON;
                }
                
                typedef struct {
                    float voltage1;
                    float voltage2;
                } analog_readings_t;
                
                analog_readings_t get_latest_voltages(void) {
                    analog_readings_t results;
                    uint16_t vref = adc_values[0];
                    
                    results.voltage1 = (adc_values[1] * 2.5f) / vref;
                    results.voltage2 = (adc_values[2] * 2.5f) / vref;
                    
                    return results;
                }
                
                void set_frequency(uint32_t new_freq) {
                    if(new_freq >= PWM_FREQ_MIN && new_freq <= PWM_FREQ_MAX) {
                        current_freq = new_freq;
                        timer_pwm_init(new_freq);
                    }
                }
                
                void main(void) {
                    analog_readings_t readings;
                    
                    // Initialize systems
                    timer_pwm_init(current_freq);
                    adc_dma_init();
                    
                    while(1) {
                        readings = get_latest_voltages();
                        
                        // Process readings here
                        // They are automatically synchronized with the TX signal
                        
                        // Example: Adjust frequency based on some condition
                        // set_frequency(new_frequency);
                    }
                }​

                Comment


                • Originally posted by moodz View Post
                  Ok I can see I am upsetting you .. and I apologise for that. But there have been many projects started and not finished on this forum ( dont worry me included ... but I am easily distracted and procrastination so I have at least 60 or 70 projects . not all metaldetectors on the go ) The goals were set out in a very clear way and you asked for advice ... so I gave you some. Obviously not everyone thinks the same way but one thing is that if you research then you will find quite a few VLF detector projects and the one you propose is really not aspiring to any new "breakthrough" so its a YAVLF project ... Yet Another VLF project and since you already nominated the hardware before knowing the "system solution" ie if the system ( ie code ) that will eliminate most people on this forum as they will not have the hardware / development environment and so the commentary will be less informed than you as the project lead / director would like. Some would call this armchair commentary.
                  For instance I use LTSPICE to simulate analogue ccts before I build them in most cases ... and this saves time .. but also if you publish the simulation on forums like this then others can also run the simulation and comment more effectively as they can easily run the sim and provide more meaningful commentary.
                  So I was essentially trying to advise you that if you want a fully digital VLF detector then just develop the code ( signal flow solution ) that does that unconstrained by any hardware consideration THEN select the appropriate hardware that MATCHES the requirements set by your code. So that was my advice not trying to shut you down or anything. If you choose to go the other way its a free world.

                  PS ... the blue pill uses its VDD as the ADC reference voltage rather than a bandgap reference so its a poor choice for frontend ADC if noise is a concern.
                  I am not annoyed.

                  I was expecting comments on this project, specially how to improve the performance, the adc with vdd as reference. thats the reason that I am trying to average out the noise over many points, many times.

                  some times, knowing the limitations, and still trying to find a way can be useful.

                  even with these limitations, this machine should work close to the best of the analog detectors and have a construction cost of around usd 30 or less, if you build the coils and the housing, which is far less than usd 600.

                  I am interested in deploying my 30 years old knowledge of signal processing with the modern low cost, general purpose processors by direct sampling. which even 80486 + low frequency low resolution adcs was not achievable some 30 years ago.

                  so let us see, what we can acheve.

                  after all, the project details are available, and the software methodology of the system is so generic that it can be implemented on any sufficiently powerful processor/development board.

                  but for the present, my aim is clear snd that is to stick to blue pill board.

                  I will later look at more capable processors. one of my friends has imx7d boards with an rtos and will try to port my methodology onto it, after its done on bluepill.
                  Last edited by Atul Asthana; 01-04-2025, 05:09 AM.

                  Comment


                  • Originally posted by Atul Asthana View Post
                    I was considering whether we could explore using 2–3 different TX frequencies interleaved in adjecent time slots, frrquencies being on either side of the main TX frequency.

                    Our coils have a low Q and perform similarly good enough at 5800 Hz and 6200 Hz. With an op-amp filter bandwidth of ±400 Hz and precise control over the TX frequency, we can operate within these limits. Additionally, the signal processing in each TX slot is independent of the preceding or succeeding slots.

                    This allows us to transmit and process different frequencies in separate time slots: Slot 1 at 5800 Hz, Slot 2 at 6000 Hz, and Slot 3 at 6200 Hz. The received signals from these slots can be analyzed using the Goertzel algorithm to extract amplitude and phase data for each frequency.
                    This represents about +/- 3.5% which isn't enough to make a difference in the target responses. MF detectors run a minimum of a 3x frequency ratio and preferably 5x. For 6kHz, you would want the second frequency to be 18kHz.

                    It is possible to switch a resonated coil between 2 frequencies but it is a slow process. It takes some time for the coil oscillation to settle after switching frequencies. This is why all MF detectors use linear ramps instead of sinusoidal oscillations.

                    Comment


                    • Originally posted by moodz View Post
                      However if you are going to get into developmental DSP you will need more powerful hardware than a blue pill for development work because there will be insufficient processing overhead for debugging code etc.
                      I suspect it will work just fine. I use STM processors for all my professional detector projects, and have used G0, L0, L4, and F7 families. Most of them running at 80Mhz and all running RTOS, no issues debugging. The ESP32 certainly has power to spare, but the F103 should do the job with no problem.

                      Comment


                      • Originally posted by Carl-NC View Post

                        This represents about +/- 3.5% which isn't enough to make a difference in the target responses. MF detectors run a minimum of a 3x frequency ratio and preferably 5x. For 6kHz, you would want the second frequency to be 18kHz.

                        It is possible to switch a resonated coil between 2 frequencies but it is a slow process. It takes some time for the coil oscillation to settle after switching frequencies. This is why all MF detectors use linear ramps instead of sinusoidal oscillations.
                        I agree that the difference in the frequencies is too small, but, hopefully we will be able to avoid some inband and synchronous noise and even look at outliers to reject them on doing statistical analysis.

                        And I am pretty sure that more data points of amplitude and phase will be helpful in better target identification.

                        please comment.

                        Comment


                        • Originally posted by Carl-NC View Post

                          I suspect it will work just fine. I use STM processors for all my professional detector projects, and have used G0, L0, L4, and F7 families. Most of them running at 80Mhz and all running RTOS, no issues debugging. The ESP32 certainly has power to spare, but the F103 should do the job with no problem.
                          The difference being that you are an experienced designer .. and you know ( presumably from knowledge and experience ) what works and does not so you can dimension the processor capbility to the code.
                          Which is not the case with kickoff projects that start with "tell me what I need to know" ... which we ( Ivica ) did.

                          Comment


                          • Carl continues to "annoy my vanity" with constant RTOS "slapping"!
                            It's as if he knows that I'm weak here and that I haven't done it before!
                            I'm going to have to get mad, sit down and learn it once and for all!
                            But if I've already decided to start with Nucleo 144... then I don't need it too much!

                            Comment


                            • You can make fast samples with slow ADC, but you need to store the signals in buffer capacitors. Of course, the number of samples is limited, but the sampling speed is as fast as you want (it depends only on the time constant of the loading circuits).

                              Something like this:
                              PI_TLO82_PUBLICATE.rar

                              Of course, this is a PI metal detector, but it illustrates the principle.

                              PS: and costs $15​

                              Comment


                              • Originally posted by boilcoil View Post
                                You can make fast samples with slow ADC, but you need to store the signals in buffer capacitors. Of course, the number of samples is limited, but the sampling speed is as fast as you want (it depends only on the time constant of the loading circuits).

                                Something like this:
                                [ATTACH]n432404[/ATTACH]

                                Of course, this is a PI metal detector, but it illustrates the principle.

                                PS: and costs $15​
                                Do we send the money to you or is it someone else's idea ?

                                good tip though.

                                Comment

                                Working...
                                X