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 dbanner View Post
    Does anyone have the floppy disk file which accompanied this book?

    Click image for larger version  Name:	Screenshot(180).gif Views:	0 Size:	248.5 KB ID:	433492
    ​​​​​​I will dig it out for you.

    Here it is .... though my book is called Signal Processing Algorithms in Fortran and C
    .... So my copy is the later book .. an expanded version of the one above (c 1988 )
    Attached Files
    Last edited by moodz; 01-28-2025, 10:00 PM. Reason: added file

    Comment


    • Oh no!

      I have installed the latest Android Studio on my Surface Tablet 4. Did a new empty project and run it (any phone simulation). After GB's of download and working hot at 100 % CPU and waiting 30 minutes, I finally gave it up.
      WTF is doing Google? I want to see my App running! And debugging! Instantly!
      KISS! KISS! KISS!
      Google KISS my Ašš!

      It is going to be difficult making Android Apps for me. Maybe I need a 32 core cpu with 32 GB RAM at 5 GHz. So I will stay at Windows platforms at the moment.

      Btw, viewing a movie on my surface tablet takes only 1 % of CPU time. This is the goal for my detector software. Extremely power efficient light weight Win32 App. No FFT. Minimum GUI and graphics output.

      Cheers
      Aziz

      Comment


      • Originally posted by moodz View Post
        ​​​​​​I will dig it out for you.

        Here it is .... though my book is called Signal Processing Algorithms in Fortran and C
        .... So my copy is the later book .. an expanded version of the one above (c 1988 )
        Thanks.
        I was able to get the '88 edition.

        On another subject, I asked deepseek to optimize some code and it refactored it with ease, even providing a step by step account of each optimization along with explanation. It spit out the new code:

        int main(void) {
        SystemInit();
        RCC_Init();
        start_1us_timer();
        io_init();

        // Clear memory
        memset((void*)0x20000000, 0, 0x2000);

        // Initialize LCD buffers
        memcpy(LCD_first_string, " Quasar ARM ", 16);
        memcpy(LCD_second_string, " ver. 2.6.5M ", 16);

        // Initialize variables
        USER_ID = -100; // Invalid value
        sound_tone = 1000;

        // Initialize FIR filters
        static const q31_t filter_coef[7] = {
        0x245CA4, 0xA563D09, 0x1FACB2A1, 0x2BB16764, 0x1FACB2A1, 0xA563D09, 0x245CA4
        };

        arm_fir_init_q31(&arm_fir_instance_X, 7, (q31_t*)filter_coef, arm_fir_state_X, 32);
        arm_fir_init_q31(&arm_fir_instance_Y, 7, (q31_t*)filter_coef, arm_fir_state_Y, 32);

        // Initialize menu
        menu_pointer = &null_menu;

        // Initialize peripherals
        lcd_init();
        start_led_blink();
        check_HSE();
        check_pullup_resistors();
        TIM15_init();
        setup_TIM2_3_4();
        init_sound_DAC_DMA_TIMER();
        init_compensator();
        setup_DMA_ADC();
        reset_I2C_bus();
        load_profile();
        ICALL_sub_menu_10(&menu_xref_audio);

        // Create mutexes and tasks
        MUTEX_SOUND = xSemaphoreCreateMutex();
        MUTEX_LCD = xSemaphoreCreateMutex();

        if (pdTRUE != xTaskCreate(task_SOUND, "SOUND", 76, NULL, 2, &handle_SOUND)) {
        ERROR_ACTION(QUEUE_NOT_CREATE, 0);
        }
        if (pdTRUE != xTaskCreate(task_PROCESS, "PROCESS", 108, NULL, 4, &handle_PROCESS)) {
        ERROR_ACTION(QUEUE_NOT_CREATE, 1);
        }
        if (pdTRUE != xTaskCreate(task_LCD, "LCD", 60, NULL, 1, NULL)) {
        ERROR_ACTION(QUEUE_NOT_CREATE, 2);
        }
        if (pdTRUE != xTaskCreate(task_MENU, "MENU", 150, NULL, 2, NULL)) {
        ERROR_ACTION(QUEUE_NOT_CREATE, 3);
        }

        // Start scheduler
        vTaskStartScheduler();
        for (; ;
        }

        Comment


        • This was deepseek's reply:



          Optimizing code for a metal detector using DSP on an STM32 microcontroller involves several considerations, such as reducing computational overhead, improving memory usage, and ensuring real-time performance. Below, I'll provide some general optimizations and specific suggestions for your code. Since I don't have the full context of your project, I'll focus on improving the structure, efficiency, and readability of the provided code.
          General Optimizations:
          1. Minimize Global Variables:
            • Global variables increase memory usage and can lead to slower access times. Use local variables where possible, and pass data via function parameters.
          2. Use const for Constants:
            • Mark constant data (e.g., filter coefficients) as const to allow the compiler to optimize memory usage.
          3. Optimize Loops:
            • Avoid unnecessary computations inside loops. For example, precompute values outside the loop if they don't change.
          4. Use Efficient Data Types:
            • Use the smallest data type that can hold the required values (e.g., uint8_t instead of int if the range allows).
          5. Enable Compiler Optimizations:
            • Use compiler flags like -O2 or -O3 for ARM Cortex-M3 to enable optimizations.
          6. Reduce Function Calls:
            • Inline small, frequently called functions to reduce overhead.
          7. Use DMA Efficiently:
            • Ensure DMA is configured for maximum throughput and minimal CPU intervention.

          Specific Optimizations for Your Code:

          1. Memory Initialization:
          • Instead of using a loop to clear memory, consider using memset for better readability and potential optimization by the compiler.
          cpp
          Copymemset((void*)0x20000000, 0, 0x2000); // Clear memory 2. Filter Initialization:
          • Use const for filter coefficients and ensure they are stored in flash memory to save RAM.
          cpp
          Copystatic const q31_t filter_coef[7] = {
          0x245CA4, 0xA563D09, 0x1FACB2A1, 0x2BB16764, 0x1FACB2A1, 0xA563D09, 0x245CA4
          }; 3. Task Creation:
          • Check the stack sizes for tasks. Ensure they are not unnecessarily large, as this wastes memory.
          cpp
          Copyif (pdTRUE != xTaskCreate(task_SOUND, "SOUND", 76, NULL, 2, &handle_SOUND)) {
          ERROR_ACTION(QUEUE_NOT_CREATE, 0);
          } 4. Avoid Redundant Initializations:
          • Ensure that variables like USER_ID, sound_tone, and sample_count are only initialized once if they don't need to be reset.
          5. Use volatile Sparingly:
          • Only use volatile for variables that are modified outside the current execution context (e.g., by interrupts or DMA).
          6. Optimize DSP Functions:
          • Use ARM CMSIS-DSP library functions efficiently. For example, ensure that arm_fir_init_q31 is used to initialize FIR filters instead of manually setting up the structure.
          cpp
          Copyarm_fir_init_q31(&arm_fir_instance_X, 7, (q31_t*)filter_coef, arm_fir_state_X, 32);
          arm_fir_init_q31(&arm_fir_instance_Y, 7, (q31_t*)filter_coef, arm_fir_state_Y, 32); 7. Reduce Critical Sections:
          • Minimize the use of taskDISABLE_INTERRUPTS and taskENABLE_INTERRUPTS to avoid long periods of interrupt blocking.
          8. Optimize LCD Updates:
          • Update the LCD only when necessary, and avoid frequent calls to memcpy for the LCD buffers.

          Optimized Code Example:


          Here’s a refactored version of your main function with some of the above optimizations applied:

          cpp
          Copyint main(void) {
          SystemInit();
          RCC_Init();
          start_1us_timer();
          io_init();

          // Clear memory
          memset((void*)0x20000000, 0, 0x2000);

          // Initialize LCD buffers
          memcpy(LCD_first_string, " Quasar ARM ", 16);
          memcpy(LCD_second_string, " ver. 2.6.5M ", 16);

          // Initialize variables
          USER_ID = -100; // Invalid value
          sound_tone = 1000;

          // Initialize FIR filters
          static const q31_t filter_coef[7] = {
          0x245CA4, 0xA563D09, 0x1FACB2A1, 0x2BB16764, 0x1FACB2A1, 0xA563D09, 0x245CA4
          };

          arm_fir_init_q31(&arm_fir_instance_X, 7, (q31_t*)filter_coef, arm_fir_state_X, 32);
          arm_fir_init_q31(&arm_fir_instance_Y, 7, (q31_t*)filter_coef, arm_fir_state_Y, 32);

          // Initialize menu
          menu_pointer = &null_menu;

          // Initialize peripherals
          lcd_init();
          start_led_blink();
          check_HSE();
          check_pullup_resistors();
          TIM15_init();
          setup_TIM2_3_4();
          init_sound_DAC_DMA_TIMER();
          init_compensator();
          setup_DMA_ADC();
          reset_I2C_bus();
          load_profile();
          ICALL_sub_menu_10(&menu_xref_audio);

          // Create mutexes and tasks
          MUTEX_SOUND = xSemaphoreCreateMutex();
          MUTEX_LCD = xSemaphoreCreateMutex();

          if (pdTRUE != xTaskCreate(task_SOUND, "SOUND", 76, NULL, 2, &handle_SOUND)) {
          ERROR_ACTION(QUEUE_NOT_CREATE, 0);
          }
          if (pdTRUE != xTaskCreate(task_PROCESS, "PROCESS", 108, NULL, 4, &handle_PROCESS)) {
          ERROR_ACTION(QUEUE_NOT_CREATE, 1);
          }
          if (pdTRUE != xTaskCreate(task_LCD, "LCD", 60, NULL, 1, NULL)) {
          ERROR_ACTION(QUEUE_NOT_CREATE, 2);
          }
          if (pdTRUE != xTaskCreate(task_MENU, "MENU", 150, NULL, 2, NULL)) {
          ERROR_ACTION(QUEUE_NOT_CREATE, 3);
          }

          // Start scheduler
          vTaskStartScheduler();
          for (;;
          }
          Additional Recommendations:
          1. Profile Your Code:
            • Use a profiler to identify bottlenecks in your code. Focus on optimizing the most time-consuming functions.
          2. Use Hardware Features:
            • Leverage STM32 hardware features like the FPU (if available) for faster DSP computations.
          3. Test and Validate:
            • After making optimizations, thoroughly test the system to ensure that performance improvements do not introduce bugs or reduce accuracy.
          4. Consider Power Consumption:
            • Optimize for low power usage if the metal detector is battery-powered. Use low-power modes when idle.

          Let me know if you need further assistance!




          Comment


          • next, I requested a complete framework. And here is the reply:

            Writing a complete firmware for a metal detector based on an STM32 microcontroller is a complex task that involves hardware-specific configurations, signal processing algorithms, and user interface implementation. Below, I'll provide a simplified framework for such a firmware. This framework will include:
            1. Hardware Initialization (e.g., GPIO, ADC, timers, DMA).
            2. Signal Processing (e.g., filtering, target detection).
            3. User Interface (e.g., LCD, buttons, sound feedback).
            4. Main Loop for real-time operation.

            This example assumes you're using an STM32 microcontroller with ARM Cortex-M3/M4, and it uses the STM32 HAL library for hardware abstraction. You'll need to adapt it to your specific hardware and requirements.
            Complete Firmware Framework

            ​#include "stm32f1xx_hal.h" // Replace with your STM32 series header
            #include <arm_math.h> // CMSIS-DSP library for signal processing
            #include <cstring> // For memset, memcpy

            // Constants and Configuration
            #define SAMPLE_RATE 10000 // 10 kHz sampling rate
            #define BUFFER_SIZE 256 // Sample buffer size
            #define TARGET_THRESHOLD 1000 // Threshold for target detection
            #define FILTER_ORDER 5 // FIR filter order

            // Global Variables
            volatile uint16_t adc_buffer[BUFFER_SIZE]; // ADC sample buffer
            volatile bool target_detected = false; // Target detection flag
            char lcd_buffer[16]; // LCD display buffer

            // FIR Filter Coefficients (example coefficients)
            const float32_t fir_coeff[FILTER_ORDER] = {0.1, 0.2, 0.4, 0.2, 0.1};

            // FIR Filter Instance
            arm_fir_instance_f32 fir_instance;
            float32_t fir_state[BUFFER_SIZE + FILTER_ORDER - 1];

            // Function Prototypes
            void SystemClock_Config(void);
            void GPIO_Init(void);
            void ADC_Init(void);
            void DMA_Init(void);
            void TIM_Init(void);
            void LCD_Init(void);
            void LCD_Display(const char* text);
            void Process_Samples(uint16_t* samples, uint16_t size);
            void Beep(uint16_t frequency, uint16_t duration);

            // Main Function
            int main(void) {
            // HAL Initialization
            HAL_Init();
            SystemClock_Config();

            // Peripheral Initialization
            GPIO_Init();
            ADC_Init();
            DMA_Init();
            TIM_Init();
            LCD_Init();

            // Initialize FIR Filter
            arm_fir_init_f32(&fir_instance, FILTER_ORDER, (float32_t*)fir_coeff, fir_state, BUFFER_SIZE);

            // Start ADC with DMA
            HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buffer, BUFFER_SIZE);

            // Main Loop
            while (1) {
            // Wait for ADC buffer to be filled
            if (HAL_ADC_PollForConversion(&hadc, 100) == HAL_OK) {
            // Process samples
            Process_Samples((uint16_t*)adc_buffer, BUFFER_SIZE);

            // Display result on LCD
            if (target_detected) {
            LCD_Display("Target Found!");
            Beep(1000, 200); // Beep for 200ms at 1kHz
            } else {
            LCD_Display("No Target");
            }
            }
            }
            }

            // Process ADC Samples
            void Process_Samples(uint16_t* samples, uint16_t size) {
            float32_t input[BUFFER_SIZE], output[BUFFER_SIZE];

            // Convert ADC samples to float
            for (uint16_t i = 0; i < size; i++) {
            input[i] = (float32_t)samples[i];
            }

            // Apply FIR Filter
            arm_fir_f32(&fir_instance, input, output, size);

            // Detect target (simple thresholding)
            float32_t max_value = 0;
            arm_max_f32(output, size, &max_value, NULL);

            if (max_value > TARGET_THRESHOLD) {
            target_detected = true;
            } else {
            target_detected = false;
            }
            }

            // Beep Function (using PWM or timer)
            void Beep(uint16_t frequency, uint16_t duration) {
            // Configure timer for PWM to generate a tone
            // Example: Use TIM2 to generate a square wave at the desired frequency
            __HAL_TIM_SET_AUTORELOAD(&htim2, (SystemCoreClock / frequency) - 1);
            __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (SystemCoreClock / frequency) / 2);
            HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);

            // Wait for the duration
            HAL_Delay(duration);

            // Stop PWM
            HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
            }

            // LCD Display Function
            void LCD_Display(const char* text) {
            // Clear LCD buffer
            memset(lcd_buffer, 0, sizeof(lcd_buffer));

            // Copy text to LCD buffer
            strncpy(lcd_buffer, text, 15);

            // Send buffer to LCD (implementation depends on your LCD hardware)
            // Example: Send via I2C or GPIO
            }

            // Hardware Initialization Functions
            void GPIO_Init(void) {
            // Initialize GPIO pins for buttons, LEDs, etc.
            __HAL_RCC_GPIOA_CLK_ENABLE();
            GPIO_InitTypeDef GPIO_InitStruct = {0};
            GPIO_InitStruct.Pin = GPIO_PIN_5; // Example: LED on PA5
            GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
            GPIO_InitStruct.Pull = GPIO_NOPULL;
            GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
            HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
            }

            void ADC_Init(void) {
            // Initialize ADC for sampling
            __HAL_RCC_ADC1_CLK_ENABLE();
            ADC_ChannelConfTypeDef sConfig = {0};
            hadc.Instance = ADC1;
            hadc.Init.ScanConvMode = ADC_SCAN_DISABLE;
            hadc.Init.ContinuousConvMode = ENABLE;
            hadc.Init.DiscontinuousConvMode = DISABLE;
            hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
            hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
            hadc.Init.NbrOfConversion = 1;
            HAL_ADC_Init(&hadc);

            // Configure ADC channel
            sConfig.Channel = ADC_CHANNEL_0; // Example: Use ADC channel 0
            sConfig.Rank = ADC_REGULAR_RANK_1;
            sConfig.SamplingTime = ADC_SAMPLETIME_28CYCLES_5;
            HAL_ADC_ConfigChannel(&hadc, &sConfig);
            }

            void DMA_Init(void) {
            // Initialize DMA for ADC
            __HAL_RCC_DMA1_CLK_ENABLE();
            hdma_adc.Instance = DMA1_Channel1;
            hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY;
            hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE;
            hdma_adc.Init.MemInc = DMA_MINC_ENABLE;
            hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
            hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
            hdma_adc.Init.Mode = DMA_CIRCULAR;
            hdma_adc.Init.Priority = DMA_PRIORITY_HIGH;
            HAL_DMA_Init(&hdma_adc);

            // Link DMA to ADC
            __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc);
            }

            void TIM_Init(void) {
            // Initialize timer for PWM (beep)
            __HAL_RCC_TIM2_CLK_ENABLE();
            htim2.Instance = TIM2;
            htim2.Init.Prescaler = 0;
            htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
            htim2.Init.Period = 0;
            htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
            htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
            HAL_TIM_PWM_Init(&htim2);

            // Configure PWM channel
            TIM_OC_InitTypeDef sConfigOC = {0};
            sConfigOC.OCMode = TIM_OCMODE_PWM1;
            sConfigOC.Pulse = 0;
            sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
            sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
            HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
            }

            void LCD_Init(void) {
            // Initialize LCD (implementation depends on your LCD hardware)
            // Example: Use I2C or GPIO to communicate with the LCD
            }

            // System Clock Configuration
            void SystemClock_Config(void) {
            // Configure system clock (e.g., 72 MHz for STM32F1)
            RCC_OscInitTypeDef RCC_OscInitStruct = {0};
            RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
            RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
            RCC_OscInitStruct.HSEState = RCC_HSE_ON;
            RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
            RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
            RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
            HAL_RCC_OscConfig(&RCC_OscInitStruct);
            RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
            RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
            RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
            RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
            RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
            HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
            }​
            Key Features of the Firmware:
            1. ADC Sampling:
              • Uses DMA to continuously sample data from the ADC.
            2. Signal Processing:
              • Applies an FIR filter to the sampled data and detects targets using a simple threshold.
            3. User Feedback:
              • Displays results on an LCD and provides audio feedback (beep) when a target is detected.
            4. Real-Time Operation:
              • Runs in a continuous loop, processing data in real-time.

            Next Steps:
            1. Adapt to Your Hardware:
              • Replace placeholders (e.g., hadc, htim2) with your actual peripheral handles.
            2. Enhance Signal Processing:
              • Implement more advanced algorithms (e.g., FFT, IIR filters) for better target discrimination.
            3. Add User Controls:
              • Implement buttons or a menu system for user interaction.
            4. Test and Debug:
              • Use a debugger (e.g., ST-Link) to verify the firmware's behavior.

            Let me know if you need further assistance or specific parts of the firmware explained in more detail!

            Comment


            • Can you believe that? It took deepseek all of 12 seconds. Now this is a powerful AI.

              It gave a basis on which to hang everything that's needed.

              I gave it no specifics, I was very vague. The request: "Write firmware for a metal detector based on an STM32 microcontroller."

              Amazing.

              Comment


              • Now I noticed it wrote the program in C. So I then asked deepseek which programming language it used (I never requested it rewrite the program in any other language). This was the reply:

                The code I provided is written in C, not C++. This is because embedded systems programming, especially for microcontrollers like the STM32, is typically done in C due to its efficiency, low-level hardware control, and widespread support in the embedded systems ecosystem. Why C and Not C++?
                1. Performance: C is generally faster and more predictable than C++ for low-level hardware control.
                2. Memory Usage: C has a smaller memory footprint, which is critical for resource-constrained microcontrollers.
                3. Compatibility: Most microcontroller vendors (like STMicroelectronics) provide hardware abstraction libraries (HAL) and examples in C.
                4. Simplicity: C is simpler and avoids the overhead of C++ features like classes, templates, and exceptions, which are often unnecessary in embedded systems.
                C++ in Embedded Systems


                While C++ can be used in embedded systems, it is less common for small microcontrollers like the STM32. However, C++ can be beneficial for larger systems or when object-oriented programming (OOP) is required. If you prefer C++, you can still use it with STM32, but you'll need to:
                1. Enable C++ support in your toolchain (e.g., STM32CubeIDE or Keil).
                2. Avoid using heavy C++ features (e.g., dynamic memory allocation, exceptions, RTTI) to keep the code efficient.
                Example of C++ for STM32


                If you'd like to use C++, here's a simple example of how you might structure the same firmware in C++:

                #include "stm32f1xx_hal.h"
                #include <cstring>

                class MetalDetector {
                public:
                MetalDetector() {
                HAL_Init();
                SystemClock_Config();
                GPIO_Init();
                ADC_Init();
                DMA_Init();
                TIM_Init();
                LCD_Init();
                arm_fir_init_f32(&fir_instance, FILTER_ORDER, (float32_t*)fir_coeff, fir_state, BUFFER_SIZE);
                }

                void Run() {
                HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buffer, BUFFER_SIZE);
                while (true) {
                if (HAL_ADC_PollForConversion(&hadc, 100) == HAL_OK) {
                ProcessSamples();
                UpdateDisplay();
                }
                }
                }

                private:
                void ProcessSamples() {
                float32_t input[BUFFER_SIZE], output[BUFFER_SIZE];
                for (uint16_t i = 0; i < BUFFER_SIZE; i++) {
                input[i] = (float32_t)adc_buffer[i];
                }
                arm_fir_f32(&fir_instance, input, output, BUFFER_SIZE);

                float32_t max_value = 0;
                arm_max_f32(output, BUFFER_SIZE, &max_value, nullptr);
                target_detected = (max_value > TARGET_THRESHOLD);
                }

                void UpdateDisplay() {
                if (target_detected) {
                LCD_Display("Target Found!");
                Beep(1000, 200);
                } else {
                LCD_Display("No Target");
                }
                }

                void Beep(uint16_t frequency, uint16_t duration) {
                __HAL_TIM_SET_AUTORELOAD(&htim2, (SystemCoreClock / frequency) - 1);
                __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, (SystemCoreClock / frequency) / 2);
                HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
                HAL_Delay(duration);
                HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1);
                }

                void LCD_Display(const char* text) {
                memset(lcd_buffer, 0, sizeof(lcd_buffer));
                strncpy(lcd_buffer, text, 15);
                // Send to LCD
                }

                // Hardware initialization functions (GPIO_Init, ADC_Init, etc.)
                void GPIO_Init() { /* ... */ }
                void ADC_Init() { /* ... */ }
                void DMA_Init() { /* ... */ }
                void TIM_Init() { /* ... */ }
                void LCD_Init() { /* ... */ }
                void SystemClock_Config() { /* ... */ }

                // Constants and variables
                static constexpr uint16_t BUFFER_SIZE = 256;
                static constexpr uint16_t TARGET_THRESHOLD = 1000;
                static constexpr uint8_t FILTER_ORDER = 5;
                const float32_t fir_coeff[FILTER_ORDER] = {0.1, 0.2, 0.4, 0.2, 0.1};

                volatile uint16_t adc_buffer[BUFFER_SIZE];
                bool target_detected = false;
                char lcd_buffer[16];
                arm_fir_instance_f32 fir_instance;
                float32_t fir_state[BUFFER_SIZE + FILTER_ORDER - 1];
                };

                int main() {
                MetalDetector detector;
                detector.Run();
                return 0;
                }​
                Key Differences in C++:
                1. Encapsulation: The firmware is encapsulated in a MetalDetector class.
                2. Readability: The code is more modular and easier to extend.
                3. Reusability: Functions like Beep and LCD_Display are reusable methods.
                Should You Use C or C++?
                • Use C if:
                  • You need maximum performance and minimal memory usage.
                  • You're working with existing C-based libraries (e.g., STM32 HAL).
                  • Your team is more familiar with C.
                • Use C++ if:
                  • You need better code organization and abstraction.
                  • You're working on a larger project with complex logic.
                  • You want to leverage C++ features like classes and templates.

                Let me know if you'd like further clarification or help with either language!

                Comment


                • Deepseek is super intuitive. I can see the war rooms being set up elsewhere.

                  Comment


                  • Once again American tech gets ahead of itself ....and is proven bigger ain't always better.

                    Thinking back to Microsoft / Linux wars.

                    Comment


                    • This is the end of AI.

                      Deepseek will cause a thermo nuclear meltdown to AI companies.

                      Yeah, back to the roots.

                      Comment


                      • Originally posted by dbanner View Post
                        Now I noticed it wrote the program in C. So I then asked deepseek which programming language it used (I never requested it ...............;
                        DMA_Init();!
                        Excellent.

                        how about asking DeepSeek to generate entire code and testing it?
                        I wont have to wait for April to start working on the code.
                        it will be really helpful
                        I guess, DeepSeek will generate the entire code.

                        Comment


                        • Deep Seek. DeepSeek. It's a good name for a metal detector.
                          Made by Deepseek for deep seeking.

                          All programmers should be fired now. Deepseek is making it for you.
                          You are all fired!

                          Aziz

                          Comment


                          • Originally posted by Atul Asthana View Post

                            Excellent.

                            how about asking DeepSeek to generate entire code and testing it?
                            I wont have to wait for April to start working on the code.
                            it will be really helpful
                            I guess, DeepSeek will generate the entire code.
                            I am confident that if you were to provide very specific instructions to deepseek, it can write most of the code.

                            I requested it to write the code for transmit signal based on Minelab's US6653838.

                            Deepseek analyzed the patent and wrote the code in a few seconds, with a full explanation.

                            Comment


                            • Originally posted by dbanner View Post

                              I am confident that if you were to provide very specific instructions to deepseek, it can write most of the code.

                              I requested it to write the code for transmit signal based on Minelab's US6653838.

                              Deepseek analyzed the patent and wrote the code in a few seconds, with a full explanation.
                              Click image for larger version

Name:	fraser.gif
Views:	216
Size:	172.5 KB
ID:	433550

                              Comment


                              • Oh well,

                                I have some good and bad news regarding the USB Sound Blasterx G6:
                                - Line output is very bad on high frequency region. It gets distorted and even clipped.
                                Vpp is 5.6 V (+- 2.8 V). Causing much noise to the low frequency region too. WTF!

                                - Ear phone output has really huge bang. It is not much distorting and not much noisy.
                                Vpp low-gain: 3.5 V (+/- 1.75 V)
                                Vpp high-gain: 14 V (+/- 7 V)
                                Low output impedance: 1 Ohm typical
                                You can make hundreds of volts on the TX-coil. This will blow out your coil. I can go up to 90 kHz TX frequency. So you have enough power for the TX-coil.

                                I have detected a glitch issue on the sound card output. Could be a software bug. Or the USB port is too much noisy on my PC. I haven't found the reason yet.

                                Aziz

                                Comment

                                Working...