![]() | ![]() | ![]() |
| |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
![]() |
| | Tools |
| | #1 |
|
I feel like an idiot here, and I can't believe there aren't any examples of this on the web already somewhere... Here is my schematic, very straight forward. 16F877 chip with a MAX232 interface chip, and a Devantech CMPS03 compass module. ![]() And here is my code (written in CCS-C): Code: #include <16F877.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,Fast,sda=PIN_C4,scl=PIN_C3)
long read_compass()
{
long value;
i2c_start();
i2c_write( 0xC0 ); // The address of the compass (READ LOW)
i2c_write( 0x02 ); // Command (read 360 degrees)
i2c_start(); // Restart to change data dir
i2c_write( 0xC1 ); // The address of the compass (READ HIGH)
// Read 2 bytes (HI/LO) and combine into one LONG
value = i2c_read() << 8; // Read the HI value * 256
value = value + i2c_read(); // Read the LO value and add it
i2c_stop();
return( value );
}
void main()
{
long heading;
setup_adc_ports(AN0_AN1_AN2_AN3_AN4);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
do
{
// Take a compass reading
heading = read_compass();
printf("%Lu\r\n", heading );
delay_ms( 1000 );
} while( TRUE );
}
Code: 65534 1023 2710 65535 2710 65535 2713 65535 2706 65535 2713 245 65534 1023 2711 65535 2710 65535 2712 65535 2716 1525 -- Rob | |
| |
| | #3 | |
| Quote:
| ||
| |
| | #4 |
|
And people argue that c makes code more portable. That code should work in any compiler. You can turn it into a the relevant functions to make it more readable once you have it working. It will also confirm that your hardware is not the problem. Mike. | |
| |
| | #5 |
|
Your output is almost correct except, once you get proper value ranging in 2710-2716 and second time 0xFFFF (65535) just check if you are reading CMPS03 very fast. Just try slowing down the reading. I haven't Checked your code but from output it seems this way
| |
| |
| | #6 | |
| Quote:
"There is no synchronism between the PWM or I2C outputs and the conversion. They both retrieve the most recent internal reading, which is continuously converted, whether it is used or not." Also note the ~1024 values and the 245 mixed in there as well, so which ones are correct? | ||
| |
| | #7 |
|
hi rob, I expect you have checked the RS232 system and 'maths' using a few fixed test values, rather than real time data from the Compass? Is the 50MHz xtal on the circuit a typo? EDIT: OK Rob, Its best to ask. I dont use C, sorry.
__________________ Eric " Good enough is Perfect " I will NOT answer PM's requesting technical help, please use the Forum PIC tutorials: Nigel's www.winpicprog.co.uk/ Bill's: www.blueroomelectronics.com/ Last edited by ericgibbs; 23rd May 2007 at 06:48 PM. | |
| |
| | #8 | |
| Quote:
I have been working with the SX28 chips recently and they run a 50 Mhz resonator.I am running the PIC at 20 Mhz. They data being sent over the RS232 appears to be working fine. | ||
| |
| | #9 |
|
Can you try this? Code: long read_compass()
{
long value;
i2c_start();
i2c_write( 0xC0 ); // The address of the compass (READ LOW)
i2c_write( 0x02 ); // Command (read 360 degrees)
i2c_start(); // Restart to change data dir
i2c_write( 0xC1 ); // The address of the compass (READ HIGH)
// Read 2 bytes (HI/LO) and combine into one LONG
value = i2c_read(); // Read the HI value * 256
value = value << 8;
value += i2c_read(); // Read the LO value and add it
i2c_stop();
return value;
}
| |
| |
| | #10 | |
| Quote:
value = i2c_read() * 256; value = i2c_read() << 8; value = i2c_read(); value *= 256; value = i2c_read(); value = value << 8; and value = value + i2c_read(); value += i2c_read(); all had the same results. | ||
| |
| | #11 |
|
Maybe you should try the example code as I suggested 2 days ago. At least you would now know if the problem is with the built in routines. BTW, how does the compiler know when you want to send a repeated start bit? Does the compiler have a different command? Mike. | |
| |
| | #12 | |
| Quote:
With the CCS compiler, if you send another i2c_start without sending an i2c_stop it assumes you want a restart. | ||
| |
| | #13 |
|
Surely it's very simple to change the code so it does work. All it is doing is writing to SFRs and setting/clearing bits. Mike. | |
| |