collapse

* Posts Recentes

Amplificador - Rockboard HA 1 In-Ear por almamater
[Ontem às 19:13]


O que é isto ? por KammutierSpule
[26 de Março de 2024, 19:35]


Bateria - Portátil por almamater
[25 de Março de 2024, 22:14]


Emulador NES em ESP32 por dropes
[13 de Março de 2024, 21:19]


Escolher Osciloscópio por jm_araujo
[06 de Fevereiro de 2024, 23:07]


TP4056 - Dúvida por dropes
[31 de Janeiro de 2024, 14:13]


Leitura de dados por Porta Serie por jm_araujo
[22 de Janeiro de 2024, 14:00]


Distancia Cabo por jm_araujo
[08 de Janeiro de 2024, 16:30]


Meu novo robô por josecarlos
[06 de Janeiro de 2024, 16:46]


Laser Engraver - Alguém tem? por almamater
[16 de Dezembro de 2023, 14:23]

Autor Tópico: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro  (Lida 8935 vezes)

0 Membros e 1 Visitante estão a ver este tópico.

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Olás.

Estou aqui com um pequeno problema de entendimento com o acelerometro.

Muito provavelmente não devo ter começado com o melhor dos integrados para uma "primeira vez"... mas "a cavalo dado...".

Na internet o geral dos problemas que vejo é malta que não consegue ligar o módulo ou que está com problemas na comunicação, etc...
No meu caso, esta parte foi ultrapassada e deixo em baixo uns pequenos excertos do código.

A comunicação foi ultrapassada, a inicialização também e a leitura dos registos com os dados também.
O meu problema (e parece que mais ninguém tem esse problema porque não encontro muita informação sobre isso) é o que fazer com os valores que recebo, até chegar à aceleração em m/s^2.

Estou a tentar fazer trabalhar um eixo apenas (neste caso o X) e quando lhe mexo há alteração dos valores recebidos.

As curiosidades são:
* só tenho variação dos valores quando empurro na direcção do eixo e não ao contrário.
* essa variação faz-se quase sempre pela alteração de 2 valores, ou seja, recebo 2 bytes (High and Low) com 192 e quando empurro recebo 2 bytes a 0.
* segundo o datasheet, "X-axis acceleration data. The value is expressed in 2’s complement.", mas não vi nenhum exemplo de código onde realmente tenham feito o complemento do valor recebido.

A pergunta é, quais os passos a seguir para conseguir obter um valor válido de aceleração?

O código em baixo não está muito aprimorado, pois foi feito só mesmo para tentar obter alguns valores de teste.

Alguns #defines
Código: [Seleccione]
#define write_LSM303_MAG    0x3C 
#define write_LSM303_ACC    0x32
#define read_LSM303_MAG     0x3D 
#define read_LSM303_ACC     0x33

/* Registers */
#define CTRL_REG1_A     0x20
#define CTRL_REG4_A     0x23
#define CRA_REG_M       0x00      //temperatura e rate data out
#define CRB_REG_M       0x01
#define MR_REG_M        0x02
#define OUT_X_H_M       0x03
#define OUT_X_L_A       0x28
#define TEMP_OUT_H_M    0x31

Inicialização do LSM303
Código: [Seleccione]
void init_LSM303(void)
{
    Start_I2C();
    Write_I2C(write_LSM303_ACC);
    Write_I2C(CTRL_REG1_A);
    Write_I2C(0x27);
    Stop_I2C();

    Start_I2C();
    Write_I2C(write_LSM303_ACC);
    Write_I2C(CTRL_REG4_A);
    Write_I2C(0x40);
    Stop_I2C();

    Start_I2C();
    Write_I2C(write_LSM303_MAG);
    Write_I2C(CRA_REG_M);
    Write_I2C(0x14);
    Stop_I2C();

   
    Start_I2C();
    Write_I2C(write_LSM303_MAG);
    Write_I2C(CRB_REG_M);
    Write_I2C(0b01100000);
    Stop_I2C();

    Start_I2C();
    Write_I2C(write_LSM303_MAG);
    Write_I2C(MR_REG_M);
    Write_I2C(0x00);
    Stop_I2C();
}

