Sure Electronics Compass Module Dc-SS503 I2C


I'm very new to MCU's so take it easy please. I'm disabled and living on a pension so doing things cheap helps alot. I saw these modues and being cheap but using an ok sensor chip thought I woud give it a go. Despite only seeing a single post on another MCU platform someone more experienced than me having issues.

Got this working on an I2C bus speed of 100K and just internal pull ups. The compass module has soldered in 4.7K but seems ok on 400K and internal pull ups disabled. Using copper hook up wire around a foot. I think this is a problem with other devices on the bus.

For around $15.00 shipped, a cheap alternative. Calibration does move a bit but I've got alot of wireless sources around maybe ? but only moving by a few degrees and reset/set the sensor seems to work.

Using a Seeed Mega and the Arduino 17.

Now tryng the improved version with UART version but having trouble. Serial ports on the seeduino loop back on each other fine, so waiting for some tech replies from Sure.

These chips are very sensitive to electro magnetic fields including mobiles and wireless and be careful with ohm meters and soldering irons ferrous connectors...LOL.

There are some funnies in the Sure electronics data sheet, but reading all of them it's sorted.

I2C data does not appear in the stated order, not sure if that is a wires library buffer issue or the slave device, I do not have a scope or data probe.

Also the order you address and write to the slave status register to request a reading is a bit ambigous in the sure data sheet but clear correct in the memsic datasheet for the sensor/i2c chip.

Not sure what the rules are on posting code and methods but more than happy to share


Thanks for sharing. Posting code is always a good idea.
Also, the link to the Sure sensor would be helpful, as well as photos, videos of it working etc.

Great find. See if you can get some demos up. I've been looking for a compass

A cheap compass is always a good thing! Can we get a link? And I'd also like to see the I2C part of the code.

Been held up trying to rebuild someones big usb enclosure, turns out it's a linux jbod......with t drives using non standard filessytems so .....

Link to site

module part numbers are so search

DC-SS503 i2c only

DC-SS504 i2c with uart can't talk to the uart yet, but I2C works

know there is both an Internet and eBay site(s), check out the overall cost inc shipping for the best deal.

select part number, wait for drop down list, they are down the very bottom, sometimes it will filter...
big zip file has memsic app notes as well

The I2C code is the easy bit, it's the calibration etc, I am writing some notes now, it's not a case of getting a direct bearing. Info is in the memsic app notes You also have to calibrate the compass and you need to obtain values for that, which go back ionto the maths.

I2C code is simple, not sure if Ihave used wiire.available() properly but it works.

There's afew more things , the modules have built in 4.7K pull-ups. they work fine with the twi.h internal pullup's on by default setting and 10-12 inches of hookup wire , I'm using a seeduino mega so no discrete pull ups on the controller board. I have not tested with other devices yet on the bus.

I had an issue with the first module, which is being replaced the straight I2C only model, but this works fine on the improved with uart (504). I do not expect there to be aproblem on the 503.
Sure were very quick to replace. they only wanted code and data.

The sample I wrote will test the compass out and will alow you to calibrate via dumping to serial console copy paste to spreadshhet. That worls well as it does not seem to need calibrating often, saves memory and code and allows you to chart the data .....which is useful when you have stray mag fields

// I left this is as LCD is easy
#include <LiquidCrystal.h>

// I2C example template I used, I also went to a 8 bit port expander to test out my I2C when I had issues so thanks helped me heaps!!!!
///Test program for PCF8574A I2C I/O expander from Futurlec
// - Blinks all pins low then high - 1 second cycle.
// by pclyne

#include <Wire.h>

// you need the maths library for arctan2 

#include <math.h>

LiquidCrystal lcd(26, 27, 22, 23, 24, 25);           

// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// From the Memsic data sheet, def I2C address for compass chip is 60 as a 7 bit binary number, it is built in no physcial address can be set 
// then write memory location which is 00Hex, 
// then write 01 Hex for read, 
// set and reset 04Hex or x02Hex need to be written to the single "status" register

#define CARD_ADR B0110000  
int myADDR = CARD_ADR;
byte comp_reg_addr  = B00000000;
byte read_comp      = B00000001;
byte reset_comp     = B00000100;
byte set_comp       = B00000010;

// used to control the cardSet function, which I have commented out of loop but when in, you do n;t need to hammer the chip please read comments in the function
boolean compass_set = false;

// "p" should sets the size of an array which in this sample code , when a specifed number of data samples has been taken a dump occurs to the comsole 
// copy the data by highlighting the values and controlc to copy and paste into a spreadsheet....quick and dirty more later on that
// and paste into a spreadsheet use that to do a quick calc for the calibration

// When you calibrate the compass, you turn it through 360 degrees and take the raw outputs of the sensor. You then take max and min values and then do a bit of calculation
// So you need an area which is easy to ove your test rig around 1.5 rev.s. you can vary delays etc after a bit of practice it's a second ot so and you can judge a turn to a few degrees which is accurate enough

