Мы пытаемся прочитать данные с акселерометра (axdl345), обработать их через PIC16F1827 (мы используем протокол I2 C), а затем управлять светодиодом с помощью ШИМ. Основная идея заключается в том, что наша конструкция должна быть установлена на велосипеде, и в зависимости от замедления велосипеда светодиод должен становиться все ярче и ярче (например, задний фонарь для велосипедов). Однако у нас возникают некоторые проблемы при попытке понять вывод adxl345 и то, как обрабатывать данные в MPLAB для достижения желаемого эффекта. Мы пытаемся считать данные как g-единицы (гравитация).
На данный момент это наш код в MPLAB:
#pragma config FOSC=INTOSC, CLKOUTEN=ON //Intern oscillator, ClockOut På
#pragma config IESO=OFF, FCMEN=OFF //FCM/IESO OFF
#pragma config STVREN=ON, MCLRE=ON //Stack overflow reset on, mclr on
#pragma config WDTE=OFF, CP=OFF //watchdog off, code protection off
#pragma config PWRTE=ON, WRT=OFF //poweuptimer on, writeprotection off
#pragma config PLLEN=OFF, LVP=ON //PLL OFF, low-voltage programming off
#pragma config CPD=OFF, BOREN=OFF, BORV=LO //data protection off, brownout off
#include <xc.h>
#include <stdio.h>
#include <stdlib.h>
#define _XTAL_FREQ 4000000
#define DATAX0 0x32
#define DATAX1 0x33
#define DATAY0 0x34
#define DATAY1 0x35
#define DATAZ0 0x36
#define DATAZ1 0x37
//funktionsdeklarationer
void init(void);
void i2c_init(void);
void i2c_wait_ready(void);
void i2c_start(void);
void i2c_write(unsigned int);
unsigned short i2c_read(void);
void i2c_stop(void);
void i2c_restart(void);
unsigned char adxl_read(int);
void i2c_ack(void);
void i2c_nack(void);
char adxl_write(int, unsigned char);
void adxl_init(void);
void main()
{
int acc_data;
init();
i2c_init();
adxl_init();
while(1)
{
signed long xraw, xhi, xlo, yraw, yhi, ylo, zraw, zhi, zlo;
for(int i = 0; i<16; i++) //read data
{
i2c_start();
i2c_write(0xA6);
i2c_write(DATAX0);
i2c_restart();
i2c_write(0xA7);
xlo = i2c_read();
i2c_ack();
xhi = i2c_read();
i2c_ack();
ylo = i2c_read();
i2c_ack();
yhi = i2c_read();
i2c_ack();
zlo = i2c_read();
i2c_ack();
zhi = i2c_read();
i2c_nack();
i2c_stop();
}
xraw = (xhi<<8)|xlo; //load raw data to one long
yraw = (yhi<<8)|ylo;
zraw = (zhi<<8)|zlo;
signed long xg, yg, zg;
xg = xraw*0.0156; //convert to g check adxl datasheet
yg = yraw*0.0156;
zg = zraw*0.0156;
CCPR3L = zg;
__delay_ms(20);
}
}
void adxl_init(void)
{
adxl_write(0x38, 0x9F); //FIFO_CTL
__delay_ms(10);
adxl_write(0x31, 0x02); //Data format
__delay_ms(10);
adxl_write(0x2C, 0x0d);
__delay_ms(10);
adxl_write(0x2D, 0x08);
}
void init()
{
OSCCON = 0b01101000; //intern klocka 4MHz
ANSELA = 0b00000000; //alla bitar RA0-RA7 digitala
ANSELB = 0b00000000; //alla bitar RB0-RB7 digitala
TRISA = 0x00; //alla A-bitar utgångar
TRISB = 0x00; //alla B-bitar utgångar
CCP3CON = 0b00001100; //ccp3 i pwm
CCPTMRS = 0b01001010; //ccp3 i timer2
//PR2 = 254;
T2CON = 0b00000100; //timer 2 på, prescaler 1, ger fpwm = 4kHz
}
void i2c_init(void)
{
SSPCON = 0b00101000; //PIC i i2c master-mode
SSPCON2 = 0;
SSPADD = 0x09; //(_XTAL_FREQ/(clock_speed-1)); Klockhastighet
SSPSTAT = 0;
TRISBbits.TRISB1 = 1; //SDA som ingång
TRISBbits.TRISB4 = 1; //SCL som ingång
}
void i2c_wait_ready(void)
{
while((SSPSTATbits.BF) || (SSPSTATbits.R_nW)); //Kollar read information i SSPSTAT och sändarfo i SSPCON2
}
void i2c_start(void)
{
SSPCON2bits.SEN = 1; //SEN = 1
while(SSPCON2bits.SEN);
}
void i2c_restart(void)
{
SSPCON2bits.RSEN = 1;
while(SSPCON2bits.RSEN);
}
void i2c_write(unsigned int address)
{
SSPBUF = address; //write to i2c
while(SSPSTATbits.BF);
i2c_wait_ready();
}
unsigned short i2c_read(void)
{
unsigned short data_buffer; //read from i2c
SSPCON2bits.RCEN = 1; //Recieve enabled
while(SSPSTATbits.BF != 1);
data_buffer = SSPBUF;
i2c_wait_ready();
return(data_buffer);
}
void i2c_stop(void)
{
SSPCON2bits.PEN = 1; //PEN = 1
while(SSPCON2bits.PEN);
}
char adxl_write(int write_adress, unsigned char int_adr)
{
i2c_start(); //write to adxl.
i2c_write(0xA6);
i2c_write(write_adress);
i2c_write(int_adr);
i2c_stop();
return 1;
}
unsigned char adxl_read(int adress) //read from adxl(not used here)
{
unsigned char byte;
unsigned char ch;
i2c_start();
i2c_write(0xA6);
i2c_write(adress);
i2c_restart();
i2c_write(0xA7);
ch= i2c_read();
i2c_nack();
i2c_stop();
return ch;
}
void i2c_ack(void) //acknowledge
{
SSPCON2bits.ACKDT = 0;
SSPCON2bits.ACKEN = 1;
while(SSPCON2bits.ACKEN);
}
void i2c_nack(void) //acknowledge
{
SSPCON2bits.ACKDT = 1;
SSPCON2bits.ACKEN = 1;
while(SSPCON2bits.ACKEN);
}
С этим кодом светодиод, похоже, игнорирует ШИМ и имеет высокий или низкий уровень (255 или 0). Можно ли преобразовать необработанные данные в g-единицы, чтобы решить эту проблему?