|
|
View previous topic :: View next topic |
Author |
Message |
Schmittz
Joined: 29 Jul 2007 Posts: 3
|
Schock and vibrations analysis using adxl330 accelerometer |
Posted: Mon Jul 30, 2007 12:06 am |
|
|
I'm a newbie to CCs picc compiler but have good c systems programming background. I'm considering buying dspic kit if this will help with the final year project.
As student my final year project is on recording vibrations and shock using accelerometer. I've at the moment a 16f877a chip & an adxl330 tria-axles accelerometer to use bcoz it gives an anoloque output. I would like to get reading from the three axis of the accelerometer and store them into an array(which could be analized in real time later by microprocessor possibly dspic). The project will build from there whereby I'll be considering using a dspic chip for further data analysis in real time. I've written the following code to calibrate the accelerometer and also simply test if adxl330 works. But it does not work at all. I tried using MPLAB7.6 simulator after commenting out printf() function but nothing seems to work. What am i doing wrong?
thank.
Code: | #include <16F877A.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#device adc=10
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
double *x;
double *y;
double *z;
double accel[2];
double adxCalib[2];
const double x_ZeroG=250; //Zero_G
const double y_ZeroG=250; //Zero_G
const double z_ZeroG=250; //Zero_G
void Adxl330_Calibrate()
{
unsigned double adc_x,adc_y, adc_z = 0;
int8 chan;
for (chan=0; chan<2; chan++)
{
set_adc_channel(chan);
adxCalib[chan]=read_adc();
delay_us(10);
}
adc_x = adxCalib[0]; // get ADC value for X channel
adc_y = adxCalib[1]; // get ADC value for Y channel
adc_y = adxCalib[2]; // get ADC value for z channel
printf("%4d %d4 %4d",adc_x,adc_y,adc_z);
}
//=============================================================================
// get xyz
//=============================================================================
void Gadxl330getxyz()
{
int i,j;
for(j=0; j<256; j++)
{
for(i=0;i<2;i++) //this loop is used to read adc values from channel 0,1,2 etc
{
set_adc_channel(chan);
accel[chan]=read_adc(); //Acceleration z, y, z
}
x[j]=accel[0] - x_ZeroG; //Acceleration x
y[j]=accel[1] - y_ZeroG; //Acceleration y
z[j]=accel[2] - z_ZeroG; //Acceleration z
}
Gvlauesdisplay(x,y,z);
}
void Gvlauesdisplay(double* x, double* y, double* z)
{
int8 j;
printf("printing 256 data points acceleration values from x,y,z axis\n\n");
for(j=0; j<256; j++)
{
printf("%4d %d4 %4d",x[j],y[j],z[j]);
}
}
void main()
{
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
Adxl330_Calibrate(); //use for obtaining x_ZeroG,y_ZeroG,z_ZeroG calibration values
while(1)
{
delay_Ms(500)
Gadxl330getxyz(); //will print 256 data points of the x,y,z acceleration values every half a second
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 30, 2007 12:41 am |
|
|
Quote: | int i,j;
for(j=0; j<256; j++) |
In CCS, an 'int' is an unsigned 8-bit value. It can only go up to 255.
Turn on the compiler Warnings. Here's what it says about the 'for' line:
Quote: | >>> Warning 203 "C:\Program Files\PICC\Projects\PCM_Test\pcm_test.c" Line 12(1,1): Condition always TRUE |
It's an endless loop. It will never exit.
See this post, about looping through all 256 elements with an 8-bit index:
http://www.ccsinfo.com/forum/viewtopic.php?t=30469&start=11
Quote: |
double *x;
double *y;
double *z;
x[j]=accel[0] - x_ZeroG; //Acceleration x
y[j]=accel[1] - y_ZeroG; //Acceleration y
z[j]=accel[2] - z_ZeroG; //Acceleration |
You've created pointers to doubles x,y,z, but the pointers are never
initialized to point to any array or block of allocated memory.
Then you start using them as arrays. That's not going to work.
Also, in this PIC, you're extremely limited on RAM. You can't do a
'double' array with 256 elements. You can't do even one, let alone three.
The largest array you can have with a 16F877A in CCS is 96 bytes.
If you want large arrays, you need to go to an 18F-series PIC. |
|
|
Schmittz
Joined: 29 Jul 2007 Posts: 3
|
Acceleration |
Posted: Mon Jul 30, 2007 5:17 am |
|
|
Thanks PCM Programmer for your input. This has indeed made it very clear to me now. But I still didn't understand when you mentioned that I cannot used pointers when not initialised. what if I declar my arrays as int8 x[256],y[256],z[256] then cast them to double later on. Will this solve my problem? How can I initialize pointers to arrays in CCS PICC?
I'm definelty going to change the IC to 18f452.
here is modified version of my previous, it still does not work...
Thanks again
Code: | #include <18F452.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOOSCSEN //Oscillator switching is disabled, main oscillator is source
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES NOPUT //No Power Up Timer
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES LVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOCPD //No EE protection
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
int8 x[256];
int8 y[256];
int8 z[256];
double accel[2];
double adxCalib[2];
const double x_ZeroG=250; //Zero_G
const double y_ZeroG=250; //Zero_G
const double z_ZeroG=250; //Zero_G
void Adxl330_Calibrate()
{
unsigned double adc_x,adc_y, adc_z = 0;
int8 chan;
for (chan=0; chan<2; chan++)
{
set_adc_channel(chan);
adxCalib[chan]=read_adc();
delay_us(10);
}
adc_x = adxCalib[0]; // get ADC value for X channel
adc_y = adxCalib[1]; // get ADC value for Y channel
adc_y = adxCalib[2]; // get ADC value for z channel
printf("%4d %d4 %4d",adc_x,adc_y,adc_z);
}
//=============================================================================
// get xyz
//=============================================================================
void Gadxl330getxyz()
{
int i,j;
for(j=0; j<255; j++)
{
for(i=0;i<2;i++) //this loop is used to read adc values from channel 0,1,2 etc
{
set_adc_channel(chan);
accel[chan]=read_adc(); //Acceleration z, y, z
}
(double)x[j]=accel[0] - x_ZeroG; //Acceleration x
(double)y[j]=accel[1] - y_ZeroG; //Acceleration y
(double)z[j]=accel[2] - z_ZeroG; //Acceleration z
}
Gvlauesdisplay(x,y,z);
}
void Gvlauesdisplay(double* x, double* y, double* z)
{
int8 j;
printf("printing 256 data points acceleration values from x,y,z axis\n\n");
for(j=0; j<255; j++)
{
printf("%4d %d4 %4d",x[j],y[j],z[j]);
}
}
void main()
{
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
Adxl330_Calibrate(); //use for obtaining x_ZeroG,y_ZeroG,z_ZeroG calibration values
while(1)
{
delay_Ms(500)
Gadxl330getxyz(); //will print 256 data points of the x,y,z acceleration values every half a second
}
}
|
|
|
|
libor
Joined: 14 Dec 2004 Posts: 288 Location: Hungary
|
Re: Acceleration |
Posted: Mon Jul 30, 2007 6:45 am |
|
|
Schmittz wrote: | I'm definelty going to change the IC to 18f452. |
That's an obsolete part, use the 18F4520 instead, or even better (with double the rom and ram size) the 18F4620.
...however I think with the possible DSP requirements of your project, you will soon run into the dsPIC33Fxxxx range, though you will have to wait some more time for a working CCS compiler for these chips. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jul 30, 2007 2:22 pm |
|
|
The LVP fuse can cause the PIC to lock-up if the PGM pin is taken to a
high level. Change that fuse to NOLVP. Do this in all your programs.
Quote: | unsigned double adc_x,adc_y, adc_z = 0; |
There is no 'unsigned' qualifier for the 'double' data type.
If you compiled your program, you would see the following error,
so I don't think you're compiling it:
Quote: | *** Error 38 "PCH_Test.c" Line 9(10,16): This type can not be
qualified with this qualifier |
Quote: | int8 x[256];
int8 y[256];
int8 z[256];
(double)x[j]=accel[0] - x_ZeroG;
(double)y[j]=accel[1] - y_ZeroG;
(double)z[j]=accel[2] - z_ZeroG; |
This won't work. You can't convert an array from an int8 to a double
array at run-time. The amount of memory allocated for the array is
determined at compile-time. An 'int8' takes one byte per array element.
A 'double' takes four bytes per element. If you cast an array element to
a double in an int8 array, you'll just overwrite the data in other elements.
You need to take a step back and study C some more, before proceeding. |
|
|
Schmittz
Joined: 29 Jul 2007 Posts: 3
|
Thanks PCM Programmer |
Posted: Tue Jul 31, 2007 4:26 am |
|
|
Thanks pcm programmer, I appreciate your explanation.It does make thing clear.
I'm very stuck now since I can't get any other way to be able to use arrays to store accelerometer reading. I was trying cast to see if this may help.
Secondly I've tried to simulate the code on MPLAB7.6 but it does not work at all.The simulator runs through the function without looping(i.e. it does not even when the for loop is encountered). Does this mean there is incompatibity of my software with MPLAB7.6?
Thanks again
Code: | #include <18F452.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES HS //High speed Osc (> 4mhz)
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOOSCSEN //Oscillator switching is disabled, main oscillator is source
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV20 //Brownout reset at 2.0V
#FUSES NOPUT //No Power Up Timer
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //Low Voltage Programming on B3(PIC16) or B5(PIC18)
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOCPD //No EE protection
#FUSES NOCPB //No Boot Block code protection
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#use delay(clock=20000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
int8 x[256];
int8 y[256];
int8 z[256];
double accel[2];
double adxCalib[2];
const double x_ZeroG=250; //Zero_G
const double y_ZeroG=250; //Zero_G
const double z_ZeroG=250; //Zero_G
void Adxl330_Calibrate()
{
double adc_x,adc_y, adc_z = 0;
int8 chan;
for (chan=0; chan<2; chan++)
{
set_adc_channel(chan);
adxCalib[chan]=read_adc();
delay_us(10);
}
adc_x = adxCalib[0]; // get ADC value for X channel
adc_y = adxCalib[1]; // get ADC value for Y channel
adc_y = adxCalib[2]; // get ADC value for z channel
printf("%4d %d4 %4d",adc_x,adc_y,adc_z);
}
//=============================================================================
// get xyz
//=============================================================================
void Gadxl330getxyz()
{
int i,j;
for(j=0; j<255; j++)
{
for(i=0;i<2;i++) //this loop is used to read adc values from channel 0,1,2 etc
{
set_adc_channel(chan);
accel[chan]=read_adc(); //Acceleration z, y, z
}
x[j]=accel[0] - x_ZeroG; //Acceleration x
y[j]=accel[1] - y_ZeroG; //Acceleration y
z[j]=accel[2] - z_ZeroG; //Acceleration z
}
Gvlauesdisplay(x,y,z);
}
void Gvlauesdisplay(double* x, double* y, double* z)
{
int8 j;
printf("printing 256 data points acceleration values from x,y,z axis\n\n");
for(j=0; j<255; j++)
{
printf("%4d %d4 %4d",x[j],y[j],z[j]);
}
}
void main()
{
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
Adxl330_Calibrate(); //use for obtaining x_ZeroG,y_ZeroG,z_ZeroG calibration values
while(1)
{
delay_Ms(500)
Gadxl330getxyz(); //will print 256 data points of the x,y,z acceleration values every half a second
}
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Jul 31, 2007 11:13 am |
|
|
Quote: |
Secondly I've tried to simulate the code on MPLAB7.6 but it does not
work at all. The simulator runs through the function without looping. |
No, you are not doing this. How do I know ? Because I pasted your
code into MPLAB and tried to compile it. It gave these errors:
Quote: |
*** Error 45 "PCH_Test.c" Line 49(24,25): Subscript out of range
*** Error 116 "PCH_Test.c" Line 51(40,45): Printf variable count (%) does not match actual count ::
*** Error 12 "PCH_Test.c" Line 67(25,29): Undefined identifier chan
*** Error 12 "PCH_Test.c" Line 68(15,19): Undefined identifier chan
*** Error 12 "PCH_Test.c" Line 77(1,15): Undefined identifier Gvlauesdisplay
*** Error 116 "PCH_Test.c" Line 86(42,43): Printf variable count (%) does not match actual count ::
*** Error 76 "PCH_Test.c" Line 99(5,19): Expect ;
7 Errors, 0 Warnings. |
The first one is "Subscript out of range". It's on this line:
Code: | adc_y = adxCalib[2]; |
It occurs because you're trying to access the 3rd element in an array
that is declared as having only two elements:
Code: | double adxCalib[2]; |
In C, array indexes start at 0, but the declaration size is done with whole
numbers.
I don't want to help you anymore, or at least for the time being.
The reason is, first, you need to study C. Take a class in it. Learn the
data types and the essentials. 2nd, you have a habit of claiming things
that you're not actually doing, such as claiming that a program is being
run in MPLAB simulator when it won't even compile. Until you fix both
those things, there's no point in asking questions on this board.
My advice is to go study C and come back in a few weeks. |
|
|
|
|
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
|