Чтение данных из ADXL345 для управления светодиодом - PullRequest
0 голосов
/ 05 марта 2020

Мы пытаемся прочитать данные с акселерометра (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-единицы, чтобы решить эту проблему?

...