Pedido de valores
Código: [Seleccione]
unsigned char M[6];
signed int X;

... ... ...

Open_I2C(MASTER, SLEW_OFF);
init_LSM303();

... ... ...

Start_I2C();
Write_I2C(write_LSM303_ACC);
Write_I2C(OUT_X_L_A);
Restart_I2C();

Write_I2C(read_LSM303_ACC);

M[0] = Read_I2C();
Ack_I2C();
M[1] = Read_I2C();
Ack_I2C();
M[2] = Read_I2C();
Ack_I2C();
M[3] = Read_I2C();
Ack_I2C();
M[4] = Read_I2C();
Ack_I2C();
M[5] = Read_I2C();

NotAck_I2C();
Stop_I2C();

X = (M[0]<<8) + M[1];



« Última modificação: 25 de Junho de 2014, 14:39 por Dave »
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #1 em: 25 de Junho de 2014, 15:05 »
De quantos bits é que são os dados? 12, 13bit?
O facto dos dados de saida estarem representados em complemento para dois significa que tens um numero inteiro com sinal em que o bit mais significativo é 1 se for um numero negativo e 0 caso contrario. Como os dados têm 12 (ou 13 bit, confirma na datasheet) e as variaveis que usas no código C têm 16 ou 32 bit (numero suficiente de bits para guardares os dados do acelerometro), e para continuar a ser um número negativo tens de fazer extensão de sinal.
Este é o unico "truque" que precisas para obter valores correctos.

Em relação a converteres para m/s² tens de ver qual a escala que estás a usar (+-2g? 4g?) e fazeres uma regra de três simples para saberes a que corresponde o valor que lês do acelerómetro (valor máximo lido 2^12-1, caso os dados sejam de 12bit, confirma, corresponde à escala usada, 2g por exemplo)

http://en.wikipedia.org/wiki/Two%27s_complement
http://en.wikipedia.org/wiki/Sign_extension
http://en.wikipedia.org/wiki/Gravity_of_Earth

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.733
  • Helpdesk do sitio
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #2 em: 25 de Junho de 2014, 15:28 »
É só atirar-lhe com a biblioteca da adafruit para cima.
Dada a audiência do arduino, 99% dos problemas é não meterem pull ups nas linhas do i2c..
https://github.com/adafruit/Adafruit_LSM303
Avr fanboy

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #3 em: 25 de Junho de 2014, 15:41 »
Segundo o datasheet a saída é de 16bits - "? 16 bit data output".

No entanto também está escrito que para o ganho com FS a 00, corresponde 1mg/LSB, por isso para os +-2g dá 12 bits...

Vou dar uma vista de olhos pela biblioteca da adafruit e ver o que difere do que eu tenho na minha.




Qualquer dia ainda perco a cabeça e compro um arduino eheh  ;D
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #4 em: 25 de Junho de 2014, 16:04 »
Na biblioteca da adafruits, ele também nada fazem com o complemento para 2...

Ou seja, o valor tem de ser analisado depois para saber se deve ou não fazer o complemento.


Código: [Seleccione]
uint8_t xlo = Wire.read();
  uint8_t xhi = Wire.read();
  uint8_t ylo = Wire.read();
  uint8_t yhi = Wire.read();
  uint8_t zlo = Wire.read();
  uint8_t zhi = Wire.read();

  // Shift values to create properly formed integer (low byte first)
  accelData.x = (xlo | (xhi << 8)) >> 4;
  accelData.y = (ylo | (yhi << 8)) >> 4;
  accelData.z = (zlo | (zhi << 8)) >> 4;
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline msr

  • Mini Robot
  • *
  • Mensagens: 798
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #5 em: 25 de Junho de 2014, 16:53 »
Há uns tempos fiz um driver para este chip, vê lá se ajuda:

