Funcionamento do Acelerômetro MMA7361 com a IDE Processing

Ola galera!!!!!!!!!

https://www.youtube.com/watch?v=ePW57SFFOks&feature=youtu.be

Estou agora demonstrando o funcionamento do Acelerômetro MMA7361.

Confesso que eu tive muita dificaldade em trabalhar com este cara.

Na internet só falava de outros acelerômetros mas eu achei esse componenete muito bom.

Achei uns códigos e fucei bastante e coloquei o bicho pra funcionar. 'ALELUIA IRMÃO!!!!!!!!!!!!'

Ai está a foto do cara:

Aqui está a especificação dos pinos:

Ao montar o circuito, repare que será necessário ligar o pino 3.3 Volts do Arduino Uno R3 ao pino AREF, para que tenhamos uma tensão de referência. Sem ele, a leitura dos dados fica totalmente prejudicada:

Se possível, recomendo a ligação fora da protoboard ou então a utilização de um mini protoboard, como mostrado no circuito, isso vai facilitar bastante na hora de testar os movimentos com o módulo.

Para teste vou usar um dos 3 programas exemplo que vem na própria biblioteca do MMA7361, o programa G_FORCE. Carregue o programa no Arduino, movimente o sensor e veja no serial monitor como se comportam as variações dos eixos X, Y, Z, e a gravidade (G).

Observando que um acelerômetro sobre a superfície terrestre está submetido à aceleração da gravidade, 1g ou -9,81g no eixo Z quando não está submetido a nenhum a inclinação ou aceleração linear, pode-se estimar a leitura do celerômetro.

Existem várias formulas matemáticas para demostrar o funcionamento do acelerômetro mas só vou apresentar as que eu usei no código se não vai ficar muito extenso o papo.

Eu estou usando o fator de correção PITCH e ROLL.

O fator multiplicativo converte os ângulos de graus para radianos é de PI/180°.

Obtidos os ângulos de rotação, os vetores de estimação (Vert, H1 e H2) são atualizados por meio da aplicação da função “rotate3D”, que aplica nestes vetores uma matriz de rotação tridimensional em torno do eixo X T e do eixo Y T, denotada por Mxy.

Neste ponto, o algoritmo já calculou uma estimação vetorial da orientação do sistema, que pode ser exibida graficamente em um computador ou em uma tela de cristal líquido acoplada ao sistema. Para se fazer uso de atuadores mecânicos (no caso deste trabalho, servomotores), porém, é necessário calcular o valor numérico dos ângulos pitch e roll.

    //Roll & Pitch equacoes para posicionamento espacial
    roll  = (atan2(-fYg, fZg)*180.0)/M_PI;
    pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg))*180.0)/M_PI;

Abaixo vocês podem observa o código usado no Arduino:

#include <AcceleroMMA7361.h>

AcceleroMMA7361 accelero;

double fXg = 0;
double fYg = 0;
double fZg = 0;

const float alpha = 0.3;

void setup()
{
  Serial.begin(9600);
 //              SL  ST  0G  GS   X   Y   Z
  accelero.begin(13, 12, 11, 10, A0, A1, A2);
  accelero.setARefVoltage(3.3);                   //Voltagem de referencia 3,3 Volts
  accelero.setSensitivity(LOW);                   //Setando a sensibilidade para +/-6G
  accelero.calibrate();
}

void loop()
{
    double pitch;
    double roll;
    double Xg;
    double Yg;
    double Zg;
        
        
    Xg = accelero.getXAccel();
    Yg = accelero.getYAccel();
    Zg = accelero.getZAccel();

    //Filtro
    fXg = Xg * alpha + (fXg * (1.2 - alpha));
    fYg = Yg * alpha + (fYg * (1.2 - alpha));
    fZg = Zg * alpha + (fZg * (1.2 - alpha));

    //Roll & Pitch equacoes para posicionamento espacial
    roll  = (atan2(-fYg, fZg)*180.0)/M_PI;
    pitch = (atan2(fXg, sqrt(fYg*fYg + fZg*fZg))*180.0)/M_PI;

    Serial.print(pitch);
    Serial.print(":");
    Serial.println(roll);

    delay(10);
}

O código no Processing vocês vem abaixo:

