Cette page présente une démonstration du Capteur à effet Hall Allegro A31301. Cette démonstration est basée sur une ESP32 connectée au capteur. Les données brutes sont lues depuis le capteur et envoyées sur l'UART. De l'autre côté de l'UART, un script Python récupère les données et les affiche à l'écran. Un des grands avantages du capteur A31301 est que son adresse I²C est configurable (16 avec des résistances externes et 127 par programmation).
La démonstration a été faite sur une breadboard avec une ESP32 Firebettle 2 et une petite carte d'interface maison pour le A31301.
Voici comment le A31301 a été câblé sur l'ESP32 :
Tout d'abord, le A31301 doit être alimenté. Comme le capteur est à faible consommation et alimenté en 3,3V, il peut être connecté au régulateur de l'ESP32 sans aucun problème. Le A31301 possède des interfaces SPI et I²C. Comme j'aimerais utiliser plusieurs capteurs, I²C est le protocole le mieux adapté. Pour cette démo, j'ai connecté les broches SA0 et SA1 à la masse pour définir l'adresse I²C 96 (0x60).
Le code source de l'ESP32 peut être téléchargé au bas de cette page. Notez qu'il devrait également fonctionner pour de nombreuses autres cartes compatibles Arduino.
Nous nous concentrerons ici sur les fonctions principales. Tout d'abord, la fonction setup()
initialise la communication série et l'interface I²C :
void setup() {
// Initialize serial communication
Serial.begin(115200);
while (!Serial);
// I²C initialization
Wire.begin();
}
Dans la fonction loop()
, nous lisons en continu la magnitude des 3 axes et l'envoyons sur le port série.
void loop() {
// Send data on serial
Serial.print(getX(I2C_A31301_ADDRESS));
Serial.print(",");
Serial.print(getY(I2C_A31301_ADDRESS));
Serial.print(",");
Serial.println(getZ(I2C_A31301_ADDRESS));
// 10ms => 100Hz frame rate
delay(10);
}
La boucle principale appelle les fonctions getX()
, getY()
et getZ()
. Cette fonction lit les données des registres internes du capteur.
Notez qu'il s'agit d'un registre de 15 bits, donc le bit 15 qui représente le signe doit être copié dans le MSB (bit 16).
int16_t getX(byte address) {
// Read MSB and LSB for X-axis
uint8_t msb = Request_info(address, REGISTER_MSB_X);
uint8_t lsb = Request_info(address, REGISTER_LSB_X);
// Merge MSB and LSB on 15 bits
int16_t combined = ((msb & 0x7F) << 8) | lsb;
// Check the 15th bit to duplicate the sign on the 16 bit (0=positive / 1=negative)
if (combined & 0x4000) combined |= 0x8000;
return combined;
}
Enfin, la fonction Request()
crée la trame I²C envoyée à l'appareil.
Elle écrit l'adresse du registre à lire et récupère ensuite la valeur du registre.
uint8_t Request_info(uint8_t address, uint8_t registerAddress) {
// Configure the I²C write/read
// 1. Write the register address
// 2. Read the register content
Wire.beginTransmission(address);
// Set register address
Wire.write(registerAddress);
Wire.endTransmission(false);
// Read register content
Wire.requestFrom(address, 1);
// Return the byte read at the register address
return Wire.read();
}
Comme pour le code Arduino, le code Python qui affiche le vecteur peut être téléchargé au bas de cette page. Le code Python crée et initialise une figure MatplotLib. Il écoute le périphérique série pour récupérer les données envoyées par l'ESP32 :
# Read a line from the serial device
line = ser.readline().decode('ascii').strip()
parts = line.split() if ' ' in line else line.split(',')
Il crée un vecteur de magnitude avec les 3 axes. Notez que le repère présenté sur la première page de la fiche technique n'est pas conforme à la valeur lue sur le capteur. Le signe de l'axe Z n'est pas conforme aux signes des axes X et Y. C'est pourquoi ces axes sont inversés dans le code.
Mag = [ -int(parts[1]), -int(parts[0]), int(parts[2])]
Les vecteurs affichés sur la figure sont construits à partir du vecteur de magnitude :
quiver = ax.quiver(*arrow, color='k', linewidths=2)
quiverX = ax.quiver(*[0,0,0,arrow[3],0,0], arrow_length_ratio=0, color='r', alpha=0.4)
quiverY = ax.quiver(*[0,0,0,0,arrow[4],0], arrow_length_ratio=0, color='g', alpha=0.4)
quiverZ = ax.quiver(*[0,0,0,0,0,arrow[5]], arrow_length_ratio=0, color='b', alpha=0.4)
Enfin, une animation est lancée avec un frame rate de 100fps (10ms) :
# Run the animation
ani = FuncAnimation(fig, update, frames=np.linspace(0,2*np.pi,200), interval=0)
plt.show()
Voici le résulta :
This page is based on the work of my students at the Institute of Technology in Angers. Thanks to them for this great work.
Cette page s'appuie sur le travail de mes étudiants de l'IUT GEII d'Angers. Merci à eux pour ce travail.
Tous les fichiers sont disponibles sur Github.