from machine import Pin, Ic2 IC2_SDA = 16 # GP16のジェネラル端子をSDA(Serial Data)に指定用変数 IC2_SCL = 17 # GP17のジェネラル端子をSCL(Serial Clock)に指定用変数 IC2_CH = 0 # IC2のチャンネル指定用変数 # SCL はスタンダードモードの100KHzの通信モードで、IC2を初期化 ic2=IC2( IC2_CH, scl=Pin(IC2_SCL), sda=IC2_SDA, freq=100000) for addr in ic2.scan(): print( f"{addr:x}" )この実行結果を以下に示します。
1c 6aモジュール内のJ1,J2が未接続の状態で、加速センサとジャイロセンサのペア 0x6A 、磁力センサはが0x1Cのアドレスで、 上記ではこれが見えています。
from machine import Pin, I2C import utime I2C_SDA=16# GP16のジェネラル端子をSDA「Serial Data」に指定用変数 I2C_SCL=17# GP17のジェネラル端子をSCL「Serial Clock」に指定用変数 I2C_CH=0# I2Cのチャンネル指定用変数(Picoでは0と1のチャンネルがある) I2C_M_ADDR=0x1C#磁力センサのアドレス # 磁気センサー関連のレジスタ番号と設定値(lsm9ds1.pdf参照) CTRL_REG1_M_N=0x20# レジスタ番号 CTRL_REG1_M=0b10010000# 温度補正 Low-power mode ODR(output data rate):10Hz デフォルト:00010000 CTRL_REG2_M_N=0x21 CTRL_REG2_M=0b00000000# Full scale:±4gauss デフォルト:00000000 CTRL_REG3_M_N=0x22 CTRL_REG3_M=0b00000000# I2Cのenable Continuous conversion mode デフォルト:00000011 CTRL_REG4_M_N=0x23 CTRL_REG4_M=0b00000000# Z-axis:low power, data LSb at lower address, デフォルト: 00000000 CTRL_REG5_M_N=0x24 CTRL_REG5_M=0b00000000# continuous update デフォルト: 00000000 STATUS_REG_M=0x27# 状態 OUT_X_L_M=0x28 OUT_X_H_M=0x29 OUT_Y_L_M=0x2A OUT_Y_H_M=0x2B OUT_Z_L_M=0x2C OUT_Z_H_M=0x2D OFFSET_X_REG_L_M=0x05 # SCL はスタンダードモードの100KHzの通信モードで、I2Cを初期化 i2c=I2C( I2C_CH, scl=Pin(I2C_SCL), sda=I2C_SDA, freq=100000) for addr in i2c.scan(): print( f"enabled address:{addr:02x}" ) #磁力センサのアドレスを指定して、各レジスタを設定 i2c.writeto_mem( I2C_M_ADDR, CTRL_REG1_M_N, bytes([CTRL_REG1_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG2_M_N, bytes([CTRL_REG2_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG3_M_N, bytes([CTRL_REG3_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG4_M_N, bytes([CTRL_REG4_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG5_M_N, bytes([CTRL_REG5_M])) CTRL_REG3_M_N=0x22 i2c.writeto_mem( I2C_M_ADDR, CTRL_REG3_M_N, bytes([0x0])) while True: while True: statu=i2c.readfrom_mem( I2C_M_ADDR, STATUS_REG_M,1) #print(f"statu:{statu[0]:08b}", end=" ") if statu[0] & 0x80 : break # 更新があれば? bxl=i2c.readfrom_mem( I2C_M_ADDR, OUT_X_L_M,1) # X軸 bxh=i2c.readfrom_mem( I2C_M_ADDR, OUT_X_H_M,1) byl=i2c.readfrom_mem( I2C_M_ADDR, OUT_Y_L_M,1) # Y軸 byh=i2c.readfrom_mem( I2C_M_ADDR, OUT_Y_H_M,1) bzl=i2c.readfrom_mem( I2C_M_ADDR, OUT_Z_L_M,1) # Z軸 bzh=i2c.readfrom_mem( I2C_M_ADDR, OUT_Z_H_M,1) bin=[bxl[0],bxh[0], byl[0],byh[0], bzl[0],bzh[0]] print(bin) pass bin=i2c.readfrom_mem( I2C_M_ADDR, OUT_X_L_M, 6) # X軸〜Z軸 bin=[v for v in bin] print( bin ) pass bin=i2c.readfrom_mem( I2C_M_ADDR, OFFSET_X_REG_L_M, 6) bin=[v for v in bin] print( bin )上記の実行結果例を以下に示します。
[9, 5, 73, 6, 172, 244] [9, 5, 73, 6, 172, 244] [0, 0, 0, 0, 0, 0] [235, 4, 108, 6, 121, 244] [235, 4, 108, 6, 121, 244] [0, 0, 0, 0, 0, 0] [9, 5, 58, 6, 189, 244] [9, 5, 58, 6, 189, 244] [0, 0, 0, 0, 0, 0] [231, 4, 95, 6, 207, 244] [231, 4, 95, 6, 207, 244] [0, 0, 0, 0, 0, 0] [13, 5, 57, 6, 176, 244] [13, 5, 57, 6, 176, 244] [0, 0, 0, 0, 0, 0] ・・・以下省略上記の の部分は個々のレジスタを指定で情報を得ているのに対し、 は、アドレスとして先頭となるOUT_X_L_Mを指定し、そこから並ぶ6byteの情報を取得しています。
以上でアクセス方法が分かったので、磁気センサーのX軸,Y軸,Z軸の16byte情報を表示するコードは次のようになりました。
from machine import Pin, I2C import utime I2C_SDA=16# GP16のジェネラル端子をSDA「Serial Data」に指定用変数 I2C_SCL=17# GP17のジェネラル端子をSCL「Serial Clock」に指定用変数 I2C_CH=0# I2Cのチャンネル指定用変数(Picoでは0と1のチャンネルがある) I2C_M_ADDR=0x1C#磁力センサのアドレス # 磁気センサー関連のレジスタ番号と設定値(lsm9ds1.pdf参照) CTRL_REG1_M_N=0x20# レジスタ番号 CTRL_REG1_M=0b10010000# 温度補正 Low-power mode ODR:10Hz デフォルト:00010000 CTRL_REG2_M_N=0x21 CTRL_REG2_M=0b00000000# Full scale:±4gauss デフォルト:00000000 CTRL_REG3_M_N=0x22 CTRL_REG3_M=0b00000000# I2Cのenable Continuous conversion mode デフォルト:00000011 CTRL_REG4_M_N=0x23 CTRL_REG4_M=0b00000000# Z-axis:low power, data LSb at lower address, デフォルト: 00000000 CTRL_REG5_M_N=0x24 CTRL_REG5_M=0b00000000# continuous update デフォルト: 00000000 STATUS_REG_M=0x27# 状態 OUT_X_L_M=0x28 # このアドレスより、OUT_X_H_M、OUT_Y_L_M、OUT_Y_H_M、OUT_Z_L_M、OUT_Z_H_Mレジスタが並ぶ OFFSET_X_REG_L_M=0x05 # SCL はスタンダードモードの100KHzの通信モードで、I2Cを初期化 i2c=I2C( I2C_CH, scl=Pin(I2C_SCL), sda=I2C_SDA, freq=100000) #for addr in i2c.scan(): print( f"enabled address:{addr:02x}" ) #磁力センサのアドレスを指定して、各制御レジスタを設定 i2c.writeto_mem( I2C_M_ADDR, CTRL_REG1_M_N, bytes([CTRL_REG1_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG2_M_N, bytes([CTRL_REG2_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG3_M_N, bytes([CTRL_REG3_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG4_M_N, bytes([CTRL_REG4_M])) i2c.writeto_mem( I2C_M_ADDR, CTRL_REG5_M_N, bytes([CTRL_REG5_M])) import math while True: while True: # データ更新を待つ statu=i2c.readfrom_mem( I2C_M_ADDR, STATUS_REG_M,1) #print(f"statu:{statu[0]:08b}", end=" ") if statu[0] & 0x80 : break bin=i2c.readfrom_mem( I2C_M_ADDR, OUT_X_L_M, 6) # X,Y,Z軸の磁気センサー情報取得 #print( [v for v in bin] ) magbin=[bin[n] + (bin[n+1]<<8) for n in range(0,len(bin),2)] # 2byteからuint16へ変換 magbin=[v if v <= 32767 else v - 65536 for v in magbin] # uint16からint16へ変換 deg = math.atan(magbin[1]/magbin[0]) * 360 / math.pi / 2 # 角度算出 print( f"X:{magbin[0]:6}, Y:{magbin[1]:6}, Z:{magbin[2]:6} , deg={deg:5.2f}" ) utime.sleep(0.5)上記の実行例を以下に示しています。0.5秒ごとに計測結果(x,y,z,y/xのアークタンジェントの角度)を表示しています。
X: 2732, Y: 1768, Z: -573 , deg=32.91 X: 2706, Y: 1786, Z: -671 , deg=33.43 X: 2649, Y: 1797, Z: -604 , deg=34.15 X: 2673, Y: 1821, Z: -581 , deg=34.26 X: 2653, Y: 1817, Z: -609 , deg=34.41 X: 2639, Y: 1858, Z: -606 , deg=35.15 X: 2751, Y: 1741, Z: -590 , deg=32.33 X: 2828, Y: 1721, Z: -669 , deg=31.32 X: 2871, Y: 1596, Z: -641 , deg=29.07 X: 3096, Y: 922, Z: -747 , deg=16.58 X: 3110, Y: 631, Z: -750 , deg=11.47 X: 2934, Y: -15, Z: -911 , deg=-0.29 X: 2232, Y: -377, Z: -945 , deg=-9.59 X: 1216, Y: -598, Z: -842 , deg=-26.19 X: 966, Y: -494, Z: -900 , deg=-27.08 X: 144, Y: -7, Z: -930 , deg=-2.78 X: -13, Y: 202, Z: -977 , deg=-86.32 X: -255, Y: 557, Z: -958 , deg=-65.40 X: -299, Y: 1012, Z: -1080 , deg=-73.54 X: -315, Y: 1517, Z: -1223 , deg=-78.27 X: -329, Y: 2172, Z: -1348 , deg=-81.39 X: -313, Y: 2270, Z: -1342 , deg=-82.15 X: -263, Y: 2541, Z: -1356 , deg=-84.09 X: 70, Y: 3050, Z: -1245 , deg=88.69 X: 827, Y: 3621, Z: -1234 , deg=77.13 X: 1110, Y: 3754, Z: -1322 , deg=73.53 X: 1736, Y: 3585, Z: -1173 , deg=64.16 X: 2810, Y: 2619, Z: -775 , deg=42.99 X: 2898, Y: 2156, Z: -688 , deg=36.65 X: 2846, Y: 1817, Z: -647 , deg=32.56 X: 2751, Y: 1583, Z: -552 , deg=29.92 X: 2725, Y: 1583, Z: -545 , deg=30.15 X: 2701, Y: 1607, Z: -549 , deg=30.75 X: 2715, Y: 1585, Z: -491 , deg=30.28 X: 2727, Y: 1555, Z: -513 , deg=29.69 X: 2715, Y: 1561, Z: -480 , deg=29.90 X: 2713, Y: 1625, Z: -460 , deg=30.92 X: 2737, Y: 1569, Z: -544 , deg=29.82 X: 2725, Y: 1569, Z: -547 , deg=29.93 X: 2697, Y: 1569, Z: -475 , deg=30.19 X: 2695, Y: 1517, Z: -500 , deg=29.37 X: 2706, Y: 1535, Z: -448 , deg=29.56上記の実行中に、ブレッドボードを左へ1回転させています。それにより、角度が約30度→約0度→約-90度→約90度→約30度と変化しています。
from machine import Pin, I2C import utime I2C_SDA=16# GP16のジェネラル端子をSDA「Serial Data」に指定用変数 I2C_SCL=17# GP17のジェネラル端子をSCL「Serial Clock」に指定用変数 I2C_CH=0# I2Cのチャンネル指定用変数(Picoでは0と1のチャンネルがある) I2C_AG_ADDR=0x6a#加速センサとジャイロセンサのアドレス # SCL はスタンダードモードの100KHzの通信モードで、I2Cを初期化 i2c=I2C( I2C_CH, scl=Pin(I2C_SCL), sda=I2C_SDA, freq=100000) for addr in i2c.scan(): print( f"enabled address:{addr:02x}" ) # ジャイロのセンサー関連のレジスタ番号と設定値(lsm9ds1.pdf参照) CTRL_REG1_G_N=0x10# レジスタ番号 CTRL_REG1_G=0b01000000# 角速度センサ制御レジスタ デフォルト:00000000 #CTRL_REG1_G[7〜5]のODR_G:010 測定周期59.5Hz #CTRL_REG1_G[4〜3]のFS_G:00 Gyroscope full-scaleを245 dps #CTRL_REG1_G[1〜0]のBW_G:00 帯域幅 CTRL_REG2_G_N=0x11 CTRL_REG2_G=0b00000000# デフォルト:00000000 CTRL_REG3_G_N=0x12 CTRL_REG3_G=0b00000000# デフォルト:00000000 STATUS_REG=0x17# 状態 OUT_X_G=0x18 # このアドレスより、OOUT_Y_G (1Ah - 1Bh)、OUT_Z_G (1Ch - 1Dh)のレジスタが並ぶ #各ジャイロセンサレジスタを設定 i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG1_G_N, bytes([CTRL_REG1_G])) i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG2_G_N, bytes([CTRL_REG2_G])) i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG3_G_N, bytes([CTRL_REG3_G])) while True: while True: statu=i2c.readfrom_mem( I2C_AG_ADDR, STATUS_REG,1) #print(f"statu:{statu[0]:08b}", end=" ") if statu[0] & 0x02 : break bin=i2c.readfrom_mem( I2C_AG_ADDR, OUT_X_G, 6) # X,Y,Z軸のジャイロセンサー情報取得 #print( [v for v in bin] ) gyro=[bin[n] + (bin[n+1]<<8) for n in range(0,len(bin),2)] gyro=[v if v <= 32767 else v - 65536 for v in gyro] print( gyro ) utime.sleep(0.5)
![]() |
ぶら下げて、手で右矢印のように回転させた時実行結果例 よって、X軸の回転角度の速度がマイナスになっています。 体感的には、合っていると感じました。 [-677, 257, -286] [102, -509, 269] [157, -189, 5] [104, -91, -33] [-496, -97, -626] [379, -83, 1084] [-242, 54, 1022] [-808, 521, 53] [-150, 76, 2308] [-567, 474, 437] [29, -503, 295] [1313, -2819, 308] [-548, -147, -1036] [-9442, 1418, -1416] [-3083, -590, 433] [-2627, -332, -2331] [-13313, 3791, -3612] [-5737, 607, -2932] [-10359, 38, -576] [-6350, 585, -1068] [-8663, 1362, -592] [-7645, 1386, -538] [-11306, 1614, -819] [-3794, 530, 404] [-9136, 1420, -1063] [-9563, 1262, -629] [-4040, 2328, 157] [1833, 400, 1146] [3814, 6263, -3505] [-1733, 4808, -1815] [-325, -78, 12] [-327, -75, 7] [-337, -72, 13] [-318, -77, 9] [-321, -62, 12] [-327, -64, 15] [-309, -84, 12]最後の方のデータは置いて固定した状態ですが、固定状態で 約[-325, -78, 12]の値になっています。 |
from machine import Pin, I2C import utime I2C_SDA=16# GP16のジェネラル端子をSDA「Serial Data」に指定用変数 I2C_SCL=17# GP17のジェネラル端子をSCL「Serial Clock」に指定用変数 I2C_CH=0# I2Cのチャンネル指定用変数(Picoでは0と1のチャンネルがある) I2C_AG_ADDR=0x6a#加速センサとジャイロセンサのアドレス # SCL はスタンダードモードの100KHzの通信モードで、I2Cを初期化 i2c=I2C( I2C_CH, scl=Pin(I2C_SCL), sda=I2C_SDA, freq=100000) for addr in i2c.scan(): print( f"enabled address:{addr:02x}" ) # ジャイロのセンサー関連のレジスタ番号と設定値(lsm9ds1.pdf参照) CTRL_REG1_G_N=0x10# レジスタ番号 CTRL_REG1_G=0b01000000# 角速度センサ制御レジスタ デフォルト:00000000 #CTRL_REG1_G[7〜5bit]のODR_G:010 測定周期59.5Hz #CTRL_REG1_G[4〜3bit]のFS_G:00 Gyroscope full-scaleを245 dps #CTRL_REG1_G[1〜0bit]のBW_G:00 帯域幅 CTRL_REG2_G_N=0x11 CTRL_REG2_G=0b00000000# デフォルト:00000000 CTRL_REG3_G_N=0x12 CTRL_REG3_G=0b00000000# デフォルト:00000000 #CTRL_REG3_G でLow-power disabled、High-pass filter desable,Gyroscope high-pass filter cutoff frequency set STATUS_REG=0x17# 状態 OUT_X_G=0x18 # このアドレスより、OOUT_Y_G (1Ah - 1Bh)、OUT_Z_G (1Ch - 1Dh)のレジスタが並ぶ #各ジャイロセンサレジスタをを上記の通り設定 i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG1_G_N, bytes([CTRL_REG1_G])) i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG2_G_N, bytes([CTRL_REG2_G])) i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG3_G_N, bytes([CTRL_REG3_G])) # 加速度のセンサー関連のレジスタ番号と設定値 CTRL_REG4_N=0x1E CTRL_REG4=0b00111000#0,0,Zen_G,Yen_G,Xen_G,0,LIR_XL1,4D_XL1 #デフォルト値:00111000 CTRL_REG5_N=0x1F CTRL_REG5=0b00111000#0,0,Zen_G,Yen_G,Xen_G,0,LIR_XL1,4D_XL1 #デフォルト値:00111000 CTRL_REG6_XL_N=0x20 CTRL_REG6_XL=0b00000000#デフォルト値:00000000 #CTRL_REG6_XL[7〜5bit]はジャイロスコープ利用時無効?で、ジャイロスコープと同じ測定周期 #CTRL_REG6_XL[4〜3bit]はAccelerometer full-scale:±2g #CTRL_REG6_XL[4〜3bit] OUT_X_L_XL=0x28#OUT_X_H_XL,OUT_Y_L_XL,OUT_Y_H_XL,OUT_Z_L_XL,OUT_Z_H_XL #各加速度のセンサーレジスタを上記の通り設定 i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG4_N, bytes([CTRL_REG4])) i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG5_N, bytes([CTRL_REG5])) i2c.writeto_mem( I2C_AG_ADDR, CTRL_REG6_XL_N, bytes([CTRL_REG6_XL])) while True: statu=i2c.readfrom_mem( I2C_AG_ADDR, STATUS_REG,1) #print(f"statu:{statu[0]:08b}", end=" ") if statu[0] & 0x02 : # ジャイロセンサー情報あり? bin=i2c.readfrom_mem( I2C_AG_ADDR, OUT_X_G, 6) # X,Y,Z軸のジャイロセンサー情報取得 #print( [v for v in bin] ) gyro=[bin[n] + (bin[n+1]<<8) for n in range(0,len(bin),2)] gyro=[v if v <= 32767 else v - 65536 for v in gyro] print( f"gyroscope:{gyro}" ) if statu[0] & 0x01: # 加速度情報情報あり? bin=i2c.readfrom_mem( I2C_AG_ADDR, OUT_X_L_XL, 6) # X,Y,Z軸の加速度情報取得 #print( [v for v in bin] ) accel=[bin[n] + (bin[n+1]<<8) for n in range(0,len(bin),2)] accel=[v if v <= 32767 else v - 65536 for v in accel] print( f"Accelerometer:{accel}" ) utime.sleep(0.5)上記の実行例で、ジャイロと加速度センサーの情報を交互に表示しています。
enabled address:1c enabled address:6a gyroscope:[-315, -79, 15] Accelerometer:[-136, -415, 15919] gyroscope:[-325, -70, 13] Accelerometer:[-136, -404, 15916] gyroscope:[-318, -84, 6] Accelerometer:[-131, -404, 15914] gyroscope:[-316, -72, 7] Accelerometer:[-124, -418, 15918] gyroscope:[-317, -66, 7] Accelerometer:[-138, -404, 15907] gyroscope:[-307, -76, 5] Accelerometer:[-131, -412, 15912] gyroscope:[-315, -68, 15] Accelerometer:[-142, -414, 15919] gyroscope:[-328, -76, 15] Accelerometer:[-140, -437, 15898] gyroscope:[-311, -78, 14]