Detecção de PicosVersão "1": Método "Simples"Versão "2": Usando DerivadasConsiderando Derivadas ConsecutivasBenefícios da Abordagem de Derivadas:
Para detectar a distância entre dois picos máximos de um sinal no Arduino, considerando um "vale de descida" entre os picos, é possível utilizar o seguinte algoritmo:
width_min para desconsiderar picos muito próximos.O código abaixo implementa essa lógica:
// Número de amostras a capturar// Limiar para considerar um pico// Distância mínima entre os picos// Pino analógico para leituraint samples[NUM_SAMPLES]; // Array para armazenar as amostrasint lastPeakIndex = -1; // Índice do último pico máximo encontradovoid setup() { Serial.begin(9600);}void loop() { // Captura os dados do sinal for (int i = 0; i < NUM_SAMPLES; i++) { samples[i] = analogRead(ANALOG_PIN); delay(10); // Delay para simular a aquisição do sinal } detectPicos(samples, NUM_SAMPLES); // Aguarda um tempo antes de nova leitura delay(1000);}void detectPicos(int *data, int length) { for (int i = 1; i < length - 1; i++) { // Verifica se é um pico máximo if (data[i] > data[i - 1] && data[i] > data[i + 1] && data[i] > THRESHOLD) { // Verifica se o pico está distante o suficiente do último pico if (lastPeakIndex == -1 || (i - lastPeakIndex) >= WIDTH_MIN) { Serial.print("Pico encontrado em: "); Serial.print(i); Serial.print(" com valor: "); Serial.println(data[i]); lastPeakIndex = i; // Atualiza o índice do último pico } } }}Explicação do Código:
Definições:
NUM_SAMPLES: O número de amostras a capturar.THRESHOLD: O limiar acima do qual um valor é considerado um pico máximo.WIDTH_MIN: O número mínimo de amostras entre dois picos.ANALOG_PIN: O pino A0 do Arduino para ler o sinal.Setup:
Loop Principal:
detectPicos para verificar os picos.Função detectPicos:
width_min.Note que o código anterior não calcula a distância entre 2 picos máximos.
Note que:
Para determinar a distância em número de amostras entre dois picos máximos de um sinal, você pode modificar o código anterior. Em vez de imprimir o valor de cada pico, você irá armazenar a distância entre o último pico encontrado e o atual. O código atualizado ficaria assim:
xxxxxxxxxx// Número de amostras a capturar// Limiar para considerar um pico// Distância mínima entre os picos// Pino analógico para leituraint samples[NUM_SAMPLES]; // Array para armazenar as amostrasint lastPeakIndex = -1; // Índice do último pico máximo encontradovoid setup() { Serial.begin(9600);}void loop() { // Captura os dados do sinal for (int i = 0; i < NUM_SAMPLES; i++) { samples[i] = analogRead(ANALOG_PIN); delay(10); // Delay para simular a aquisição do sinal } int distance = detectPicos(samples, NUM_SAMPLES); // Mostra a distância entre picos, se um novo pico foi encontrado if (distance >= 0) { Serial.print("Distância entre picos: "); Serial.println(distance); } // Aguarda um tempo antes de nova leitura delay(1000);}int detectPicos(int *data, int length) { for (int i = 1; i < length - 1; i++) { // Verifica se é um pico máximo if (data[i] > data[i - 1] && data[i] > data[i + 1] && data[i] > THRESHOLD) { // Verifica se o pico está distante o suficiente do último pico if (lastPeakIndex == -1 || (i - lastPeakIndex) >= WIDTH_MIN) { int distance = (lastPeakIndex == -1) ? 0 : (i - lastPeakIndex); lastPeakIndex = i; // Atualiza o índice do último pico return distance; // Retorna a distância entre os picos } } } return -1; // Retorna -1 se nenhum novo pico foi encontrado}Detalhes do código:
Detecção de Picos:
detectPicos agora retorna a distância em número de amostras entre dois picos.WIDTH_MIN do último pico, a distância entre eles é calculada e retornada.Loop Principal:
detectPicos, se uma distância válida for retornada, ela é impressa no console serial.Retorno de Distância:
Observações:
THRESHOLD e WIDTH_MIN para melhor se adaptar ao seu sinal (adequando às características do sinal que está analisando.)Para incluir a abordagem de derivadas no código de detecção de picos, você pode calcular a primeira derivada (ou diferença entre amostras consecutivas) para identificar quando o sinal está subindo ou descendo. Isso pode ajudar a garantir que um pico seja detectado apenas após uma subida e uma descida, confirmando a formação de um pico verdadeiro.
Aqui está uma versão do código que implementa essa abordagem:
xxxxxxxxxx// Número de amostras a capturar// Limiar para considerar um pico// Distância mínima entre os picos// Pino analógico para leituraint samples[NUM_SAMPLES]; // Array para armazenar as amostrasint lastPeakIndex = -1; // Índice do último pico máximo encontradovoid setup() { Serial.begin(9600);}void loop() { // Captura os dados do sinal for (int i = 0; i < NUM_SAMPLES; i++) { samples[i] = analogRead(ANALOG_PIN); delay(10); // Delay para simular a aquisição do sinal } int distance = detectPicos(samples, NUM_SAMPLES); // Mostra a distância entre picos, se um novo pico foi encontrado if (distance >= 0) { Serial.print("Distância entre picos: "); Serial.println(distance); } // Aguarda um tempo antes de nova leitura delay(1000);}int detectPicos(int *data, int length) { // Variável para armazenar o valor da primeira derivada int derivativePrev = data[1] - data[0]; for (int i = 1; i < length - 1; i++) { // Calcula a primeira derivada int derivativeCurr = data[i + 1] - data[i]; // Verifica se é um pico máximo if (derivativePrev > 0 && derivativeCurr < 0 && data[i] > THRESHOLD) { // Verifica se o pico está distante o suficiente do último pico if (lastPeakIndex == -1 || (i - lastPeakIndex) >= WIDTH_MIN) { int distance = (lastPeakIndex == -1) ? 0 : (i - lastPeakIndex); lastPeakIndex = i; // Atualiza o índice do último pico return distance; // Retorna a distância entre os picos } } derivativePrev = derivativeCurr; // Atualiza a derivada anterior } return -1; // Retorna -1 se nenhum novo pico foi encontrado}Detalhes do Código:
Cálculo das Derivadas Consecutivas:
derivativeCurr).derivativePrev armazena o valor da derivada da iteração anterior.Detecção de Pico:
THRESHOLD.Cálculo da Distância:
WIDTH_MIN), a distância é calculada e retornada.
🌊 Fernando Passold 📬 ,