پروژه های AVR, پروژه‌ها

پروژه راه اندازی ماژول سنسور مغناطیسی سه محوره RM3100 با استفاده از میکروکنترلر ATMEGA

راه-اندازی-rm3100با-avr

فهرست مطالب

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

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

1. ماژول سنسور RM3100

طبق تکنولوژی انحصاری magneto-inductive شرکت PNI، این سنسورها رزولوشن و عملکرد بالایی داشته و نسبت به سنسورهای اثرهال، تکرارپذیری با بیش از ده برابر رزولوشن بهتر و 20 مرتبه نویز کمتر را دارا می‌باشند. این ویژگی‌ها سبب شده تا بتوان جهت‌یابی دقیقی توسط این سنسورها داشت. این سنسورها گین و نرخ نمونه برداری بالایی داشته و هیسترزیس ندارند. همچنین مغناطیس‌سنج‌های PNI نیازی به کالیبراسیون دمایی یا پالس‌های set & reset قبل از هر اندازه‌گیری ندارند.

سنسورهای ژئو مغناطیسی برای اندازه‌گیری میدان مغناطیسی زمین مورد استفاده قرار می‌گیرند، اما چالش بزرگی که به آن روبرو هستند، تغییرات میدان‌های مغناطیسی است که به طور موقت اطلاعات مسیریابی را مختل می‌کنند؛ مانند اجزای فلزی وسایل، خودروی درحال عبور یا مجاورت در کنار تلفن همراه و کامپیوتر. بنابراین سنسور باید بتواند به طور دقیق بین میدان‌های مغناطیسی گذرا و تغییرات واقعی میدان زمین، تفاوت قائل شود. سنسورهای ژئو مغناطیسی PNI این توانایی را دارند تا با کاهش نویز، میدان مغناطیسی صحیحی را ارائه دهند.

از کاربردهای آن به ردیابی حرکت (Motion tracking)، قطب نما، کنترل بازی، کنترل تلویزیون و ست-آپ باکس و اندازه‌گیری میدان مغناطیسی، می‌توان اشاره کرد.

راه اندازی RM3100 توسط برد AVR WIZARD

هدف: در این پروژه سنسور ژئو مغناطیسی RM3100 توسط برد AVR WIZARD راه‌اندازی شده و داد‌ه‌های مربوط به هر محور ضمن نمایش بر روی LCD، از طریق درگاه سریال نیز ارسال می‌شود.

قطعات مورد نیاز:

کدنویسی

 

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

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

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

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

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

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

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

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

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

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

حال تنظیمات مربوط به UART را انجام می‌دهیم.

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

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

				
					
