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 leitura
int samples[NUM_SAMPLES]; // Array para armazenar as amostras
int lastPeakIndex = -1; // Índice do último pico máximo encontrado
void 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 leitura
int samples[NUM_SAMPLES]; // Array para armazenar as amostras
int lastPeakIndex = -1; // Índice do último pico máximo encontrado
void 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 leitura
int samples[NUM_SAMPLES]; // Array para armazenar as amostras
int lastPeakIndex = -1; // Índice do último pico máximo encontrado
void 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 📬 ,