import processing.serial.*;

Serial fd;

int pitch = 0;
int roll = 0;

void setup ()
{
  size(640, 360, P3D);
  //Conexao com a porta
  fd = new Serial(this, "/dev/ttyUSB0", 9600);
  fd.bufferUntil('\n');
 
  noStroke();
  colorMode(RGB, 1);
}

void draw ()
{
  //Set background
  background(0);

  pushMatrix();
 
  translate(width/2, height/2, -30);

  //Roatcao
  rotateX(((float)roll ) * PI / 180);
  rotateZ(((float)pitch) * PI / 180);
 
  print("Pitch: ");
  print(pitch);
  print(", Roll: ");
  println(roll);
 
  scale(90);
  beginShape(QUADS);

  fill(0, 1, 1); vertex(-1,  1,  1);
  fill(1, 1, 1); vertex( 1,  1,  1);
  fill(1, 0, 1); vertex( 1, -1,  1);
  fill(0, 0, 1); vertex(-1, -1,  1);

  fill(1, 1, 1); vertex( 1,  1,  1);
  fill(1, 1, 0); vertex( 1,  1, -1);
  fill(1, 0, 0); vertex( 1, -1, -1);
  fill(1, 0, 1); vertex( 1, -1,  1);

  fill(1, 1, 0); vertex( 1,  1, -1);
  fill(0, 1, 0); vertex(-1,  1, -1);
  fill(0, 0, 0); vertex(-1, -1, -1);
  fill(1, 0, 0); vertex( 1, -1, -1);

  fill(0, 1, 0); vertex(-1,  1, -1);
  fill(0, 1, 1); vertex(-1,  1,  1);
  fill(0, 0, 1); vertex(-1, -1,  1);
  fill(0, 0, 0); vertex(-1, -1, -1);

  fill(0, 1, 0); vertex(-1,  1, -1);
  fill(1, 1, 0); vertex( 1,  1, -1);
  fill(1, 1, 1); vertex( 1,  1,  1);
  fill(0, 1, 1); vertex(-1,  1,  1);

  fill(0, 0, 0); vertex(-1, -1, -1);
  fill(1, 0, 0); vertex( 1, -1, -1);
  fill(1, 0, 1); vertex( 1, -1,  1);
  fill(0, 0, 1); vertex(-1, -1,  1);


  endShape();

  popMatrix();
}

// Interrupcao serial
void serialEvent (Serial fd)
{
 
  String rpstr = null;
 
  try {
    rpstr = fd.readStringUntil(10);

    if (rpstr != null) {
      String[] list = split(rpstr, ':');
     
      
        pitch = ((int)float(list[0]));
        roll =  ((int)float(list[1]));
    }
 
  } catch( ArrayIndexOutOfBoundsException e ) {
    print("Erro!!!!!!\n");
  }
}

Podem copiar e colar sem dó. Está funcionando perfeitamente.

Exibições: 2360

Comentar

Você precisa ser um membro de Laboratorio de Garagem (arduino, eletrônica, robotica, hacking) para adicionar comentários!

Entrar em Laboratorio de Garagem (arduino, eletrônica, robotica, hacking)

Comentário de Francisco Lucena Gomes Jr em 12 fevereiro 2016 às 18:58

Ola Christiano. Fiz uns testes, mas sem muito progresso. Os valores lidos ficaram em torno de 500 para os eixos que estavam na horizontal e 600 para o que estava na vertical. Então, eu dividi por 100 e subtrai 5. Os valores ficaram próximos de 1, mas ainda assim valores meio malucos. As vezes chegava quase a 2. Será que tem alguma coisa a ver com a rotação? Vc poderia me dar uma explicação sobre as variáveis alpha, pitch e roll?

Comentário de Francisco Lucena Gomes Jr em 10 fevereiro 2016 às 14:17

Há, agora entendi. Então, baseado nos números que vc me forneceu, conclui-se que, g é inversamente proporcional a tensão lida no AD. Quando g aumenta a tensão cai. É o contrário do que eu estava pensando. Vou fazer uns testes pra ver. Obrigado pela dica.

Comentário de Christiano Reis em 10 fevereiro 2016 às 11:15

