CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Adafruit Magnetometer Compass Board and New Haven Serial LCD

 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
Arizona Chris



Joined: 20 Dec 2014
Posts: 69
Location: Arizona

View user's profile Send private message Visit poster's website

Adafruit Magnetometer Compass Board and New Haven Serial LCD
PostPosted: Sun Jun 21, 2015 8:23 pm     Reply with quote

Greetings all,

I wish to share with you my experiences in using these two new ground breaking products, one superb HMC5883L breakout board and a new series of LCD displays from Jameco. I have to first tell you I have spent every waking hour in the past month diving head first into the triple axis magnetometer learing the significance of every byte of data and pouring over the graphs and data sheets on this very fine Honywell product.

Several manufacturers sell breakout boards for this tiny surface mount part, but let me tell you this - The Adafruit version is the only one with complete 5v interface circuitry built in, and the a killer $9 price too! I bought a handful of them and they work very well indeed.

You can read about this product here: http://www.adafruit.com/product/1746

Second, Jameco now sells a new line of LCD displays that are serial driven, have a awesome contrasty transreflective screen and are a fraction of the cost of anybody elses in this quality range. I'm using this LCD - a 20 x 4 model in the code below, and you can use the functions/drivers I have in this program to operate the display. You might
buy a handful of these as well. ;)

Here is a link to the Jameco catalog with the displays:

20 x 4: http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_2118686_-1

16 x 2: http://www.jameco.com/webapp/wcs/stores/servlet/Product_10001_10001_2118651_-1

I bought several of each.

About the Magenetometer.

This is a triple axis magnetometer which uses three tiny magneto-resistive sensors, made of a nickel iron alloy called "permalloy". The chip mounts them as part of a bridge and includes a digitally selectable internal amp to select different field ranges. A 12 bit a/d converter sends all data out a two wire serial port using I2C format.

If your are unfamiliar with I2C format, here is a nice small write up I found that explains it pretty well. After reading this you will get a good handle on what the code is doing:
http://robot-electronics.co.uk/acatalog/I2C_Tutorial.html

Description of the code below. The code is written as a continous loop that reads the magnetometer, sends the results to the display. I wrote everything up as a few separate functions to allow more flexibility in the applications. Our use for now is robot navigation.
Code:

//****************************************************************************
//Chris Schur
//Adafruit HMC5883L magnetometer -  16F877A)
//Date:  6/16/15
//****************************************************************************

/*Description of this Program:

Version 8 - continuous reading version of 7.*/


//I/O Designations ---------------------------------------------------

// RB0:  Status LED output
// RB1:  LCD output
// RB2:  Piezzo Speaker output

// RC3:  INPUT - SCL - to magnetometer
// RC4:  INPUT - SDA - to magnetometer

//--------------------------------------------------------------------

//Include Files:
#include <16F877A.h> 
#include "math.h"  //required for compass

//Directives and Defines:
#fuses NOPROTECT,HS,NOWDT   //xtal is used
#use delay(crystal=10MHz)   //xtal speed

//set up i2c - data, clock pins are here hardware on 877a.part uses slow spec. 
#use I2C(master, sda=PIN_C4, scl=PIN_C3, slow, FORCE_HW)  //HARDWARE IMPLEMENT

#use fast_io(ALL)          //must define tris below in main when using this

// HMC5883 required Registers
#define W_DATA   0x3C     //Used to perform a Write operation
#define R_DATA   0x3D     //Used to perform a Read operation
#define CON_A    0x00     //Sets up measurement and sampling parameters.
#define CON_B    0x01     //Send continuous MeVARurement mode.
#define MOD_R    0x02     //Read/Write Register, Selects the operating mode. Default =

Single meVARurement
#define X_MSB    0x03     //Read Register, Output of X MSB 8-bit value.
#define X_LSB    0x04     //Read Register, Output of X LSB 8-bit value.
#define Z_MSB    0x05     //Read Register, Output of Z MSB 8-bit value.
#define Z_LSB    0x06     //Read Register, Output of Z LSB 8-bit value.
#define Y_MSB    0x07     //Read Register, Output of Y MSB 8-bit value.
#define Y_LSB    0x08     //Read Register, Output of Y LSB 8-bit value.

//for LCD:
#use rs232(baud=9600, xmit=Pin_B1, bits=8, parity=N,stream=SERIALNH)

//****************************************************************************
//Global Variables:
int16 n; //counting var

int8 M_data[6]; //Array - 6 units 8 bit Measured datas (compass)
int16 Xm=0,Ym=0,Zm=0; //16 bit X,Y,Z variables (compass)
float bearing;  //final compass reading.

//****************************************************************************
   
//Functions/Subroutines, Prototypes:

//for compass only:
void hmc5883_write(int add, int data);  //write to function
int16 hmc5883_read(int add);            //Read from function
void hmc5883_init();                    //Sets up starting conditions
void read_reg();                        //reads compass registers, calc xyz
float calc_heading();                  //calculates returns bearing.