#include <mega32a.h>
// SPI functions
#include <spi.h>
// Alphanumeric LCD functions
#include <alcd.h>
#include <stdint.h>
#include <delay.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
// Declare your global variables here
Const int Data_rate[] = {0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F};
//600Hz,300Hz,150Hz,75Hz,37Hz,18Hz,9Hz,4.5Hz,2.3Hz,1.2Hz,.6Hz,.3Hz,.015Hz,.075Hz//
//0 1 2 3 4 5 6 7 8 9 10 11 12 13
uint8_t Status=0x00,i,mag[9],page=0;
uint8_t Status_add=0xB4;
int32_t x,y,z;
char x_ch[8],y_ch[8],z_ch[8],sta[8];
float norm;
void uart_putchar(char );
void cycleCount(uint8_t,uint8_t) ;
void reg_write(uint8_t,uint8_t ) ;
uint8_t reg_read(uint8_t );
void uart_print(char *st);
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=Out Bit2=In Bit1=In Bit0=In
DDRB=(1<<DDB7) | (0<<DDB6) | (1<<DDB5) | (1<<DDB4) | (1<<DDB3) | (0<<DDB2) | (0<<DDB1) | (0<<DDB0);
// State: Bit7=0 Bit6=T Bit5=0 Bit4=0 Bit3=0 Bit2=T Bit1=T Bit0=T
PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (1<<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) | (1<<PORTD1) | (0<<PORTD0);
// USART initialization
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=(0<<URSEL) | (0<<UMSEL) | (0<<UPM1) | (0<<UPM0) | (0<<USBS) | (1<<UCSZ1) | (1<<UCSZ0) | (0<<UCPOL);
UBRRH=0x00;
UBRRL=0x67;
// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 125.000 kHz
// SPI Clock Phase: Cycle Start
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=(1<<SPIE) | (1<<SPE) | (0<<DORD) | (1<<MSTR) | (0<<CPOL) | (0<<CPHA) | (1<<SPR1) | (0<<SPR0);
SPSR=(0<<SPI2X);
// 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_clear();
lcd_gotoxy(6,0); //row 0 column 6
lcd_printf("KEI");
lcd_gotoxy(6,1); //row 1 column 6
lcd_printf("CAN");
delay_ms(3000);
lcd_clear();
cycleCount(0x04,100); //cycle count register
reg_write(0x0B,0x96); //dataRate
reg_write(0x01,0x79); //measurment mode (CMM register)
while (1)
{
// Place your code here
Status=reg_read(0xB4); //reading status register to check DRDY bit
Status=(Status & 0x80); //DRDY is bit 8th
if (Status == 0x80) //if DRDY=1
{
PORTB.4=0; //CS Low
for (i=0;i<20;i++); //delay
SPDR=0xA4; //sending register address
while(!(SPSR & (1<<SPIF))); //Wait for transmission complete
for(i=0;i<9;i++) //getting 9 byte data,each axis has 3 byte data
{
SPDR=0xFF; //sending any data to sensor's buffer to recieve it's data
while(!(SPSR & (1<<SPIF))); //Wait for transmission complete
mag[i]=SPDR; //recieved data
}
PORTB.4=1; //cs pin go to high
x=((int32_t)((int8_t) mag[0])<<16)|(int32_t)(mag[1])<<8|(mag[2]);//24 bit data X-axis
y=((int32_t)((int8_t) mag[3])<<16)|(int32_t)(mag[4])<<8|(mag[5]);//24 bit data Y-axis
z=((int32_t)((int8_t) mag[6])<<16)|(int32_t)(mag[7])<<8|(mag[8]);//24 bit data Z-axis
if (page==0) // selecting which axis data display on LCD
{
itoa(x,x_ch); // converting int data to string for displaying on LCD
lcd_clear(); //clearing LCD display
lcd_gotoxy(0,0); //row 0 column 0
lcd_printf("X = ");
lcd_puts(x_ch); //X axis data
uart_print("X= ");
uart_print(x_ch); // sending data by UART
uart_print(", ");
}
else if (page==1)
{
lcd_clear();
itoa(y,y_ch);
lcd_gotoxy(0,0);
lcd_printf("Y = ");
lcd_puts(y_ch); //Y axis data
uart_print("Y= ");
uart_print(y_ch); // sending data by UART
uart_print(", ");
}
else if (page==2)
{
itoa(z,z_ch);
lcd_clear();
lcd_gotoxy(0,0);
lcd_printf("Z = ");
lcd_puts(z_ch); //Z axis data
uart_print("Z= ");
uart_print(z_ch); // sending data by UART
uart_print(", ");
}
else if (page==3)
{
itoa(x,x_ch);
itoa(y,y_ch);
itoa(z,z_ch);
uart_print(x_ch);
uart_print(", ");
uart_print(y_ch);
uart_print(", ");
uart_print(z_ch);
uart_print(", ");
lcd_clear();
lcd_gotoxy(0,0);
lcd_printf("axises data are on serial port!");
}
if(PINC.3==0) // SW2 KEY
{
delay_ms(500);
page++;
}
if(page==4)
page=0;
}
delay_ms(1);
}
}
void cycleCount(uint8_t address,uint8_t data) //function for config cyclecount register
{
if(data==50)data=0x32; else if(data==100)data=0x64; else data=0xC8;
PORTB.4=0; //cs pin go to low
for (i=0;i<20;i++); //delay
SPDR=address; //send config register address to spi buffer
while(!(SPSR & (1<<SPIF))); //Wait for transmission complete
for(i=0;i<3;i++) //config 3-axis cyclecount registers
{
SPDR=0x00; //MSB data
while(!(SPSR & (1<<SPIF))); //Wait for transmission complete
SPDR=data; //LSB data
while(!(SPSR & (1<<SPIF)));//Wait for transmission complete
}
PORTB.4=1; //cs pin go to high
delay_ms(10);
}
void reg_write(uint8_t address,uint8_t data)
{
PORTB.4=0; //cs pin go to low
for (i=0;i<20;i++); //delay
SPDR=address; //send config register address to spi buffer
while(!(SPSR & (1<<SPIF))); //Wait for transmission complete
SPDR=data; //config data
while(!(SPSR & (1<<SPIF)));//Wait for transmission complete
PORTB.4=1; //cs pin go to high
delay_ms(10);
}
uint8_t reg_read(uint8_t address)
{
PORTB.4=0; //cs pin go to low
for (i=0;i<20;i++); //delay
SPDR=address; //send reading register address to spi buffer
while(!(SPSR & (1<<SPIF))); //Wait for transmission complete
SPDR=0xFF; //sending any data to sensor's buffer to recieve it's data
while(!(SPSR & (1<<SPIF)));//Wait for transmission complete
PORTB.4=1; //cs pin go to high
delay_ms(10);
return SPDR ;
}
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++);
}

				
			

