B4R Tutorial Inertial Measurements (MPU 6050) and Magnetometer (HMC5883L)

With big help from Erel here are two examples of connecting two boards by the I2C/TWI (A4 and A5 pins), using the rWire library.
Inertial Measurements (mpu6050) :
B4X:
' MPU 6050 board - Inertial Measurements
' connect SCL to A5, SDA to A4, 3.3V and ground
#Region Project Attributes
    #AutoFlushLogs: True
    #StackBufferSize: 300
#End Region
Sub Process_Globals
   Public Serial1 As Serial
   Private wire As WireMaster
   Private raf As RandomAccessFile
   Private const MPU As Int = 0x68
   Private AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ As Int
   Private tmr As Timer
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   wire.Initialize
   wire.WriteTo(MPU, Array As Byte(0x6b, 0))
   tmr.Initialize("tmr_tick",700)
   tmr.Enabled = True

End Sub

Sub tmr_tick
   wire.WriteTo(MPU, Array As Byte(0x3b))
   Dim b() As Byte = wire.RequestFrom(MPU, 14)
   If b.Length = 14 Then
    raf.Initialize(b,False)
    AcX  = raf.ReadInt16(raf.CurrentPosition)
     AcY  = raf.ReadInt16(raf.CurrentPosition)
     AcZ  = raf.ReadInt16(raf.CurrentPosition)
    Dim temp As Double
    Tmp  = raf.ReadInt16(raf.CurrentPosition)
     temp = Tmp /340.00+36.53
    GyX  = raf.ReadInt16(raf.CurrentPosition)
     GyY  = raf.ReadInt16(raf.CurrentPosition)
    GyZ  = raf.ReadInt16(raf.CurrentPosition)
     Log("acx: ", AcX , ", acy: ", AcY ," ,acz: ", AcZ,", Tmp: ",NumberFormat(temp,1,1) , ", GyX: ", GyX , ", GyY: ", GyY ," ,GyZz: ", GyZ)
   Else
     Log("Missing data...")
   End If
End Sub

Magnetometer (HMC5883L) :
B4X:
' HMC5883L board - magnetometer
' connect SCL to A5, SDA to A4, 3.3v and ground

#Region Project Attributes
    #AutoFlushLogs: True
    #StackBufferSize: 300
#End Region

Sub Process_Globals
   Public Serial1 As Serial
   Private wire As WireMaster
   Private raf As RandomAccessFile
   Private const addr As Int = 0x1E
   Private X,Y,Z As Int
   Private tmr As Timer
End Sub

Private Sub AppStart
   Serial1.Initialize(115200)
   wire.Initialize
   wire.WriteTo(addr, Array As Byte(0x02, 0))
   tmr.Initialize("tmr_tick",700)
   tmr.Enabled = True
End Sub

Sub tmr_tick
   wire.WriteTo(addr, Array As Byte(0x03))
   Dim b() As Byte = wire.RequestFrom(addr, 6)
   If b.Length = 6 Then
    raf.Initialize(b,False)
    X  = raf.ReadInt16(raf.CurrentPosition)
     Z  = raf.ReadInt16(raf.CurrentPosition)
     Y  = raf.ReadInt16(raf.CurrentPosition)
    Dim heading As Double = ATan2(y, x) *180/cPI
    If heading < 0 Then heading = heading + 360
    Log("x:  ", X , ",  y:  ", Y ,",  z:  ", Z,  "   Hdg:  ", NumberFormat(heading,1,1))
   Else
     Log("Missing data...")
   End If
End Sub

Tip: the magnetometer will not function correctly near running motors due to their effect on the magnetic field.
Note: Since the two devices have different addresses you can connect both of them in one program.
Edit: corrected per Erel's recomendation.
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Don't use a Looper + delay. You should instead use a timer with an interval of 700ms.

AddLooper should only be used when you want to create a timer that runs as fast as possible.

B4X:
Sub Process_Globals
 Private Timer1 As Timer
 ...

End Sub

Sub AppStart
 ...
 Timer1.Initialize("Timer1_Tick", 700)
 Timer1.Enabled = True
End Sub

Sub Timer1_Tick
 wire.Write(...)
 ...
 

derez

Expert
Licensed User
Longtime User
To use the boards on WEMOS D1 - connect to SCL and SDA on the board (two options !).
To connect to NodeMcu - connect SCL to D1 and SDA to D2.
If anyone knows how to use the SD pins on the left side of the NodeMcu for it - please let me know.
 
Last edited:
Top