Código: [Seleccione]
void LSM303DLHC_readOutputs(uint8_t sel, int16_t *x, int16_t *y, int16_t *z)
{
  uint8_t *msb, *lsb, v1, v2;
  uint8_t sad, sad_w, sad_r, sub;
 
  if(x == 0 || y == 0 || z == 0)
    return;
 
  if(sel == LSM303DLHC_ACC) {
    msb = &v2;
    lsb = &v1;
    sub = LSM303DLHC_OUT_X_L_A;
  }
  else if(sel == LSM303DLHC_MAG) {
    msb = &v1;
    lsb = &v2;
    sub = LSM303DLHC_OUT_X_H_M;
  }
  else
    return;
   
  sad = sel;
  sad_w = (sad << 1) & 0xFE;
  sad_r = (sad << 1) | 0x01;
 
  hal_i2c_start();
  hal_i2c_write(sad_w);
  hal_i2c_idle(); // SAK
  hal_i2c_write(sub | 0x80); // SUB, read multiple bytes
  hal_i2c_idle(); // SAK
  hal_i2c_restart();
  hal_i2c_write(sad_r);
  hal_i2c_idle(); // SAK
  v1 = hal_i2c_read(); // Read X Acc (X Mag)
  hal_i2c_ack();
  v2 = hal_i2c_read();
  hal_i2c_ack();
  *x = (*msb << 8) | *lsb;
  v1 = hal_i2c_read(); // Read Y Acc (Z Mag)
  hal_i2c_ack();
  v2 = hal_i2c_read();
  hal_i2c_ack();
  if(sel == LSM303DLHC_ACC)
    *y = (*msb << 8) | *lsb;
  else
    *z = (*msb << 8) | *lsb;
  v1 = hal_i2c_read(); // Read Z Acc (Y Mag)
  hal_i2c_ack();
  v2 = hal_i2c_read();
  hal_i2c_nack();
  if(sel == LSM303DLHC_ACC)
    *z = (*msb << 8) | *lsb;
  else
    *y = (*msb << 8) | *lsb;
  hal_i2c_stop();
}

edit: como os dados de saída sao de 16bit não precisas de fazer extensão de sinal caso uses variaveis do tipo int16_t
« Última modificação: 25 de Junho de 2014, 17:24 por msr »

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #6 em: 27 de Junho de 2014, 15:51 »
Olá.

Estive fora estes dias e cheguei hoje.

Em relação ao código que apresentas, msr, é precisamente o que estou a fazer.
*
* faço start i2c
* escrevo para o ACC
* indico o endereço de leitura
* faço restart i2c
* coloco o ACC para leitura
* vou ler os 6 bytes seguidos do eixo X, Y, Z, sempre com ACK entre leituras
* faço NACK
* stop i2c
* e por fim : X = (M[0] | (M[1] << 8 ));

O problema é que X varia, quando lhe mexo, de 64524 e 0....

 ???

David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #7 em: 27 de Junho de 2014, 16:09 »
ahahahaha

Já descobri o meu erro!

Estava a fazer múltipla leitura, mas não tinha colocado o MSB a "1", o que fazia com que apenas fizesse uma leitura...

Write_I2C(OUT_X_L_A | 0x80);

Agora já tenho muitos valores eheheheh


Vamos manter este tópico em aberto, porque acho que mais dúvidas irão surgir :)


Obrigado.
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #8 em: 30 de Junho de 2014, 10:23 »
Olá novamente.

Estou a ter alguma dificuldade em perceber se devo ou não fazer algum tipo de calibração/ajuste ao acelerometro, pois estou a receber os dados em baixo (para o eixo X, OUT_X_L_A/OUT_X_H_A) sem qualquer tipo de vibração.

Tenho lido que é feita uma calibração para o magnetometro mas nada encontro para o acelerometro...



Há sem dúvida algo enorme que me continua a escapar.... o datasheet do IC parece-me algo muito mal explicado.
Já pensei se até não haverá um documento para toda a "familia" LSM303, mas nada encontro também no site da ST...

Alguma sugestão?
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline jm_araujo

  • Mini Robot
  • *
  • Mensagens: 2.947
  • NERD!
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #9 em: 30 de Junho de 2014, 10:28 »
Força da gravidade?

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #10 em: 30 de Junho de 2014, 10:44 »
Isto é o que é mostrado quando oponho o eixo X à gravidade, ou seja, quando coloco a pastilha na vertical.

