Eeprom memory, ADC and USART from PIC18F4550

Thread Starter

Tainara

Joined Sep 10, 2014
6
Hello,

I am trying to read the acceleration of three axis of an acellerometer with the microcontroller PIC18F4550's ADC and store the samples data at its eeprom memory. Also after filling the eeprom memory I want to send the data to computer via bluetooth using serial communication.

According the datasheet the eeprom memory has 128 bytes but PIC ADC uses 10 bits so I am trying to store 64 samples, using 2 bytes from eeprom to each sample. And I am trying to collect one sample for second by now. When it reaches the 64 samples written at eeprom the microcontroller has to wait a command from computer and after this command sample by sample will be sent to the computer.

I am not confident with the program I made though so I would like to ask your opinion and if you have any advice, please.

Here is my program:
//Inclusion of libraries
#include<xc.h>
#include <ctype.h>
#include <usart.h>


//Settings
#pragma config PLLDIV = 5 //PLL to 20MHz
#pragma config CPUDIV = OSC1_PLL2 //PLL off
#pragma config FOSC = HS //High speed oscillator - 20MHz
#pragma config WDT = OFF //Disable watchdog
#pragma config PBADEN = OFF //PORTB starts as digital
#pragma config LVP = OFF //No recording in low voltage
#pragma config DEBUG = OFF //Disable debug
#pragma config PWRT = ON //Enable power-up timer
#pragma config BOR = ON //Enable brown-out reset on
#pragma config MCLRE = OFF //Disable master clear


#define _XTAL_FREQ 20000000

#define EIXO_X PORTAbits.RA1 //Analogue signal from accelerometer’s X axis
#define EIXO_Y PORTAbits.RA2 // Analogue signal from accelerometer’s Y axis
#define EIXO_Z PORTAbits.RA3 // Analogue signal from accelerometer’s Z axis


//Definitions to serial communication
#define RXFLAG PIR1bits.RCIF //Byte arrival by serial’s flag
#define TXFLAG PIR1bits.TXIF // TXREG emptying’s flag


//Global variables
unsigned long int result_x[64], result_y[64], result_z[64], x, y, z;
unsigned char x_msb, x_lsb, y_msb, y_lsb, z_msb, z_lsb, m, l;
unsigned char AD_MSB, AD_LSB;
int time, axis_write, axis_read, sample, read, s;
unsigned int address_h, address_l;
char CHAR_RX; // Character received by serial


//Function to read the A/D converter
unsigned int Le_ADC ()
{
unsigned int SUM;
ADCON0bits.GO_NOT_DONE = 1; //Starts the conversion
while (ADCON0bits.GO_NOT_DONE != 0) {}; //Waits until the end of the conversion
AD_MSB = ADRESH; //Stores bits from ADRESH
AD_LSB = ADRESL; //Stores bits from ADRESL
SUM = AD_MSB + AD_LSB;
return SUM; //SUM’s value is returned to main function
}


//Interruption
void interrupt interruption (void){
time++;

TMR0IF = 0;

}

//Function to receive a character by serial
char Reception(void)
{
if (RXFLAG == 0)
{
return 0;
}
else
{
return RCREG;
}
}


//Function to interpret the commands from Labview
void Labview_command (void)
{
CHAR_RX = Reception(); // Reads char on the serial port

if (CHAR_RX == '1')//Checks if LabVIEW sent 1 to the microcontroller
{
read = 1;
return;
}
return;
}


