B4J Question Raspberry pi - integrating magnetometer HMC5883

derez

Expert
Licensed User
Longtime User
I try to integrate a magnetometer HMC5883 to a pi application.
I got the device connected and I get its address 1e on the monitor.
I have found the following java code, how do I use it in b4j ?
The used addresses are compatible with what I use in b4r code https://www.b4x.com/android/forum/t...nts-mpu-6050-and-magnetometer-hmc5883l.65917/.

B4X:
// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// HMC5883
// This code is designed to work with the HMC5883_I2CS I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Compass?sku=HMC5883_I2CS#tabs-0-product_tabset-2#tabs-0-product_tabset-2

import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
import java.io.IOException;

public class HMC5883
{
    public static void main(String args[]) throws Exception
    {
        // Create I2C bus
        I2CBus Bus = I2CFactory.getInstance(I2CBus.BUS_1);
        // Get I2C device, HMC5883 I2C address is 0x1E(30)
        I2CDevice device = Bus.getDevice(0x1E);

        // Select Configuration register A
        // Normal measurement configuration, data rate o/p = 0.75 Hz
        device.write(0x00, (byte)0x60);
        // Select Mode register
        // Continuous measurement mode
        device.write(0x02, (byte)0x00);
        Thread.sleep(500);

        // Read 6 bytes of data from 0x03(3)
        // xMag msb, xMag lsb, zMag msb, zMag lsb, yMag msb, yMag lsb
        byte[] data = new byte[6];
        device.read(0x03, data, 0, 6);

        // Convert the data
        int xMag = ((data[0] & 0xFF) * 256 + (data[1] & 0xFF));
        if(xMag > 32767)
        {
            xMag -= 65536;
        }

        int zMag = ((data[2] & 0xFF) * 256 + (data[3] & 0xFF));
        if(zMag > 32767)
        {
            zMag -= 65536;
        }

        int yMag = ((data[4] & 0xFF) * 256 + (data[5] & 0xFF));
        if(yMag > 32767)
        {
            yMag -= 65536;
        }

        // Output data to screen
        System.out.printf("Magnetic field in X-Axis : %d %n", xMag);
        System.out.printf("Magnetic field in Y-Axis : %d %n", yMag);
        System.out.printf("Magnetic field in Z-Axis : %d %n", zMag);
    }
}
 
Last edited:

Michael1968

Active Member
Licensed User
Longtime User
I try to integrate a magnetometer HMC5883 to a pi application.
I got the device connected and I get its address 1e on the monitor.
I have found the following java code, how do I use it in b4j ?
The used addresses are compatible with what I use in b4r code https://www.b4x.com/android/forum/t...nts-mpu-6050-and-magnetometer-hmc5883l.65917/.

B4X:
// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// HMC5883
// This code is designed to work with the HMC5883_I2CS I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Compass?sku=HMC5883_I2CS#tabs-0-product_tabset-2#tabs-0-product_tabset-2

import com.pi4j.io.i2c.I2CBus;
import com.pi4j.io.i2c.I2CDevice;
import com.pi4j.io.i2c.I2CFactory;
import java.io.IOException;

public class HMC5883
{
    public static void main(String args[]) throws Exception
    {
        // Create I2C bus
        I2CBus Bus = I2CFactory.getInstance(I2CBus.BUS_1);
        // Get I2C device, HMC5883 I2C address is 0x1E(30)
        I2CDevice device = Bus.getDevice(0x1E);

        // Select Configuration register A
        // Normal measurement configuration, data rate o/p = 0.75 Hz
        device.write(0x00, (byte)0x60);
        // Select Mode register
        // Continuous measurement mode
        device.write(0x02, (byte)0x00);
        Thread.sleep(500);

        // Read 6 bytes of data from 0x03(3)
        // xMag msb, xMag lsb, zMag msb, zMag lsb, yMag msb, yMag lsb
        byte[] data = new byte[6];
        device.read(0x03, data, 0, 6);

        // Convert the data
        int xMag = ((data[0] & 0xFF) * 256 + (data[1] & 0xFF));
        if(xMag > 32767)
        {
            xMag -= 65536;
        }

        int zMag = ((data[2] & 0xFF) * 256 + (data[3] & 0xFF));
        if(zMag > 32767)
        {
            zMag -= 65536;
        }

        int yMag = ((data[4] & 0xFF) * 256 + (data[5] & 0xFF));
        if(yMag > 32767)
        {
            yMag -= 65536;
        }

        // Output data to screen
        System.out.printf("Magnetic field in X-Axis : %d %n", xMag);
        System.out.printf("Magnetic field in Y-Axis : %d %n", yMag);
        System.out.printf("Magnetic field in Z-Axis : %d %n", zMag);
    }
}