//For New Haven LCD only:
void LCDCLR();
void LCDLN2();
void LCDLN3();
void LCDLN4();

//****************************************************************************
//-- Main Program
//****************************************************************************

void main(void) {

// Set TRIS I/O directions, define analog inputs, compartors:
      set_tris_A(0b11111);
      set_tris_B(0b11001000);
      set_tris_C(0b11111111);  //set both sda and sclk for inputs (float)
      set_tris_D(0b11111111);
      set_tris_E(0b111);

   output_low(Pin_B0);  //status off
   delay_ms(1000);  //LCD warmup time
 
   //SET BRIGHTNESS OF LCD TO MID RANGE.  (DEFAULT = 1)
   fputc(0xFE,SERIALNH);   //Command Prefix
   fputc(0x53,SERIALNH);   //set cursor command
   fputc(8,SERIALNH);   //LCD backlight - 4 is mid 0-8
   
   delay_ms(250);
   
   LCDCLR();
   delay_ms(250);
   fprintf(SERIALNH,"CBOT-1");
   delay_ms(250);
   LCDLN2();
   fprintf(SERIALNH,"READY");
   
   //start compass single read: ----------------------------------------------
   
   hmc5883_init();   //Initialize compass settings.
   
   while(true)  {
   
   read_reg();  //read compass registers, calc xyz
   
   bearing = calc_heading();  //calculates & returns final compass bearing
 
   LCDCLR();
   delay_ms(10);
   fprintf(SERIALNH,"H= %f  ",bearing);
   delay_ms(50);
 
  }
 
}  //niam

//********* Functions which have prototypes at top of program ****************

//for compass only:
void hmc5883_write(int add, int data)  {
         i2c_start();
         i2c_write(W_DATA);      //0x03
         i2c_write(add);
         i2c_write(data);
         i2c_stop();  }
     
int16 hmc5883_read(int add)  {
         int retval;
         i2c_start();
         i2c_write(W_DATA);      //0x03
         i2c_write(add);
         i2c_start();
         i2c_write(R_DATA);      //0x3D
         retval=i2c_read(0);
         i2c_stop();
         return retval;  }
 
void hmc5883_init()  {
         hmc5883_write(MOD_R,  0x00);     //0x02, 0x00
         delay_ms(100);
         hmc5883_write(CON_A,  0x10);     //0x00, 0x10
         delay_ms(100);
         hmc5883_write(CON_B,  0x20);     //0x01, 0x20
         delay_ms(100);  }
         
void read_reg()  {   //read compass registers
         //read registers in compass
   M_data[0]=hmc5883_read(0x04); //Read X (LSB)
   M_data[1]=hmc5883_read(0x03); //Read X (MSB)
   M_data[2]=hmc5883_read(0x08); //Read Y (LSB)
   M_data[3]=hmc5883_read(0x07); //Read Y (MSB)
   M_data[4]=hmc5883_read(0x06); //Read Z (LSB)
   M_data[5]=hmc5883_read(0x05); //Read Z (MSB)
   
   //Create Word from Highbyte and Lowbyte data:
   Xm=make16(M_data[1],M_data[0]);
   Ym=make16(M_data[3],M_data[2]);
   Zm=make16(M_data[5],M_data[4]);
   
   }

float calc_heading()  {
   //Calculate using math.h function the bearing.
   float Heading = atan2((signed int16)Ym,(signed int16)Xm)* 180 / pi + 180;
   
   //correct for this equation yielding values 180 off:
   if (Heading < 180)
      Heading = Heading + 180;
   else if (Heading > 180)
      Heading = Heading - 180;
   else if (Heading == 180)
      Heading = 0;
     
   return Heading;

}

//For New Haven LCD only:
//Clears LCD Display:
void LCDCLR()  {
   fputc(0xFE,SERIALNH);   //Command Prefix
   fputc(0x51,SERIALNH);   //Clear screen
}

//Sets LCD to line 2 start point
void LCDLN2()  {
   fputc(0xFE,SERIALNH);   //Command Prefix
   fputc(0x45,SERIALNH);   //set cursor command
   fputc(0x40,SERIALNH);   //Set cursor to next line, pos 40 = start line 2
}

//Sets LCD to line 3 start point
void LCDLN3()  {
   fputc(0xFE,SERIALNH);   //Command Prefix
   fputc(0x45,SERIALNH);   //set cursor command
   fputc(0x14,SERIALNH);   //Set cursor to next line, pos 14 = start line 3
}

//Sets LCD to line 4 start point
void LCDLN4()  {
   fputc(0xFE,SERIALNH);   //Command Prefix
   fputc(0x45,SERIALNH);   //set cursor command
   fputc(0x54,SERIALNH);   //Set cursor to next line, pos 54 = start line 4
}
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group