Jump to content
ELFORUM - Forumul electronistilor

PIC16f887 cu accelerometru MMA7455, mikroc pro, I2C


Guest andrei_wsk

Recommended Posts

Guest andrei_wsk

Buna ziua,

Incerc sa realizez un proiect cu ajutorul unui pic 16f887 si a unui accelerometru MMA7455. Programul pe care il folosesc este mikroc pro si biblioteca pusa la dispozitie de acesta. Controller-ul comunica cu accelerometrul prin I2c. Am studiat datasheet-ul si am vazut ca adresa accelerometrului este 0x0D. Pt inceput vreau sa citesc doar axa X deci ma intereseaza doar registrul 0x06 sau 0x00(va rog corectati-ma daca gresesc). Conexiuile le-am facut in felul urmator: VCC -VCC, GND -GND, SCL- RC3, SDA- RC4, CS -VCC. Accelerometrul ar trebui sa imi furnizeze pe axa X atat valori negative cat si valori pozitive. Ceea ce am incercat sa realizez defapt a fost sa aprind un led cand citesc valori pozitive si sa il inchid cand citesc valori negative. Din pacate nu reusesc sa fac comunicarea intre controller si accelerometru. Am cautat pe interet si am gasit unele thread-uri unde lumea spunea ca adresa ar fi 0x3A sau 0xD1. Am incercat si cu aceste adrese tot fara succes. Postez si codul

 

 

 

// Software I2C connectionssbit Soft_I2C_Scl           at RC3_bit;sbit Soft_I2C_Sda           at RC4_bit;sbit Soft_I2C_Scl_Direction at TRISC3_bit;sbit Soft_I2C_Sda_Direction at TRISC4_bit;// End Software I2C connectionschar X;void Read_X() {  Soft_I2C_Start();               // Issue start signal  Soft_I2C_Write(0x3A);            Soft_I2C_Write(0x00);                Soft_I2C_Start();               // Issue repeated start signal  Soft_I2C_Write(0x3B);           X = Soft_I2C_Read(0u);       Soft_I2C_Stop();}void Init_Main() {  ANSEL  = 0;                // Configure AN pins as digital I/O  ANSELH = 0;  C1ON_bit = 0;              // Disable comparators  C2ON_bit = 0;  Soft_I2C_Init();           // Initialize Soft I2C communication}void main() {                // Main procedure  Delay_ms(500);  Init_Main();               // Perform initialization  while (1) {    Read_X();      if (X<0)          {  trisb.b5=0;         portb.b5=1;}  else                    {  trisb.b5=1;         portb.b5=0;}  }}

Multumesc

Link to comment
  • Replies 8
  • Created
  • Last Reply

Top Posters In This Topic

In primul data-sheet gasit cu google adresa e 0x1D.

SINGLE BYTE WRITETo start a write command, the Master transmits a start condition (ST) to the MMA7455L, slave address ($1D) with the R/W bit setto “0” for a write,

Cu adresa asta si cu bitul read/write se "contruieste" byte-ul de adresare - b00111010 - scriere si b00111011 - citire. Adica ce ai folosit tu, 0x3A la scriere si 0x3B la citire.Da' de ce zici ca nu merge? Ce nu face?Ca partea cu negativ e "de la tine". Acceleratia e pe 10 biti, in complement fata de 2.

$00: 10bits Output Value X LSB (Read only)...Signed byte data (2’s compliment):

Asta inseamna ca trebuie sa citesti si adresa 2 si sa "construiesti" acceleratia, dupa care sa o convertesti in complement fata de 2.
Link to comment
Guest andrei_wsk

Nu interfateaza. Imi indica 255,valoare maxima, constant indiferent cum misc accelerometrul. Am vazut in tabel pe acest site http://www.parallax.com/Portals/0/Downl ... l-v1.1.pdf la pagina 4 de aceea credeam ca imi va returna numere negative. Apropo de led... il conectez normal prin rezistenta la pinul integratului si la GND. Pur si simplu am schimbat starea lui pt ca daca il lasam ca iesire se aprindea led-ul in continuare chiar daca portb=0.

Link to comment

