/* * spreadspace avr utils * * * Copyright (C) 2016 Bernhard Tittelbach * appreciative nod to Adafruit for writing a great example, go buy their stuff * * This file is part of spreadspace avr utils. * * spreadspace avr utils is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * spreadspace avr utils is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with spreadspace avr utils. If not, see . */ #include #include #include #include "bmp280.h" int32_t bmp280_t_fine = 0; void bmp280_cs(bmp280_sensor *sensor, uint8_t select) { if (!select) *(sensor->cs_port) |= _BV(sensor->cs_pin); else *(sensor->cs_port) &= ~ _BV(sensor->cs_pin); } void bmp280_write8(uint8_t reg, uint8_t value) { SPI_SendByte(reg & ~0x80); //bit 7 needs to be low for write mode SPI_SendByte(value); } uint8_t bmp280_read8(uint8_t reg) { SPI_SendByte(reg | 0x80); //bit 7 high for read mode return SPI_ReceiveByte(); } uint16_t bmp280_read16(uint8_t reg) { uint16_t value = 0; SPI_SendByte(reg | 0x80); //bit 7 high for read mode value |= ((uint16_t) SPI_ReceiveByte() & 0xFF) << 8; value |= (uint16_t) SPI_ReceiveByte() & 0xFF; return value; } uint32_t bmp280_read24(uint8_t reg) { uint32_t value = 0; SPI_SendByte(reg | 0x80); //bit 7 high for read mode value |= ((uint32_t) SPI_ReceiveByte() & 0xFF) << 16; value |= ((uint32_t) SPI_ReceiveByte() & 0xFF) << 8; value |= (uint32_t) SPI_ReceiveByte() & 0xFF; return value; } int16_t bmp280_readS16(uint8_t reg) { return (int16_t) bmp280_read16(reg); } uint16_t bmp280_read16_LE(uint8_t reg) { uint16_t value = 0; SPI_SendByte(reg | 0x80); //bit 7 high for read mode value |= (uint16_t) SPI_ReceiveByte() & 0xFF; value |= ((uint16_t) SPI_ReceiveByte() & 0xFF) << 8; return value; } int16_t bmp280_readS16_LE(uint8_t reg) { return (int16_t)bmp280_read16_LE(reg); } void bmp280_readCoefficients(bmp280_sensor *sensor) { bmp280_cs(sensor, true); sensor->dig_T1 = bmp280_read16_LE(BMP280_REGISTER_DIG_T1); sensor->dig_T2 = bmp280_readS16_LE(BMP280_REGISTER_DIG_T2); sensor->dig_T3 = bmp280_readS16_LE(BMP280_REGISTER_DIG_T3); sensor->dig_P1 = bmp280_read16_LE(BMP280_REGISTER_DIG_P1); sensor->dig_P2 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P2); sensor->dig_P3 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P3); sensor->dig_P4 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P4); sensor->dig_P5 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P5); sensor->dig_P6 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P6); sensor->dig_P7 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P7); sensor->dig_P8 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P8); sensor->dig_P9 = bmp280_readS16_LE(BMP280_REGISTER_DIG_P9); bmp280_cs(sensor, false); } //need to init SPI beforehand void bmp280_init(bmp280_sensor *sensor, volatile uint8_t *cs_port, uint8_t cs_pin) { memset(sensor,0,sizeof(bmp280_sensor)); sensor->cs_port = cs_port; sensor->cs_pin = cs_pin; bmp280_readCoefficients(sensor); } float bmp280_readTemp(bmp280_sensor *sensor) { int32_t var1, var2; bmp280_cs(sensor, true); int32_t adc_T = bmp280_read24(BMP280_REGISTER_TEMPDATA); bmp280_cs(sensor, false); adc_T >>= 4; var1 = ((((adc_T>>3) - ((int32_t)sensor->dig_T1 <<1))) * ((int32_t)sensor->dig_T2)) >> 11; var2 = (((((adc_T>>4) - ((int32_t)sensor->dig_T1)) * ((adc_T>>4) - ((int32_t)sensor->dig_T1))) >> 12) * ((int32_t)sensor->dig_T3)) >> 14; bmp280_t_fine = var1 + var2; float T = (bmp280_t_fine * 5 + 128) >> 8; return T/100; } float bmp280_readPressure(bmp280_sensor *sensor) { int64_t var1, var2, p; // Must be done first to get the bmp280_t_fine variable bmp280_readTemp(sensor); bmp280_cs(sensor, true); int32_t adc_P = bmp280_read24(BMP280_REGISTER_PRESSUREDATA); bmp280_cs(sensor, false); adc_P >>= 4; var1 = ((int64_t)bmp280_t_fine) - 128000; var2 = var1 * var1 * (int64_t)sensor->dig_P6; var2 = var2 + ((var1*(int64_t)sensor->dig_P5)<<17); var2 = var2 + (((int64_t)sensor->dig_P4)<<35); var1 = ((var1 * var1 * (int64_t)sensor->dig_P3)>>8) + ((var1 * (int64_t)sensor->dig_P2)<<12); var1 = (((((int64_t)1)<<47)+var1))*((int64_t)sensor->dig_P1)>>33; if (var1 == 0) { return 0; // avoid exception caused by division by zero } p = 1048576 - adc_P; p = (((p<<31) - var2)*3125) / var1; var1 = (((int64_t)sensor->dig_P9) * (p>>13) * (p>>13)) >> 25; var2 = (((int64_t)sensor->dig_P8) * p) >> 19; p = ((p + var1 + var2) >> 8) + (((int64_t)sensor->dig_P7)<<4); return (float)p/256; } /*float bmp280_readAltitude(bmp280_sensor *sensor, float sealevelp) { float altitude; float pressure = bmp280_readPressure(sensor); // in Si units for Pascal pressure /= 100; altitude = 44330 * (1.0 - pow(pressure / seaLevelhPa, 0.1903)); return altitude; }*/ /// Helper Functions