O sensor incluído é um "sensor inercial de 9 Eixos", vejamos o que é isso e como usá-lo.
O sensor utilizado é o LSM9D1 da ST (datasheet), que contém acelerômetro, giroscópio e bússola (magnetômetro), cada um deles capaz de medir nas três dimensões.
O acelerômetro fornece a força que está sendo aplicada no sensor (gravidade incluída). O giroscópio informa a velocidade com que o sensor está sendo rotacionado. O magnetômetro mede a intensidade do campo magnético.
O Getting Started do arduino.cc sugere usar a biblioteca oficial para acessar o LSM9D1, o gerenciador de bibliotecas nos oferece 5 opções.
Vejamos rapidamente o que estas opções fornecem:
- Arduino: é a oficial mas é extremamente simples, retornando os valores dos sensores e não permite mudar as sensibilidades.
- Adafruit: apesar da documentar dizer que foi projetada para o módulo LSM9D1 da Adafruit, deve funcionar com o Nano 33 BLE. É ligeiramente mais completa que a biblioteca oficial.
- Melopero: além da leitura dos valores dos sensores, tem suporte a interrupção. Infelizmente no Nano 33 BLE os pinos de interrupção do LSM9D1 estão desconectados.
- SmartEverything: mais ou menos equivalente à oficial.
- Sparkfun: é a mais completa, com métodos para mudar a sensibilidade e métodos para medir e compensar o offset dos sensores.
Vamos fazer um teste rápido, enviando pela serial os valores X e Y dos sensores lidos pela biblioteca oficial:
/*
 * Teste simples do sensor inercial do Nano 33 BLE
 * Envia leitura dos sensores pela serial
 * 
 * Daniel Quadros
 */
#include <Arduino_LSM9DS1.h>
// Iniciação
void setup() {
  Serial.begin(9600);
  if (!IMU.begin()) {
    Serial.println("Falha ao iniciar a IMU!");
    while (1);
  }
}
// Laço principal
void loop() {
  float xAcc = 0.0, yAcc = 0.0, zAcc = 0.0;
  float xMag = 0.0, yMag = 0.0, zMag = 0.0;
  float xGir = 0.0, yGir = 0.0, zGir = 0.0;
  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(xAcc, yAcc, zAcc);
  }
  if (IMU.magneticFieldAvailable()) {
    IMU.readMagneticField(xMag, yMag, zMag);
  }
    
  if (IMU.gyroscopeAvailable()) {
    IMU.readGyroscope(xGir, yGir, zGir);
  }
  
  Serial.print (xMag);
  Serial.print (";");
  Serial.print (yMag);
  Serial.print (";");
  Serial.print (xAcc);
  Serial.print (";");
  Serial.print (yAcc);
  Serial.print (";");
  Serial.print (xGir);
  Serial.print (";");
  Serial.print (yGir);
  Serial.println ();
  delay(200);
}
O programa python abaixo, para ser executado em um micro, lê os valores enviados pelo Nano 33 BLE e os apresenta de forma gráfica. O programa foi testado com Python 3.6 (era o que tinha instalado no micro) e requer a instalação do pySerial. Uma dificuldade foi descobrir a escala a usar para os sensores. Os valores máximos retornados são +/-2000 graus/segundo para o giroscópio, +/-4G para a aceleração e +/-400 microTesla para o magnetômetro. O programa usa valores máximos menores para ficar mais visível os valores típicos.import tkinter
import serial
import threading
from tkinter import Canvas
from tkinter import Label
top = tkinter.Tk()
canvBussola = Canvas(top, bg = "white", height = 300, width = 300)
canvAccel = Canvas(top, bg = "white", height = 300, width = 300)
canvGiro = Canvas(top, bg = "white", height = 300, width = 300)
lblBussola = Label(top, text="Bussola")
lblAccel = Label(top, text="Acelerometro")
lblGiro = Label(top, text="Giroscopio")
canvBussola.grid(row=0, column=0)
lblBussola.grid(row=1, column=0)
canvAccel.grid(row=0, column=1)
lblAccel.grid(row=1, column=1)
canvGiro.grid(row=0, column=2)
lblGiro.grid(row=1, column=2)
canvBussola.create_line(0, 150, 300, 150, fill="blue")
canvBussola.create_line(150, 0, 150, 300, fill="blue")
canvAccel.create_line(0, 150, 300, 150, fill="blue")
canvAccel.create_line(150, 0, 150, 300, fill="blue")
canvGiro.create_line(0, 150, 300, 150, fill="blue")
canvGiro.create_line(150, 0, 150, 300, fill="blue")
def read_from_port(ser):
    global running
    ptMag = None
    ptAcc = None
    ptGir = None
    while running:
        linha = ser.readline().decode()
        partes = linha.split(";")
        if len(partes) == 6:
           xMag = (float(partes[0])+60.0)/120.0*300.0
           yMag = 300.0 - (float(partes[1])+60.0)/120.0*300.0
           xAcc = (float(partes[2])+4.0)/8.0*300.0
           yAcc = 300.0 - (float(partes[3])+4.0)/8.0*300.0
           xGir = (float(partes[4])+1000.0)/2000.0*300.0
           yGir = 300.0 - (float(partes[5])+1000.0)/2000.0*300.0
           try:
               if not (ptMag is None):
                   canvBussola.delete(ptMag)
               ptMag = canvBussola.create_oval(xMag+2, yMag+2, xMag-2, yMag-2, fill="red")
               if not (ptAcc is None):
                   canvAccel.delete(ptAcc)
               ptAcc = canvAccel.create_oval(xAcc+2, yAcc+2, xAcc-2, yAcc-2, fill="red")
               if not (ptGir is None):
                   canvGiro.delete(ptGir)
               ptGir = canvGiro.create_oval(xGir+2, yGir+2, xGir-2, yGir-2, fill="red")
           except:
               print ("Fim")
ser = serial.Serial('COM7', 9600)
thread = threading.Thread(target=read_from_port, args=(ser,))
running = True
thread.start()
top.mainloop()
running = False
Nos testes deu para observar um offset bem grande nos valores retornados pelo magnetômetro.



Nenhum comentário:
Postar um comentário