// you need around 30 points per revolution of the compass I would alwayd do 1.5 revolutions so 45 is a good number, there's a potential array over run or pointer going out of bounds so you need to change an loop
// at the bottom of compassReader() if you decrease the value of "p". P should be  a constant but I will you to change these values as you see fit

// As you turn the compass through the main north south east west points make very small changes, this is important in the calibration process

// store_x and store_y will contain the raw output of the sensor, WHY a big array we need some data points to calc the calibration, "p" sets the size for these arrays
// when not calibrating this can be changed
// need to work out how to do an arduino min and max on the arrays, at a later date when I add a calibration function, 

// I am yet I am not sure how often calibration is required, I have seen some drift over the past few days around 5 degrees but that maybe because of a hspda modem not too far away

// now I have the lcd set up I've left the calls to the LCD in but commented out.

// setup arrays for raw sensor data
int p = 0; 
// P is used as an index for store_x and y, dirty I've used the index in 2 functions sorry ba style but this is demo code for calibration
double  store_x[55];
double  store_y[55];

// IMPORTANT I've left a hard coded value in the very bottom of the compassReader() which is also set to 45 so if you change the value assigned to P change that also
// it will run the array put of bound s or you want a big sample spend hours slowly rotating the compass and only get 45 points....


void setup() {
Wire.begin(); // needed this sets the controller i2c as master () is empty

// from liquid crystal
// I used a SEEED Mega, I2c @ default 100K,  ardiono/seeduino internal pullups enabled by def by Wires Library
// amend this when I have tested at 400K and mixed in some other I2C devices
// by the way the compass modules have internal resistors on both SDA and SDL 4.7K

void loop() {

Serial.print("Lets talk to the compass, sample count = ");

//Serial.println("!!!!!!!!!!Card set!!!!!!!!!!!!!!!!!!!");
// see cardSet() comments, disable if not required
//  compassSet(); 
// delay(5);

// A delay for calibration gives you tme to move the compass and knock all the wires out......
// compass needs a few microseconds fro power on or set reset to recover
// Never moind the more you practice the better you get, after a few goes you can quite accurately rotate the comapss by 10 degrees and in 1 second
// reads the compass sensor over I2c

void compassReader() {
  // delay so when looping you give the compass time for a new measurement I think the delay is 5ms between samples
// the compass read should return 5 bytes with 4 bytes containing sensor values  
  byte comp_status = 0;
  byte avail = 0;
  byte x_msb = 0;
  byte x_lsb = 0;
  byte y_msb = 0;
  byte y_lsb = 0;

// first byte is a status byte I'm currently using that to control the wires reads 

// The i2c bus moves the remaining bytes according to the datasheets in order they are 

// x msb
// x lsb
// y msb
// y lsb

// the msb seems to be 0000 XXXX in binary watch the order carefully if you have issues
// lsb XXXX XXXX in binary

// Next we need to do the read request there is alittle ambiguity over wording in a section of a datasheet so check the MEMSIC one it is crystal clear 
// address of the compass module status register 
  // command to address status register or memory location
  // Wires will not write a command to compass status register to read compass sensor
  // you must use the wires end transmission
  // sensor needs a bit of wake up time and take a fresh sample
  // now read the data from the sensor, address and request or hope for 5 bytes
  Wire.requestFrom(myADDR, 5);
  // read status, seems to be 5  should put some handling on this for other status values.....
  avail = Wire.available();
   //avail = avail ;
  Serial.print("Wire Available = ");
  // just want to keep an eye on the status as not yet happy I understand what is being passed as a status value but it
  // has worked well for 4 days
  if ( avail == B00000101 ) {
  avail = avail -1;
  while( avail > 1 ) {
       // comp_status = Wire.receive();
        x_msb = Wire.receive();
        avail = avail -1;
        x_lsb = Wire.receive();
        avail = avail -1;
        y_msb = Wire.receive();
       avail = avail -1;
        y_lsb = Wire.receive();
        avail = avail -1;
       // comp_status = Wire.receive();
       // avail = avail -1;
  else ( Serial.println )("compass sensor status not 5, probable I2C read error, or sensor recovering"); 

int x = (int) x_msb;
x =  x_msb << 8;
int x_small = (int) x_lsb;
int x_big= x | x_small;

int y = (int) y_msb;
y  = y_msb << 8;
int y_small = (int) y_lsb ;
int y_big= y | y_small;

Serial.print("Raw Sensor Values for x and raw_y");

Hi davo,

I picked up one of these modules the other day to have a play.

I've read through the documentation and I noticed the need to calibrate but they did mention a Z-axis which we do not have?

May I ask how you calibrated your device? I'd like to use it as a cheap method of identifying magnetic north. I presume you need to convert the XY into polar?


sorry been ill

In i2c mode ?

The ones I have are only dual axis so only x and y, NO z

but from what I have seen no need for z if the robot is near horizontal and the local earth's magnetic field is fairly horizontal where you live.

Overview of Process.....

you rotate the compass module around I would recommend 1.5 revs, each increment around 5 to 10 degrees.

You record the outputs of the x y axis

The memsic calibration app note, tells you to get a max and min value for both x and y

Using the memsic app note you work out from the readings two values for both x and y

  1. a peak or memsic call this a "sense" value
  2. the "offset" which is the null point

You should expect offset to be around 2048.

the peak seems to be 128 ish.

the MEmsic app note then gives you a formula, to work out the unit circle sin and cos angle theta. This basically gives you a sin and cos value for y and x respectively, but this is unit circle not bearing.

Using the sign ( pos or neg) of x and y you can work out the unit circle quad angle you are in and then use the appropriate unit circle formala depending on the quadrant.


In practice the code will do everything except the calibration.

If you start the rotation the code dumps the last 45 values to the console, I copy paste into a spreadsheet then get the values from that. Then enter them into the code.


I can email/pm the spreadsheet i have it's Openoffice calc 3.0xx

but it only takes a few minutes to set one up for yourself.

Good luck dave

Sorry to ask this, but english is not my native language and want to make sure, this compass module is nothing more than this ? The electronic version ?

Asking because if it´s an positive answer I have great interest on it.



Hi Dave,

Ah so you basically just create a lookup table?

If X and Y = something then it's 0* degrees or North.

@Dan poster

Yes it has the same ability as the compass you posted

Just to clear things up, the memsic app note of calibration is really several stages.

  1. calibration...getting max and min values for the raw output of x and y. then calc sense and offset, which is peak and null.
  2. linearisation or normalisation as I call it....which converts the raw_x and raw_y to a range of -1 through 0 to 1
  3. then we do unit circle maths.

Just to get north!

You could but you would still need to calibrate, ie record the full range of raw_x and raw_y from the sensor.

You would need the midpoint or offset for raw_y as this equates to a sine of 0 for 0 degrees

You would need the max of raw_x as this is the equivalent to a cosine of 1 for 0 degrees.

Both these together would give you 0 degress.

If you are using the raw values you will need to calibrate very very carefully.

Hope this helps, but to me the compass is worth doing properly it is quite accurate. I appreciate you have different requirements and needs and have to budget memory and cpu


I decided to drop Memsic an email from work and they came back with this answer for converting XY to the associated degrees.


Whether it works I'm not sure. I need to spend some time with this device. I'm not entirely sure how to calibrate it by hand and without an existing compass

Sorry for the rather brief post. I'm trying to get my head around the math required to pull this off - sadly that isn't my strong point


just back from a few days in Sydney, sorry...

the code I posted is truncated, sorry the original post was requesting the i2c part only.

there's a function missing which has the memsic formula's in it!

I'll pm that to you now and maybe that'll help. then sort out where/how I'll post it here!

My apologies.


Thanks Davo, feel free to send any code or documents to my catch all account here:
tmcsmiles (a-t) g-mail dot. com

(I'll leave you to decode that, bloody spammers ;))

code was sent

do you use open office got a speadsheet will get you going quickly


I am a newcomer .
I purchasd the DCss503 several months ago and was a bit disgusted thet there was no code for the i2c. I tried the i2c on pickaxe but could not get it to work
I have purchased microchip pickit2 with Mlab but do not have C assembler.
I was very pleased to read that the 503 actually works.
However as I am retired it is about 40 years since I wrote assembler code and I am still working up to write the i2c code.
I have pic 16F628A so if any one can give me assembler code for microchip 16Fxxx it would be great
Thanks ;D

the arduino fourm is a place for people to discuss hardware and software for a simplified rapid development system based on atmel microcontrollers

I doubt you will find a large support for other platforms in asm here

(besides its a standard issue lib with mplab, what you would use on a pic16x)

Sorry I can't help with a PIC or coding it, are you getting data off the i2c bus?

From there it's easy just some maths I can help you with that.

There's another version of the module out now with a PIC that you use the serial comms you just send a string and it rplies with "angle xxx" that may be easier.

I choice arduino as a platform because the "opensource" nature and the c style development environment.

assembler/machine thanks only if I reallly really had to.


Hi Dave
Thanks for your reply
I considered buying the unit with the PIC included using UART but I would still be faced with having to modify it for my needs. It would be better for me to buy the PIC with the I2c interface or alternatively find out how to reprogram it in situ
I have not tried to write the code for I2c at this time as I am still working up my code skills
However I was pleased to hear that you had got these to work. I note that you had some initial problems with the UART but your later note indicates you have overcome this.
Your comments have indicated to me that it is worth my while continuing. Thanks
Regards ;D

i got the i2c working, but not the uart and the uart is on the backburner for now. I need a logic probe or scope and that's down the line the i2c works well so staying with that and will only consider the uart if memory etc gets constained.

why assembler ? no no and no if I do n;t have to I won't hence arduino.