¿Es posible medir la aceleración en actividades deportivas con un acelerómetro?

0

He estado tratando de hacer un prototipo simple capaz de medir un puñetazo o un lanzamiento con un acelerómetro, pero repentinamente dejó de funcionar y se "fijó" en un valor, si lo estaba probando.
Cuando lo estaba probando, aunque intenté que el código fuera lo más eficiente posible para maximizar la frecuencia de medición, a veces obtenía valores irregulares (baja precisión). La forma en que probé mi prototipo fue dejarlo caer sobre una superficie dura. Los componentes que utilicé donde:

  1. Microcontrolador (msp430g2553)
  2. Mostrar (QDSP 6064)
  3. acelerómetro (ADXL377):
  4.  - Rango: +/- 200g
     - respuesta de frecuencia: 1000Hz
     - máximo absoluto g: 10000g

El código que usé es el siguiente (lo siento, está en portugués):

#include <msp430.h>
#include <math.h>
#include <stdio.h>

#define CAT_1 BIT3
#define CAT_2 BIT4
#define CAT_3 BIT5
#define CAT_4 BIT6

#define SEG_A BIT0
#define SEG_B BIT1
#define SEG_C BIT2
#define SEG_D BIT3
#define SEG_E BIT4
#define SEG_F BIT5
#define SEG_G BIT6
#define SEG_DP BIT7

#define EIXO_X BIT0
#define EIXO_Y BIT1
#define EIXO_Z BIT2

#define BOTAO BIT7

unsigned int adc[3];
unsigned int eixo_x = 0;
unsigned int eixo_y = 0;
unsigned int eixo_z = 0;
unsigned int maior = 0;
unsigned int soma = 0;

float gx;
float gy;
float gz;

float gxy;
float gxyz;
int total;

char total_string[3];

int flag_display = 0;

const int zero_g = 512;
const float escala = 2.6165;

int i = 0;                                                              // tempo de atraso

void escolher_digito(int digito);
void escolher_numero(char numero);
void digito_um(void);
void digito_dois(void);
void digito_tres(void);
void digito_quatro(void);
void zero(void);
void um(void);
void dois(void);
void tres(void);
void quatro(void);
void cinco(void);
void seis(void);
void sete(void);
void oito(void);
void nove(void);
void vazio(void);
void atraso(void);

void main(void) {

    WDTCTL = WDTPW | WDTHOLD;

    P1REN |= BOTAO;                                                     // Ativa resistância interna para os modos "pull-up"/"pull-down"
    P1IES |= BOTAO;                                                     // Selecionar botão de alto para baixo (modo "pull-up") (alto -> baixo, 1 -> 0)
    P1IFG &= ~BOTAO;                                                    // Limpar a flag BOTAO antes de permitir interrupções
                                                                        // Desta forma previne-se uma possível interrupção imediata
    P1IE |= BOTAO;                                                      // Permitir interupções em BOTAO

    _enable_interrupt();                                                // Permitir interrupções


    P2SEL &= ~(SEG_G | SEG_DP);                                         // Seleciona modo I/O para P1.6 e P1.7 (por defeito estão configurados para o cristal do relógio externo)
    P1OUT |= CAT_1 | CAT_2 | CAT_3 | CAT_4;
    P2OUT = 0;
    P1DIR |= CAT_1 | CAT_2 | CAT_3 | CAT_4;
    P2DIR |= SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP;

    BCSCTL1 = CALBC1_16MHZ;
    DCOCTL = CALDCO_16MHZ;

    ADC10CTL1 = INCH_2 + CONSEQ_1;                                      // Canal máximo: A2, modo de conversão: sequência de canais
    ADC10CTL0 = ADC10SHT_1 + MSC + ADC10ON;                             // Tempo de amostra: 8 x ADC10CLK                           ????????? alterar?
                                                                        // Multiplas amostras e conversão (apenas válido para modo de sequência ou repetição)
                                                                        // ADC10 ligado

    ADC10DTC1 = 0x03;                                                   // Transferência de dados -> numero de transferências por bloco: 3
    ADC10AE0 |= 0x07;                                                   // Ligar entradas analógicas A2, A1 e A0

    for(;;) {

        // Modo de observação (quando o display se encontra desligado) (ciclo infinito)
        if(!flag_display) {
            ADC10CTL0 &= ~ENC;                                              // Desligar conversão
            while (ADC10CTL1 & BUSY);                                       // Esperar que ADC10 fique ativo

            ADC10SA = (unsigned int)adc;                                    // Copia dados em ADC10SA para o array adc
            ADC10CTL0 |= ENC + ADC10SC;                                     // Iniciar conversão de amostra

            //__bis_SR_register(CPUOFF + GIE);        // Modo de poupança de energia LPM0 (CPU e MCLK) desativados
                                                    // Permitir interrupções

            soma = adc[2] + adc[1] + adc[0];

            if(soma > maior) {
                maior = soma;
                eixo_x = adc[2];
                eixo_y = adc[1];
                eixo_z = adc[0];
            }
        }

        // Modo de display (ciclo infinito)
        if(flag_display) {

            escolher_digito(2);
            escolher_numero(total_string[2]);
            atraso();
            escolher_digito(3);
            escolher_numero(total_string[1]);
            atraso();
            escolher_digito(4);
            escolher_numero(total_string[0]);
            atraso();

            escolher_digito(1);
            escolher_numero(' ');
            atraso();

        }

    }   // ciclo infinito
}   // main

