LAB - RTOS - IMU
Lab 6 |
---|
Data limite para entrega: 04/10/2023 |
Entregue o código pelo repositório do Classroom |
- Fechar issues pertinentes ao conceito atingido na entrega |
Neste laboratório iremos realizar uma comunicação I2C com um sensor inercial, e aplicar um processamento de fusão de dados para obtermos a localização no espaço do sensor.
Teoria
I2C (eye-squared-C) é um protocolo de comunicação do tipo machine-to-machine (m2m) muito utilizado para comunicação entre microcontrolador e um dispositivo (sensor ou atuador) externo, criado pela Philips Semiconductor em 1982 e liberado para uso sem licença em 2006. O i2c é uma comunicação síncrona e utiliza duas vias: serial data line (SDA) e serial clock line (SCL), a comunicação é sempre inicializada pelo Controlador (o microcontrolador) e respondida pelo Target (componente).
A imagem a seguir é um exemplo de como utilizar o i2c para conectar múltiplos dispositivos em um controlador:
Tip
Cuidado, usaremos o termo periférico não só para referenciar os componentes do microcontrolador, da placa, mas agora também novos componentes plugados no kit.
- i2c é diferenre de SPI (outro protocolo muito popular)!
Existem no mercado vários sensores que possuem comunicação i2c, no lab temos vários:
- IMU
- Câmera
- temperatura
- pressão
- batimento cardíaco
- Dê uma olhada nos sensores da adafruit i2c: https://www.adafruit.com/?q=i2c+sensor&sort=BestMatch
Protocolo
Info
Apenas uma breve apresentação, o I2C é um protocolo mais complicado do que aparenta ser:
A comunicacão i2c faz uso de dois sinais: clk e data, o clock é sempre gerado pelo controlador, diferente da UART (a de camada física, e a que usamos para o módulo bluetooth) o i2c usa um tipo de sinal chamado de open drain, que significa que o sinal na linha é sempre positivo (vcc
) e os dispositivos quando querem enviar o valor zero, apenas aterram a linha, notem que para isso é necessário um pull-up na linha.
Info
A ideia do dreno aberto é permitir que mais de um dispositivo controle a linha, como o controle é apenas aterrando o sinal, não há risco de queimar o pino.
O protocolo do I2C é mais complexo que a da UART (o de camada física, e o usado para comunicação com o módulo bluetooth), no I2C cada dispositivo possui um endereço que deve ser enviado no começo da comunicação, a cada envio de dado pelo controlador, o dispositivo responde com um sinal de ACK (um bit no final do pacote). O controlador pode executar duas tarefas diferente:
- Requisitar um dado
- Enviar um dado
As tarefas são definidas pelo último bit no pacote de endereço.
Info
O envio de dado pode ser utilizado para a configuração de um sensor, uma vez configurado, podemos requisitar dados.
Após o envio do endereço, o controlador começa enviar o pacote de dados, o envio só termina quando um STOP é enviado. A seguir uma visão geral bem simplificada da comunicação
Informações importantes:
- O i2c pode operar com pacotes de 8 ou 10 bits
- O controlador deve enviar o endereço do periférico no início da comunicação
- O controlador deve definir se irá ler ou escrever no periférico (W/R)
- Tanto na leitura quanto na escrita quem gera o clock é o controlador
- Ao final de cada pacote um ACK deve ser gerado
- Uma comunicação pode transmitir um ou mais pacotes
- O fim de uma comunicação é definido pelo STOP bit
Two-wire Interface (TWIHS)
O nosso microcontrolador possui um periférico chamado de TWIHS que implementa a comunicação i2c, notem que o periférico precisa controlar os pinos do PIO (para gerar o clock, escrever no pino, ler um valor), o diagrama extraído do manual mostra como o periférico interfaceia com o PIO:
No nosso uC possuímos um total de 3 TWIHS e cada um possui pino do PIO pré definido:
Warning
Na placa que utilizamos (SAME70-XPLD), nem todos os pinos do uC que tem acesso ao perífico TWIHS estão disponíveis. Na coluna XPLD-CONN da tabela acima está indicado quais e onde os pinos estão disponíveis.
Exercise
MPU-6050
Antes de falar do chip que vamos usar, o MPU-6050, vamos entender o que é uma IMU. Um sensor IMU(Inercial Measurement Unit ou, em português, unidade de medida de inércia), trata-se de um sensor que pode ser composto por acelerômetro, giroscópio e magnetômetro. Esses sensores fazem parte do grupo de sensores inerciais com tecnologia MEMS (Micro Electro Mechanical Systems – sistemas microeletromecânicos) que basicamente são dispositivos com a capacidade de sentir de forma direta ou indireta as forças inerciais e converte em sinal eletrico que será microprocessado. O uso da tecnologia MEMS está inserida em nosso dia-a-dia em equipamentos embarcados como celulares, tablets, carros, drones, video game, Smart Watch, biomedicina e etc.
Os acelerômetro são sensores com a capacidade de medir a acelaração linear, ou seja, capta a variação da velociade no tempo, nos eixos de translação, coordenadas X,Y e Z.
O sensor giroscópio consegue medir a velocidade angular em torno dos eixos X, Y e Z.
Já o sensor magnetômetro é capaz de medir o sentido e a intensidade de campos magnéticos.
Uma IMU com acelerômetro e giroscópio possui 6 eixos DOF (Degrees of Freedom – graus de liberdade) e uma IMU com acelerômetro, giroscópio e magnetometro possui 9 DOF.
O MPU-6050 é uma IMU do tipo MEMS com 6DOF, realiza medições independentes com precisão de 16bits (ADC) por canal e prcessadas no proprio chip na DMP (Digital Motion Processor) responsável por e comunicação com protocolo I2C. A faixa do Acelerômetro é ±2, ±4, ±8, ±16g e a faixa do giroscópio é ±250, 500, 1000, 2000°/s;
Exercise
Exercise
Módulo GY-521
Para termos acesso ao MPU6050
iremos usar um módulo GY-521, no Brasil é possível achar por R$25. Um módulo com maior qualidade pode ser comprado e importado pela sparkfun:
"Our breakout board for the MPU-6050 makes this tiny QFN package easy to work into your project. Every pin you need to get up and running is broken out to 0.1" headers, including the auxiliary master I2C bus which allows the MPU-6050 to access external magnetometers and other sensors."
Exercise
LAB
Agora que já vimos um pouco sobre o I2C e sobre o chip que iremos interagir, podemos começar o lab.
task_imu
Vamos criar uma task
para realizar a leitura da IMU.
Exercise
TWIHS
Para fazermos uso periférico TWIHS será necessário adicionarmos ele no asf wizard:
Exercise
Com a biblioteca adicionada agora devemos criar uma função para configurar o periférico:
- Ativar o clock do PMC
- Operar como controlador
- Definir a frequência de operação
- Permitir que o TWIHS controle os pinos do PIO
Exercise
Exercise
Exercise
Biblioteca MCU6050
Para facilitar o controle da IMU iremos importar um arquivo mcu6050.h
que possui dados extraídos do manual e que irá facilitar o acesso ao sensor:
Exercise
Funções auxiliares
Iremos declarar duas funções que irão facilitar a escrita e leitura do I2C:
int8_t mcu6050_i2c_bus_write(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t cnt)
int8_t mcu6050_i2c_bus_read(uint8_t dev_addr, uint8_t reg_addr, uint8_t *reg_data, uint8_t cnt)
Onde:
dev_addr
: Endereço do dispositivo que pretendemos manipularreg_addr
: Endereço do registrador que pretendemos escrever/lerreg_data
: Vetor com os valores que serão escritos/lidoscnt
: Quantidade de dados que serão escritos/lidos
Exercise
Para usar as funções será necessário utilizarmos dois buffers (um para recebimento e outro para envio de dados) além de uma variável para armazenarmos o valor do retorno da função, que informa se o comando no i2c foi bem sucedido ou não.
Exercise
Probe
Uma das formas de verificarmos se o sensor está conectado corretamente e se o básico do I2C funciona é realizarmos uma "verificaćão" na linha e verificar se o periférico responde com um ACK a um acesso. Isso é chamado de probe.
Exercise
Lendo ID sensor
A maioria dos módulos que operam por algum tipo de comunicação (uart, i2c, spi) possuem um registrador que tem um ID único que referencia o módulo, a ideia deste registrador é a de:
- Confirmar que a comunicação i2c está funcionando e que consegue ler do periférico
- Garantir que o controlador está acessando o periférico certo
Para facilitar a nossa vida, importamos o arquivo mcu6050.h
no nosso projeto, se derem uma olhada nele vão encontrar as seguintes informações:
#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board
#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW
...
#define MPU6050_RA_WHO_AM_I 0x75
Com isso conseguirmos usar a função que realiza uma leitura no I2C (mcu6050_i2c_bus_read
) e validar a comunicação.
Exercise
Vamos analisar os parâmetros do comando anterior:
MPU6050_DEFAULT_ADDRESS
: Endereço do IMU no i2cMPU6050_RA_WHO_AM_I
: Endereço do registradorWHO_AM_I
bufferRX
: Buffer para armazenar o resultado da leitura1
: Quantidade de bytes a serem lido no I2C
Exercise
Com a leitura realizada, agora temos que analisar o conteúdo do buffer RX e verificar se estamos lendo a coisa certa.
Exercise
Configurando IMU e lendo informações
Agora temos que configurar a IMU para fornecer as informações necessárias: Giroscópio e Acelerômetro, isso tudo está na documentação do sensor.
O código configura o acelerômetro para operar com escala máxima de 2G (o que é ok para nossa aplicação, mas se estivessem desenvolvendo alguma aplicação para uma montanha russa, um carro ou um míssil poderia não funcionar.), mas também poderiamos escolher entre: ± 2G, ± 4G, ± 8G e ± 16G
.
Tip
Ler a documentação pode ser muito difícil e trabalhoso, uma outra opção é a de ver como outras pessoas usam o sensor, e uma boa referencia são códigos de arduino ou bibliotecas de fabricantes de placa de desenvolvimento.
Exercise
Exercise
Agora com tudo configurado podemos fazer a leitura do sensor (acelerômetro e imu):
Exercise
Exercise
Exercise
Exercise
Entrega parte 1
Exercise
Fusão de dados
Legal, teoricamente agora temos tudo pronto e funcionado. Mas como usar esses dados para fazer alguma coisa útil? Conseguimos estimar a orientação da placa no espaço? Para isso existem algorítimos de processamento de sinais, isso foi uma área muito fértil em meados de 2010, quando este tipo de sensor se popularizou, e agora tem ganhado mais estudos sendo utilizado com redes neurais.
Agora vamos fazer algo mais valioso, que inclui realizarmos uma fusão de dados e obter a orientação no espaço 3D do acelerômetro, para isso iremos utilizar uma biblioteca em C desenvolvida pela https://x-io.co.uk/ chamada de FUSION:
A biblioteca implementa o filtro de orientação chamado Madgwick, notem que a nossa IMU não possui magnetômetro, isso atrapalha um pouco a correção do giroscópio que possui drift no tempo.
Tip
Existem diversos algoritmos diferentes que fazem isso, se quiserem se aprofundar eu indico a eletiva de Drones do Fábio Bobrow que trabalha mais a fundo com isso.
Exercise
Exercise
Agora que já temos a biblioteca no nosso projeto, temos que preparar o dados para utilizarmos nela.
Exercise
Exercise
Exercise
Trabalhando com os dados - parte 2
Vamos detectar para onde o sistema está apontando, a ideia é acender os LEDs da placa OLED da seguinte maneira:
Exercise
Info
Até aqui é C
B - IRQ
Warning
TBD
A - RTT
Warning
TBD