پروژه شتاب سنج سه محوره ADXL335 با استفاده از میکروکنترلر ATMEGA

 پروژه شتاب سنج سه محوره ADXL335 با استفاده از میکروکنترلر  ATMEGA

راهنمای راه اندازی سنسور شتاب سنج سه محوره ADXL335  با استفاده از برد آموزشی  پلاریس Polaris

هدف از انجام این پروژه آموزش و فراگیری کار با پورت های SPI   میکروکنترلر ATMEGA  میباشد

سنسور ADXL355
سنسور ADXL355

مقدمه‌ای بر سنسور ADXL355

حسگر ADXL355 ، یک حسگر شتاب سنج سه محوره با خروجی دیجیتال (SPI یا I2C) است که دارای چگالی نویز پایین، آفست دریفت 0 g کم و مصرف توان پایین می‌باشد. ADXL355 قادر به اندازه‌گیری شتاب، در محدوده‌های 2.048g±، 4.096g± و 8.192g± می‌باشد. از دیگر ویژگی‌های آن به توانایی کار در محیط‌های صنعتی، آفست دریفت پایین متاثر از تغییرات دمایی و Long term stability، می‌توان اشاره کرد که برای کاربردهای دقیق با حداقل کالیبراسیون مناسب است.

همچنین به خاطر مجتمع سازی فشرده و مصرف توان پایین، این حسگر برای استفاده در گره‌های حسگری اینترنت اشیا و دیگر تولیدات بی‌سیم مناسب است.

بلوک دیاگرام عملیاتی ADXL355
شکل 1 :بلوک دیاگرام عملیاتی ADXL355

حسگر ADXL355 دارای یک فیلتر میان‌گذر داخلی قابل تنظیم است. قطب‌های فیلتر بالا گذر و پایین گذر از طریق رجیسترهای مربوط به آن ها قابل تنظیم است. در حالت پیش‌فرض تنظیمات فیلتر به صورت زیر است:

  • فیلتر بالا گذر (HPF) off ¬
  • فیلتر میان گذر(LPF): 1000 Hz
  • نرخ داده خروجی(ODR): 4000 Hz

راه‌اندازی ADXL355 توسط برد AVR WIZZARD

راه‌اندازی ADXL355 توسط برد AVR WIZZARD
شکل 2 : راه‌اندازی ADXL355 توسط برد AVR WIZZARD

هدف: در این پروژه سنسور شتاب‌سنج سه محوره adxl355 توسط برد AVR WIZZARD راه‌اندازی شده و داد‌ه‌های مربوطه بر روی LCDنمایش داده می‌شود.

نیازمندی‌ها:

  • برد AVR WIZZARD
  • ماژول ADXL355
  • آداپتور تغذیه
  • سیم جامپر

کدنویسی:

ADXL355 از طریق درگاه SPI ارتباط برقرار می‌کند. برای نوشتن کد مربوطه، ابتدا در CodeVision پروژه جدید تعریف کرده و درگاه‌های SPI آن را راه اندازی می‌کنیم. همچنین تنظیمات مربوط به LCD  را انجام می‌دهیم.

ایجاد پروژه در CodeVision

برای ایجاد پروژه جدید، از شاخه File، گزینه New و سپس Project را انتخاب کنید.

ایجاد پروژه در CodeVision
پنجره ایجاد پروژه

سپس پیغام مربوط به code wizard را مشاهده خواهید کرد؛ دکمه Yes را بزنید.

پیغام مربوط به code wizard
پیغام مربوط به code wizard

سپس پنجره دیگری نشان داده خواهد شد؛ گزینه اول را انتخاب کرده و Ok را بزنید.

code wizard انتخاب خانواده

پس از تایید این گزینه، وارد صفحه جدیدی خواهید شد. در این صفحه تنظیمات مربوط به پورت‌های ورودی و خروجی، LCD و SPI را انجام خواهیم داد. میکرو کنترلر استفاده شده ATMEGA32A می‌باشد.

پورت‌های ورودی و خروجی

پایه CS ماژول به PORTB.4 متصل است. در قسمت PORT، این پورت را به عنوان خروجی تعریف می کنیم.

قسمت PORT

سپس تنظیمات مربوط به LCD را انجام می‌دهیم.

تنظیمات مربوط به LCD

همانطور که روی برد مشخص شده است، خطوط داده LCD به PORTA و خطوط فرمان به PORTB متصل هستند.

در ادامه SPI را فعال سازی می‌کنیم.

در پایان تنظیمات را ذخیره کرده و گزینه تولید فایل‌ها را می‌زنیم.

ذخیره سازی

پس از ذخیره سازی، وارد پنجره کدنویسی خواهیم شد. در این پنجره قسمت‌های مشخص شده اند که کاربر کد خود را در آن جا وارد کند.

