|
|
View previous topic :: View next topic |
Author |
Message |
ressas
Joined: 15 Nov 2019 Posts: 135
|
AS5045 Hall Rotary with 18f46k22 |
Posted: Wed Jul 08, 2020 5:36 am |
|
|
Hello everyone.
I plan to make an angle measurement with the As5045 integrated.
In Datasheet, I created a code with the figure on page 15.
But it works very bad. I never see 0 to 360.
sometimes I measure between 150 and 3 degrees, sometimes between 270 and 130.
It is increasing and decreasing quite unstable in change. (No sensitivity)
I wonder what I'm doing wrong
Code: |
void readAngle (){
int1 index[12];
int1 dummyIndex[6];
unsigned int16 readValue=0;
unsigned int16 dummyValue=0;
unsigned int16 lastValue=0;
output_high(_pinCS);
output_high(_pinCLK);
output_low(_pinCs);
delay_ms(1);
output_low(_pinCLK);
for(int i =12;i>0;i--) //12 bits angle value read
{
output_high(_pinCLK);
output_low(_pinCLK);
index[i-1] =input(_pinDO);
if(index[i-1]==1) bit_set(readValue,i-1); //12 bit value write
else if(index[i-1]==0) bit_clear(readValue,i-1);
}
for(int j =6;j>0;j--) //6bit other value read
{
output_high(_pinCLK);
if(j != 1) output_low(_pinCLK);
dummyIndex[j-1] =input(_pinDO);
if(dummyIndex[j-1]==1) bit_set(dummyValue,j-1); //6 bit value write
else if(dummyIndex[j-1]==0) bit_clear(dummyValue,j-1);
}
lastValue=bubble_sort_filter(readValue,20);
printf("Angle: %f",lastValue*0.08789);
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Wed Jul 08, 2020 6:34 am |
|
|
This is an SPI interface. You don't need/want to be doing the clocking
yourself, use the #use SPI capability of the compiler. You also don't want to
be pausing for 1mSec after the CS. Have you got the mode pin high or low?.
The mode pin needs to be tied to either Vss or Vdd _before_ the supply is
applied. Pause needs to be 384uSec or 96uSec according to this.
Are you running off 3.3v or 5v?.
If you are running off 3.3v, then both the Vdd3v3 pin and the Vdd5v pin can
be connected to your supply. If you are running off 5v, then only the Vdd5v
pin goes to the supply, and the Vdd3v3 pin must be NC.
What PIC?.
So:
Code: |
#use SPI(DI=_pinDO, CLK=_pinCLK, baud=1000000, bits=32, MODE=2, stream=AS5045)
//at boot
unsigned int32 val;
float angle;
output_high(_pinCs);
//then to read from the chip
output_low(_pinCs);
delay_us(384); //change to 96 if mode is high
val=spi_xfer(AS5045,0,17);
output_high(_pinCs);
angle = (val>>5)*0.08789;
|
The bottom 5 bits of val are the status bits. |
|
|
ressas
Joined: 15 Nov 2019 Posts: 135
|
|
Posted: Wed Jul 08, 2020 7:05 am |
|
|
Datasheet d used ssi interface expression instead of spi interface.
I didn't use the spi, thinking that the two are different from each other.
I connected the mode pin to vss with a resistance of 1k, not directly.
Although Datasheet has no such suggestion, appNote did so.
I remember I couldn't read the value when I connected it directly to vss.
I use with 5v. I use pic18f46k22.
Are you saying SPI and SSI are the same.
If so, can I use spi pins software? I don't want to print(pcb) again
You are very fast thanks
I tried the code. It works decisively.
I wonder why it ranges from 0 to 180.
Why 0 is not 360. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Wed Jul 08, 2020 9:45 am |
|
|
SSI is Synchronous Serial Interface.
SPI is Serial Peripheral Interface.
They are both synhcronous serial interfaces, the only 'difference' is
that SPI is normally bi-directional, whereas SSI is normally only one
direction.
Using the 'software' SPI offered by CCS, the interface supports
unidirectional operation, so SSI as well as SPI.
Now on the 46K22, what CPU clock are you using?.
If you are running at one of the faster clock rates, your sequence of
setting and clearing the clock pin, will actually be happening faster than
the chip supports. This is a big advantage of using the #USE SPI, since
it will ensure the that clock rate does not exceed the maximum baud
specified. |
|
|
ressas
Joined: 15 Nov 2019 Posts: 135
|
|
Posted: Wed Jul 08, 2020 12:07 pm |
|
|
As seen in the code, I use 64mhz with the pll
N
Code: |
#include <18F46k22.h>
#device ADC=16
#fuses NOWDT,NOBROWNOUT,PUT,NOWRT,NODEBUG,INTRC_IO, NOMCLR, NOPROTECT, NOWDT, NOLVP,PLLEN
#use delay(internal=64000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,sda=PIN_c4,scl=PIN_c3,slow=400000,FORCE_hw)
#use standard_io(A)
#use standard_io(B)
#use standard_io(C)
#use standard_io(D)
#use standard_io(E)
#define _pinCS pin_D2
#define _pinCLK pin_D1
#define _pinDO pin_D0
#define _pinMagIN pin_D3
#define _pinMagDEC pin_D4
#define _pinPROG pin_C2
#use SPI(DI=_pinDO, CLK=_pinCLK, baud=1000000, bits=32, MODE=2, stream=AS5045)
#include "Oled.c"
#include "As5045.c"
VOID main()
{
setup_oscillator(OSC_64MHZ , OSC_PLL_ON);
//at boot
unsigned int32 val;
float angle;
WHILE (TRUE)
{
output_high(_pinCs);
//then to read from the chip
output_low(_pinCs);
delay_us(384); //change to 96 if mode is high
val=spi_xfer(AS5045,0,17);
output_high(_pinCs);
angle = (val>>5)*0.08789; [b] // Angle Value : 0- 180 ???[/b]
}
}
|
|
|
|
ressas
Joined: 15 Nov 2019 Posts: 135
|
|
Posted: Thu Jul 09, 2020 1:06 am |
|
|
Hello Ttelmah.
can I ask one more question?
I want to perform the reset according to the diagram shown on page 24.
I guess. I can accomplish this by sending the value of val in your code there.
Can I do this as follows;
Code: |
#use SPI(DI=_pinDO, CLK=_pinCLK, baud=1000000, bits=32, MODE=2, stream=AS5045)
#use SPI(DI=_pinPROG, CLK=_pinCLK, baud=1000000, bits=32, MODE=2, stream=AS5045_PROG)
void only_at_first(){
//Ttelmah's code
//at boot
unsigned int32 val;
float angle;
output_high(_pinCs);
//then to read from the chip
output_low(_pinCs);
delay_us(384); //change to 96 if mode is high
val=spi_xfer(AS5045,0,17);
output_high(_pinCs);
val = val >>5;
//the part I want to add
unsigned int16 valProg=0;
unsigned int8 dummy1=0;
unsigned int8 dummy2=0;
dummy1=make8(val,0);
dummy2=make8(val,1);
valProg =make16(dummy2,dummy1);
valprog = valprog << 3;
bit_Set(valProg,15); //because counter clockwise
bit_Set(valProg,2); // pwm disable
//***************
output_low(_pinPROG);
//the prog pin should be stepped to 7.5 volts for programming
// I use pnp transistor, so prog Pinlow
//***************
output_low(_pinCs);
output_high(_pinCs);
delay_us(384); //slow mode
spi_xfer(AS5045_PROG, valProg, 16);
output_low(_pinCs);
output_low(_pinPROG);
//When the programming was over, I made it passive again. I'm not sure about that
}
|
Prog pin is not directly connected, it is connected with pnp.
So should I apply a NOT to valProg value?
Last edited by ressas on Thu Jul 09, 2020 1:41 am; edited 3 times in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 09, 2020 1:15 am |
|
|
ressas wrote: |
I connected the mode pin to vss with a resistance of 1k, not directly.
|
If the Mode pin is connected to Gnd, the power-up delay is 80ms.
This is listed on page 8 of the AS5045 data sheet.
You need to add a delay of 100ms (for safety margin) at the start of main(). |
|
|
ressas
Joined: 15 Nov 2019 Posts: 135
|
|
Posted: Thu Jul 09, 2020 8:19 am |
|
|
Thank you pcm programmer.
Can I get answers to the questions I asked above? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Thu Jul 09, 2020 9:53 am |
|
|
All you need to do to reset the chip, is drop the prog line, and send
one clock bit. So:
spi_xfer(AS5045_PROG, 0, 1);
However though this is listed as the way to reset the chip after alignment
mode, after _programming_, it says a power on reset is _required_. |
|
|
ressas
Joined: 15 Nov 2019 Posts: 135
|
|
Posted: Fri Jul 10, 2020 3:13 am |
|
|
Thankyou Ttelmah.
I am trying to add a transistor to the circuit for a hardware PUT.
But I could not understand why I read a value between 0-180, not 0-360. When the value I read multiplies by 2, the result improves. However, my sensitivity is reduced. How can I fix this? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9232 Location: Greensville,Ontario
|
|
Posted: Fri Jul 10, 2020 4:48 am |
|
|
It's curious that you're getting 1/2 of what you want and that says '/2' to me..hmm 180 is 1/2 of 360, hmm >>6 not >>5 error ?? so I downloaded the datasheet.
The data from the device is consists of 12 bit position and 6 'status' bits, yet you only receive 17 bits and then >>5 which should be correct.
A simple test would be to read and display the raw data as position(0-4096) and then the 5 bits( as '1s and 0s' BEORE you compute the position in * (degrees). If you slowly move the magnet you should see the data increment.
As there are 6 status bit, I'd actually read all 18 bits(12+6) then process the data.
I quickly read the datasheet, but they do talk about the magnet placement being 'critical' though I suspect a software bug not hardware.
just something to try, it might help.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Fri Jul 10, 2020 5:55 am |
|
|
Actually I think it is just the way the sensor is done. Try switching to reading
18 bits not 17. If you look at figure 13, for the 17 bits of data, they send
18 clocks. The chip ignores the first clock. So though it is 17bit data, you
actually have to send 18 clocks. Only sending 17 clocks the result will be that
the value is shifted right by one bit. |
|
|
ressas
Joined: 15 Nov 2019 Posts: 135
|
|
Posted: Fri Jul 10, 2020 6:53 am |
|
|
Thankyou masters
This code was created with the help of Ttelmah pcm Programmer and temtronic.
Code: |
#include <18F46k22.h>
#device ADC=16
#fuses NOWDT,NOBROWNOUT,PUT,NOWRT,NODEBUG,INTRC_IO, NOMCLR, NOPROTECT, NOWDT, NOLVP,PLLEN
#use delay(internal=64000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
#use i2c(Master,sda=PIN_c4,scl=PIN_c3,slow=400000,FORCE_hw)
#define _pinCS pin_D2
#define _pinCLK pin_D1
#define _pinDO pin_D0
#define _pinMagIN pin_D3
#define _pinMagDEC pin_D4
#define _pinPROG pin_C2
#use SPI(DI=_pinDO, CLK=_pinCLK, baud=1000000, bits=32, MODE=2, stream=AS5045)
//#use SPI(DI=_pinPROG, CLK=_pinCLK, baud=1000000, bits=32, MODE=2, stream=AS5045_PROG)
unsigned int32 val=0;
float angle=0;
float angle2=0;
float zeroPoint = 0;
Void as5045_read();
float temp=0;
float index1[10];
float bubble_sort_filter_float(float data,unsigned int8 number);
VOID main()
{
setup_oscillator(OSC_64MHZ , OSC_PLL_ON);
delay_ms(100);
WHILE (TRUE)
{
as5045_read();
}
}
float bubble_sort_filter_float(float data,unsigned int8 number)
{
//1.Filtre
index1[0]=data;
for(int a=9;a>0;a--)
{
index1[a]=index1[a-1];
}
for (int b=1; b<10; b++)
{
for(int c=0; c<9; c++)
{
if (index1[c] > index1[c+1])
{
temp = index1 [c];
index1 [c] = index1 [c+1];
index1 [c+1] = temp;
} } }
return index1[5];
}
Void as5045_read(){
//at boot
output_high(_pinCs);
output_low(_pinCs);
delay_us(384);
val=spi_xfer(AS5045,0,18);
output_high(_pinCs);
angle = (val>>5)*0.08789;
angle2=bubble_sort_filter_float(angle,10);
zeroPoint= (angle2 - 144.22); //software RST
// 144.22 my zeropoint
// I cant use prog pin RESET
//spi_xfer(AS5045_PROG, 0, 1);
printf("%f",zeroPoint)
}
|
While using it, I may have broken a couple of my AS5045 integrated.
Interestingly, although I could not read data from the digital part, I was able to read from the analog part (if the data was not correct).
Secondly, I did not use the pnp transistor correctly with the pic. Therefore, I could not reset with progpini. As on page 25, the PNP transistor is connected directly to the MCU. In real applications, resistance connection should be done, right?
I guess it would be more comfortable if it was programmed with 5V instead of 7.5V.
Finally, I have to check the feed of the integrated supply transistor for Power on reset. Hopefully it doesn't have to be a pnp transistor.
Thanka again and again.
Last edited by ressas on Fri Jul 10, 2020 11:39 pm; edited 1 time in total |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19529
|
|
Posted: Fri Jul 10, 2020 7:46 am |
|
|
I would wonder about the warnings on page 22 about the programming
line and the capacitors needed on it.
Really there are two ways to work:
1) Never actually 'program' the chip. Instead use the option on Page 24
for what they call 'non permanent programming' (which is really just
'configuration', rather than programming, which can be done without the
need for the high voltage on the Prog pin). This to me looks the safer
way to work, unless you very carefully make a programming board that
has all the capacitors etc. Beware also that you need to be able to
deliver a lot of current on the 'programming' supply (150mA). If this
droops during 'programming' it's a fairly sure way of corrupting the chip.
2) Design a programmer, and program the chips once.
I suspect it'd be much safer and easier to just go with option 1, and
have your code 'configure' the chip to the required settings at boot, and
never actually 'program' it. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9232 Location: Greensville,Ontario
|
|
Posted: Fri Jul 10, 2020 7:55 am |
|
|
Before you do any 'fancy math', you should just read the sensor and display the data. The 'low level' proceedure will confirm/deny that the sensor data is proper.
Have a simple 'read sensor- display data-delay 1 second-loop again' program.
Without turning magnet the reading should be stable, close to 000 for position.
Turn the magnet 90* CW. Now the reading should be close to 1024 and stable.
Turn to 180* CW, should be 2048 more or less, but stable(within 2-5 counts ??)
Turn to 270*CW, reading is 3072, +- and stable
Turn to almost 359* CW, reading should be 4000+-, and stable.
These few steps need to be done BEFORE doing any math calculations. This way you KNOW the sensor is functioning properly AND your 'driver code' ( basic access) to the sensor IS working as desired.
Once you do this THEN do the 'math'. If the math results are wrong, then there's something wrong with the math calculations.
Jay |
|
|
|
|
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
|