// Rotina de serviço de interrupção
#pragma vector = PORT1_VECTOR
__interrupt void P1_ISR(void) {

    atraso();

    switch(P1IFG & BOTAO) {         // Se a flag de interrupção for ativada
                                    // xxxx1xxx & 00001000 = 00001000
                                    // xxxx1xxx & 00001000 = 00000000
    case BOTAO:
        P1IFG &= ~BOTAO;            // Fazer reset à flag de interrupção

        // Ciclo único

        // Se o display não estiver ativo, fazer os cálculos para determinar a soma vetorial
        if(!flag_display) {

            // valor em Gs de cada eixo
            gx = (eixo_x - zero_g) / escala;
            gy = (eixo_y - zero_g) / escala;
            gz = (eixo_z - zero_g) / escala;

            // soma vetoral dos eixos
            gxy = sqrt((gx*gx) + (gy*gy));
            gxyz = sqrt((gxy*gxy) + (gz*gz));
            total = gxyz - 1;

            // Conversão de inteiro para string da soma vetorial
            sprintf(total_string, "%d", total);

        }

        // Se o display estiver ativo, desligar display (ao calcar em BOTAO)
        if(flag_display) {
            // desligar display
            //P1OUT |= CAT_1 | CAT_2 | CAT_3 | CAT_4;
            P2OUT = 0;
        }

        // Ligar/desligar display
        flag_display = !flag_display;

        return;
    default:
        P1IFG = 0;                  // Caso ocorra outra interrupção em P1, limpar a flag
                                    // Provavelmente desnecessário, mas uma boa prática
        return;
    }   // switch
}   // interrupção para P1


void escolher_digito(int digito) {
  switch(digito) {
    case 1: digito_um(); break;
    case 2: digito_dois(); break;
    case 3: digito_tres(); break;
    case 4: digito_quatro(); break;
  }
}

void escolher_numero(char numero) {
  switch(numero) {
    case '1': um(); break;
    case '2': dois(); break;
    case '3': tres(); break;
    case '4': quatro(); break;
    case '5': cinco(); break;
    case '6': seis(); break;
    case '7': sete(); break;
    case '8': oito(); break;
    case '9': nove(); break;
    case '0': zero(); break;
    case ' ': vazio(); break;
  }
}

void digito_um(void) {
    P1OUT |= CAT_1 | CAT_2 | CAT_3;
    P1OUT &= ~CAT_4;
}

void digito_dois(void) {
    P1OUT |= CAT_1 | CAT_2 | CAT_4;
    P1OUT &= ~CAT_3;
}

void digito_tres(void) {
    P1OUT |= CAT_1 | CAT_3 | CAT_4;
    P1OUT &= ~CAT_2;
}

void digito_quatro(void) {
    P1OUT |= CAT_2 | CAT_3 | CAT_4;
    P1OUT &= ~CAT_1;
}

void zero(void) {
    P2OUT &= ~(SEG_G | SEG_DP);
    P2OUT |= SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F;
}

void um(void) {
    P2OUT &= ~(SEG_A | SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP);
    P2OUT |= SEG_B | SEG_C;
}

void dois(void) {
    P2OUT &= ~(SEG_C | SEG_F| SEG_DP);
    P2OUT |= SEG_A | SEG_B | SEG_D | SEG_E | SEG_G;
}

void tres(void) {
    P2OUT &= ~(SEG_E | SEG_F | SEG_DP);
    P2OUT |= SEG_A | SEG_B | SEG_C | SEG_D | SEG_G;
}

void quatro(void) {
    P2OUT &= ~(SEG_A | SEG_D | SEG_E | SEG_DP);
    P2OUT |= SEG_B | SEG_C | SEG_F | SEG_G;
}

void cinco(void) {
    P2OUT &= ~(SEG_B | SEG_E | SEG_DP);
    P2OUT |= SEG_A | SEG_C | SEG_D | SEG_F | SEG_G;
}

void seis(void) {
    P2OUT &= ~(SEG_B | SEG_DP);
    P2OUT |= SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
}

void sete(void) {
    P2OUT &= ~(SEG_D | SEG_E | SEG_F | SEG_G | SEG_DP);
    P2OUT |= SEG_A | SEG_B | SEG_C;
}

void oito(void) {
    P2OUT &= ~SEG_DP;
    P2OUT |= SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G;
}

void nove(void) {
    P2OUT &= ~(SEG_D | SEG_E | SEG_DP);
    P2OUT |= SEG_A | SEG_B | SEG_C | SEG_F | SEG_G;
}

void vazio(void) {
    P2OUT = 0;
}

void atraso(void) {
    for(i = 0; i < 0xFFF; i++) {
    }
}   // atraso

El diseño es bastante sencillo, aquí hay una foto:

Me temo que rompí el sensor de aceleración o el microcontrolador, pero también podría ser debido a que es físicamente imposible medir este tipo de aceleraciones debido al ruido no deseado de la vibración o incluso a la codificación de aficionados. ¿Es posible medir estas propiedades físicas, por ejemplo, en un lanzamiento de lanzamiento?

    
pregunta Rui Lima

1 respuesta

3

La caída de un objeto rígido sobre una superficie dura produce aceleraciones de miles a decenas de miles de Gs, y probablemente superó la clasificación de choque de 10 kG de su sensor.

Hay mejores maneras de probar y / o calibrar acelerómetros. Puede comenzar girándolo a diferentes orientaciones y asegurándose de que puede medir la gravedad en ambas direcciones en cada eje. Puede colocarlo en un plato giratorio y medir la aceleración radial a varias velocidades de rotación. O puede obtener tiempo en una "mesa vibratoria" calibrada.

    
respondido por el Dave Tweed

Lea otras preguntas en las etiquetas