No geral aparece "16xxx", ao contrário dos "00xxx" da imagem anterior. Posso supor que aquele "1" será de 1g...
Se virar a placa no sentido contrário e colocar a favor do eixo, tenho as mesmas medições, mas com sinal negativo.



Mas, segundo o datasheet, eu deveria medir 0.001g por cada 1LSB, ou seja, com 1g, eu deveria medir 1000. Certo?
Mas eu estou a ter medidas significativas das dezenas de milhar.

David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline jm_araujo

  • Mini Robot
  • *
  • Mensagens: 2.947
  • NERD!
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #11 em: 30 de Junho de 2014, 11:29 »
Lido assim por alto, entendi que os valor do FS defíne o valor "full scale".
Com FS a 00, full scale são 2g.
Em 16 bits signed, a fullscale de [32767, -32768] equivale a [+2g,-2g]
Fazendo um 3 simples com o valor mais usual quando estavas na vertical (16128):
aceleração=2g/32767*16128=0.984g , está lá perto, a diferença para 1g pode ser da precisão do alinhamento.

Agora reparei que os teus valores "saltam" em passos de 256 (-512,-768,-1024), o que quer dizer que não estás a receber os 8 bits LSB, ou vem a zero (talvez por causa do HR do CTRL_REG4_A??? não sei, a datasheet é pouco clara do que faz)

edit:
Mesmo sem o HR, devias estar a receber 10 bits de resolução (granularidade 2^(16-10)=64: saltar 64 entre medidas), mas estas a saltar 256. Estar a perder o byte LSB na leitura.

Tirado desta informação: http://www.pololu.com/product/1268
Citar
The gyro, accelerometer, and magnetometer all output readings in a 16-bit format (obtained by combining the values in two 8-bit registers for each axis), but only the gyro readings contain 16 bits of precision. The accelerometer and magnetometer readings contain a maximum of 12 bits of precision; for the accelerometer, at least the lowest 4 bits of the output values are always 0, and for the magnetometer, the highest 4 bits of the output values are always 0.
The accelerometer gives low-resolution 10-bit readings by default (the lowest 6 bits of the output are always 0). To get the full 12-bit resolution, you must set the HR (high resolution) bit in the CTRL_REG4_A register.
« Última modificação: 30 de Junho de 2014, 11:43 por jm_araujo »

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #12 em: 30 de Junho de 2014, 12:01 »
Ah... muito bem visto!

É daquelas coisas que, ler até li, mas não entendi muito bem o que queriam dizer com aquilo...
Mas poderá estar aí a justificação para que o meu byte menos significativo venha a zeros...

Outra coisa interessante que estive aqui a ver é que olhando para a resolução (1mg/LSB), +-2g ocupam 12bits (4g->4000). Se pensar (imaginar) que os bits vêm alinhados à esquerda e fizer 4 deslocamentos à direita (16bits-12bits = 4), talvez obtenha um valor mais próximo.

Fiz este exercício para +-2g e obtive leituras de 1008 (16128>>4 = 1008). Ora fazendo para +-4g, eu teria de obter metade desse valor (perto de 500). Fiz as leituras e obtive 8192, que deslocado 4 vezes para a direita dá os tais 512, perto do valor 500 como era previsível.

O que acham?
O datasheet é muito vago infelizmente....

Vou agora alterar o bit do HR.... sem dúvida muito bem observado jm_araujo ;).
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline Dave

  • Mini Robot
  • *
  • Mensagens: 368
    • "O Engenhocas"
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #13 em: 30 de Junho de 2014, 12:15 »
Aparentemente não tenho alterações no CTRL_REG4_A, a escrever 0x88.
Deveria "activar" o HR, mas continuo com a mesma "escala de saltos".
David Martins
Eng. Electrotécnica e de Computadores, UBI

Offline senso

  • Global Moderator
  • Mini Robot
  • *****
  • Mensagens: 9.733
  • Helpdesk do sitio
Re: LSM303DLHC - os problemas de uma "primeira vez" - acelerometro
« Responder #14 em: 30 de Junho de 2014, 12:19 »
Acho extremamente estranho que não tenhas um byte inteiro de dados, ou estás a fazer algo errado na comunicação, ou estás a deitar o byte fora quando fazes a junção dos valores.
Avr fanboy