Topic: Initial test HMC5883L

Here you can find some examples on how to get it running.

If someone can hint me how to get the correct data I would appreciate it either via the forum or as PM.

Link to the Python sources: http://think-bowl.com/raspberry-pi/i2c- … pberry-pi/

Chrs

Ps my error:

python3 basicexample.py
Traceback (most recent call last):
  File "basicexample.py", line 8, in <module>
    print(hmc5883l)
UnicodeEncodeError: 'ascii' codec can't encode character '\xb0' in position 59: ordinal not in range(128)

With C code all works fine:
Code HMC5883L.c

/*
 * 
 * Compile with: gcc -lm -Wall -o hmc5883l smbus.c HMC5883L.c 
 * 
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/i2c-dev.h>

#define HMC5883L_I2C_ADDR 0x1e

void selectDevice(int fd, int addr, char * name)
{
   if (ioctl(fd, I2C_SLAVE, addr) < 0)
   {
      fprintf(stderr, "%s not present\n", name);
      //exit(1);
   }
}

void writeToDevice(int fd, int reg, int val)
{
   char buf[2];
   buf[0]=reg; buf[1]=val;
   if (write(fd, buf, 2) != 2)
   {
      fprintf(stderr, "Can't write to HMC5883L\n");
      //exit(1);
   }
}

int main(int argc, char **argv)
{
   int x, y, z;
   float head;
   int fd;
   int buf[16];
   
   if ((fd = open("/dev/i2c-1", O_RDWR)) < 0)
   {
      // Open port for reading and writing
      fprintf(stderr, "Failed to open i2c bus\n");
      exit(1);
   }
   
   /* initialise HMC5883L */

   selectDevice(fd, HMC5883L_I2C_ADDR, "HMC5883L");

     writeToDevice(fd, 0x3c, 0x70);
     writeToDevice(fd, 0x3c, 0xA0);
     writeToDevice(fd, 0x3c, 0x00);

usleep(67000);
     writeToDevice(fd, 0x3c, 0x03);

   while (1)
   {   

      /* select HMC5883L */

      selectDevice(fd, HMC5883L_I2C_ADDR, "HMC5883L");

      buf[0] = 0x06;
   
      if ((write(fd, buf, 1)) != 1)
      {
         // Send the register to read from
         fprintf(stderr, "Error writing to i2c slave\n");
         //exit(1);
      }
   
      if (read(fd, buf, 6) != 6)
      {
         //  X, Y, Z readings
         fprintf(stderr, "Unable to read from HMC5883L\n");
         //exit(1);
      }
      else
      {
    x = buf[0]<<8| buf[1];
         y = buf[2]<<8| buf[3];
         z = buf[4]<<8| buf[5];
         head = atan2 (y,x) * 180 / 3.14159265358979323846;

         printf("%4.0f\n", head);
    writeToDevice(fd, 0x3c, 0x03);
      }
      usleep(67000);
   }
   
   return 0;
}

Code smbus.c

/*
    smbus.c - SMBus level access helper functions

    Copyright (C) 1995-97 Simon G. Vogl
    Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
    Copyright (C) 2012    Jean Delvare <khali@linux-fr.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
    MA 02110-1301 USA.
*/

#include <errno.h>
#include <stddef.h>
#include </root/projects/BMP085/smbus.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>


/* Compatibility defines */
#ifndef I2C_SMBUS_I2C_BLOCK_BROKEN
#define I2C_SMBUS_I2C_BLOCK_BROKEN I2C_SMBUS_I2C_BLOCK_DATA
#endif
#ifndef I2C_FUNC_SMBUS_PEC
#define I2C_FUNC_SMBUS_PEC I2C_FUNC_SMBUS_HWPEC_CALC
#endif

__s32 i2c_smbus_access(int file, char read_write, __u8 command,
                       int size, union i2c_smbus_data *data)
{
        struct i2c_smbus_ioctl_data args;
        __s32 err;

        args.read_write = read_write;
        args.command = command;
        args.size = size;
        args.data = data;

        err = ioctl(file, I2C_SMBUS, &args);
        if (err == -1)
                err = -errno;
        return err;
}