کد برنامه

/*******************************************************
Chip type               : ATmega32A
Program type            : Application
AVR Core Clock frequency: 8.000000 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 512
*******************************************************/
#include <mega32a.h>
// SPI functions
#include <spi.h>
// Alphanumeric LCD functions
#include <alcd.h>
// Declare your global variables here
// Standard Input/Output functions
#include <stdio.h>
#include <stdint.h>
#include <delay.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
//adxl registers
uint8_t status_reg=0x04;
uint8_t temp2=0x06;
uint8_t temp1=0x07;
uint8_t xdata3=0x08;
uint8_t xdata2=0x09;
uint8_t xdata1=0x0A;
uint8_t ydata3=0x0B;
uint8_t ydata2=0x0C;
uint8_t ydata1=0x0D;
uint8_t zdata3=0x0E;
uint8_t zdata2=0x0F;
uint8_t zdata1=0x10;
uint8_t filter=0x28;
uint8_t range=0x2C;
uint8_t mode=0x2D;
uint8_t mode_off=0x01;
uint8_t mode_on=0x00;
long int  x,y,z;
float e=0,e1=0,e2=0,k1=.01,k2=.01,k3=0,delta_u=0,out; //PID variables (change k1,k2,k3 (must be<1) to see theire effects)
float acc_x,acc_y,acc_z;
float temperatur;
char x_ch[10],y_ch[10],z_ch[10];
/************** 2G,  4G,  8G *********/
uint8_t range_value[]={0x01,0x02,0x03};
/*******************4000,2000,1000,500,250,125,62.5,31.25,15.625,7.813,3.906 HZ****/
uint8_t ODR_LPF[]= {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A};

