--- /dev/null
+#include "main.h"\r
+\r
+uint8_t InitBME(BME280* bme280){\r
+\r
+ uint8_t dataToWrite = 0; //Temporary variable\r
+ \r
+ //Reading all compensation data, range 0x88:A1, 0xE1:E7\r
+ bme280->calibration.dig_T1 = ((uint16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_T1_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_T1_LSB_REG)));\r
+ bme280->calibration.dig_T2 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_T2_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_T2_LSB_REG)));\r
+ bme280->calibration.dig_T3 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_T3_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_T3_LSB_REG)));\r
+\r
+ bme280->calibration.dig_P1 = ((uint16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P1_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P1_LSB_REG)));\r
+ bme280->calibration.dig_P2 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P2_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P2_LSB_REG)));\r
+ bme280->calibration.dig_P3 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P3_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P3_LSB_REG)));\r
+ bme280->calibration.dig_P4 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P4_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P4_LSB_REG)));\r
+ bme280->calibration.dig_P5 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P5_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P5_LSB_REG)));\r
+ bme280->calibration.dig_P6 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P6_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P6_LSB_REG)));\r
+ bme280->calibration.dig_P7 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P7_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P7_LSB_REG)));\r
+ bme280->calibration.dig_P8 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P8_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P8_LSB_REG)));\r
+ bme280->calibration.dig_P9 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_P9_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_P9_LSB_REG)));\r
+\r
+ bme280->calibration.dig_H1 = ((uint8_t)(readRegister(bme280->settings.I2CAddress,BME280_DIG_H1_REG)));\r
+ bme280->calibration.dig_H2 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_H2_MSB_REG) << 8) + readRegister(bme280->settings.I2CAddress,BME280_DIG_H2_LSB_REG)));\r
+ bme280->calibration.dig_H3 = ((uint8_t)(readRegister(bme280->settings.I2CAddress,BME280_DIG_H3_REG)));\r
+ bme280->calibration.dig_H4 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_H4_MSB_REG) << 4) + (readRegister(bme280->settings.I2CAddress,BME280_DIG_H4_LSB_REG) & 0x0F)));\r
+ bme280->calibration.dig_H5 = ((int16_t)((readRegister(bme280->settings.I2CAddress,BME280_DIG_H5_MSB_REG) << 4) + ((readRegister(bme280->settings.I2CAddress,BME280_DIG_H4_LSB_REG) >> 4) & 0x0F)));\r
+ bme280->calibration.dig_H6 = ((uint8_t)readRegister(bme280->settings.I2CAddress,BME280_DIG_H6_REG)); \r
+\r
+ //Set the oversampling control words.\r
+ //config will only be writeable in sleep mode, so first insure that.\r
+ writeRegister(bme280->settings.I2CAddress,BME280_CTRL_MEAS_REG, 0x00);\r
+\r
+ //Set the config word\r
+ dataToWrite = (bme280->settings.tStandby << 0x5) & 0xE0;\r
+ dataToWrite |= (bme280->settings.filter << 0x02) & 0x1C;\r
+ writeRegister(bme280->settings.I2CAddress,BME280_CONFIG_REG, dataToWrite);\r
+ \r
+ //Set ctrl_hum first, then ctrl_meas to activate ctrl_hum\r
+ dataToWrite = bme280->settings.humidOverSample & 0x07; //all other bits can be ignored\r
+ writeRegister(bme280->settings.I2CAddress,BME280_CTRL_HUMIDITY_REG, dataToWrite);\r
+ \r
+ //set ctrl_meas\r
+ //First, set temp oversampling\r
+ dataToWrite = (bme280->settings.tempOverSample << 0x5) & 0xE0;\r
+ //Next, pressure oversampling\r
+\r
+ dataToWrite |= (bme280->settings.pressOverSample << 0x02) & 0x1C;\r
+ //Last, set mode\r
+ dataToWrite |= (bme280->settings.runMode) & 0x03;\r
+ //Load the byte\r
+ writeRegister(bme280->settings.I2CAddress,BME280_CTRL_MEAS_REG, dataToWrite);\r
+\r
+ return readRegister(bme280->settings.I2CAddress,0xD0);\r
+}\r
+\r
+\r
+//Strictly resets. Run .begin() afterwards\r
+void reset( BME280* bme280)\r
+{\r
+ writeRegister(bme280->settings.I2CAddress,BME280_RST_REG, 0xB6);\r
+}\r
+\r
+\r
+float readFloatPressure( BME280 *bme280)\r
+{\r
+\r
+ // Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).\r
+ // Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa\r
+ int32_t adc_P = ((uint32_t)readRegister(bme280->settings.I2CAddress,BME280_PRESSURE_MSB_REG) << 12) | ((uint32_t)readRegister(bme280->settings.I2CAddress,BME280_PRESSURE_LSB_REG) << 4) | ((readRegister(bme280->settings.I2CAddress,BME280_PRESSURE_XLSB_REG) >> 4) & 0x0F);\r
+ \r
+ int64_t var1, var2, p_acc;\r
+ var1 = ((int64_t)bme280->t_fine) - 128000;\r
+ var2 = var1 * var1 * (int64_t)bme280->calibration.dig_P6;\r
+ var2 = var2 + ((var1 * (int64_t)bme280->calibration.dig_P5)<<17);\r
+ var2 = var2 + (((int64_t)bme280->calibration.dig_P4)<<35);\r
+ var1 = ((var1 * var1 * (int64_t)bme280->calibration.dig_P3)>>8) + ((var1 * (int64_t)bme280->calibration.dig_P2)<<12);\r
+ var1 = (((((int64_t)1)<<47)+var1))*((int64_t)bme280->calibration.dig_P1)>>33;\r
+ if (var1 == 0)\r
+ {\r
+ return 0; // avoid exception caused by division by zero\r
+ }\r
+ p_acc = 1048576 - adc_P;\r
+ p_acc = (((p_acc<<31) - var2)*3125)/var1;\r
+ var1 = (((int64_t)bme280->calibration.dig_P9) * (p_acc>>13) * (p_acc>>13)) >> 25;\r
+ var2 = (((int64_t)bme280->calibration.dig_P8) * p_acc) >> 19;\r
+ p_acc = ((p_acc + var1 + var2) >> 8) + (((int64_t)bme280->calibration.dig_P7)<<4);\r
+ \r
+ return (float)p_acc / 256.0;\r
+ \r
+}\r
+\r
+\r
+float readFloatHumidity( BME280* bme280 )\r
+{\r
+ // Returns humidity in %RH as unsigned 32 bit integer in Q22. 10 format (22 integer and 10 fractional bits).\r
+ // Output value of “47445” represents 47445/1024 = 46. 333 %RH\r
+ int32_t adc_H = ((uint32_t)readRegister(bme280->settings.I2CAddress,BME280_HUMIDITY_MSB_REG) << 8) | ((uint32_t)readRegister(bme280->settings.I2CAddress,BME280_HUMIDITY_LSB_REG));\r
+ \r
+ int32_t var1;\r
+ var1 = (bme280->t_fine - ((int32_t)76800));\r
+ var1 = (((((adc_H << 14) - (((int32_t)bme280->calibration.dig_H4) << 20) - (((int32_t)bme280->calibration.dig_H5) * var1)) +\r
+ ((int32_t)16384)) >> 15) * (((((((var1 * ((int32_t)bme280->calibration.dig_H6)) >> 10) * (((var1 * ((int32_t)bme280->calibration.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + ((int32_t)2097152)) *\r
+ ((int32_t)bme280->calibration.dig_H2) + 8192) >> 14));\r
+ var1 = (var1 - (((((var1 >> 15) * (var1 >> 15)) >> 7) * ((int32_t)bme280->calibration.dig_H1)) >> 4));\r
+ var1 = (var1 < 0 ? 0 : var1);\r
+ var1 = (var1 > 419430400 ? 419430400 : var1);\r
+\r
+ return (float)(var1>>12) / 1024.0;\r
+}\r
+\r
+\r
+float readTempC( BME280* bme280 )\r
+{\r
+ // Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.\r
+ // t_fine carries fine temperature as global value\r
+\r
+ //get the reading (adc_T);\r
+ int32_t adc_T = ((uint32_t)readRegister(bme280->settings.I2CAddress,BME280_TEMPERATURE_MSB_REG) << 12) | ((uint32_t)readRegister(bme280->settings.I2CAddress,BME280_TEMPERATURE_LSB_REG) << 4) | ((readRegister(bme280->settings.I2CAddress,BME280_TEMPERATURE_XLSB_REG) >> 4) & 0x0F);\r
+\r
+ //By datasheet, calibrate\r
+ int64_t var1, var2;\r
+\r
+ var1 = ((((adc_T>>3) - ((int32_t)bme280->calibration.dig_T1<<1))) * ((int32_t)bme280->calibration.dig_T2)) >> 11;\r
+ var2 = (((((adc_T>>4) - ((int32_t)bme280->calibration.dig_T1)) * ((adc_T>>4) - ((int32_t)bme280->calibration.dig_T1))) >> 12) *\r
+ ((int32_t)bme280->calibration.dig_T3)) >> 14;\r
+ bme280->t_fine = var1 + var2;\r
+ float output = (bme280->t_fine * 5 + 128) >> 8;\r
+\r
+ output = output / 100;\r
+ \r
+ return output;\r
+}\r
+\r
+\r
+void readRegisterRegion(uint8_t Addr, uint8_t *outputPointer , uint8_t offset, uint8_t length)\r
+{\r
+ //define pointer that will point to the external space\r
+ ///uint8_t i = 0;\r
+ uint8_t c = 0;\r
+ twi_writeTo(Addr,&offset,1,1,true);\r
+\r
+ for(int i = 0 ; i<length;i++){\r
+ // request bytes from slave device\r
+ if (i < length-1){\r
+ twi_readFrom(Addr, &c, 1, false);\r
+ }else {\r
+ twi_readFrom(Addr, &c, 1, true);\r
+ }\r
+ *outputPointer = c;\r
+ outputPointer++;\r
+ }\r
+\r
+}\r
+\r
+uint8_t readRegister(uint8_t Addr, uint8_t offset)\r
+{\r
+ //Return value\r
+ uint8_t result;\r
+\r
+ twi_writeTo(Addr, &offset,1,1,true);\r
+ twi_readFrom(Addr, &result, 1, true);\r
+\r
+ \r
+ return result;\r
+}\r
+\r
+int16_t readRegisterInt16(uint8_t Addr, uint8_t offset )\r
+{\r
+ uint8_t myBuffer[2];\r
+ readRegisterRegion(Addr, myBuffer, offset, 2); //Does memory transfer\r
+ int16_t output = (int16_t)myBuffer[0] | (int16_t)(myBuffer[1] << 8);\r
+ \r
+ return output;\r
+}\r
+\r
+void writeRegister(uint8_t Addr,uint8_t offset, uint8_t dataToWrite)\r
+{\r
+ //Write the byte\r
+ uint8_t value[2];\r
+ value[0]=offset;\r
+ value[1]=dataToWrite;\r
+ twi_writeTo(Addr,value,2,1,true);\r
+}\r
--- /dev/null
+/******************************************************************************\r
+SparkFunBME280.h\r
+BME280 Arduino and Teensy Driver\r
+Marshall Taylor @ SparkFun Electronics\r
+May 20, 2015\r
+https://github.com/sparkfun/BME280_Breakout\r
+\r
+Resources:\r
+Uses Wire.h for i2c operation\r
+Uses SPI.h for SPI operation\r
+\r
+Development environment specifics:\r
+Arduino IDE 1.6.4\r
+Teensy loader 1.23\r
+\r
+This code is released under the [MIT License](http://opensource.org/licenses/MIT).\r
+Please review the LICENSE.md file included with this example. If you have any questions \r
+or concerns with licensing, please contact techsupport@sparkfun.com.\r
+Distributed as-is; no warranty is given.\r
+******************************************************************************/\r
+\r
+// Test derived class for base class SparkFunIMU\r
+#ifndef __BME280_H__\r
+#define __BME280_H__\r
+\r
+//#include "stdint.h"\r
+#include "main.h"\r
+\r
+#define I2C_MODE 0\r
+#define SPI_MODE 1\r
+\r
+//Register names:\r
+#define BME280_DIG_T1_LSB_REG 0x88\r
+#define BME280_DIG_T1_MSB_REG 0x89\r
+#define BME280_DIG_T2_LSB_REG 0x8A\r
+#define BME280_DIG_T2_MSB_REG 0x8B\r
+#define BME280_DIG_T3_LSB_REG 0x8C\r
+#define BME280_DIG_T3_MSB_REG 0x8D\r
+#define BME280_DIG_P1_LSB_REG 0x8E\r
+#define BME280_DIG_P1_MSB_REG 0x8F\r
+#define BME280_DIG_P2_LSB_REG 0x90\r
+#define BME280_DIG_P2_MSB_REG 0x91\r
+#define BME280_DIG_P3_LSB_REG 0x92\r
+#define BME280_DIG_P3_MSB_REG 0x93\r
+#define BME280_DIG_P4_LSB_REG 0x94\r
+#define BME280_DIG_P4_MSB_REG 0x95\r
+#define BME280_DIG_P5_LSB_REG 0x96\r
+#define BME280_DIG_P5_MSB_REG 0x97\r
+#define BME280_DIG_P6_LSB_REG 0x98\r
+#define BME280_DIG_P6_MSB_REG 0x99\r
+#define BME280_DIG_P7_LSB_REG 0x9A\r
+#define BME280_DIG_P7_MSB_REG 0x9B\r
+#define BME280_DIG_P8_LSB_REG 0x9C\r
+#define BME280_DIG_P8_MSB_REG 0x9D\r
+#define BME280_DIG_P9_LSB_REG 0x9E\r
+#define BME280_DIG_P9_MSB_REG 0x9F\r
+#define BME280_DIG_H1_REG 0xA1\r
+#define BME280_CHIP_ID_REG 0xD0 //Chip ID\r
+#define BME280_RST_REG 0xE0 //Softreset Reg\r
+#define BME280_DIG_H2_LSB_REG 0xE1\r
+#define BME280_DIG_H2_MSB_REG 0xE2\r
+#define BME280_DIG_H3_REG 0xE3\r
+#define BME280_DIG_H4_MSB_REG 0xE4\r
+#define BME280_DIG_H4_LSB_REG 0xE5\r
+#define BME280_DIG_H5_MSB_REG 0xE6\r
+#define BME280_DIG_H6_REG 0xE7\r
+#define BME280_CTRL_HUMIDITY_REG 0xF2 //Ctrl Humidity Reg\r
+#define BME280_STAT_REG 0xF3 //Status Reg\r
+#define BME280_CTRL_MEAS_REG 0xF4 //Ctrl Measure Reg\r
+#define BME280_CONFIG_REG 0xF5 //Configuration Reg\r
+#define BME280_PRESSURE_MSB_REG 0xF7 //Pressure MSB\r
+#define BME280_PRESSURE_LSB_REG 0xF8 //Pressure LSB\r
+#define BME280_PRESSURE_XLSB_REG 0xF9 //Pressure XLSB\r
+#define BME280_TEMPERATURE_MSB_REG 0xFA //Temperature MSB\r
+#define BME280_TEMPERATURE_LSB_REG 0xFB //Temperature LSB\r
+#define BME280_TEMPERATURE_XLSB_REG 0xFC //Temperature XLSB\r
+#define BME280_HUMIDITY_MSB_REG 0xFD //Humidity MSB\r
+#define BME280_HUMIDITY_LSB_REG 0xFE //Humidity LSB\r
+\r
+\r
+//Class SensorSettings. This object is used to hold settings data. The application\r
+//uses this classes' data directly. The settings are adopted and sent to the sensor\r
+//at special times, such as .begin. Some are used for doing math.\r
+//\r
+//This is a kind of bloated way to do this. The trade-off is that the user doesn't\r
+//need to deal with #defines or enums with bizarre names.\r
+//\r
+//A power user would strip out SensorSettings entirely, and send specific read and\r
+//write command directly to the IC. (ST #defines below)\r
+//\r
+typedef struct\r
+{\r
+ //Main Interface and mode settings\r
+ uint8_t commInterface;\r
+ uint8_t I2CAddress;\r
+ uint8_t chipSelectPin;\r
+ uint8_t runMode;\r
+ uint8_t tStandby;\r
+ uint8_t filter;\r
+ uint8_t tempOverSample;\r
+ uint8_t pressOverSample;\r
+ uint8_t humidOverSample;\r
+} SensorSettings;\r
+\r
+//Used to hold the calibration constants. These are used\r
+//by the driver as measurements are being taking\r
+typedef struct\r
+{\r
+ uint16_t dig_T1;\r
+ int16_t dig_T2;\r
+ int16_t dig_T3; \r
+\r
+ uint16_t dig_P1;\r
+ int16_t dig_P2;\r
+ int16_t dig_P3;\r
+ int16_t dig_P4;\r
+ int16_t dig_P5;\r
+ int16_t dig_P6;\r
+ int16_t dig_P7;\r
+ int16_t dig_P8;\r
+ int16_t dig_P9;\r
+ \r
+ uint8_t dig_H1;\r
+ int16_t dig_H2;\r
+ uint8_t dig_H3;\r
+ int16_t dig_H4;\r
+ int16_t dig_H5;\r
+ uint8_t dig_H6; \r
+} SensorCalibration;\r
+\r
+//This is the man operational class of the driver.\r
+\r
+typedef struct {\r
+ //settings\r
+ SensorSettings settings;\r
+ SensorCalibration calibration;\r
+ int32_t t_fine;\r
+} BME280;\r
+\r
+ \r
+ //Init Sensor \r
+ uint8_t InitBME(BME280* bme280);\r
+\r
+ //Software reset routine\r
+ void reset( BME280* bme280);\r
+\r
+ //Returns the values as floats.\r
+ float readFloatPressure( BME280* bme280 );\r
+ \r
+ float readFloatHumidity( BME280* bme280 );\r
+\r
+ float readTempC( BME280* bme280 );\r
+\r
+ //The following utilities read and write\r
+\r
+ //ReadRegisterRegion takes a uint8 array address as input and reads\r
+ //a chunk of memory into that array.\r
+ void readRegisterRegion(uint8_t Addr, uint8_t*, uint8_t, uint8_t );\r
+ //readRegister reads one register\r
+ uint8_t readRegister(uint8_t, uint8_t);\r
+ //Reads two regs, LSByte then MSByte order, and concatenates them\r
+ //Used for two-byte reads\r
+ int16_t readRegisterInt16(uint8_t Addr, uint8_t offset );\r
+ //Writes a byte;\r
+ void writeRegister(uint8_t, uint8_t, uint8_t);\r
+ \r
+#endif // End of __BME280_H__ definition check\r
MCU = atmega328p\r
FORMAT = ihex\r
TARGET = main\r
-SRC = $(TARGET).c uart/uart.c twi/twi.c MagnetSensor.c\r
+SRC = $(TARGET).c uart/uart.c twi/twi.c MagnetSensor.c BME280.c TSL2591.c\r
ASRC = \r
OPT = 2\r
\r
--- /dev/null
+/*#include <avr/pgmspace.h>
+#include <util/delay.h>
+#include <stdlib.h>
+*/
+#include "TSL2591.h"
+
+void Init_TSL2591(TSL2591* tsl)
+{
+ tsl->_initialized = true;
+ tsl->_integration = TSL2591_INTEGRATIONTIME_100MS;
+ tsl->_gain = TSL2591_GAIN_MED;
+ TSL2591_setTiming(tsl, tsl->_integration);
+ TSL2591_setGain(tsl, tsl->_gain);
+ TSL2591_disable();
+}
+
+
+void TSL2591_enable()
+{
+ // Enable the device by setting the control bit to 0x01
+ TSL2591_write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWERON | TSL2591_ENABLE_AEN | TSL2591_ENABLE_AIEN | TSL2591_ENABLE_NPIEN);
+}
+
+void TSL2591_disable()
+{
+ // Disable the device by setting the control bit to 0x00
+ TSL2591_write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWEROFF);
+}
+
+void TSL2591_setGain(TSL2591* tsl, tsl2591Gain_t gain)
+{
+ TSL2591_enable();
+ tsl->_gain = gain;
+ TSL2591_write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, tsl->_integration | tsl->_gain);
+ TSL2591_disable();
+}
+
+tsl2591Gain_t TSL2591_getGain(TSL2591* tsl)
+{
+ return tsl->_gain;
+}
+
+void TSL2591_setTiming(TSL2591* tsl, tsl2591IntegrationTime_t integration)
+{
+ TSL2591_enable();
+ tsl->_integration = integration;
+ TSL2591_write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, tsl->_integration | tsl->_gain);
+ TSL2591_disable();
+}
+
+tsl2591IntegrationTime_t TSL2591_getTiming(TSL2591* tsl)
+{
+ return tsl->_integration;
+}
+
+uint32_t TSL2591_calculateLux(TSL2591* tsl, uint16_t ch0, uint16_t ch1)
+{
+ float atime, again;
+ float cpl, lux1, lux2, lux;
+ uint32_t chan0, chan1;
+
+ // Check for overflow conditions first
+ if ((ch0 == 0xFFFF) | (ch1 == 0xFFFF))
+ {
+ // Signal an overflow
+ return 0;
+ }
+
+ // Note: This algorithm is based on preliminary coefficients
+ // provided by AMS and may need to be updated in the future
+
+ switch (tsl->_integration)
+ {
+ case TSL2591_INTEGRATIONTIME_100MS :
+ atime = 100.0F;
+ break;
+ case TSL2591_INTEGRATIONTIME_200MS :
+ atime = 200.0F;
+ break;
+ case TSL2591_INTEGRATIONTIME_300MS :
+ atime = 300.0F;
+ break;
+ case TSL2591_INTEGRATIONTIME_400MS :
+ atime = 400.0F;
+ break;
+ case TSL2591_INTEGRATIONTIME_500MS :
+ atime = 500.0F;
+ break;
+ case TSL2591_INTEGRATIONTIME_600MS :
+ atime = 600.0F;
+ break;
+ default: // 100ms
+ atime = 100.0F;
+ break;
+ }
+
+ switch (tsl->_gain)
+ {
+ case TSL2591_GAIN_LOW :
+ again = 1.0F;
+ break;
+ case TSL2591_GAIN_MED :
+ again = 25.0F;
+ break;
+ case TSL2591_GAIN_HIGH :
+ again = 428.0F;
+ break;
+ case TSL2591_GAIN_MAX :
+ again = 9876.0F;
+ break;
+ default:
+ again = 1.0F;
+ break;
+ }
+
+ // cpl = (ATIME * AGAIN) / DF
+ cpl = (atime * again) / TSL2591_LUX_DF;
+
+ lux1 = ( (float)ch0 - (TSL2591_LUX_COEFB * (float)ch1) ) / cpl;
+ lux2 = ( ( TSL2591_LUX_COEFC * (float)ch0 ) - ( TSL2591_LUX_COEFD * (float)ch1 ) ) / cpl;
+ lux = lux1 > lux2 ? lux1 : lux2;
+
+ // Alternate lux calculation
+ //lux = ( (float)ch0 - ( 1.7F * (float)ch1 ) ) / cpl;
+
+ // Signal I2C had no errors
+ return (uint32_t)lux;
+}
+
+uint32_t TSL2591_getFullLuminosity (TSL2591* tsl)
+{
+ // Enable the device
+ TSL2591_enable();
+
+ // Wait x ms for ADC to complete
+ for (uint8_t d=0; d<=tsl->_integration; d++)
+ {
+ _delay_ms(120);
+ }
+
+ uint32_t x;
+ x = TSL2591_read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW);
+ x <<= 16;
+ x |= TSL2591_read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW);
+
+ TSL2591_disable();
+
+ return x;
+}
+
+uint16_t TSL2591_getLuminosity (TSL2591* tsl, uint8_t channel)
+{
+ uint32_t x = TSL2591_getFullLuminosity(tsl);
+
+ if (channel == TSL2591_FULLSPECTRUM)
+ {
+ // Reads two byte value from channel 0 (visible + infrared)
+ return (x & 0xFFFF);
+ }
+ else if (channel == TSL2591_INFRARED)
+ {
+ // Reads two byte value from channel 1 (infrared)
+ return (x >> 16);
+ }
+ else if (channel == TSL2591_VISIBLE)
+ {
+ // Reads all and subtracts out just the visible!
+ return ( (x & 0xFFFF) - (x >> 16));
+ }
+
+ // unknown channel!
+ return 0;
+}
+
+
+uint8_t TSL2591_read8(uint8_t reg)
+{
+ uint8_t x;
+ twi_writeTo(TSL2591_ADDR, ®, 1,1, true);
+ twi_readFrom(TSL2591_ADDR, &x, 1, true);
+
+ return x;
+}
+
+uint16_t TSL2591_read16(uint8_t reg)
+{
+ uint16_t x[2];
+
+ twi_writeTo(TSL2591_ADDR, ®, 1,1, true);
+ twi_readFrom(TSL2591_ADDR, x, 2, true);
+
+ x[1] <<= 8;
+ x[1] |= x[0];
+ return x;
+}
+
+void TSL2591_write8 (uint8_t reg, uint8_t value)
+{
+ uint8_t write_val[2] = {reg, value};
+ twi_writeTo(TSL2591_ADDR, reg, 2,1, true);
+}
+
+
--- /dev/null
+#include "main.h"
+
+#ifndef _TSL2591_H_
+#define _TSL2591_H_
+
+#define TSL2591_VISIBLE (2) // channel 0 - channel 1
+#define TSL2591_INFRARED (1) // channel 1
+#define TSL2591_FULLSPECTRUM (0) // channel 0
+
+#define TSL2591_ADDR (0x29)
+#define TSL2591_READBIT (0x01)
+
+#define TSL2591_COMMAND_BIT (0xA0) // 1010 0000: bits 7 and 5 for 'command normal'
+#define TSL2591_CLEAR_INT (0xE7)
+#define TSL2591_TEST_INT (0xE4)
+#define TSL2591_WORD_BIT (0x20) // 1 = read/write word (rather than byte)
+#define TSL2591_BLOCK_BIT (0x10) // 1 = using block read/write
+
+#define TSL2591_ENABLE_POWEROFF (0x00)
+#define TSL2591_ENABLE_POWERON (0x01)
+#define TSL2591_ENABLE_AEN (0x02) // ALS Enable. This field activates ALS function. Writing a one activates the ALS. Writing a zero disables the ALS.
+#define TSL2591_ENABLE_AIEN (0x10) // ALS Interrupt Enable. When asserted permits ALS interrupts to be generated, subject to the persist filter.
+#define TSL2591_ENABLE_NPIEN (0x80) // No Persist Interrupt Enable. When asserted NP Threshold conditions will generate an interrupt, bypassing the persist filter
+
+#define TSL2591_LUX_DF (408.0F)
+#define TSL2591_LUX_COEFB (1.64F) // CH0 coefficient
+#define TSL2591_LUX_COEFC (0.59F) // CH1 coefficient A
+#define TSL2591_LUX_COEFD (0.86F) // CH2 coefficient B
+
+enum
+{
+ TSL2591_REGISTER_ENABLE = 0x00,
+ TSL2591_REGISTER_CONTROL = 0x01,
+ TSL2591_REGISTER_THRESHOLD_AILTL = 0x04, // ALS low threshold lower byte
+ TSL2591_REGISTER_THRESHOLD_AILTH = 0x05, // ALS low threshold upper byte
+ TSL2591_REGISTER_THRESHOLD_AIHTL = 0x06, // ALS high threshold lower byte
+ TSL2591_REGISTER_THRESHOLD_AIHTH = 0x07, // ALS high threshold upper byte
+ TSL2591_REGISTER_THRESHOLD_NPAILTL = 0x08, // No Persist ALS low threshold lower byte
+ TSL2591_REGISTER_THRESHOLD_NPAILTH = 0x09, // etc
+ TSL2591_REGISTER_THRESHOLD_NPAIHTL = 0x0A,
+ TSL2591_REGISTER_THRESHOLD_NPAIHTH = 0x0B,
+ TSL2591_REGISTER_PERSIST_FILTER = 0x0C,
+ TSL2591_REGISTER_PACKAGE_PID = 0x11,
+ TSL2591_REGISTER_DEVICE_ID = 0x12,
+ TSL2591_REGISTER_DEVICE_STATUS = 0x13,
+ TSL2591_REGISTER_CHAN0_LOW = 0x14,
+ TSL2591_REGISTER_CHAN0_HIGH = 0x15,
+ TSL2591_REGISTER_CHAN1_LOW = 0x16,
+ TSL2591_REGISTER_CHAN1_HIGH = 0x17
+};
+
+typedef enum
+{
+ TSL2591_INTEGRATIONTIME_100MS = 0x00,
+ TSL2591_INTEGRATIONTIME_200MS = 0x01,
+ TSL2591_INTEGRATIONTIME_300MS = 0x02,
+ TSL2591_INTEGRATIONTIME_400MS = 0x03,
+ TSL2591_INTEGRATIONTIME_500MS = 0x04,
+ TSL2591_INTEGRATIONTIME_600MS = 0x05,
+}
+tsl2591IntegrationTime_t;
+
+typedef enum
+{
+ // bit 7:4: 0
+ TSL2591_PERSIST_EVERY = 0x00, // Every ALS cycle generates an interrupt
+ TSL2591_PERSIST_ANY = 0x01, // Any value outside of threshold range
+ TSL2591_PERSIST_2 = 0x02, // 2 consecutive values out of range
+ TSL2591_PERSIST_3 = 0x03, // 3 consecutive values out of range
+ TSL2591_PERSIST_5 = 0x04, // 5 consecutive values out of range
+ TSL2591_PERSIST_10 = 0x05, // 10 consecutive values out of range
+ TSL2591_PERSIST_15 = 0x06, // 15 consecutive values out of range
+ TSL2591_PERSIST_20 = 0x07, // 20 consecutive values out of range
+ TSL2591_PERSIST_25 = 0x08, // 25 consecutive values out of range
+ TSL2591_PERSIST_30 = 0x09, // 30 consecutive values out of range
+ TSL2591_PERSIST_35 = 0x0A, // 35 consecutive values out of range
+ TSL2591_PERSIST_40 = 0x0B, // 40 consecutive values out of range
+ TSL2591_PERSIST_45 = 0x0C, // 45 consecutive values out of range
+ TSL2591_PERSIST_50 = 0x0D, // 50 consecutive values out of range
+ TSL2591_PERSIST_55 = 0x0E, // 55 consecutive values out of range
+ TSL2591_PERSIST_60 = 0x0F, // 60 consecutive values out of range
+}
+tsl2591Persist_t;
+
+typedef enum
+{
+ TSL2591_GAIN_LOW = 0x00, // low gain (1x)
+ TSL2591_GAIN_MED = 0x10, // medium gain (25x)
+ TSL2591_GAIN_HIGH = 0x20, // medium gain (428x)
+ TSL2591_GAIN_MAX = 0x30, // max gain (9876x)
+}
+tsl2591Gain_t;
+
+typedef struct {
+ tsl2591Gain_t _gain;
+ tsl2591IntegrationTime_t _integration;
+ bool _initialized;
+}
+TSL2591;
+
+
+ void Init_TSL2591 ( TSL2591* tsl );
+
+ void TSL2591_enable ( void );
+ void TSL2591_disable ( void );
+ void TSL2591_write8 ( uint8_t r, uint8_t v );
+ uint16_t TSL2591_read16 ( uint8_t reg );
+ uint8_t TSL2591_read8 ( uint8_t reg );
+
+ uint32_t TSL2591_calculateLux (TSL2591* tsl, uint16_t ch0, uint16_t ch1 );
+ void TSL2591_setGain (TSL2591* tsl, tsl2591Gain_t gain );
+ void TSL2591_setTiming (TSL2591* tsl, tsl2591IntegrationTime_t integration );
+ uint16_t TSL2591_getLuminosity (TSL2591* tsl, uint8_t channel );
+ uint32_t TSL2591_getFullLuminosity (TSL2591* tsl );
+
+ tsl2591IntegrationTime_t TSL2591_getTiming(TSL2591* tsl);
+ tsl2591Gain_t TSL2591_getGain(TSL2591* tsl);
+
+
+#endif
+
int main(void)\r
{ char s[30];\r
char SerNum[10];\r
- uint8_t Status[4]={0,0,0,0};\r
+ uint8_t Status[5]={0,0,0,0,0};\r
uint8_t TC_Enabled[4]={0,0,0,0};\r
uint8_t Status_Mag[4]={0,0,0,0};\r
uint16_t TRef[4]={0,0,0,0};\r
float SensX[4];\r
float SensY[4];\r
float SensZ[4];\r
+ BME280 bme280;\r
+ TSL2591 tsl;\r
+\r
\r
//For CLK setting\r
CLKPR = (1<<CLKPCE); // No prescale\r
\r
//Init Magnetic field Sensor\r
Status[0] = InitMagSensor(ADDR_MAG_0, &TRef[0], &SensX[0], &SensY[0], &SensZ[0], &TC_Enabled[0]);\r
+#if MULTISENSE == 0\r
Status[1] = InitMagSensor(ADDR_MAG_1, &TRef[1], &SensX[1], &SensY[1], &SensZ[1], &TC_Enabled[1]);\r
Status[2] = InitMagSensor(ADDR_MAG_2, &TRef[2], &SensX[2], &SensY[2], &SensZ[2], &TC_Enabled[2]);\r
Status[3] = InitMagSensor(ADDR_MAG_3, &TRef[3], &SensX[3], &SensY[3], &SensZ[3], &TC_Enabled[3]);\r
+#endif\r
+ //Init BME280 Sensor Variables\r
+#if MULTISENSE == 1\r
+ bme280.settings.commInterface = I2C_MODE;\r
+ bme280.settings.I2CAddress = ADDR_ENV;\r
+ bme280.settings.runMode = 3; //Normal mode\r
+ bme280.settings.tStandby = 0;\r
+ bme280.settings.filter = 1;\r
+ bme280.settings.tempOverSample = 1;\r
+ bme280.settings.pressOverSample = 4;\r
+ bme280.settings.humidOverSample = 4;\r
+\r
+ Status[1] = InitBME(&bme280); \r
+\r
+ tsl._gain = TSL2591_GAIN_MAX;\r
+ tsl._integration = TSL2591_INTEGRATIONTIME_200MS;\r
+ Init_TSL2591(&tsl);\r
\r
+ \r
+#endif \r
// sprintf(s,"%u", Status[0]);\r
//uputs(s);\r
_delay_ms(300);\r
} else if (strcmp(uart_string,"END") == 0 ) {\r
mode = 0;\r
InitMagSensor(ADDR_MAG_0, &TRef[0], &SensX[0], &SensY[0], &SensZ[0], &TC_Enabled[0]);\r
+#if MULTISENSE == 0 \r
InitMagSensor(ADDR_MAG_1, &TRef[1], &SensX[1], &SensY[1], &SensZ[1], &TC_Enabled[1]);\r
InitMagSensor(ADDR_MAG_2, &TRef[2], &SensX[2], &SensY[2], &SensZ[2], &TC_Enabled[2]);\r
InitMagSensor(ADDR_MAG_3, &TRef[3], &SensX[3], &SensY[3], &SensZ[3], &TC_Enabled[3]);\r
+#endif \r
} else if (strcmp(uart_string,"EXIT") == 0 ) {\r
status2 = twi_writeTo(0x0C, 0x80, 1,1, true);\r
sprintf(s,"Status:0x%x",status2);\r
// normal running mode\r
if (Status[0] == 0) { MeasureMagSens(ADDR_MAG_0, TRef[0], &SensX[0], &SensY[0], &SensZ[0], TC_Enabled[0]);}\r
else { uputs("ERR Mag ");sprintf(SerNum,"%2u ",SERIALNUM);uputs(SerNum); uputsnl("0 NO_DEVICE"); }\r
+#if MULTISENSE == 0\r
if (Status[1] == 0) { MeasureMagSens(ADDR_MAG_1, TRef[1], &SensX[1], &SensY[1], &SensZ[1], TC_Enabled[1]);}\r
else { uputs("ERR Mag ");sprintf(SerNum,"%2u ",SERIALNUM);uputs(SerNum); uputsnl("1 NO_DEVICE"); }\r
if (Status[2] == 0) { MeasureMagSens(ADDR_MAG_2, TRef[2], &SensX[2], &SensY[2], &SensZ[2], TC_Enabled[2]);}\r
else { uputs("ERR Mag ");sprintf(SerNum,"%2u ",SERIALNUM);uputs(SerNum); uputsnl("2 NO_DEVICE"); }\r
if (Status[3] == 0) { MeasureMagSens(ADDR_MAG_3, TRef[3], &SensX[3], &SensY[3], &SensZ[3], TC_Enabled[3]);}\r
else { uputs("ERR Mag ");sprintf(SerNum,"%2u ",SERIALNUM);uputs(SerNum); uputsnl("3 NO_DEVICE"); }\r
- \r
+#endif\r
+#if MULTISENSE == 1\r
+ char Temp[30]; char Pres[30]; char Hum[30];\r
+ sprintf(Temp,"%3.2f",readTempC(&bme280));\r
+ sprintf(Pres,"%6.3f",readFloatPressure(&bme280));\r
+ sprintf(Hum,"%4.3f",readFloatHumidity(&bme280));\r
+ uputs("Temp: ");uputs(Temp);uputs(" Pres: ");uputs(Pres);uputs(" Humid: ");uputsnl(Hum);\r
+ \r
+ uint32_t lum = TSL2591_getFullLuminosity(&tsl);\r
+ uint16_t ir = lum >> 16;\r
+ uint16_t full = lum & 0xFFFF;\r
+ \r
+ uputs("Bright: ");\r
+ sprintf(s,"%u",full); uputs(s);\r
+ uputs(" / ");\r
+ sprintf(s,"%u",ir); uputsnl(s);\r
+#endif\r
_delay_ms(500);\r
} else {// CONFIG MODE\r
//Setting: I2C Address, Mode, RegAddr, Data Byte Low, Data byte high.\r
#include <math.h>\r
#include "uart/uart.h"\r
#include "MagnetSensor.h"\r
+#include "BME280.h"\r
+#include "TSL2591.h"\r
#include "twi/twi.h"\r
#include <avr/interrupt.h>\r
#include <avr/pgmspace.h>\r
#define ADDR_MAG_3 0x0F\r
\r
\r
+#define ADDR_ENV 0x76\r
\r
+#define MULTISENSE 1 //0: 4 magnetic sensors, 1: 1x magnetic, environment\r
\r
#ifndef __AVR_ATmega168P__\r
#define __AVR_ATmega168P__\r
The board can be powered with 3V3 or 5V.
3V3 operation is only stable with 8MHz. Thus, a prescaler of 2 for the main clock is applied in the early startup of the uC.
+In main.h, set MULTISENSE to define the type of board
+
Each board will get a serial number that is being compiled into the firmware.
It needs to be specified at compile time: