atmega328p SPI with BME680

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hey guys!

Im trying to learn how to program the Atmeag328p, without all the libraries from Arduino.

So i made up a silly project of a voice activated fan that communicates over USART with a python program.

I got this working, but now i want to add a BME680 enviroment sensor over SPI, so i can get the temperature and humidity data.
I dont have any experience in the matter, but im hoping to learn by doing, this far i've just been struggeling.

 

I found these functions in the Atmega328p datasheet, and adjusted it to my pin connections.

void SPI_MasterInit(void)
{
	/* Set MOSI and SCK output, all others input */
	DDRB = (1<<DDB3)|(1<<DDB5);					//DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
	/* Enable SPI, Master, set clock rate fck/16 */
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
	
 	//setting the CS pin as output; EXTRA digital pin 10(PB2)
	DDRB |= (1<<DDB2);
	
}
void SPI_MasterTransmit(char cData)
{
	/* Start transmission */
	SPDR = cData;
	/* Wait for transmission complete */
	while(!(SPSR & (1<<SPIF)))
	;
}

There is a BME680 C-library that i found here
i tried to add the things mentioned in the Usage guide but im struggeling on how to write the "user_spi_read" and "user_spi_write" functions, and connect everything together.
 

Sorry for asking, but im not sure how to proceed.
Any help or fingers that could point me forward is highly apprecaited!

Thanks!
 

I've added the code isolated for the SPI under.

/*
 * testingSPI.c
 *
 * Created: 16.08.2019 11:51:28
 * Author : isolani
 */ 

#include <avr/io.h>
#include "bme680.h"
#include <stdio.h>
#include "USART.h"


// prototypes
int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len);
void user_delay_ms(uint32_t period);


char str[128] ; /*print buffer */


int main(void)
{	
        SPI_MasterInit();
	USART_init();
	
	
	
	//INITIALIZING THE SENSOR//**********************************************************************************************************	
	
	struct bme680_dev gas_sensor;

    /* You may assign a chip select identifier to be handled later */
    gas_sensor.dev_id = 0;
    gas_sensor.intf = BME680_SPI_INTF;
    gas_sensor.read = user_spi_read;
    gas_sensor.write = user_spi_write;
    gas_sensor.delay_ms = user_delay_ms;
    /* amb_temp can be set to 25 prior to configuring the gas sensor 
     * or by performing a few temperature readings without operating the gas sensor.
     */
    gas_sensor.amb_temp = 25;

    int8_t rslt = BME680_OK;
    rslt = bme680_init(&gas_sensor);
	
	
	
	
	//CONFIGURING THE SENSOR//************************************************************************************************************
		
	uint8_t set_required_settings;

	/* Set the temperature, pressure and humidity settings */
	gas_sensor.tph_sett.os_hum = BME680_OS_2X;
	gas_sensor.tph_sett.os_pres = BME680_OS_4X;
	gas_sensor.tph_sett.os_temp = BME680_OS_8X;
	gas_sensor.tph_sett.filter = BME680_FILTER_SIZE_3;

	/* Set the remaining gas sensor settings and link the heating profile */
	gas_sensor.gas_sett.run_gas = BME680_ENABLE_GAS_MEAS;
	/* Create a ramp heat waveform in 3 steps */
	gas_sensor.gas_sett.heatr_temp = 320; /* degree Celsius */
	gas_sensor.gas_sett.heatr_dur = 150; /* milliseconds */

	/* Select the power mode */
	/* Must be set before writing the sensor configuration */
	gas_sensor.power_mode = BME680_FORCED_MODE;

	/* Set the required sensor settings needed */
	set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL
	| BME680_GAS_SENSOR_SEL;

	/* Set the desired sensor configuration */
	rslt = bme680_set_sensor_settings(set_required_settings,&gas_sensor);

	/* Set the power mode */
	rslt = bme680_set_sensor_mode(&gas_sensor);
	
	
	
	
	//READING THE SENSOR DATA//************************************************************************************************************
	
	/* Get the total measurement duration so as to sleep or wait till the
     * measurement is complete */
    uint16_t meas_period;
    bme680_get_profile_dur(&meas_period, &gas_sensor);

    struct bme680_field_data data;

    while(1)
    {
        user_delay_ms(meas_period); /* Delay till the measurement is ready */

        rslt = bme680_get_sensor_data(&data, &gas_sensor);
        sprintf(str,"T: %.2f degC, P: %.2f hPa, H %.2f %%rH ", data.temperature / 100.0f,data.pressure / 100.0f, data.humidity / 1000.0f );
		USART_putstring(str);
		
        /* Avoid using measurements from an unstable heating setup */
        if(data.status & BME680_GASM_VALID_MSK)
            sprintf(str, ", G: %d ohms", data.gas_resistance);
			USART_putstring(str);

        printf("\r\n");

        /* Trigger the next measurement if you would like to read data out continuously */
        if (gas_sensor.power_mode == BME680_FORCED_MODE) {
            rslt = bme680_set_sensor_mode(&gas_sensor);
        }
    }
	return 0;
}

void SPI_MasterInit(void)
{
	/* Set MOSI and SCK output, all others input */
	DDRB = (1<<DDB3)|(1<<DDB5);											//DDR_SPI = (1<<DD_MOSI)|(1<<DD_SCK);
	/* Enable SPI, Master, set clock rate fck/16 */
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);
	
 	//setting the CS pin as output; EXTRA digital pin 10(PB2)
	DDRB |= (1<<DDB2);
	
}

void SPI_MasterTransmit(char cData)
{
	/* Start transmission */
	SPDR = cData;
	/* Wait for transmission complete */
	while(!(SPSR & (1<<SPIF)))
	;
}

void user_delay_ms(uint32_t period)
{
    /*
     * Return control or wait,
     * for a period amount of milliseconds
     */
}

int8_t user_spi_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */

    /*
     * The parameter dev_id can be used as a variable to select which Chip Select pin has
     * to be set low to activate the relevant device on the SPI bus
     */
    /*
     * Data on the bus should be like
     * |----------------+---------------------+-------------|
     * | MOSI           | MISO                | Chip Select |
     * |----------------+---------------------|-------------|
     * | (don't care)   | (don't care)        | HIGH        |
     * | (reg_addr)     | (don't care)        | LOW         |
     * | (don't care)   | (reg_data[0])       | LOW         |
     * | (....)         | (....)              | LOW         |
     * | (don't care)   | (reg_data[len - 1]) | LOW         |
     * | (don't care)   | (don't care)        | HIGH        |
     * |----------------+---------------------|-------------|
     */
	
	PORTB &= ~(1<<PORTB2);          //CS LOW
	SPI_MasterTransmit(reg_addr);	//REG ADRESS
	
	//reading data from MISO (PORTB4)
	for(int i=0; i < len; i++){
		reg_data[i] = PORTB4;       //????
	}		
	PORTB |= (1<<PORTB2);			//CS HIGH -- transfer stopped
	

    return rslt;
}

int8_t user_spi_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len)
{
    int8_t rsult = 0; /* Return 0 for Success, non-zero for failure */

    /*
     * The parameter dev_id can be used as a variable to select which Chip Select pin has
     * to be set low to activate the relevant device on the SPI bus
     */

    /*
     * Data on the bus should be like
     * |---------------------+--------------+-------------|
     * | MOSI                | MISO         | Chip Select |
     * |---------------------+--------------|-------------|
     * | (don't care)        | (don't care) | HIGH        |
     * | (reg_addr)          | (don't care) | LOW         |
     * | (reg_data[0])       | (don't care) | LOW         |
     * | (....)              | (....)       | LOW         |
     * | (reg_data[len - 1]) | (don't care) | LOW         |
     * | (don't care)        | (don't care) | HIGH        |
     * |---------------------+--------------|-------------|
     */
		
	PORTB &= ~(1<<PORTB2);          //CS LOW
	SPI_MasterTransmit(reg_addr);	//REG ADRESS
	
	//reading data from MISO (PORTB4)
	for(int i=0; i < len; i++){
		reg_data[i] = SPDR;
	}
	PORTB |= (1<<PORTB2);			//CS HIGH -- transfer stopped

    return rsult;
}

 

Attachment(s): 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

SPI transfers data in both directions at the same time, so while sending, you are also receiving.  Your SPI_write, SPI_read should only be one function, SPI_Xfer() and should return the contents of the data reg after the transmission is complete. 

 

Like this:

  /* general SPI transfer function */
  uint8_t SPI_Transfer(uint8_t data)
    {
        SPDR = data;
        while (!(SPSR & (1<<SPIF)));
        return SPDR;
    }

With that, you should be able to get this to work.

 

Jim

 

Click Link: Get Free Stock: Retire early! PM for strategy

share.robinhood.com/jamesc3274
get $5 free gold/silver https://www.onegold.com/join/713...

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks a lot you for your reply Ki0bk! I will try it :)