Pai daca ledul se aprinde oricum ai seta portul respectiv (high sau low), inseamna ca ai probleme (probabil de configurare) pe care trebuie sa le rezolvi inainte de comunicatia i2c (adica fa ledul sa clipoceasca asa cum vrei tu, dupa care treci la problemele mai complicate).Eu asa as face.

Link to comment

daca tot nu ai reusit cu accelerometrul.

 

Compilerul este CCS(PCWHD)

Driver pentru I2C

 

/*********************************************************************  Writer Tanase Bogdan  (c) copyright www.hexhoby.ro  ALL RIGHTS RESERVED ******************************************************************** Ver 0.1 release 19/iunie/2011********************************************************************/#include <33FJ64GS406.h>#use delay(clock=81070000)  // real clock (masurat)//#use delay(clock=80000000)   // clock //#use i2c(Master,Slow,sda=PIN_G3,scl=PIN_G2, force_HW)#use i2c(Master,Slow,sda=PIN_B5,scl=PIN_B6, force_HW) unsigned int8 x_ax, y_ax, z_ax; 	int1 flag_x, flag_y, flag_z;//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~void start_acc_I2C()	{i2c_start(); i2c_write(0x3A); //0x1D shifted in with a 0 had been 0x3A i2c_write(0x16); //MODE CONTROL REGISTER i2c_write(0x05); //CONTINOUS MEASUREMENT i2c_stop(); delay_ms(30); 	}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~unsigned int8 acc_i2c_read(unsigned int8 reg)	{ unsigned int8 data; //	delay_ms(1);i2c_start(); i2c_write(0x3A); i2c_write(reg); //8 bits output value Z i2c_start(); i2c_write(0x3B); //0x1D shifted in with a 1 had been 0x3B data=i2c_read(0); i2c_stop(); //	delay_ms(1);return(data);	}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~void acc_i2c_write(unsigned int8 reg,unsigned int8 data)	{i2c_start(); i2c_write(0x3A); //0x1D shifted in with a 0 had been 0x3A i2c_write(reg); //MODE CONTROL REGISTER i2c_write(data); //CONTINOUS MEASUREMENT i2c_stop(); 	}// from interrupts//~~~~~~~~~~~~~~ set to 240Hz bandwitch ?? s-au bandwich  ~~~~~~~~~~~~~~~~~void sel_250_Hz()	{acc_i2c_write(0x18, 0x80);	}//~~~~~~~~~~~~~~~~set offset to 0 ~~~~~~~~~~~~~~~~~~void calib_off_acc_0 ()	{	acc_i2c_write(0x10, 0x00);	delay_ms(10);	acc_i2c_write(0x12, 47);	delay_ms(10);//	acc_i2c_write(0x14, 0x00);//	delay_ms(10);	}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~void auto_calibrate()	{	int16 i;signed char Xdata,Ydata,Zdata;signed short Xcal,Xcalp, Ycal, Ycalp, Zcal, Zcalp;byte Xcal_L, Xcal_H, Ycal_L,Ycal_H, Zcal_L, Zcal_H;acc_i2c_write(0x16,0x05);//Asigura daca calibratia registrilor este claraacc_i2c_write(0x10,0);acc_i2c_write(0x11,0);Xcal=0;for (i=0;i<=50;i++)	{Xdata= acc_i2c_read(0x06);Ydata= acc_i2c_read(0x07);Zdata= acc_i2c_read(0x08);Xcal+= -2*Xdata; //Calculeaza biasul acesteiaYcal+= -2*Ydata;if (Zdata>65){Zcal+=(Zdata-64)*2;}else{Zcal+=(64-Zdata)*2;}Xcalp=Xcal; //Daca calp este pozitiv asuma variabilaif (Xcalp<0) Xcalp +=2048; //daca este neg, convert for 2's complementYcalp=Ycal;if(Ycalp<0) Ycalp+=2048;Zcalp=Zcal;if(Zcalp<0) Zcalp+=2048;Xcal_L= (byte)(Xcalp&0x00FF); //shift low byte to lower 8 bitsXcal_H= (byte)((Xcalp&0xFF00)>>8); //shift high byte to upper 8 bitsYcal_L= (byte)(Ycalp&0x00FF); //shift low byte to lower 8 bitsYcal_H= (byte)((Ycalp&0xFF00)>>8); //shift high byte to upper 8 bitsZcal_L= (byte)(Zcalp&0x00FF); //shift low byte to lower 8 bitsZcal_H= (byte)((Zcalp&0xFF00)>>8); //shift high byte to upper 8 bitsXcal += -2*Xdata;delay_ms(10);Xdata=acc_i2c_read(0x00);	}acc_i2c_write(0x10,Xcal_L); //Write low calibration value to the low calibration registeracc_i2c_write(0x11,Xcal_H); //Write high calibration value to the high calibration registeracc_i2c_write(0x12,Ycal_L); //Write low calibration value to the low calibration registeracc_i2c_write(0x13,Ycal_H); //Write high calibration value to the high calibration registeracc_i2c_write(0x14,Zcal_L); //Write low calibration value to the low calibration registeracc_i2c_write(0x15,Zcal_H); //Write high calibration value to the high calibration register	}//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~void X_axis()	{	if(flag_x == false)		{		i2c_start(); 		i2c_write(0x3A); 		i2c_write(0x06);  		i2c_start(); 		i2c_write(0x3B); 		x_ax = i2c_read(0); 		i2c_stop(); 		flag_x = true;		}		}//=============================== //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~void Y_axis()	{	if(flag_y == false)		{		i2c_start(); 		i2c_write(0x3A); 		i2c_write(0x07);  		i2c_start(); 		i2c_write(0x3B); 		y_ax = i2c_read(0); 		i2c_stop(); 		flag_y = true;		} 	}//=============================== //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~void Z_axis()	{	if(flag_z == false)		{		i2c_start(); 		i2c_write(0x3A); 		i2c_write(0x08);  		i2c_start(); 		i2c_write(0x3B); 		z_ax = i2c_read(0); 		i2c_stop(); 		flag_z = true;		}	}//===============================