خروجی برنامه

2. خروجی سنسور قطب نما با استفاده از برد اموزشی پلاریس

نظرتان را درباره این مقاله بگویید 1 نظر

پروژه راه اندازی ماژول سنسور مغناطیسی سه محوره RM3100 با استفاده از میکروکنترلر ATMEGA

نوشته های مشابه

4 دیدگاه در “پروژه راه اندازی ماژول سنسور مغناطیسی سه محوره RM3100 با استفاده از میکروکنترلر ATMEGA

  1. میثم گفت:

    سلام
    آیا میشود سنسور flc 100 جایگزین سنسور فوق کرد وباید چه تغیراتی را اعمال کرد

  2. آیدا عزیزی گفت:

    با سلام و احترام
    خیر امکان پذیر نیست.

  3. مجتبی گفت:

    سلام. وقت بخیر. ضمن تشکر از آموزش خوبتون …
    من این سنسور رو از سایت شما تهیه کردم و سعی داشتم با استفاده از اردوئینو راه اندازیش کنم. علی رغم تلاش بسیار، با اینکه مقادیر رو طبق دیتاشیت در رجیسترهای مربوطه مینویسم و سیکل خواندن و نوشتن رجیسترها رو هم رعایت میکنم (هم خودم کدزدم هم از کدهای اماده استفاده کردم مثل لینک https://github.com/hnguy169/RM3100-Arduino ) سنسور DRDY رو یک نمیکنه (به این معنی که داده امادست) و داده خوانده شده از رجیسترهای هر محور مقدار صفر هست کلا.

    از آموزش بالا هم کمک گرفتم و روی ATMEGA8 پیاده کردم کد بالا رو اما اعداد نمایشی برای هر سه محور صفر هستند.
    علت رو متوجه نمیشم …
    کسی میتونه راهنمایی کنه؟

    ضمنا سعی کردم موارد فوق رو با I2C هم انجام بدم. اما علی رغم ادرس دهی درست سنسور، برنامه I2C SCANNER اردوئینو سنسور رو پیدا نمیکنه …

  4. مجتبی گفت:

    در ادامه پیام قبل باید بپرسم که اصلا مطمئن هستین که این ماژول I2C رو پشتیبانی میکنه؟ به نظر اون ماژولی که علاوه بر I2C، SPI هم داره ماژولی هست که خود شرکت PNICORP زده (که چاپ مشکی داره و کمی هم بزرگتره)، چون پایه I2C ENABLE تراشه اصلی رو ( تراشه MAGI2C) رو بیرون اورده تا کاربر بتونه اینترفیس ارتباطی رو انتخاب کنه. اما این ماژول (که چاپ سبز داره و کوچکتره) چنین پایه ای رو، روی کناره های PCB نداره بدین معنی که طراح بورد پایه I2C ENABLE تراشه اصلی رو ( تراشه MAGI2C) یا به زمین یا به VCC وصل کرده.
    ضمنا من بررسی کردم فروشنده های خارجی که این ماژول رو (به شکل تصویر) میفروشن صرفا SPI رو قید کردن به عنوان اینترفیس.

دیدگاهتان را بنویسید

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

سه × یک =