void adxl_config(uint8_t,uint8_t);
void adxl_readData(uint8_t);
void uart_print(char*);
void uart_putchar(char); 
void main(void)
{
// Declare your local variables here

// Input/Output Ports initialization
// Port A initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRA=(0<<DDA7) | (0<<DDA6) | (0<<DDA5) | (0<<DDA4) | (0<<DDA3) | (0<<DDA2) | (0<<DDA1) | (0<<DDA0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
// Port B initialization
// Function: Bit7=Out Bit6=In Bit5=Out Bit4=Out Bit3=In Bit2=In Bit1=In Bit0=In
DDRB=(1<<DDB7) | (0<<DDB6) | (1<<DDB5) | (1<<DDB4) | (0<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=0 Bit6=T Bit5=0 Bit4=0 Bit3=T Bit2=T Bit1=T Bit0=T 
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);
// Port C initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRC=(0<<DDC7) | (0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTC=(0<<PORTC7) | (0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);
// Port D initialization
// Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In 
DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
// State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T 
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 9600
UCSRA=(0<<RXC) | (0<<TXC) | (0<<UDRE) | (0<<FE) | (0<<DOR) | (0<<UPE) | (0<<U2X) | (0<<MPCM);
UCSRB=(0<<RXCIE) | (0<<TXCIE) | (0<<UDRIE) | (1<<RXEN) | (1<<TXEN) | (0<<UCSZ2) | (0<<RXB8) | (0<<TXB8);
UCSRC=(1<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x33;
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 500.000 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=(0<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (0<<SPR1) | (1<<SPR0);
SPSR=(0<<SPI2X);
// TWI initialization
// TWI disabled
TWCR=(0<<TWEA) | (0<<TWSTA) | (0<<TWSTO) | (0<<TWEN) | (0<<TWIE);
// Alphanumeric LCD initialization
// Connections are specified in the
// Project|Configure|C Compiler|Libraries|Alphanumeric LCD menu:
// RS - PORTB Bit 0
// RD - PORTB Bit 1
// EN - PORTB Bit 2
// D4 - PORTA Bit 4
// D5 - PORTA Bit 5
// D6 - PORTA Bit 6
// D7 - PORTA Bit 7
// Characters/line: 16
lcd_init(16);
lcd_init(16);
lcd_clear();
lcd_gotoxy(6,0); //row 0 column 6
lcd_printf("KEI");
lcd_gotoxy(6,1); //row 1 column 6
lcd_printf("CAN");
adxl_config(mode,mode_off);
adxl_config(filter, ODR_LPF[8]);
adxl_config(range,range_value[0]);
delay_ms(500);
adxl_config(mode,mode_on);
delay_ms(500);
while (1)
      {
// Place your code here
       adxl_readData(temp2);  
      }
}
void adxl_config(uint8_t address,uint8_t value)
{
 uint8_t i;
 PORTB.4=0;                             
 for (i=0;i<20;i++);  
 SPDR=(address<<1 | 0x00);                         //sending register address   
 while(!(SPSR & (1<<SPIF)));       //Wait for transmission complete
 SPDR=value;                         //sending register value
 while(!(SPSR & (1<<SPIF)));       //Wait for transmission complete
 PORTB.4=1; 
}
void adxl_readData(uint8_t address)
{
 uint8_t status_r,i,read_data[11];  
 char st[5],temp_ch[5],acc_xch[10],acc_ych[10],acc_zch[10];   
 
 /*********check status register************/
 PORTB.4=0;//chip select pin                              
 for (i=0;i<20;i++);//delay
SPDR=(status_reg<<1 | 0x01);//status register address
 while(!(SPSR & (1<<SPIF)));  
 SPDR=0xFF;    
 while(!(SPSR & (1<<SPIF))); 
 status_r=SPDR; 
 PORTB.4=1;
 for (i=0;i<60;i++); 
 if(status_r &0x01==1)//if data ready?
 {
 PORTB.4=0;   
 for (i=0;i<20;i++);
 SPDR=((address)<<1 | 0x01);
 while(!(SPSR & (1<<SPIF)));
 for(i=0;i<11;++i)
 {
 SPDR=0xFF;    
 while(!(SPSR & (1<<SPIF)));
 read_data[i]=SPDR;   
 }      
 for (i=0;i<20;i++);
 PORTB.4=1; 
 /**************temperature data***********/
temperatur=(long)read_data[0]<<8| read_data[1];
 temperatur=((1852-temperatur)/9.05)+25; //from datasheet   
 
 /**************PID controller*************/
        e2=e1;
        e1=e;
        e=-temperatur;
        delta_u=k1*e + k2*e1 + k3*e2;
        temperatur=temperatur+delta_u;
        out=temperatur-delta_u;   
 /**************************************/ 
       
  x=(long)read_data[2]<<12 | (long)read_data[3]<<4 | read_data[4]>>4; //x-axis data(20 bit)
 if(x>=0x00080000)  //Data is left justified and formatted as twos complement.
  {
  x=-1048576 - (~x+1);
  } 
  y=(long)read_data[5]<<12 | (long)read_data[6]<<4 | read_data[7]>>4;
  if(y>=0x00080000)
  {
  y=-1048576 - (~y+1);
  }
z=(long)read_data[8]<<12 | (long)read_data[9]<<4 | read_data[10]>>4; 
  if(z>=0x00080000)
  {
  z=-1048576 - (~z+1);
  }
  ltoa(x,x_ch);//ltoa() function in C language converts long data type to string data type
  ltoa(y,y_ch);
  ltoa(z,z_ch);  
  acc_x=(float)x/262144;  //This formula is for 2G range mode!
  acc_y=(float)y/262144;
  acc_z=(float)z/262144;  
  ftoa(acc_x,1,acc_xch); //convert a floating point number to a character array  to display on LCD
  ftoa(acc_y,1,acc_ych);
  ftoa(acc_z,1,acc_zch);
  ftoa(out,2,temp_ch); 
  lcd_clear();
  lcd_gotoxy(0,0); //row 0 column 0
  lcd_puts(acc_xch);
  lcd_puts(", ");
  lcd_puts(acc_ych);
  lcd_puts(", ");
  lcd_puts(acc_zch);
  lcd_gotoxy(0,1); //row 1 column 0   
  lcd_puts("Temp: ");
  lcd_puts(temp_ch);
  lcd_puts(" 0C");
  uart_print("X= ");                 
  uart_print(x_ch); // sending data by UART
  uart_print(", ");
               
  uart_print(y_ch); // sending data by UART
  uart_print(", ");
  uart_print(z_ch); // sending data by UART
  uart_print(". \r\n "); 
   }
}

void uart_putchar(char z) 
{
        UDR = z; 
        while ( !( UCSRA & (1<<UDRE)) ) ; //Wait for transmission complete
}
void uart_print(char  *st)
{
	int stl, i;
stl = strlen(st);
	for (i=0; i<stl; i++)
	uart_putchar(*st++);
}

نتایج خروجی

 

نتایج خروجیADXL355 با ATMEGA32A
نتایج خروجیADXL355 با ATMEGA32A

نکات

  • داده‌های سطر اول LCD، داده‌های مربوط به محورهای مختلف شتاب سنج هستند که به صورت عددی در بازه‌ی g± نشان داده‌شده‌اند.
  • سطر دوم داده مربوط به سنسور دمای ADXL355 را نشان می‌دهد که برای نمایش بهتر آن، یک کنترل‌کننده PID بر روی آن اعمال شده است. برای تغییر ضرایب کنترل کننده، می‌توان مقادیر مربوط به آن را در کد اصلاح کرد

zahra_ahmadi

پاسخ دهید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

هجده + 15 =