Robostix and HM55B Compass

Here is some example interface code for the HM55B Compass Module and the robostix. Thanks to Dave Hylands and others that helped increase my knowledge.

/**************************************************************************** /**
 * Copyright (c) 2007 Brian Gregory    
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 * Alternatively, this software may be distributed under the terms of BSD
 * license.
 * See README and COPYING for more details.
 * Alternatively, this software may be distributed under the terms of BSD
 * license.
 * See README and COPYING for more details.
 * See README and COPYING for more details.
 * @file  hm55b.c
 * @brief Defines api functions and support code for reading the HM55B compass.
 * @brief Defines api functions and support code for reading the HM55B compass.
 * @brief Defines api functions and support code for reading the HM55B compass.


 * 1) include 
 * 2) include 
 * 3) include 


 * 1) include "i2c-io.h"
 * 2) include "Hardware.h"
 * 3) include "Log.h"
 * 4) include "Delay.h"
 * 5) include "Timer.h"


 * 1) include "hm55b.h"

/* ---[ 4 PINS: ENABLE,CLOCK,DataIN,DataOUT - currently defined on PortC 0-3 ]--- NOTE: Connect DIN (C.3) to device Dout, and DOUT (C.2) to device Din
 * 1) define ENABLE_PORT PORTC
 * 2) define ENABLE_PIN (1<<0)
 * 3) define ENABLE_DDR DDRC
 * 1) define ENABLE_DDR DDRC


 * 1) define CLOCK_PORT PORTC
 * 2) define CLOCK_PIN  (1<<1)
 * 3) define CLOCK_DDR  DDRC


 * 1) define DIN_PORT   PINC
 * 2) define DIN_PIN    (1<<3)
 * 3) define DIN_DDR	   DDRC


 * 1) define DOUT_PORT  PORTC
 * 2) define DOUT_PIN   (1<<2)
 * 3) define DOUT_DDR   DDRC

/* ---[ commands to the device ]--- */


 * 1) define HM55B_RESET 	0x00
 * 2) define HM55B_MEASURE 	0x08
 * 3) define HM55B_REPORT	0x0C

/* ---[ status constants from the device ]--- */


 * 1) define HM55B_READY	0x0C
 * 2) define HM55B_ERROR	0x03
 * 3) define HM55B_NOINPUT 0x00

/* ---[ These are so I don't make any stupid mistakes ]--- */
 * 1) define PIN_HIGH	1
 * 2) define PIN_LOW		0
 * 3) define DDR_INPUT	0
 * 4) define DDR_OUTPUT	1

/* ---[ simplify pin access ]--- */


 * 1) define SET_PIN( port, pin, state ) (state ? (port |= pin) : (port &= ~pin))
 * 2) define GET_PIN( port, pin) ((port & pin) ? 1 : 0)

/* ---[ function prototypes ]--- */

void en( uint8_t state ); void clk( uint8_t state ); void dout( uint8_t state ); uint8_t din( void ); void shiftout( uint16_t data, uint8_t len ); void shiftin( uint16_t *data, uint8_t len );

/* ---[ initialize input/output pins and initial state ]--- */

void hm55b_init( void ) {   SET_PIN( ENABLE_DDR, ENABLE_PIN, DDR_OUTPUT ); SET_PIN( CLOCK_DDR, CLOCK_PIN, DDR_OUTPUT ); SET_PIN( DOUT_DDR, DOUT_PIN, DDR_OUTPUT ); SET_PIN( DIN_DDR, DIN_PIN, DDR_INPUT );

en( PIN_HIGH ); clk( PIN_LOW ); }

/* ---[ take a reading ]--- */ /* NOTE: To convert these to degrees use the following formula: angle = atan( -y/x ) * 180/M_PI void hm55b_read( int16_t *x, int16_t *y ) { uint16_t status = 0; uint16_t negmask = 0xF800;

en( PIN_LOW ); clk( PIN_LOW );

/* ---[ send the reset command ]--- */ en( PIN_HIGH ); en( PIN_LOW ); shiftout( HM55B_RESET, 4 ); en( PIN_HIGH );

/* ---[ send the measure command ]--- */ en( PIN_HIGH ); en( PIN_LOW ); shiftout( HM55B_MEASURE, 4 ); en( PIN_HIGH );

/* ---[ typical measurement time 40ms (by spec) ]--- */ ms_spin( 40 );

/* ---[ poll the status until we get "READY" ]--- */ do { /* ---[ send "gimme status" command ]--- */ en( PIN_HIGH ); en( PIN_LOW ); shiftout( HM55B_REPORT, 4 ); clk( PIN_LOW ); /* ---[ read status ]--- */ shiftin(&status,4); switch ( status ) { case HM55B_ERROR: LogError("HM55B: ADC overflow error\n"); en( PIN_HIGH ); return; case HM55B_READY: break; case HM55B_NOINPUT: LogError("HM55B: No input error (Device not present?)\n"); en( PIN_HIGH ); return; default: us_spin( 10 ); break; }   } while ( status != HM55B_READY );

/* ---[ read 11-bit x,y values ]--- */ shiftin(x,11); shiftin(y,11); en( PIN_HIGH );

/* ---[ sign-extend 11-bits to 16-bits ]--- */ if ( *x & (1<<10) ) { *x |= negmask; }   if ( *y & (1<<10) ) { *y |= negmask; }

}

/* ---[ set/clear relevant PINs ]--- */ void en( uint8_t state ) { SET_PIN( ENABLE_PORT, ENABLE_PIN, state );} void clk( uint8_t state ) { SET_PIN( CLOCK_PORT, CLOCK_PIN, state );} void dout( uint8_t state ) { SET_PIN( DOUT_PORT, DOUT_PIN, state );} /* ---[ read input PIN ]--- */ uint8_t din( void ) { return GET_PIN( DIN_PORT, DIN_PIN );}

/* ---[ simple shift-out and shift-in functions: would be nice to generalize these ]--- */

void shiftout( uint16_t data, uint8_t len ) {   int i;    clk( PIN_LOW ); for ( i = len-1; i >= 0; i-- ) {    // assume MSB dout( (data & (1<= 0; i-- ) {     // assume MSB clk( PIN_LOW ); clk( PIN_HIGH ); *data += (din<<i); } }

Briangregory2000 18:59, 1 June 2007 (PDT)