AD é o pino de leitura analógica do Arduino(A0, A1, A2...). AD( Analógico para Digital).

Comentário de Francisco Lucena Gomes Jr em 10 fevereiro 2016 às 9:11

Agora complicou. Esse "AD" pra mim é grego. Será que vc teria alguma literatura pra me indicar pra eu me aprofundar mais nesse assunto?

Comentário de Christiano Reis em 9 fevereiro 2016 às 23:35

Esses valores são referências. Quando ele está no 0G está só lendo o AD do Arduino e está com o valor 660.

Exemplificando. Quando o AD está lendo um valor 660 no eixo X, a gravidade está exercendo neste eixo 0G de força gravitacional.

Comentário de Francisco Lucena Gomes Jr em 9 fevereiro 2016 às 19:02

Eu estava pensando que era assim:

Como este acelerômetro mede de -3g a +3g

0 Volts (leitura 0) => -3g

3,3 Volts (leitura 1023) => 3g

Mas não funcionou. Estou achando que é defeito do acelerômettro,

De qualquer forma, de onde vc tirou esses valores? Por exemplo:

X Axis:

-1G = 754

0G = 660

1G = 567

Comentário de Christiano Reis em 9 fevereiro 2016 às 18:09

Você deve transformar este valor de leitura que a porta analógica ler (que vai de 0 a 1023), para a força G que é 1. Um, é a leitura para em que a força da gravidade da terra exerce para um determinado eixo do seu acelerômetro.

Primeiro você fará a leitura do acelerômetro normalmente.

sv1 = analogRead(0);

sv2 = analogRead(1);

sv3 = analogRead(2);

Depois você irá comparar os valores:

Z Axis:
-1G = 750
0G = 660
1G = 565

X Axis:

-1G = 754

0G = 660

1G = 567

Y Axis:

-1G = 770

0G = 677

1G = 588

Pegando a tensão de referência que você usa:

VoltsRx = sv1 * 3.3V / 1023 =~ 1.89V
VoltsRy = sv2 * 3.3V / 1023 =~ 2.03V
VoltsRz = sv3 * 3.3V / 1023 =~ 1.81V

Agora pegamos a voltagem do 0(Zero Gravitacional) ou delta volts:

DeltaVoltsRx = VoltsRx – 1.65V = 0.24V
DeltaVoltsRy = VoltsRy – 1.65V = 0.38V
DeltaVoltsRz = VoltsRz – 1.65V = 0.16V

Agora aqui você precisa saber a sensibilidade do seu acelerômetro para fazer está parte:

Rx = DeltaVoltsRx / Sensibilidade do acelerômetro

Rx = 0.24V / 0.4785V/g =~ 0.5g
Ry = 0.38V / 0.4785V/g =~ 0.79g
Rz = 0.16V / 0.4785V/g =~ 0.33g

Ai está sua força G.

Lembre-se de fazer um algorítimo para calibragem do seu acelerômetro quando for ligar seu arduino.

Eu não conheço este modelo, mas o velho Google sabe.

Comentário de Francisco Lucena Gomes Jr em 9 fevereiro 2016 às 15:00

Christiano,  no ADLX 335 não tem nenhuma libe, eu pego a leitura dele direto nas entradas analógicas:

sv1 = analogRead(0);
delay(2);
sv2 = analogRead(1);
delay(2);
sv3 = analogRead(2);

No 435 tem uma libe SPI.h, mas eu acho que é pra comunicação I²C. Eu baixei um sketch do site da spakfun, mas não funcionou. Também ficou apresentando números malucos.

Comentário de José Gustavo Abreu Murta em 6 fevereiro 2016 às 8:23

Libe ? = Library (Biblioteca)

Comentário de Christiano Reis em 6 fevereiro 2016 às 3:26

A libe do meu acelerômetro é está: AcceleroMMA7361.h (arquivo header)

Ai eu coloco:

#include <AcceleroMMA7361.h>

Ai você terá que abrir o do seu acelerômetro e ver qual a função que retorna o valor da força g

No meu caso são estes:

accelero.getXAccel();
accelero.getYAccel();
accelero.getZAccel();

Cada um retorna o valor que a gravidade está influenciando sobre os três eixos.

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço