cancel
Showing results for 
Search instead for 
Did you mean: 

How to develop code for getting Sine Wave as Analog input and apply it as AO with STM32F407G.

umairgist
Associate II

Hello Everyone,

Problem: I am working with a instrument where we frequently get the problem of frequency drop out, i.e. suddenly frequency signal goes missing i.e. goes to zero, this cause the loss in data as shown in the below image. Yellow is received frequency signal from Photodetector and Purple is the demodulated data (our desire output). When frequency goes zero the purple line is constant so data is lost.

Solution: 

In order to solve this problem, I have solution in my mind, i.e. I should develop an algorithm which could work as follow,

In this case I will have two Analog Inputs F_A, F_B and one analog output A_out.

// F_A is our sensor data 

// Based on F_A, F_B is our final result obtained by demodulation of F_A.

I want to developed following logic 

 

When data is not missing (i.e. F_A is not zero then output (A_out) of microprocessor should be zero, while F_B should store in the buffer zone.

If F_A =0 is detected then the output (A_out) should be the (F_B stored in buffer zone) i.e. I want to utilize the previous value of F_B when F_A was not zero. 

As a visualization: Look at picture 

umairgist_0-1720578075998.png

 

 

Yellow (F_A) will be continuously monitored, Purple (F_B) should be store in buffer zone. As can be seen rectangular point yellow goes zero and purple become constant, so this constant purple gap should be filled by buffer zone.

P.S I am Mechanical Engineering Student and I never had programming experience with MCU, I just used arduino once in my life. So, I developed a code with ChatGPT but it's giving me error, The code is of 250+ lines but my logic part is just of 10-20 lines starting from line 115 to 137

Sincerely.

Umair

//After providing a lot of errors and my code in main.c file this code is directly copied from chat-gpt
//Instead of using main.c I can use this main2.c file for further developments
// All the errors are resolved with ChatGPT and internet search. So, use main2c file for further developement of your work.


#include "stm32f4xx.h"
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_conf.h"
#include "stm32f4xx_hal_rcc.h"
#include "stm32f4xx_hal_adc.h"
#include "stm32f4xx_hal_dma.h"
#include "stm32f4xx_hal_gpio.h"
#include "stm32f4xx_hal_dac.h"
#include "stm32f4xx_hal_tim.h"
#include "stm32f4xx_hal_rcc_ex.h"
#include "stm32f4xx_hal_adc_ex.h"
#include "stm32f4xx_hal_dma_ex.h"
#include "stm32f4xx_hal_gpio_ex.h"
#include "stm32f4xx_hal_dac_ex.h"
#include "stm32f4xx_hal_tim_ex.h"

#define BUFFER_SIZE 1000  // Adjust buffer size as needed

uint16_t F_B_Buffer[BUFFER_SIZE]; // This will store pulses when frequency is greater than zero
uint16_t Verification_Buffer[BUFFER_SIZE]; // This will store pulses when frequency is zero
volatile int F_B_Index = 0; // This will initialize it to 0. Volatile means value may change
volatile int Ver_Index = 0; // This will initialize it to 0. Ver means it will track the verification buffer 
volatile int F_A_Val = 0; // This will initialize it to 0. This will hold the frequency values

ADC_HandleTypeDef hadc1;
DAC_HandleTypeDef hdac;
TIM_HandleTypeDef htim2;


void Error_Handler(void)
{
    // User can add their own implementation to report the HAL error return state
    while(1)
    {
    }
}
void ADC_Config(void)
{
    ADC_ChannelConfTypeDef sConfig = {0};

    // Common config
    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.ScanConvMode = DISABLE;
    hadc1.Init.ContinuousConvMode = ENABLE;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.NbrOfConversion = 1;
    hadc1.Init.DMAContinuousRequests = ENABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    if (HAL_ADC_Init(&hadc1) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }

    // Configure for the selected ADC regular channel
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = 1;
    sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
    {
        // Channel Configuration Error
        Error_Handler();
    }
}

void DAC_Config(void)
{
    DAC_ChannelConfTypeDef sConfig = {0};

    hdac.Instance = DAC;
    if (HAL_DAC_Init(&hdac) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }

    sConfig.DAC_Trigger = DAC_TRIGGER_NONE;
    sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
    if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1) != HAL_OK)
    {
        // Channel configuration Error
        Error_Handler();
    }
}

void SystemClock_Config(void);
void ADC_Config(void);
void DMA_Config(void);
void GPIO_Config(void);
void TIM_Config(void);
void DAC_Config(void);



int main(void)
{
    HAL_Init(); // This function initialize the Hardware Abstraction Layer
    SystemClock_Config(); // This function configures the system clock.
    ADC_Config(); // This function configures the ADC (Analog-to-Digital Converter)
    DMA_Config(); // This function configures the DMA (Direct Memory Access)
    GPIO_Config(); // This function configures the GPIO (General-Purpose Input/Output) pins 
    TIM_Config(); // This function configures the timers.
    DAC_Config(); // This function configures the DAC (Digital-to-Analog Converter)

    while (1)
    {
        if (F_A_Val > 0)
        {
            // Step 1: F_A > 0, store F_B in buffer
            HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&F_B_Buffer[F_B_Index], 1);
            F_B_Index = (F_B_Index + 1) % BUFFER_SIZE;
            // Analog output A_out = 0
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
        }
        else
        {
            // Step 2: F_A == 0, output F_B from buffer
            for (int i = 0; i < BUFFER_SIZE; i++)
            {
                HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R, F_B_Buffer[i]);
                HAL_Delay(1); // Adjust delay for correct timing
            }
            // Store current F_B for verification
            HAL_ADC_Start_DMA(&hadc1, (uint32_t*)&Verification_Buffer[Ver_Index], 1);
            Ver_Index = (Ver_Index + 1) % BUFFER_SIZE;
        }
    }
	}

void DMA_Config(void)
{
    // DMA Initialization
    __HAL_RCC_DMA2_CLK_ENABLE();
    DMA_HandleTypeDef hdma_adc1;
    hdma_adc1.Instance = DMA2_Stream0;
    hdma_adc1.Init.Channel = DMA_CHANNEL_0;
    hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
    hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
    hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    hdma_adc1.Init.Mode = DMA_CIRCULAR;
    hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
    hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    HAL_DMA_Init(&hdma_adc1);
    __HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1);
}

void GPIO_Config(void)
{
    // GPIO Initialization
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_0;
    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 TIM_Config(void)
{
    // Timer Initialization
    TIM_HandleTypeDef htim2;
    __HAL_RCC_TIM2_CLK_ENABLE();

    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 84 - 1;  // 1 MHz frequency
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 1000 - 1;   // 1 kHz update rate
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }

    if (HAL_TIM_Base_Start_IT(&htim2) != HAL_OK)
    {
        // Starting Error
        Error_Handler();
    }
    HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
}

void TIM2_IRQHandler(void)
{
    // Timer interrupt handler
    if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE) != RESET)
    {
        if (__HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_UPDATE) != RESET)
        {
            __HAL_TIM_CLEAR_IT(&htim2, TIM_IT_UPDATE);
            HAL_ADC_Start(&hadc1);
            HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
            F_A_Val = HAL_ADC_GetValue(&hadc1);
        }
    }
}

 

2 REPLIES 2
tjaekel
Lead

How do you get the digital signal from the analog signal?
It looks to me, you use a digital input, e.g. with a Schmitt Trigger.

This works fine until the analog signal amplitude drops below a threshold. Therefore, you get this "strange" constant digital signal (the Schmitt-Trigger will not trigger or flips into other state without a chance to come back, hysteresis is too small).

You could add an external amplifier to increase the values during this period where you do not have a signal (it is too small for your input, Schmitt Trigger).
BTW: why does your signal drops below a threshold?

You could also try to sample this signal as real analog, with an ADC. Now you might see that the amplitude of your signal goes below a minimum threshold. Potentially, you can see still a waveform with low amplitudes (but based on your scope picture it looks to me more like "there is not a signal anymore, just noise").

Before starting with some SW work arounds - check your external signal:

  • is it expected that your signal goes down in amplitude so much (maybe because the sensor sees darkness)?
  • how to distinguish a still reasonable signal (not yet so dark) from noise (sensor does not see anything)?
  • have you done an elaboration about the sensor values you could get (e.g. full light, not light)?
  • what is the SNR of your photo sensor? (it will start to provide no or unreliable data below a minimum lightning threshold)
  • make sure to understand the noise floor (e.g. sensor without any light) and the maximum sensor value (full light) = SNR (or DNR)
  • when dealing with analog sensors - consider the noise (on signals with low amplitude) - do not try to "improve" by processing "just noise".

I think, you get in a region for your sensor cannot provide anymore correct (reliable) data. There is not any solution in SW or HW (just to change to a different sensor with other characteristics).

umairgist
Associate II
  • Yes Its true>>>> is it expected that your signal goes down in amplitude so much (maybe because the sensor sees darkness)?In simple words, its an speckle noise which arises in the LiDAR systems and it is usually sometimes frequency is not captured well. 

So, I want to solve that issue using the SW as I explained above.