|
|
View previous topic :: View next topic |
Author |
Message |
victor_constantin
Joined: 14 Dec 2010 Posts: 10
|
SPI issues with 18F2420 and AS5048A rotary encoder |
Posted: Mon Jul 30, 2012 1:25 am |
|
|
Hello all,
Setup is: PIC18F2420@8Mhz, AS5048A SPI-enabled transducer, CCS PIC 4.114.
I'm using 4-wire single slave SPI, all signals are OK, they modify with the magnetic field, checked with oscilloscope. SPI is 16 bit, got around that by using software SPI:
Code: | #use spi(Master,Enable=PIN_C2,ENABLE_ACTIVE=0, BITS=16, DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, SAMPLE_FALL, IDLE=0, MSB_FIRST) |
What I am however having some issues with is actually outputting those signals into something useful. What I'm getting with Realterm for the code below(citit is a 16bit integer):
Code: |
output_high(CS); //Idle state for rotary encoder
citit=spi_xfer(0x0001); //Clear any errors, as per transducer datasheet
while(true){
citit=spi_xfer(0xFFFF); //Read command for device
printf("%ld", citit);printf(" "); //Output read value over RS232 FTDI cable
}
} |
Is:
Code: | 2896 0 128 128 32768 0 0 0 32896 128 32768
0 32768 0 0 0 32896 128 128 32768 0 32768 0
128 0 0 0 32768 128 0 128 0 0 0
0 32896 32768 0 32768 0 0 0 0 32896 32768 0
32768 0 0 0 0 0 128 32768 0 0 0
0 32768 0 0 0 0 0 0 0 32896 32768 0
32768 0 0 0 0 128 32768 0 32768 0 0
0 0 0 128 0 0 0 32896 128 128 32768
0 128 0 0 0 0 0 32896 32768 32896 0 128
0 32896 128 32768 0 32768 128 32768 0 0 0
0 0 32896 32768 32896 0 0 0 0 0 0 32896
128 0 0 0 32768 128 128 0 0 0 0
|
I've tried long long for the citit variable, no luck.
I believe the issue is with the signal the transducer is outputting, meaning that out of the 16bits, the first two are MSB and Error flag, followed by the actual 14 bits of angle data I need.
Should I get rid of MSB and the Error flag bits? If so, how do I do that? Typecasting an int into something else(byte array) has not worked for me.
Last edited by victor_constantin on Mon Jul 30, 2012 2:42 am; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Jul 30, 2012 1:48 am |
|
|
citit &= 0x3FFF;
Removes the top two bits.
Long, is 16bit. Exactly the same.
Now, on what you show, several of the values do not involve these bits. 128 (for example), is 0b00000.....10000000. The 2896 you show for the first value, is 0000.....101101010000. Again no involvement of the high bits. The two high bits will give you the 32768. The 32896, is 128+32768. So you seem to be getting data on bit 7 quite repeatedly. So is this legitimate?.
As some further comments. Being 16bit, doesn't stop you using the hardware SPI. Just do two 8bit transfers.
You have the device wired for 5v operation, with the separate capacitor on the 3.3v regulator output?.
Best Wishes |
|
|
victor_constantin
Joined: 14 Dec 2010 Posts: 10
|
|
Posted: Mon Jul 30, 2012 2:29 am |
|
|
Thanks for the answer. I am powering it at 5V so yes, the capacitor is in place. Never really got the bitwise operator part, so from what I'm getting the code you sent really just does an AND between what I'm reading and a 3FFF, giving me the last 14 bits of what I got from the transducer. I replaced thus my code to:
Code: | output_high(CS);
spi_xfer(0x0001);
while(true){
citit=spi_xfer(0xFFFF);
citit&=0x3FFF;
printf("%ld", citit);printf(" ");
}
} |
But I'm getting the exact same rubbish. What I'm currently seeing as an issue is that even though my signal is pretty random, I'm only getting those exact same values. So maybe it's a conversion issue? |
|
|
victor_constantin
Joined: 14 Dec 2010 Posts: 10
|
|
Posted: Mon Jul 30, 2012 2:41 am |
|
|
Changing to #use delay(clock=2000000) from #use delay(clock=8000000) outputs:
Code: | 3864 3936 -26490 6368 -2048 3846 3864 3870 -26490
798 -464 3846 3864 3942 3846 6278 -2048 3846
3864 3936 3960 3960 -2048 3846 3864 3870 3936
-30976 -2048 3846 3864 3870 6278 6348 -2048 3846
3864 3936 -30976 6272 -2048 3846 3864 3936 -30976
3966 -2048 3846 3864 3936 3966 6272 -2048 3846
3864 3936 -30976 3942 -2048 3846 3864 3936 3960
3864 -2048 3846 3864 3936 -26496 6374 -2048 3846
3864 3870 6278 6351 -2048 3846 3864 3942 3864
|
And if i change it to clock=32000000, i get only 0.
Main.h is :
Code: | #include <18F2420.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#use delay(clock=2000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=PORT1)
#define LED PIN_A0
#define DELAY 10
#define CS PIN_C2
|
LE: sorry about the PIC, i changed it in all of the posts, i'm currently on two projects and i got them mixed. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Jul 30, 2012 3:37 am |
|
|
First thing to do, is add ENABLE_ACTIVE=1 to the setup SPI. The default is zero, and the faster you clock the chip, the shorter the actual delay will be. The chip you are talking to, requires a _minimum_ of 350nSec for this. It is possible the code is failing because of this.
Then, there is something very odd about what you are showing. 32768 for example, is an impossible output from %ld, unless citit is not declared as an int16. It should display as -32640. You also can't get any -ve numbers displayed after using the &=3FFF operation (the top bit is the 'sign' bit in an int16, and this is removed).
long long, changes everything, since you are then using an int32. Pointless, but would give the numbers you are showing in your original post. Suspect this is what you are doing, but this doesn't then agree with what you _say_.
Key is that you _must_ make what you show as as an output, agree with the code actually used. Otherwise you are wasting _our time, and yours_.
Now, I don't think you are talking to the chip completely correctly. Your _first_ read, when you start, _will_ be effectively garbage, containing the contents of the error register. You need to do an extra write after clearing this. Also, the clear error flag command is not correct. Look at table 12. Needs bit 14 set.
So the sequence needs to be:
Code: |
spi_xfer(0x4001); //Clear error flag
spi_xfer(0xFFFF); //select read angle as next command
while(true){
citit=spi_xfer(0xFFFF);
citit&=0x3FFF;
printf("%5ud ", citit); //Will make output tidier
}
}
|
Best Wishes |
|
|
victor_constantin
Joined: 14 Dec 2010 Posts: 10
|
|
Posted: Mon Jul 30, 2012 3:53 am |
|
|
Thank you for the response, however, no luck yet. I know output does not seem linked to the results, it's not making any sense for me either.
Ok, so my code is currently(i changed it as per your indications):
Code: | #include <main.h>
//!#USE SPI (MASTER, FORCE_HW, SPI1, MODE=0, BITS=16, STREAM=SPI_1, MSB_FIRST)
#use spi(Master,Enable=PIN_C2,ENABLE_ACTIVE=1, BITS=16, DI=PIN_C4, DO=PIN_C5, CLK=PIN_C3, SAMPLE_FALL, IDLE=0, MSB_FIRST)
long long citit;
void main()
{
spi_xfer(0x4001); //Clear error flag
spi_xfer(0xFFFF); //select read angle as next command
while(true){
citit=spi_xfer(0xFFFF);
citit&=0x3FFF;
printf("%5ud ", citit); //Will make output tidier
}
} |
With:
Code: | #use delay(clock=1000000) |
Output is:
Code: |
25648 8224 8224 12320 8292 8224 8224 25648 8224
8224 12320 8292 8224 8224 25648 8224 8224 12320
8292 8224 8224 25648 8224 8224 12320 8292 8224
8224 25648 8224 8224 12320 8292 8224 8224 25648
8224 8224 12320 8292 8224 8224 25648 8224 8224
12320 8292 8224 8224 25648 8224 8224 12320 8292
8224 8224 25648 8224 8224 12320 8292 8224
|
============
Using:
Code: | #use delay(clock=8000000) |
Output becomes:
Code: |
0 128 0 0 0 0 0 0 -32768
0 0 0 0 0 0 0 128 0
0 0 0 0 0 -32768 0 0 0
0 0 0 0 128 0 0 0 0
0 0 -32768 0 0 0 0 0 0
0 128 0 0 0 0 0 0 -32768
0 0 0 0 0 0 0 128 0
0 0 0 0 0 -32768 0 0 0
0 0 0 0 128 0 0 0 0
0 0 -32768 0 0 0 0 0 0
|
For any higher frequency, output is all 0. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19539
|
|
Posted: Mon Jul 30, 2012 4:31 am |
|
|
long long in not wanted/needed. This prevents the code from working properly, since it allows -ve results randomly to happen in the print. I've said this before. Just use int16. It is _always_ better/safer to use the intxx forms, since 'long', or 'long long', have different meanings on different compilers, which is asking for problems....
Use %5lu for the format. I meant to remove the 'd', but accidentally left it. Ugh.
Now, seriously, are you actually changing the crystal, when you switch clock rates?. The only time you can change rates without changing a crystal, is using the internal oscillator, and only then when using rates this supports. It doesn't support 20MHz, or 10MHz. So what are you actually doing here?. The rate in this, _must_ match exactly what the chip is actually clocked at.
Switch to using SPI mode numbers. Much more reliable than trying to set stuff up yourself. The chip uses MODE1.
Specify a baud rate. This will at least attempt to keep the bus rate constant as you change clock rates, ruling out another possible problem.
Code: |
use spi(Master, FORCE_HW, Enable=PIN_C2, ENABLE_DELAY=1,
BITS=16, MODE=1, BAUD=500000)
|
Best Wishes |
|
|
victor_constantin
Joined: 14 Dec 2010 Posts: 10
|
|
Posted: Mon Jul 30, 2012 4:50 am |
|
|
Again, thanks for the response. I will try this tomorrow and get back to you. |
|
|
|
|
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
|