// ---------------------------------------------------------------------------
/* Código para Arduino Uno
Leitura de canal analógico A0 (potenciometro) e cálculo de estatísticas
de tendência central e de dispersão do sinal.
Renan Ribeiro Machado e Prof. Jaime A Mosquera Sanchez, EESC/USP, 2024 */
// ---------------------------------------------------------------------------
// Diretivas de pré-processador:
#define PINO_POTENCIOMETRO A0
#define TAMANHO_BUFFER 16
// ---------------------------------------------------------------------------
// Declaração de variáveis, protótipos de funções, etc.
bool coletaIniciada = false;
bool sistemaTravado = false;
int indiceAmostra = 0;
float amostras[ TAMANHO_BUFFER ];
float mediaMovel = 0;
float valorInicial = 0;
//float posicaoInicial = 0;
unsigned long tempoInicialColeta = 0;
unsigned long tempoFimColeta = 0;
// ---------------------------------------------------------------------------
// Configuração da porta serial
void setup() {
// Salvar o valor de tensão inicial:
valorInicial = analogRead( PINO_POTENCIOMETRO );
//float posicaoInicial = map( valorInicial , 0 , 1023 , 225, -45 );
// Configura a porta serial:
Serial.begin( 9600 );
Serial.println("Aguardando movimento do potenciômetro...");
}
// ---------------------------------------------------------------------------
// Loop principal
void loop() {
// Leitura do potenciômetro (0 a 1023):
float tensao = analogRead( PINO_POTENCIOMETRO );
// Lógica para iniciar a medição:
if ( !coletaIniciada && !sistemaTravado && abs( tensao - valorInicial ) > 10 ) {
coletaIniciada = true;
tempoInicialColeta = millis();
Serial.println( "Movimento detectado. Iniciando coleta por 10 segundos..." );
}
// Condição principal para armazenar as medições e calcular as medidas estatísticas
if ( coletaIniciada && ( millis() - tempoInicialColeta <= 10000 ) ){
// armazenar a posicao atual no array de amostras enquanto o deadline não estoura:
float posicao = map( tensao , 0 , 1023 , 225, -45 );
amostras[ indiceAmostra ] = posicao;
indiceAmostra = ( indiceAmostra + 1 ) % TAMANHO_BUFFER;
// ----------------------------------------------------------------------
// Cálculo das medidas estatísticas:
float media = calculaMedia(amostras, TAMANHO_BUFFER);
float mediana = calculaMediana(amostras, TAMANHO_BUFFER);
float moda = calculaModa(amostras, TAMANHO_BUFFER);
float desvio = calculaDesvio(amostras, TAMANHO_BUFFER, media);
mediaMovel = calculaMediaMovel(amostras, TAMANHO_BUFFER);
// ----------------------------------------------------------------------
// Formato para o Serial Plotter:
Serial.print("Posicao:");
Serial.print(posicao);
Serial.print(" | Media:");
Serial.print(media);
Serial.print(" | Mediana:");
Serial.print(mediana);
Serial.print(" | Moda:");
Serial.print(moda);
Serial.print(" | Desvio:");
Serial.print(desvio);
Serial.print(" | MediaMovel:");
Serial.println(mediaMovel); // Adiciona uma nova linha para o plotter
delay( 100 );
// ----------------------------------------------------------------------
// Se o tempo de coleta estourou o deadline de 10 s:
} else if ( coletaIniciada && (millis() - tempoInicialColeta > 10000 ) ) {
Serial.println( "Coleta finalizada. Sistema travado por 10 segundos..." );
coletaIniciada = false;
sistemaTravado = true;
tempoFimColeta = millis();
}
// ----------------------------------------------------------------------
// Se o tempoFimColeta é igual a 10 s, então libera o sistema para nova medição:
if( sistemaTravado && (millis() - tempoFimColeta >= 10000 ) ) {
Serial.println( "Sistema pronto. Aguardando novo movimento do potenciômetro...") ;
sistemaTravado = false;
valorInicial = analogRead( PINO_POTENCIOMETRO ); // Atualiza o valor inicial
}
}
// ----------------------------------------------------------------------
// Funções estatísticas
float calculaMedia(float data[], int size) {
float sum = 0;
for (int i = 0; i < size; i++) {
sum += data[i];
}
return sum / size;
}
float calculaMediana(float data[], int size) {
float sorted[size];
memcpy(sorted, data, size * sizeof(float));
for (int i = 0; i < size - 1; i++) {
for (int j = i + 1; j < size; j++) {
if (sorted[i] > sorted[j]) {
float temp = sorted[i];
sorted[i] = sorted[j];
sorted[j] = temp;
}
}
}
if (size % 2 == 0) {
return (sorted[size / 2 - 1] + sorted[size / 2]) / 2;
} else {
return sorted[size / 2];
}
}
float calculaModa(float data[], int size) {
float moda = data[0];
int maxCount = 0;
for (int i = 0; i < size; i++) {
int count = 1;
for (int j = i + 1; j < size; j++) {
if (data[j] == data[i]) count++;
}
if (count > maxCount) {
maxCount = count;
moda = data[i];
}
}
return maxCount > 1 ? moda : NAN;
}
float calculaDesvio(float data[], int size, float media) {
float sumSq = 0;
for (int i = 0; i < size; i++) {
sumSq += pow(data[i] - media, 2);
}
return sqrt(sumSq / size);
}
float calculaMediaMovel(float data[], int size) {
float sum = 0;
for (int i = 0; i < size; i++) {
sum += data[i];
}
return sum / size;
}