Import ESP_UniClock (upstream 1189810)
Vendored from https://github.com/gpeter62/ESP_UniClock: the sketch source, the web UI and the libraries the ESP8266 build needs, unpacked from the bundled zips. Adds a PlatformIO project for the ESP-12. The source is unchanged; local changes follow as separate commits. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8efa810e4e
commit
b347f1c63f
843 files changed
+122061
No files matched your search
@@ -0,0 +1,450 @@
|
||||
// ============================================================================
|
||||
// I2Csensors.ino
|
||||
// ----------------------------------------------------------------------------
|
||||
// Drivers for the I2C environmental sensors supported by this codebase.
|
||||
// All sensors below share ONE physical I2C bus (Wire, PIN_SDA/PIN_SCL, set
|
||||
// per-CLOCK_NN in clocks.h) and can be enabled in ANY combination for a given
|
||||
// clock build - several CLOCK_NN configs enable 3-5 of them at once:
|
||||
//
|
||||
// USE_BME280 - Bosch BME280, temperature + humidity + pressure (Adafruit_BME280_Library)
|
||||
// I2C address 0x76 (hardcoded here; chip also supports 0x77)
|
||||
// USE_BMP280 - Bosch BMP280, temperature + pressure only (Adafruit_BMP280_Library)
|
||||
// I2C address 0x77 (hardcoded here; chip also supports 0x76)
|
||||
// -> BME280 and BMP280 are deliberately pinned to different
|
||||
// default addresses so both can coexist on the same bus.
|
||||
// USE_AHTX0 - AHT10/AHT20, temperature + humidity (Adafruit_AHTX0)
|
||||
// I2C address 0x38 (fixed, not configurable on the chip)
|
||||
// USE_SHT21 - Sensirion SHT21, temperature + humidity (custom SHT21 lib)
|
||||
// I2C address 0x40 (7-bit); see getSHT21()/detection code below
|
||||
// USE_BH1750 - Ambient light / lux meter (BH1750 lib)
|
||||
// I2C address 0x23 (hardcoded; chip also supports 0x5C)
|
||||
//
|
||||
// Which CLOCK_NN configs use which sensor (see clocks.h):
|
||||
// USE_SHT21 alone : CLOCK_23, CLOCK_23A, CLOCK_23B
|
||||
// BME280+BMP280+AHTX0+SHT21 : CLOCK_26
|
||||
// All five (incl. BH1750) : CLOCK_46, CLOCK_48, CLOCK_50 (and, commented
|
||||
// out / inactive by default, CLOCK_51, 52, 54,
|
||||
// 55, 56, 57, 57A), CLOCK_99
|
||||
// BME280+AHTX0+SHT21 : CLOCK_80, CLOCK_81, CLOCK_82
|
||||
//
|
||||
// USE_I2CSENSORS (the #ifdef guarding this whole file) is NOT set directly by
|
||||
// any CLOCK_NN block - it is auto-derived in clocks.h:
|
||||
// #if defined(USE_BME280) || defined(USE_BMP280) || defined(USE_AHTX0) ||
|
||||
// defined(USE_SHT21) || defined(USE_BH1750) || defined(USE_RTC)
|
||||
// #define USE_I2CSENSORS
|
||||
// i.e. it turns on automatically as soon as any one sensor (or the RTC) is
|
||||
// requested for the selected clock.
|
||||
//
|
||||
// MULTI-SENSOR INDEXING: temperature[6]/humid[6]/pressur[6] (declared in the
|
||||
// core .ino) are shared result arrays. Each sensor type that measures a given
|
||||
// quantity claims the NEXT FREE slot in that quantity's array at boot, using
|
||||
// three independent counters (useTemp/useHumid/usePress) - see the detailed
|
||||
// comment in setupI2Csensors() below for exactly how collisions are avoided
|
||||
// when several sensors are active simultaneously (e.g. CLOCK_26).
|
||||
//
|
||||
// Calibration offsets (prm.corrT0/corrT1/corrH0/corrH1) are NOT applied in
|
||||
// this file - they are added later, at display time, in displayTemp()/
|
||||
// displayHumid() in the core .ino. This file only stores raw (rounded)
|
||||
// readings, so there is no risk of double-applying the correction here.
|
||||
// ============================================================================
|
||||
#ifdef USE_I2CSENSORS
|
||||
|
||||
// NOTE: these are commented-out and inert by design - the real per-build
|
||||
// enabling of each sensor happens in clocks.h inside the relevant CLOCK_NN
|
||||
// block. Since this .ino is compiled into every build regardless of which
|
||||
// clock is selected, uncommenting one of these lines here would force that
|
||||
// sensor ON for EVERY clock (as long as USE_I2CSENSORS ends up defined by
|
||||
// some other means), not just the one you're working on. Leave commented;
|
||||
// they exist only as a quick reference of the five supported macros.
|
||||
//#define USE_BME280
|
||||
//#define USE_BMP280
|
||||
//#define USE_AHTX0
|
||||
//#define USE_SHT21
|
||||
//#define USE_BH1750
|
||||
|
||||
#include <Wire.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#ifdef USE_BME280
|
||||
#include <Adafruit_BME280.h>
|
||||
Adafruit_BME280 bme; // use I2C interface address = 0x76 or 0x77
|
||||
Adafruit_Sensor *bme_temp = bme.getTemperatureSensor();
|
||||
Adafruit_Sensor *bme_pressure = bme.getPressureSensor();
|
||||
Adafruit_Sensor *bme_humidity = bme.getHumiditySensor();
|
||||
// *Ptr variables below hold this sensor's assigned slot (index) in the
|
||||
// shared temperature[]/humid[]/pressur[] arrays. They are filled in once,
|
||||
// in setupI2Csensors(), and stay 0 (default global init) if the sensor
|
||||
// isn't found - harmless, since the getBME280() reader is only ever
|
||||
// called when BME280exist is true.
|
||||
byte BME280tempPtr;
|
||||
byte BME280humidPtr;
|
||||
byte BME280pressPtr;
|
||||
#endif
|
||||
|
||||
#ifdef USE_BMP280
|
||||
#include <Adafruit_BMP280.h>
|
||||
// Hardcoded to 0x77 (BME280 above is hardcoded to 0x76) so that both chips
|
||||
// can be wired to the same bus at once without an address clash - several
|
||||
// CLOCK_NN configs (e.g. CLOCK_26, CLOCK_46/48/50, CLOCK_99) enable both
|
||||
// USE_BME280 and USE_BMP280 simultaneously.
|
||||
Adafruit_BMP280 bmp; // use I2C interface address = 0x76 or 0x77
|
||||
Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
|
||||
Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();
|
||||
byte BMP280tempPtr;
|
||||
byte BMP280humidPtr; // NOTE: BMP280 has no humidity sensor - this pointer is declared for symmetry but never used/assigned (BMP280 never touches humid[]).
|
||||
byte BMP280pressPtr;
|
||||
#endif
|
||||
|
||||
#ifdef USE_AHTX0
|
||||
#include <Adafruit_AHTX0.h> //I2C address: 0x38
|
||||
Adafruit_AHTX0 aht;
|
||||
Adafruit_Sensor *aht_humidity, *aht_temp;
|
||||
byte AHTX0tempPtr;
|
||||
byte AHTX0humidPtr;
|
||||
#endif
|
||||
|
||||
#ifdef USE_SHT21
|
||||
// POSSIBLE BUG (see detection code in setupI2Csensors() below): this header
|
||||
// comment says the 8-bit write/read addresses are 0x80/0x81, which
|
||||
// correspond to 7-bit address 0x40 (the SHT21's actual, standard I2C
|
||||
// address). The Arduino Wire library used here takes a 7-bit address
|
||||
// (0-127), so 0x80 is out of range for Wire.beginTransmission() - see the
|
||||
// detection code further down which probes both 0x40 (correct) and 0x80
|
||||
// (likely meaningless/dead check for this Wire API).
|
||||
#include <SHT21.h> //I2C address: 0x80 and 0x81
|
||||
SHT21 sht;
|
||||
float SHT21temp,SHT21humid =0;
|
||||
byte SHT21tempPtr;
|
||||
byte SHT21humidPtr;
|
||||
#endif
|
||||
|
||||
#ifdef USE_BH1750
|
||||
#include <BH1750.h>
|
||||
BH1750 lightMeter(0x23); // fixed address 0x23 (ADDR pin low/floating); chip's alternate address is 0x5C
|
||||
#endif
|
||||
|
||||
void setupI2Csensors() {
|
||||
DPRINTLN("Starting I2Csensors sensors...");
|
||||
|
||||
// pinMode(OUTPUT) here is just for regPin() bookkeeping (pin-conflict
|
||||
// registration/debug); Wire.begin() below reconfigures both pins for I2C
|
||||
// (open-drain + pull-ups) regardless of this pinMode call.
|
||||
pinMode(PIN_SDA,OUTPUT); regPin(PIN_SDA,"PIN_SDA");
|
||||
pinMode(PIN_SCL,OUTPUT); regPin(PIN_SCL,"PIN_SCL");
|
||||
Wire.begin(PIN_SDA,PIN_SCL);
|
||||
delay(100);
|
||||
I2Cscanner(); // debug-only bus scan; logs every ACKing address, does not affect detection below
|
||||
|
||||
#ifdef USE_RTC
|
||||
DPRINTLN("Starting RTC Clock...");
|
||||
while(millis()<2000) {yield();} //waiting for 2 sec from startup
|
||||
//I2C_ClearBus();
|
||||
delay(100);
|
||||
#if defined(PIN_SDA) && defined(PIN_SCL)
|
||||
Wire.beginTransmission(0x68);
|
||||
byte error = Wire.endTransmission();
|
||||
if (error == 0) { //DS3231_get_addr(0x68)
|
||||
RTCexist = true;
|
||||
DPRINTLN("RTC found on 0x68.");
|
||||
}
|
||||
else {
|
||||
DPRINTLN("!!!No RTC found on 0x68!!!");
|
||||
}
|
||||
#else
|
||||
RTCexist = false;
|
||||
DPRINTLN("PIN_SDA or PIN_SCL not defined!");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// MULTI-SENSOR INDEXING SCHEME (applies to every #ifdef block below):
|
||||
// temperature[]/humid[]/pressur[] are shared 6-slot arrays that can hold
|
||||
// readings from several sensors at once. There are THREE INDEPENDENT
|
||||
// counters - useTemp, useHumid, usePress - one per array/quantity, each
|
||||
// incremented only by sensors that actually measure that quantity.
|
||||
// Each sensor, when found, "reserves" the array slot equal to the CURRENT
|
||||
// value of the relevant counter (its own <Sensor>xxxPtr), then increments
|
||||
// that counter so the NEXT detected sensor of that quantity gets the next
|
||||
// free slot. Because each array has its own counter, two sensors can
|
||||
// never collide/overwrite each other's slot in the SAME array, even when
|
||||
// several are active together (e.g. CLOCK_26: BME280+BMP280+AHTX0+SHT21):
|
||||
// temperature[]: BME280->0, BMP280->1, AHTX0->2, SHT21->3 (useTemp=4)
|
||||
// humid[] : BME280->0, AHTX0->1, SHT21->2 (useHumid=3, BMP280 has none)
|
||||
// pressur[] : BME280->0, BMP280->1 (usePress=2, AHTX0/SHT21 have none)
|
||||
// Detection order below (BME280, BMP280, AHTX0, SHT21, BH1750) therefore
|
||||
// determines slot order. Downstream, only slots 0 and 1 of temperature[]/
|
||||
// humid[] receive a manual calibration offset (prm.corrT0/corrT1/corrH0/
|
||||
// corrH1, applied in displayTemp()/displayHumid() in the core .ino) - a
|
||||
// 3rd+ simultaneous temperature/humidity sensor (e.g. SHT21 at slot 2/3
|
||||
// above) is displayed uncorrected. That is a limitation of the core
|
||||
// display code, not of the indexing here, but worth knowing when wiring
|
||||
// up configs with 3+ temp/humid sensors.
|
||||
// ---------------------------------------------------------------------
|
||||
#ifdef USE_BME280
|
||||
if (!bme.begin(0x76)) {
|
||||
DPRINTLN("Could not find a valid BME280 sensor on address 0x76, check wiring!");
|
||||
}
|
||||
else {
|
||||
BME280exist = true;
|
||||
DPRINTLN("BME280 Found!");
|
||||
bme_temp->printSensorDetails();
|
||||
bme_pressure->printSensorDetails();
|
||||
bme_humidity->printSensorDetails();
|
||||
BME280tempPtr = useTemp; //remember my ID-s
|
||||
BME280humidPtr = useHumid;
|
||||
BME280pressPtr = usePress;
|
||||
useTemp++; //increase the number of sensors
|
||||
useHumid++;
|
||||
usePress++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_BMP280
|
||||
if (!bmp.begin(0x77)) {
|
||||
DPRINTLN("Could not find a valid BMP280 sensor on address 0x77, check wiring!");
|
||||
}
|
||||
else {
|
||||
BMP280exist = true;
|
||||
/* BMP280 default settings from datasheet. */
|
||||
DPRINTLN("BMP280 Found!");
|
||||
bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */
|
||||
Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */
|
||||
Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */
|
||||
Adafruit_BMP280::FILTER_X16, /* Filtering. */
|
||||
Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
|
||||
bmp_temp->printSensorDetails();
|
||||
BMP280tempPtr = useTemp; //remember my ID-s
|
||||
BMP280pressPtr = usePress; //remember my ID-s
|
||||
useTemp++; //increase the number of sensors
|
||||
usePress++; //increase the number of sensors
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_AHTX0
|
||||
if (!aht.begin()) {
|
||||
DPRINTLN("Could not find a valid AHT10/AHT20 sensor, check wiring!");
|
||||
}
|
||||
else {
|
||||
AHTX0exist = true;
|
||||
DPRINTLN("AHT10/AHT20 Found!");
|
||||
aht_temp = aht.getTemperatureSensor();
|
||||
aht_temp->printSensorDetails();
|
||||
aht_humidity = aht.getHumiditySensor();
|
||||
aht_humidity->printSensorDetails();
|
||||
AHTX0tempPtr = useTemp; //remember my ID-s
|
||||
AHTX0humidPtr = useHumid;
|
||||
useTemp++; //increase the number of sensors
|
||||
useHumid++;
|
||||
}
|
||||
#endif
|
||||
DPRINTLN(" ");
|
||||
|
||||
#ifdef USE_SHT21
|
||||
int error1,error2;
|
||||
Wire.beginTransmission(0x40); // correct 7-bit SHT21 address
|
||||
error1 = Wire.endTransmission();
|
||||
// POSSIBLE BUG: 0x80 is not a valid 7-bit I2C address for Wire.beginTransmission()
|
||||
// (Wire expects 0-127; 0x80/128 is the 8-bit write address, i.e. 0x40<<1).
|
||||
// This second probe is likely a no-op/dead check left over from confusing
|
||||
// 7-bit vs 8-bit addressing (see comment above the #include <SHT21.h> line).
|
||||
// Harmless as written because of the "&&" below (SHT21exist still gets set
|
||||
// correctly whenever the real 0x40 probe succeeds), but error2 does not
|
||||
// reliably indicate anything about a real device.
|
||||
Wire.beginTransmission(0x80);
|
||||
error2 = Wire.endTransmission();
|
||||
if ((error1 !=0) && (error2!=0)) {
|
||||
DPRINTLN("Could not find a valid SHT21 sensor on 0x40 / 0x80, check wiring!");
|
||||
}
|
||||
else {
|
||||
SHT21exist = true;
|
||||
DPRINTLN("SHT21 Found!");
|
||||
SHT21tempPtr = useTemp; //remember my ID-s
|
||||
SHT21humidPtr = useHumid;
|
||||
useTemp++; //increase the number of sensors
|
||||
useHumid++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_BH1750
|
||||
// BH1750 doesn't share temperature[]/humid[]/pressur[] - it has its own
|
||||
// dedicated useLux counter/flow (see getBH1750() at the bottom of this
|
||||
// file, called from getLightSensor() in the core .ino), so no slot/Ptr
|
||||
// bookkeeping is needed here.
|
||||
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) {
|
||||
DPRINTLN("BH1750 luxmeter sensor found");
|
||||
BH1750exist = true;
|
||||
useLux++;
|
||||
}
|
||||
else {
|
||||
DPRINTLN("Error initialising BH1750 on address 0x23");
|
||||
}
|
||||
#endif
|
||||
|
||||
DPRINTLN(" ");
|
||||
} //end of SetupI2Csensors()
|
||||
|
||||
|
||||
// getBME280()/getBMP280()/getAHTX0()/getSHT21() below each write ONLY into
|
||||
// their own reserved slot (the *Ptr index assigned in setupI2Csensors(), see
|
||||
// the indexing scheme comment there) and store the RAW rounded reading - no
|
||||
// calibration offset (prm.corrT0/corrT1/corrH0/corrH1) is applied here; that
|
||||
// happens later, at display time, in displayTemp()/displayHumid() (core
|
||||
// .ino), so there's no double-correction between this file and that one.
|
||||
void getBME280() {
|
||||
#ifdef USE_BME280
|
||||
temperature[BME280tempPtr] = round1(bme.readTemperature());
|
||||
humid[BME280humidPtr] = round1(bme.readHumidity());
|
||||
pressur[BME280pressPtr] = round1(bme.readPressure()/100);
|
||||
DPRINT("BME280: ");
|
||||
DPRINT("Temperature = ");
|
||||
DPRINT(temperature[BME280tempPtr]);
|
||||
DPRINT(" *C");
|
||||
|
||||
DPRINT(" Humidity = ");
|
||||
DPRINT(humid[BME280humidPtr]);
|
||||
DPRINT(" %");
|
||||
|
||||
DPRINT(" Pressure = ");
|
||||
DPRINT(pressur[BME280pressPtr]);
|
||||
DPRINTLN(" hPa");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void getBMP280() {
|
||||
#ifdef USE_BMP280
|
||||
temperature[BMP280tempPtr] = round1(bmp.readTemperature());
|
||||
pressur[BMP280pressPtr] = round1(bmp.readPressure()/100);
|
||||
DPRINT("BMP280: ");
|
||||
DPRINT(F("Temperature = "));
|
||||
DPRINT(temperature[BMP280tempPtr]);
|
||||
DPRINT(" *C");
|
||||
|
||||
DPRINT(F(" Pressure = "));
|
||||
DPRINT(pressur[BMP280pressPtr]);
|
||||
DPRINTLN(" hPa");
|
||||
#endif
|
||||
}
|
||||
|
||||
void getAHTX0() {
|
||||
#ifdef USE_AHTX0
|
||||
// /* Get a new normalized sensor event */
|
||||
sensors_event_t humidity;
|
||||
sensors_event_t temp;
|
||||
aht_humidity->getEvent(&humidity);
|
||||
aht_temp->getEvent(&temp);
|
||||
temperature[AHTX0tempPtr] = round1(temp.temperature);
|
||||
DPRINT("AHT sensor: ");
|
||||
DPRINT(" Temperature ");
|
||||
DPRINT(temperature[AHTX0tempPtr]);
|
||||
DPRINT(" deg C");
|
||||
|
||||
DPRINT(" Humidity: "); /* Display the results (humidity is measured in % relative humidity (% rH) */
|
||||
humid[AHTX0humidPtr] = round1(humidity.relative_humidity);
|
||||
DPRINT(humid[AHTX0humidPtr]);
|
||||
DPRINTLN(" % rH");
|
||||
#endif
|
||||
}
|
||||
|
||||
void getSHT21() {
|
||||
#ifdef USE_SHT21
|
||||
temperature[SHT21tempPtr] = round1(sht.getTemperature());
|
||||
DPRINT("SHT21 sensor: ");
|
||||
DPRINT(" Temperature ");
|
||||
DPRINT(temperature[SHT21tempPtr]);
|
||||
DPRINT(" deg C");
|
||||
|
||||
DPRINT(" Humidity: "); /* Display the results (humidity is measured in % relative humidity (% rH) */
|
||||
humid[SHT21humidPtr] = round1(sht.getHumidity());
|
||||
DPRINT(humid[SHT21humidPtr]);
|
||||
DPRINTLN(" % rH");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void getI2Csensors() {
|
||||
static unsigned long lastRun = 0;
|
||||
|
||||
// Called every ~200ms from timeProgram() (core .ino), but the actual I2C
|
||||
// reads only happen once every 30s per sensor - this throttle avoids
|
||||
// hammering the bus/sensors and is independent of the caller's cadence.
|
||||
// lastRun==0 lets the very first call (at millis()==0..~30000) through
|
||||
// immediately so readings are available right after boot.
|
||||
if (((millis()-lastRun)<30000) && (lastRun !=0)) return; // || (second()!=TEMP_START)
|
||||
lastRun = millis();
|
||||
if (BME280exist) getBME280();
|
||||
if (BMP280exist) getBMP280();
|
||||
if (AHTX0exist) getAHTX0();
|
||||
if (SHT21exist) getSHT21();
|
||||
if (BH1750exist) getBH1750();
|
||||
}
|
||||
|
||||
|
||||
void I2Cscanner() {
|
||||
byte error, address;
|
||||
int nDevices=0;
|
||||
DPRINTLN(F("________________________________"));
|
||||
DPRINTLN("Scanning I2C devices...");
|
||||
|
||||
for(address = 1; address < 127; address++ ) {
|
||||
// The i2c_scanner uses the return value of
|
||||
// Wire.endTransmission() to see if
|
||||
// a device acknowledged the address.
|
||||
Wire.beginTransmission(address);
|
||||
error = Wire.endTransmission();
|
||||
|
||||
if (error == 0) {
|
||||
DPRINT("I2C device found at address 0x");
|
||||
if (address<16)
|
||||
DPRINT("0");
|
||||
DPRINT(address,HEX);
|
||||
DPRINTLN(" !");
|
||||
|
||||
nDevices++;
|
||||
}
|
||||
else if (error==4) {
|
||||
DPRINT("Unknown error at address 0x");
|
||||
if (address<16)
|
||||
DPRINT("0");
|
||||
DPRINTLN(address,HEX);
|
||||
}
|
||||
} //end for
|
||||
|
||||
if (nDevices == 0)
|
||||
DPRINTLN("No I2C devices found\n");
|
||||
DPRINTLN(F("_________________________________"));
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
void setupI2Csensors() {}
|
||||
void getI2Csensors() {}
|
||||
#endif
|
||||
|
||||
#ifdef USE_BH1750
|
||||
// Called directly from getLightSensor() (core .ino) whenever BH1750exist is
|
||||
// true - unlike the other get*() functions this is NOT gated through
|
||||
// getI2Csensors()'s 30s throttle, so it can be polled as often as needed;
|
||||
// the BH1750 library itself paces new measurements (measurementReady()).
|
||||
int getBH1750() {
|
||||
static float oldLux = MAXIMUM_LUX;
|
||||
|
||||
if (lightMeter.measurementReady()) {
|
||||
float lux = lightMeter.readLightLevel();
|
||||
//DPRINT("BH1750 Light: "); DPRINT(lux); DPRINTLN(" lx");
|
||||
|
||||
if (lux>MAXIMUM_LUX) lux = MAXIMUM_LUX; //Limited //Limit lux value to maximum
|
||||
if (lux<0) lux = oldLux; // negative reading = bus glitch/error from the library; ignore and keep last good value
|
||||
oldLux = oldLux + (lux-oldLux)/10; //slow down Lux change (simple exponential smoothing, ~10-sample time constant)
|
||||
}
|
||||
return (int)oldLux;
|
||||
}
|
||||
#else
|
||||
// Stub used when USE_BH1750 is not defined for the selected clock, so
|
||||
// getLightSensor() (core .ino) can call getBH1750() unconditionally.
|
||||
int getBH1750() {
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
Reference in new issue
Block a user