__s32 i2c_smbus_write_quick(int file, __u8 value)
{
        return i2c_smbus_access(file, value, 0, I2C_SMBUS_QUICK, NULL);
}

__s32 i2c_smbus_read_byte(int file)
{
        union i2c_smbus_data data;
        int err;

        err = i2c_smbus_access(file, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data);
        if (err < 0)
                return err;

        return 0x0FF & data.byte;
}

__s32 i2c_smbus_write_byte(int file, __u8 value)
{
        return i2c_smbus_access(file, I2C_SMBUS_WRITE, value,
                                I2C_SMBUS_BYTE, NULL);
}

__s32 i2c_smbus_read_byte_data(int file, __u8 command)
{
        union i2c_smbus_data data;
        int err;

        err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
                               I2C_SMBUS_BYTE_DATA, &data);
        if (err < 0)
                return err;

        return 0x0FF & data.byte;
}

__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value)
{
        union i2c_smbus_data data;
        data.byte = value;
        return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
                                I2C_SMBUS_BYTE_DATA, &data);
}

__s32 i2c_smbus_read_word_data(int file, __u8 command)
{
        union i2c_smbus_data data;
        int err;

        err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
                               I2C_SMBUS_WORD_DATA, &data);
        if (err < 0)
                return err;

        return 0x0FFFF & data.word;
}

__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value)
{
        union i2c_smbus_data data;
        data.word = value;
        return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
                                I2C_SMBUS_WORD_DATA, &data);
}

__s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
{
        union i2c_smbus_data data;
        data.word = value;
        if (i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
                             I2C_SMBUS_PROC_CALL, &data))
                return -1;
        else
                return 0x0FFFF & data.word;
}

/* Returns the number of read bytes */
__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values)
{
        union i2c_smbus_data data;
        int i, err;

        err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
                               I2C_SMBUS_BLOCK_DATA, &data);
        if (err < 0)
                return err;

        for (i = 1; i <= data.block[0]; i++)
                values[i-1] = data.block[i];
        return data.block[0];
}

__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
                                 const __u8 *values)
{
        union i2c_smbus_data data;
        int i;
        if (length > I2C_SMBUS_BLOCK_MAX)
                length = I2C_SMBUS_BLOCK_MAX;
        for (i = 1; i <= length; i++)
                data.block[i] = values[i-1];
        data.block[0] = length;
        return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
                                I2C_SMBUS_BLOCK_DATA, &data);
}

/* Returns the number of read bytes */
/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
   ask for less than 32 bytes, your code will only work with kernels
   2.6.23 and later. */
__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length,
                                    __u8 *values)
{
        union i2c_smbus_data data;
        int i, err;

        if (length > I2C_SMBUS_BLOCK_MAX)
                length = I2C_SMBUS_BLOCK_MAX;
        data.block[0] = length;

        err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
                               length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
                                I2C_SMBUS_I2C_BLOCK_DATA, &data);
        if (err < 0)
                return err;

        for (i = 1; i <= data.block[0]; i++)
                values[i-1] = data.block[i];
        return data.block[0];
}

__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length,
                                     const __u8 *values)
{
        union i2c_smbus_data data;
        int i;
        if (length > I2C_SMBUS_BLOCK_MAX)
                length = I2C_SMBUS_BLOCK_MAX;
        for (i = 1; i <= length; i++)
                data.block[i] = values[i-1];
        data.block[0] = length;
        return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
                                I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
}

/* Returns the number of read bytes */
__s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
                                   __u8 *values)
{
        union i2c_smbus_data data;
        int i, err;

        if (length > I2C_SMBUS_BLOCK_MAX)
                length = I2C_SMBUS_BLOCK_MAX;
        for (i = 1; i <= length; i++)
                data.block[i] = values[i-1];
        data.block[0] = length;

        err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
                               I2C_SMBUS_BLOCK_PROC_CALL, &data);
        if (err < 0)
                return err;

        for (i = 1; i <= data.block[0]; i++)
                values[i-1] = data.block[i];
        return data.block[0];
}