si pentru SPI.

 

#include <main.h>//#int_EXT0///#use rs232(UART1,baud=19200,parity=N,bits=8)//#use rs232(baud=9600,parity=N,xmit=PIN_F3,rcv=PIN_F2,bits=8)//#USE SPI (MASTER, SPI1, ENABLE=PIN_G8, MODE=0, BITS=8, STREAM=SPI_0, MSB_FIRST)//#USE SPI (MASTER, CLK=PIN_C3, DI=PIN_C5, DO=PIN_C4, ENABLE=PIN_D1, MODE=0, BITS=8, STREAM=SPI_0, MSB_FIRST)#define ACC_CS  PIN_G9 // SPI modes #define SPI_MODE_0  (SPI_L_TO_H | SPI_XMIT_L_TO_H) #define SPI_MODE_1  (SPI_L_TO_H) #define SPI_MODE_2  (SPI_H_TO_L) #define SPI_MODE_3  (SPI_H_TO_L | SPI_XMIT_L_TO_H) //---------------------------------- //#import(RELOCATABLE, file = E:\PIC_Lucru\dsPIC33FJ64GS406\C30_teste\External_test\test_3\4\intrerrupt_ext.o)//#import(hex,file = E:\PIC_Lucru\dsPIC33FJ64GS406\C30_teste\External_test\test_3\4\test_monitor_1024_768.hex, range = 0x1200 : 0x2003)void  EXT0_isr(void) {}volatile signed int Xdata=0, Ydata=0, Zdata=0; //*********************************************************************void Acc_Write_Register(int8 reg, int8 data) { //output_low(ACC_CS); 	delay_ms(1);spi_write(((reg & 0x3F) << 1) | 0x80); 	delay_ms(1);spi_write(data); 	delay_ms(1);//output_high(ACC_CS); } //--------------------------------- int8 Acc_Read_Register(int8 reg) { int8 data; //output_low(ACC_CS); 	delay_ms(1);spi_write((reg & 0x3F) << 1); 	delay_ms(1);data = spi_read(0); 	delay_ms(1);//output_high(ACC_CS); return(data); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Pentru filtre daca ai nevoie ceri.

Ambele sunt functionale , restul depinde de tine

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.Terms of Use si Guidelines