PDA

View Full Version : Programming a Devantech Magnetic Compass - CMPS03


kE7JLM
09-27-2007, 10:17 AM
I am using a 2004 FIRST Robot Controller, I need help getting the 0-5 read show up on the the IFI Dashboard (I know it will will show as 0-255). So far I have plug it into an analog port and made an aliases-

#define Compass ADC_CH3

I also call it from user_routine_fast-

{
pwm13 = Get_Analog_Value(Compass)/4.023;
printf("%d", pwm13);
}

Can someone show me what is wrong? I can send you the code if you would like.

Qbranch
09-27-2007, 11:36 AM
You have datatyping issues. The result of Get_Analog_Value() (if its like the one in the '06 controller) returns an unsigned integer... and your dividing by a floating point... and assiging to an unsigned character!

You might try:

{
unsigned int temp;
temp = Get_Analog_Value(Compass);
temp *= 4023; //fraction version of
temp /= 1000; //your conversion factor - avoid floating point
pwm13 = (unsigned char)temp;
printf("%d", pwm13);
}

kE7JLM
09-27-2007, 06:31 PM
did not work. Any Ideas why?

Alan Anderson
09-27-2007, 09:50 PM
(One bit of general advice: avoid using printf() in the "fast" section. It's too easy to get characters trying to go out faster than the serial port can handle them.)

You say it doesn't work, but we don't really know what "it" or "work" mean to you. What do you expect to happen, and what is happening instead?

Gdeaver
09-27-2007, 11:22 PM
Interfacing a digital compass is a good project. However, after you master the compass you may not find it meets your needs. These devices measure the earths magnetic field in 2 axis and can give orientation. The problem is a FRC robot usually has some ferrous metal in it and our motors have some big powerful magnets in them. Even if you mounted the compass far away from these fields, they will affect them. You can calibrate for hard iron effects but the margin of error is going to be less than desirable. I played with a PNI VX2e and the best I could get with a FRC robot environment was +- 5 degrees. That was with out the motors running. If another robot is near you and it has allot of ferrous metal, The compass is going to get real bad. I have given up on digital compasses for FRC uses. For the tele-operated part of the match the organic analog computer- sensor network between the drivers ears may be your best bet for detecting the robots orientation. Don't give up though. The skills you learn for the compass have other applications for our robots.

kE7JLM
09-28-2007, 12:31 AM
Ok I was vague on the problems with the compass, so here is the problem-
I am using the IFI Dashboard to read the PWM output (0-255) but when I turn on the robot the value shots up to 60 (not exactly) then quickly goes back to 0 then repeats the process at a slower rate. Then about a minute in to the process it eventually stops at 28. Nothing affect the process, if I turn the compass or put it by the motors it stays the same.
This is the Aliases-
* Below are aliases for reading an analog voltage on the ANALOG INPUTS
* using the Get_Analog_Value() function.
*/
#define Temp_Guage ADC_CH0
#define Pressure_Guage ADC_CH1
#define rc_ana_in03 ADC_CH2
#define Compass ADC_CH3
#define rc_ana_in05 ADC_CH4
#define rc_ana_in06 ADC_CH5
#define rc_ana_in07 ADC_CH6
#define rc_ana_in08 ADC_CH7
#define rc_ana_in09 ADC_CH8
#define rc_ana_in10 ADC_CH9
#define rc_ana_in11 ADC_CH10
#define rc_ana_in12 ADC_CH11
#define rc_ana_in13 ADC_CH12
#define rc_ana_in14 ADC_CH13
#define rc_ana_in15 ADC_CH14
#define rc_ana_in16 ADC_CH15

#define SIXTEEN_ANALOG ADC_16ANA /* All analog */

This is how I call it-
pwm11 = Get_Analog_Value(Pressure_Guage)/4;
pwm12 = Get_Analog_Value(Temp_Guage)/4.023;
pwm13 = Get_Analog_Value(Compass)/4.023;
{
unsigned int temp;
temp = Get_Analog_Value(Compass);
temp *= 4023; //fraction version of
temp /= 1000; //your conversion factor - avoid floating point
pwm13 = (unsigned char)temp;
printf("%d", pwm13);
}


Thank you!
By the way, I am using the Devantech Magnetic Compass - CMPS03 on a ROV so there no other robots around and also the motors we are using are about a 1.5 feet away and are small. (Nothing like the big CIMs) The only things that could interfere is the Aluminum water proof housing, or the electronics beside the compass.


Heres a link to some Pictures if that could help you- (The compass is not in these pictures but is inside the Aluminum water proof housing)
http://picasaweb.google.com/KE7JLM/RobotAllan

Phil Mack
09-28-2007, 12:39 AM
Can someone show me what is wrong?

This compass does not output an analog voltage. It outputs a pulse with a specific time, or byte values can be read over an I2C bus.

The timing pulse is high for 1mS to 37mS in 0.1mS increments and then low for 65mS. The rise and fall time is much faster (a few nanoseconds if i recall, but i cant find the datasheet right now). The ADC in the robot controller works fast enough that whenever it measures the voltage, the voltage will be either high or low... not in between.

You essentially have three options... use an additional micro controller, design a circuit, or write interrupt driven software.

The first option is the easiest (in my oppinion) and will give you the most accurate results. You can purchase or build an I2C master with an RS232 interface that the robot controller can communicate with. One elegant implementation of this is available at http://www.emicros.com/i2c232.htm for about $90, but one could be built for much less than that (I built a less elegant one in college using an AVR Butterfly that cost $20 and that was processing overkill.)

The second option would require a series of filters and amplifiers that would translate the pulse into a voltage. This one is a bit outside of my field of expertise, so I'll leave an explanation to someone else, because it would be a relatively complex circuit.

The third option to interface with this compass you have to measure the length of the pulse width using on board timers triggered by interrupts. You would want to scale one of the timers to use increments fairly close to but not over .1ms. The pulse out on the compass would trigger an interrupt, at which point the timer's count would be noted. The (count_at_fall - count_at_rise)/clock_scale_factor would be the width of the pulse and also your heading.

I hope this helps.
~Phil

Gdeaver
09-28-2007, 08:23 AM
Is this an underwater ROV? If so you have another problem. The compass you're using is a 2 axis one. If there is any tilt the reading will be way off. For apps that tilt there are 3 axis compasses with accelerometers that can compensate and give good accuracy. There are models that are ready to go with an easier RS232 interface that would work better for this app. However, they are hundreds of dollars.