//Main function
void main (void)
{
PORTA = 0;
TRISA = 0b00001110;
INTCON = 0;
PORTC = 0;
TRISC = 0xF9; //0b11111001

// ADC settings
ADCON1 = 0x0B;
ADCON2 = 0x84;

//Interruption settings
IPEN = 0; //No interruption priority
TMR0IE = 1; //Enable Timer0 interruption
TMR0ON = 1; // Enable Timer0
T08BIT = 1; //Timer0 to 8bits
T0CS = 0; // Timer0’s increases by duty cycle
PSA = 0; //Scheduler on
T0PS2 = 1; //Scheduler 1:256
T0PS1 = 1;
T0PS0 = 1;
TMR0L = 0; //Initializes Timer0 value
GIEH = 1; //Enable interruptions


//Inicialização da porta serial
TXSTA = 0x24; //0b00100100 = 8 bits asynchronous mode
SPBRG = 129; //Oscillator to 20MHz - BaudRate = 9600bps
RCSTA = 0x90; //0b10010000 = Enable serial transmission

INTCON2bits.RBPU = 0;

//Variables inicialisation
axis_write = 0;
address_h = -2;
address_l = -1;
sample = 0;
time = 0;
read = 0;

while (1)
{
/*Interruption time of occurenceTMR0:1 / 20MHz x 4 x 256 x 256 = 13,11
*ms, so 13,11 ms * 82 almost 1 second */
if (time == 82)
{
sample++;
//Write acceleration axis values at eeprom memory
switch (axis_write)
{
case 0:
address_h =+ 2;
address_l =+ 2;
ADCON0 = 0b00000101; //AN1 as X axis
__delay_ms(10);
x_msb = Le_ADC () - AD_LSB;
x_lsb = Le_ADC () - AD_MSB;
eeprom_write(address_h, x_msb);
eeprom_write(address_l, x_lsb);
axis_write++;
break;
case 1:
address_h =+ 2;
address_l =+ 2;
ADCON0 = 0b00001001; //AN2 as Y axis
__delay_ms(10);
y_msb = Le_ADC () - AD_LSB;
y_lsb = Le_ADC () - AD_MSB;
eeprom_write(address_h, y_msb);
eeprom_write(address_l, y_lsb);
axis_write++;
break;
case 2:
address_h =+ 2;
address_l =+ 2;
ADCON0 = 0b00001101; //AN3 as Z axis
__delay_ms(10);
z_msb = Le_ADC () - AD_LSB;
z_lsb = Le_ADC () - AD_MSB;
eeprom_write(address_h, z_msb);
eeprom_write(address_l, z_lsb);
axis_write++;
break;
default: ADCON0 = 0;
}


if (axis_write == 3)
{
axis_write = 0;
time = 0;
}


if (sample == 63)
{//After filling eeprom memory(128 bytes), to lock the structure
axis_write = 4;
}


}//End of if (time == 82)
while (axis_write == 4)
{
__delay_ms(30);
Labview_command (); //Reads Labview_Command
if (read == 1)
{
m = 0;
l = 1;
s = 0;
axis_read = 0;
address_h = -2;
address_l = -1;
//Reads the values stored at eeprom memory
switch (axis_read)
{
case 0:
s++;
address_h =+ 2;
address_l =+ 2;
result_x[m] = eeprom_read(address_h);
result_x[l] = eeprom_read(address_l);
x = (result_x[m] & 0x03) * 256 + result_x[l];
x = (255 * x)/1023;
__delay_ms(10);
putsUSART(x); //Transmits string
__delay_ms(10);
m =+ 2;
l =+ 2;
axis_read++;
break;
case 1:
s++;
address_h =+ 2;
address_l =+ 2;
result_y[m] = eeprom_read(address_h);
result_y[l] = eeprom_read(address_l);
y = (result_y[m] & 0x03) * 256 + result_y[l];
y = (255 * y)/1023;
__delay_ms(10);
putsUSART(y); //Transmits string
__delay_ms(10);
m =+ 2;
l =+ 2;
axis_read++;
break;
case 2:
s++;
address_h =+ 2;
address_l =+ 2;
result_z[m] = eeprom_read(address_h);
result_z[l] = eeprom_read(address_l);
z = (result_z[m] & 0x03) * 256 + result_z[l];
z = (255 * z)/1023;
__delay_ms(10);
putsUSART(z); //Transmits string
__delay_ms(10);
m =+ 2;
l =+ 2;
axis_read = 0;
break;
default:;
}

if (s == 63)
{//After reading all eeprom memory, to lock the structure
axis_read = 3;
}
}//End of if (read == 1)
}//End of while (axis_write == 4)
}//End of while(1)
}//End of main function
 

tshuck

Joined Oct 18, 2012
3,534
A few things:
  1. Post the datasheet for the accelerometer so we can see how it operates and what the interface is.
  2. It doesn't seem like you really need to use the EEPROM to store your data (it has a limited number of write cycles), you may want to consider using RAM to store it since it's just getting dumped to a computer anyway.
  3. If you don't need the full 10-bit resolution of the ADC, take the most significant 8 bits to alleviate storage waste. Or, you could pack the bits, but that would be a bit more complicated.
Edit: also, your ADC function will return erroneous results.
SUM = AD_MSB + AD_LSB;
you need to shift the bits to the appropriate places - see left/right justification in the ADC section of the datasheet.
 
Last edited:

Thread Starter

Tainara

Joined Sep 10, 2014
6
A few things:
  1. Post the datasheet for the accelerometer so we can see how it operates and what the interface is.
  2. It doesn't seem like you really need to use the EEPROM to store your data (it has a limited number of write cycles), you may want to consider using RAM to store it since it's just getting dumped to a computer anyway.
  3. If you don't need the full 10-bit resolution of the ADC, take the most significant 8 bits to alleviate storage waste. Or, you could pack the bits, but that would be a bit more complicated.
Edit: also, your ADC function will return erroneous results.
you need to shift the bits to the appropriate places - see left/right justification in the ADC section of the datasheet.
I am using an ADXL335 accelerometer which I uploaded the datasheet and breakout board scheme.
Well, I did the ADC function that way to return a value which I could "easily" manipulate to separate the msb from the lsb to store them in separate bytes of the memory because of the 10 bit resolution and I'd set the values according to the justification only when reading data from memory. Anyway I'd find problems in using the three axis data individually and simultaneously. But with your tips I think I can make changes to improve my program thank you.
 

Attachments

atferrari

Joined Jan 6, 2004
5,015
Eu acho...

While using EEprom is simple, better if you do all in RAM as suggested.

Later you can send as many as you like using INDFx pointers (a powerful thing).

Assembler?
 
Top