Hi derez,
you can use the pi4j lib.
 
Upvote 0

derez

Expert
Licensed User
Longtime User
I followed the example and the B4R code's sequence of writing and reading addresses and came out with this code:
B4X:
Sub Process_Globals
    Dim bus1 As JavaObject
    Dim hmc As JavaObject
    Dim tmr As Timer
End Sub

Sub AppStart (Args() As String)
    Log("app start")
    bus1 = GetBus(1)
    hmc  = GetDevice(bus1,0x1e)

    Log(bus1)
    Log(hmc)
    Write(hmc, 0x02 )

    tmr.Initialize("tmr",1000)
    tmr.Enabled = True

    StartMessageLoop
End Sub

Sub tmr_Tick
    Write(hmc, 0x03 )
    Dim buffer(6) As Byte
    Read2(hmc, buffer, 0, 6)

    Dim raf As RandomAccessFile
    raf.Initialize3(buffer,False)

    Dim X As Short = raf.ReadShort(raf.CurrentPosition)
    Dim Z As Short = raf.Readshort(raf.CurrentPosition)
    Dim Y As Short = raf.Readshort(raf.CurrentPosition)
    Log(x & "  " & y & "  " & Z)

End Sub

It runs but the values do not change so I am reading the wrong data...:mad:

maybe the problem is here - writing values to addresses like this from the java code :
B4X:
   // Select Configuration register A
        // Normal measurement configuration, data rate o/p = 0.75 Hz
        device.write(0x00, (byte)0x60);
        // Select Mode register
        // Continuous measurement mode
        device.write(0x02, (byte)0x00);

I have to write data byte to an address , how to do it ?
 
Last edited:
Upvote 0

Michael1968

Active Member
Licensed User
Longtime User
Hi
I do it like this for a ads1015:

Write2(device, Array As Byte(0x01,config_reg_high,0x03), 0, 3) set 'single shot
Delay (100)' verzögerung Messung
Write(device,0x00)'set pointer to adresse 00
Read2(device,buffer,0,2) 'read value from addr 00-01
 
Upvote 0

derez

Expert
Licensed User
Longtime User
I write to the registers and read - the content changes:
B4X:
Write2(hmc,Array As Byte(0x06,0x00,0x00),0,3)
Sleep(100)
Read2(hmc,buf,0,3)
But the reading from the data registers does not change.

Does the line Write(hmc, 0x03 ) tells the device to read from 0x03 ?

Edit: the problem is that the device is faulty, it gives fix data on b4r app as well.
I'll have to check with another.
 

Attachments

  • regs.png
    regs.png
    75.2 KB · Views: 298
Last edited:
Upvote 0

Michael1968

Active Member
Licensed User
Longtime User
Does the line Write(hmc, 0x03 ) tells the device to read from 0x03 ?
it sets the Pointer to the Data Out Register.

Sorry I have no device here to play with your Code and only short time for a quick look to the datasheet.

pls check if this work:
B4X:
Sub Process_Globals
    Dim bus1 As JavaObject
    Dim hmc As JavaObject
    Dim tmr As Timer

dim hmc5883ModeRegister as int  = 0x02;
dim hmcContinuousMode as int = 0x00;

End Sub

Sub AppStart (Args() As String)
    Log("app start")
    bus1 = GetBus(1)
    hmc  = GetDevice(bus1,0x1e)

    Log(bus1)
    Log(hmc)
    '*******Write(hmc, 0x02 )
 
Write2(hmc, Array As Byte(hmc5883ModeRegister,hmcContinuousMode), 0, 2) 'Continuous measurement mode
Delay (100)' verzögerung Messung

    tmr.Initialize("tmr",1000)
    tmr.Enabled = True

    StartMessageLoop
End Sub

Sub tmr_Tick
    Write(hmc, 0x03 )
    Dim buffer(6) As Byte
    Read2(hmc, buffer, 0, 6)

    Dim raf As RandomAccessFile
    raf.Initialize3(buffer,False)

    Dim X As Short = raf.ReadShort(raf.CurrentPosition)
    Dim Z As Short = raf.Readshort(raf.CurrentPosition)
    Dim Y As Short = raf.Readshort(raf.CurrentPosition)
    Log(x & "  " & y & "  " & Z)

End Sub

best regards
Michael
 
Upvote 0

derez

Expert
Licensed User
Longtime User
I re-soldered all the pins and modified the code to your code above and it works. There is a waiting period until reading is changing after starting the device with power so be patient .
The azimuth may be to the opposite direction - depends on which side of the device is up (add/delete the - in atan2).
 

Attachments

  • hmc5883.zip
    1.3 KB · Views: 304
Upvote 0
Top