voilà une programme ne micropython mais très facielemnt adaptable pour python3 sur Raspi
Code : Tout sélectionner
""" attention ce programme contient l'exploitation d'une multiplexeur I2C TCA9548A
par défaut on ne connecte à A0 A1 A2 à rien , la connexion à 3,3volt de ces lignes d'adresse permet d'incrémenter l'adresse
du multiplexer dont l'adresse de base sur le bus I2C est 0x70 ainsi avec ces trois fils d'adresse
il est possible d'obtenir la communication avec 8 multiplexeurs qui redoivent dont on programme les adresses ainsi de 0xF0 à 0xF7.
Ceci étant l'ouverture d'un des port du multiplexeur se fait par une "commande envoyé sur le bus I2C lui même.
par exemple pour ouvrir le canal "0" du multiplexeur il faut en voyer sur le bus I2c par writeto(0xF0,1) ensuite on constate
par exemple en scanant le bus que c'est bien le composant qui répond sur ce canal et lui seul. un print du scan donne
la ou les adresses du composant connecté sur ce port suivi toujours de l'adresse du multiplexeur lui même, ici 112 puisque
les lignes d'adresse ne sont pas actives et que donc par de faut l'adresse I2c du multiplexeur est 0xF0 soit 112 valeur numérique.
par la on comprend que les autres ports étant isolés nous pourrons mettre ensuquer 8 de composants identique de mêmes adresses
sans générer de conflit. par exemple un write(0xf0, 128) permettra de communiquer uniquement avec le composant connecté au port 8.
la valeur transmise dans cette ordre de connexion est fait un octet donc chaque bit à 1 active un port
d'où les seules valeurs autorisées: 1,2,4,8,16,32,64,128. Un scan après un commande type write(0xF0, 5)
qui en valeur digitale donne 00000101 entre comme seule réponse invariable 112 qui indique que le mutiplexeur qui répond toujours
présent à son adresse n'a ouvert aucun de ses ports
"""
import time
from machine import I2C
import math
import utime
from machine import Pin
print("c'est fait")
# configure the I2C bus
bus = I2C(0,I2C.MASTER, baudrate=100000)
accel_address=25
mag_address=30
class lsm303DLHC:
# LSM303 Address definitions
LSM303Accel_ADDR = 25 # ou l'inverse
LSM303Mag_ADDR = 30
CTRL_REG1_A = 0x20
CTRL_REG2_A = 0x21
CTRL_REG3_A = 0x22
CTRL_REG4_A = 0x23
CTRL_REG5_A = 0x24
CTRL_REG6_A = 0x25
REFERENCE_A = 0x26
STATUS_REG_A = 0x27
OUT_X_L_A = 0x28
OUT_X_H_A = 0x29
OUT_Y_L_A = 0x2A
OUT_Y_H_A = 0x2B
OUT_Z_L_A = 0x2C
OUT_Z_H_A = 0x2D
FIFO_CTRL_REG_A = 0x2E
FIFO_SRC_REG_A = 0x2F
INT1_CFG_A = 0x30
INT1_SRC_A = 0x31
INT1_THS_A = 0x32
INT1_DURATION_A = 0x33
INT2_CFG_A = 0x34
INT2_SRC_A = 0x35
INT2_THS_A = 0x36
INT2_DURATION_A = 0x37
CLICK_CFG_A = 0x38
CLICK_SRC_A = 0x39
CLICK_THS_A = 0x3A
TIME_LIMIT_A = 0x3B
TIME_LATENCY_A = 0x3C
TIME_WINDOW_A = 0x3D
#Magnetic field sensing register description . . . . . . . . . . . . . . . . . . . . . . . 37
CRA_REG_M = 0x00
CRB_REG_M = 0x01
MR_REG_M = 0x02
OUT_X_H_M = 0x03
OUT_X_L_M = 0x04
OUT_Z_H_M = 0x05
OUT_Z_L_M = 0x06
OUT_Y_H_M = 0x07
OUT_Y_L_M = 0x08
SR_REG_M = 0x09
MAG_IRA_REG_M = 0x0A
MAG_IRB_REG_M = 0x0B
MAG_IRC_REG_M = 0x0C
TEMP_OUT_H_M = 0x31
TEMP_OUT_L_M = 0x32
####################""""
MAG_DEVICE_ID = 0b01000000
# Magnetometer gains
MAGGAIN_1_3 = 0x20 # +/- 1.3
MAGGAIN_1_9 = 0x40 # +/- 1.9
MAGGAIN_2_5 = 0x60 # +/- 2.5
MAGGAIN_4_0 = 0x80 # +/- 4.0
MAGGAIN_4_7 = 0xA0 # +/- 4.7
MAGGAIN_5_6 = 0xC0 # +/- 5.6
MAGGAIN_8_1 = 0xE0 # +/- 8.1
# Magentometer rates
MAGRATE_0_7 = 0x00 # 0.75 Hz
MAGRATE_1_5 = 0x01 # 1.5 Hz
MAGRATE_3_0 = 0x02 # 3.0 Hz
MAGRATE_7_5 = 0x03 # 7.5 Hz
MAGRATE_15 = 0x04 # 15 Hz
MAGRATE_30 = 0x05 # 30 Hz
MAGRATE_75 = 0x06 # 75 Hz
MAGRATE_220 = 0x07 # 220 Hz
# Conversion constants
GRAVITY_STANDARD = 9.80665 # Earth's gravity in m/s^2
GAUSS_TO_MICROTESLA = 100.0 # Gauss to micro-Tesla multiplier
###################""""""
ACCELE_SCALE = 2
X = 0
Y = 1
Z = 2
# Set up the sensor
def __init__(self,):
self.write_regAccel(0b01000111, self.CTRL_REG1_A) # 0x57 = ODR=50hz, all accel axes on
self.write_regAccel(0x00, self.CTRL_REG2_A) # set full-scale
self.write_regAccel(0x00, self.CTRL_REG3_A) # no interrupt
self.write_regAccel(0x00, self.CTRL_REG4_A) # no interrupt
self.write_regAccel(0x00, self.CTRL_REG5_A) # 0x10 = mag 50Hz output rate
self.write_regAccel(0x00, self.CTRL_REG6_A)
self.write_regMag(0b10010000,self.CRA_REG_M) # activation température et frequence mag à 35 Hz
self.write_regMag(0b00100000,self.CRB_REG_M) # +- 1,3 Gauss champ terrete 0,5 gauss
self.write_regMag(0b00000000,self.MR_REG_M) # pour mesure continuelle 00000011 pour mise en sommeil
self.lsm303mag_gauss_lsb_xy= 1100.0
self.lsm303mag_gauss_lsb_z= 980.0
print("toto")
# get the status of the sensor
def status(self):
if self.read_regAccel(self.STATUS_REG_A) !=73:
return -1
return 1
# Write data to a reg on the I2C device
def write_regAccel(self,data,reg):
bus.writeto_mem(self.LSM303Accel_ADDR, reg, data)
# Read data from the sensor
def read_regAccel(self,reg):
return bus.readfrom_mem(self.LSM303Accel_ADDR, reg,1)
# Write data to a reg on the I2C device
def write_regMag(self,data,reg):
bus.writeto_mem(self.LSM303Mag_ADDR, reg, data)
# Read data from the sensor
def read_regMag(self,reg):
return bus.readfrom_mem(self.LSM303Mag_ADDR, reg,1)
# Check if compass is ready
def isMagReady(self):
if int.from_bytes(self.read_regMag(self.SR_REG_M),"big") & 0x03 != 0 :
return 1
return 0
def dec2bin(self,d,nb):
#"""Représentation d'un nombre entier en chaine binaire (nb: nombre de bits du mot)"""
if d == 0:
return "0".zfill(nb)
if d<0:
d += 1<<nb
b=""
while d != 0:
d, r = divmod(d, 2)
b = "01"[r] + b
return '{:0>{w}}'.format(b, w=nb) # en effet en micropyhton il n'y a pas de fonction zfill
def temperature2(self):
temp=((int.from_bytes(self.read_regMag(self.TEMP_OUT_H_M),"big")<<8)|(int.from_bytes(self.read_regMag(self.TEMP_OUT_L_M),"big")))
if temp > 32767: # 2's complement
temp -= 65536
temperature = float( 20 + ( temp >> 4 )/ 8 )
return temperature
# Get raw accelerometer values
def getAccel(self):
raw_accel=[0,0,0]
#print("titi ",int.from_bytes(self.read_reg(self.OUT_X_H_A),"big"))
raw_accel[0]=((int.from_bytes(self.read_regAccel(self.OUT_X_H_A),"big")<<8)|int.from_bytes(self.read_regAccel(self.OUT_X_L_A),"big"))
raw_accel[1]=((int.from_bytes(self.read_regAccel(self.OUT_Y_H_A),"big")<<8)|int.from_bytes(self.read_regAccel(self.OUT_Y_L_A),"big"))
raw_accel[2]=((int.from_bytes(self.read_regAccel(self.OUT_Z_H_A),"big")<<8)|int.from_bytes(self.read_regAccel(self.OUT_Z_L_A),"big"))
#2's compiment
for i in range(3):
if raw_accel[i]>32767:
raw_accel[i]=raw_accel[i]-65536
return raw_accel
# Get accelerometer values in g
def getRealAccel(self):
realAccel=[0.0,0.0,0.0]
accel=self.getAccel()
for i in range(3):
realAccel[i] = round(accel[i] / math.pow(2, 15) * self.ACCELE_SCALE,3)
return realAccel
# Get compass raw values
def getMag(self):
raw_mag=[0,0,0]
raw_mag[0]=((int.from_bytes(self.read_regMag(self.OUT_X_H_M),"big")<<8)|int.from_bytes(self.read_regMag(self.OUT_X_L_M),"big"))
raw_mag[1]=((int.from_bytes(self.read_regMag(self.OUT_Y_H_M),"big")<<8)|int.from_bytes(self.read_regMag(self.OUT_Y_L_M),"big"))
raw_mag[2]=((int.from_bytes(self.read_regMag(self.OUT_Z_H_M),"big")<<8)|int.from_bytes(self.read_regMag(self.OUT_Z_L_M),"big"))
#2's compiment
for i in range(3):
if raw_mag[i]>32767:
raw_mag[i]=raw_mag[i]-65536
return raw_mag
# Get heading from the compass
def getHeading(self):
magValue=self.getMag()
print(magValue)
heading = 180*math.atan2(magValue[self.Y], magValue[self.X])/math.pi# // assume pitch, roll are 0
if (heading <0):
heading += 360
return round(heading,3)
def getTiltHeading(self):
magValue=self.getMag()
raw_accel=self.getAccel()
if [0.0,0.0,0.0] != raw_accel:
accXnorm= raw_accel[0]/math.sqrt(raw_accel[0]*raw_accel[0]+raw_accel[1]*raw_accel[1]+raw_accel[2]*raw_accel[2])
accYnorm= raw_accel[1]/math.sqrt(raw_accel[0]*raw_accel[0]+raw_accel[1]*raw_accel[1]+raw_accel[2]*raw_accel[2])
pitch = math.asin(accXnorm)
roll = -math.asin(accYnorm/math.cos(pitch))
#print(accelValue[Y],pitch,math.cos(pitch),accelValue[Y]/math.cos(pitch),math.asin(accelValue[Y]/math.cos(pitch)))
xh = (magValue[0] * math.cos(pitch)) +( magValue[2] * math.sin(pitch))
yh = (magValue[1] * math.sin(roll) * math.sin(pitch)) + (magValue[1] * math.cos(roll)) - (magValue[2] * math.sin(roll) * math.cos(pitch))
zh = (-magValue[0] * (roll) * math.sin(pitch)) +( magValue[1] * math.sin(roll)) +( magValue[2] * math.cos(roll) * math.cos(pitch))
heading = 180 * math.atan2(yh, xh)/math.pi
#heading = 180 * math.atan2(yh*zh, xh*zh)/math.pi
print("xh ", xh,"yh ",yh, "zh ",zh)
if (yh >= 0):
return heading
else:
return (360 + heading)
if __name__ == "__main__":
bus.writeto( 0x70, 1) # ouverture du bus N° 0
print(bus.scan()) # returns list of slave addresses
acc_mag=lsm303DLHC() # création de l'objet gérant le premier acc-mag
time.sleep(1)
bus.writeto( 0x70, 128) # ouverture du bus N° 7
print(bus.scan()) # returns list of slave addresses
acc_mag2=lsm303DLHC() # création de l'objet gérant le deuxième acc-mag
while True:
#if acc_mag.status()==1:
bus.writeto( 0x70, 1) # ouverture du bus N° 0
print("accélération",acc_mag.getRealAccel())
while True:
if acc_mag.isMagReady():
break
print("*")
print(acc_mag.getHeading())
print (acc_mag.getTiltHeading())
print("température2 ", acc_mag.temperature2())
time.sleep(5)
# ici on change de canal du multiplexeur I2c
bus.writeto( 0x70, 128) # ouverture du bus N° 0
print("accélération",acc_mag2.getRealAccel())
while True:
if acc_mag2.isMagReady():
break
print("*")
print(acc_mag2.getHeading())
print (acc_mag2.getTiltHeading())
print("température2 ", acc_mag2.temperature2())
time.sleep(5)