mirror of https://github.com/arendst/Tasmota.git
v4.0.6
4.0.6 20170316 * Fix to better find device by Wifi hostname * Fix compile error when some I2C devices are disabled * Add (experimental) support for SHT1X emulating I2C (#97) * Add ADC to ElectroDragon (#203) * Add support for Sonoff Dev (#206)
This commit is contained in:
parent
7aebdbbacf
commit
c4cdd4459c
|
@ -1,7 +1,7 @@
|
|||
## Sonoff-Tasmota
|
||||
Provide ESP8266 based Sonoff by [iTead Studio](https://www.itead.cc/) and ElectroDragon IoT Relay with Serial, Web and MQTT control allowing 'Over the Air' or OTA firmware updates using Arduino IDE.
|
||||
|
||||
Current version is **4.0.5** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **4.0.6** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
|
||||
|
||||
- This version provides all (Sonoff) modules in one file and starts up with Sonoff Basic.
|
||||
- Once uploaded select module using the configuration webpage or the commands ```Modules``` and ```Module```.
|
||||
|
@ -24,6 +24,7 @@ The following devices are supported:
|
|||
- [iTead Slampher](http://sonoff.itead.cc/en/products/residential/slampher-rf)
|
||||
- [iTead Sonoff Touch](http://sonoff.itead.cc/en/products/residential/sonoff-touch)
|
||||
- [iTead Sonoff Led](http://sonoff.itead.cc/en/products/appliances/sonoff-led)
|
||||
- [iTead Sonoff Dev](https://www.itead.cc/sonoff-dev.html)
|
||||
- [iTead 1 Channel Switch 5V / 12V](https://www.itead.cc/smart-home/inching-self-locking-wifi-wireless-switch.html)
|
||||
- [iTead Motor Clockwise/Anticlockwise](https://www.itead.cc/smart-home/motor-reversing-wifi-wireless-switch.html)
|
||||
- [Electrodragon IoT Relay Board](http://www.electrodragon.com/product/wifi-iot-relay-board-based-esp8266/)
|
||||
|
|
Binary file not shown.
|
@ -1,4 +1,11 @@
|
|||
/* 4.0.5 20170314
|
||||
/* 4.0.6 20170316
|
||||
* Fix to better find device by Wifi hostname
|
||||
* Fix compile error when some I2C devices are disabled
|
||||
* Add (experimental) support for SHT1X emulating I2C (#97)
|
||||
* Add ADC to ElectroDragon (#203)
|
||||
* Add support for Sonoff Dev (#206)
|
||||
*
|
||||
* 4.0.5 20170314
|
||||
* Add command Status 11 to show power status with Vcc if define USE_ADC_VCC is enabled (default)
|
||||
* Add ADC input to Sonoff SV and Wemos D1 mini - Needs recompile with define USE_ADC_VCC disabled (#137)
|
||||
* Add MQTT host:port to timeout message (#199)
|
||||
|
|
|
@ -12,9 +12,9 @@
|
|||
|
||||
//#define ALLOW_MIGRATE_TO_V3
|
||||
#ifdef ALLOW_MIGRATE_TO_V3
|
||||
#define VERSION 0x03091C00 // 3.9.28
|
||||
#define VERSION 0x03091D00 // 3.9.29
|
||||
#else
|
||||
#define VERSION 0x04000500 // 4.0.5
|
||||
#define VERSION 0x04000600 // 4.0.6
|
||||
#endif // ALLOW_MIGRATE_TO_V3
|
||||
|
||||
enum log_t {LOG_LEVEL_NONE, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_DEBUG, LOG_LEVEL_DEBUG_MORE, LOG_LEVEL_ALL};
|
||||
|
@ -149,7 +149,7 @@ enum butt_t {PRESSED, NOT_PRESSED};
|
|||
#error "MQTT_MAX_PACKET_SIZE is too small in libraries/PubSubClient/src/PubSubClient.h, increase it to at least 427"
|
||||
#endif
|
||||
|
||||
#include <Ticker.h> // RTC
|
||||
#include <Ticker.h> // RTC, HLW8012, OSWatch
|
||||
#include <ESP8266WiFi.h> // MQTT, Ota, WifiManager
|
||||
#include <ESP8266HTTPClient.h> // MQTT, Ota
|
||||
#include <ESP8266httpUpdate.h> // Ota
|
||||
|
@ -1528,6 +1528,9 @@ void sensors_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
|||
#endif // USE_DHT
|
||||
#ifdef USE_I2C
|
||||
if (i2c_flg) {
|
||||
#ifdef USE_SHT
|
||||
sht_mqttPresent(svalue, ssvalue, djson);
|
||||
#endif // USE_SHT
|
||||
#ifdef USE_HTU
|
||||
htu_mqttPresent(svalue, ssvalue, djson);
|
||||
#endif // USE_HTU
|
||||
|
@ -1544,13 +1547,6 @@ void sensors_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
|||
|
||||
/********************************************************************************************/
|
||||
|
||||
void every_second_cb()
|
||||
{
|
||||
// 1 second rtc interrupt routine
|
||||
// Keep this code small (every_second is to large - it'll trip exception)
|
||||
|
||||
}
|
||||
|
||||
void every_second()
|
||||
{
|
||||
char svalue[MESSZ];
|
||||
|
@ -1605,6 +1601,9 @@ void every_second()
|
|||
#endif // USE_DHT
|
||||
#ifdef USE_I2C
|
||||
if (i2c_flg) {
|
||||
#ifdef USE_SHT
|
||||
sht_detect();
|
||||
#endif // USE_SHT
|
||||
#ifdef USE_HTU
|
||||
htu_detect();
|
||||
#endif // USE_HTU
|
||||
|
@ -2053,7 +2052,7 @@ void GPIO_init()
|
|||
|
||||
#ifdef USE_I2C
|
||||
i2c_flg = ((pin[GPIO_I2C_SCL] < 99) && (pin[GPIO_I2C_SDA] < 99));
|
||||
if (i2c_flg) Wire.begin(pin[GPIO_I2C_SDA],pin[GPIO_I2C_SCL]);
|
||||
if (i2c_flg) Wire.begin(pin[GPIO_I2C_SDA], pin[GPIO_I2C_SCL]);
|
||||
#endif // USE_I2C
|
||||
|
||||
#ifdef USE_WS2812
|
||||
|
@ -2123,7 +2122,7 @@ void setup()
|
|||
} else {
|
||||
snprintf_P(Hostname, sizeof(Hostname)-1, sysCfg.hostname);
|
||||
}
|
||||
WIFI_Connect(Hostname);
|
||||
WIFI_Connect();
|
||||
|
||||
getClient(MQTTClient, sysCfg.mqtt_client, sizeof(MQTTClient));
|
||||
|
||||
|
@ -2151,7 +2150,7 @@ void setup()
|
|||
}
|
||||
blink_powersave = power;
|
||||
|
||||
rtc_init(every_second_cb);
|
||||
rtc_init();
|
||||
|
||||
snprintf_P(log, sizeof(log), PSTR("APP: Project %s %s (Topic %s, Fallback %s, GroupTopic %s) Version %s"),
|
||||
PROJECT, sysCfg.friendlyname[0], sysCfg.mqtt_topic, MQTTClient, sysCfg.mqtt_grptopic, Version);
|
||||
|
|
|
@ -114,6 +114,7 @@ enum module_t {
|
|||
EXS_RELAY,
|
||||
WION,
|
||||
WEMOS,
|
||||
SONOFF_DEV,
|
||||
MAXMODULE };
|
||||
|
||||
/********************************************************************************************/
|
||||
|
@ -308,7 +309,7 @@ const mytmplt modules[MAXMODULE] PROGMEM = {
|
|||
GPIO_USER, // GPIO14 Optional sensor
|
||||
GPIO_USER, // GPIO15 Optional sensor
|
||||
GPIO_LED1, // GPIO16 Green/Blue Led (1 = On, 0 = Off)
|
||||
0
|
||||
GPIO_ADC0 // ADC0 A0 Analog input
|
||||
},
|
||||
{ "EXS Relay", // Latching relay https://ex-store.de/ESP8266-WiFi-Relay-V31 (ESP8266)
|
||||
// Module Pin 1 VCC 3V3, Module Pin 6 GND
|
||||
|
@ -352,6 +353,21 @@ const mytmplt modules[MAXMODULE] PROGMEM = {
|
|||
GPIO_USER, // GPIO15 D8
|
||||
GPIO_USER, // GPIO16 D0 Wemos Wake
|
||||
GPIO_ADC0 // ADC0 A0 Analog input
|
||||
},
|
||||
{ "Sonoff Dev", // Sonoff Dev (ESP8266)
|
||||
GPIO_KEY1, // GPIO00 E-FW Button
|
||||
GPIO_USER, // GPIO01 TX Serial RXD and Optional sensor
|
||||
0, // GPIO02
|
||||
GPIO_USER, // GPIO03 RX Serial TXD and Optional sensor
|
||||
GPIO_USER, // GPIO04 Optional sensor
|
||||
GPIO_USER, // GPIO05 Optional sensor
|
||||
0, 0, 0, 0, 0, 0, // Flash connection
|
||||
GPIO_USER, // GPIO12
|
||||
GPIO_LED1_INV, // GPIO13 BLUE LED
|
||||
GPIO_USER, // GPIO14 Optional sensor
|
||||
0, // GPIO15
|
||||
0, // GPIO16
|
||||
GPIO_ADC0 // ADC0 A0 Analog input
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -288,6 +288,7 @@ void WIFI_begin(uint8_t flag)
|
|||
#ifdef USE_STATIC_IP_ADDRESS
|
||||
WiFi.config(ipadd, ipgat, ipsub, ipdns); // Set static IP
|
||||
#endif // USE_STATIC_IP_ADDRESS
|
||||
WiFi.hostname(Hostname);
|
||||
WiFi.begin(sysCfg.sta_ssid[sysCfg.sta_active], sysCfg.sta_pwd[sysCfg.sta_active]);
|
||||
snprintf_P(log, sizeof(log), PSTR("Wifi: Connecting to AP%d %s in mode 11%c as %s..."),
|
||||
sysCfg.sta_active +1, sysCfg.sta_ssid[sysCfg.sta_active], PhyMode[WiFi.getPhyMode() & 0x3], Hostname);
|
||||
|
@ -417,10 +418,9 @@ int WIFI_State()
|
|||
return state;
|
||||
}
|
||||
|
||||
void WIFI_Connect(char *Hostname)
|
||||
void WIFI_Connect()
|
||||
{
|
||||
WiFi.persistent(false); // Solve possible wifi init errors
|
||||
WiFi.hostname(Hostname);
|
||||
_wifistatus = 0;
|
||||
_wifiretry = WIFI_RETRY_SEC;
|
||||
_wificounter = 1;
|
||||
|
@ -591,8 +591,6 @@ static const char monthNames[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
|
|||
|
||||
uint32_t utctime = 0, loctime = 0, dsttime = 0, stdtime = 0, ntptime = 0, midnight = 1451602800;
|
||||
|
||||
rtcCallback rtcCb = NULL;
|
||||
|
||||
String getBuildDateTime()
|
||||
{
|
||||
// "2017-03-07T11:08:02"
|
||||
|
@ -821,21 +819,13 @@ void rtc_second()
|
|||
midnight = loctime;
|
||||
}
|
||||
rtcTime.Year += 1970;
|
||||
if (rtcCb) rtcCb();
|
||||
}
|
||||
|
||||
void rtc_init(rtcCallback cb)
|
||||
void rtc_init()
|
||||
{
|
||||
rtcCb = cb;
|
||||
|
||||
// sntp_setservername(0, (char*)NTP_SERVER1);
|
||||
// sntp_setservername(1, (char*)NTP_SERVER2);
|
||||
// sntp_setservername(2, (char*)NTP_SERVER3);
|
||||
|
||||
sntp_setservername(0, sysCfg.ntp_server[0]);
|
||||
sntp_setservername(1, sysCfg.ntp_server[1]);
|
||||
sntp_setservername(2, sysCfg.ntp_server[2]);
|
||||
|
||||
sntp_stop();
|
||||
sntp_set_timezone(0); // UTC time
|
||||
sntp_init();
|
||||
|
|
|
@ -134,6 +134,7 @@
|
|||
#define USE_BH1750 // Add I2C code for BH1750 sensor
|
||||
#define USE_BMP // Add I2C code for BMP/BME280 sensor
|
||||
#define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor
|
||||
#define USE_SHT // Add I2C emulating code for SHT1X sensor
|
||||
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+4k code, 0.3k mem)
|
||||
|
||||
|
|
|
@ -452,9 +452,18 @@ void handleAjax2()
|
|||
#endif // USE_DHT
|
||||
#ifdef USE_I2C
|
||||
if (i2c_flg) {
|
||||
#ifdef USE_SHT
|
||||
tpage += sht_webPresent();
|
||||
#endif
|
||||
#ifdef USE_HTU
|
||||
tpage += htu_webPresent();
|
||||
#endif
|
||||
#ifdef USE_BMP
|
||||
tpage += bmp_webPresent();
|
||||
#endif
|
||||
#ifdef USE_BH1750
|
||||
tpage += bh1750_webPresent();
|
||||
#endif
|
||||
}
|
||||
#endif // USE_I2C
|
||||
String page = "";
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
Copyright (c) 2017 Theo Arends. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_SHT
|
||||
/*********************************************************************************************\
|
||||
* SHT1x - Temperature and Humidy
|
||||
*
|
||||
* Reading temperature and humidity takes about 320 milliseconds!
|
||||
* Source: Marinus vd Broek https://github.com/ESP8266nu/ESPEasy
|
||||
\*********************************************************************************************/
|
||||
|
||||
enum {
|
||||
SHT1X_CMD_MEASURE_TEMP = B00000011,
|
||||
SHT1X_CMD_MEASURE_RH = B00000101,
|
||||
SHT1X_CMD_SOFT_RESET = B00011110
|
||||
};
|
||||
|
||||
uint8_t sht_sda_pin, sht_scl_pin, shttype = 0;
|
||||
|
||||
boolean sht_reset()
|
||||
{
|
||||
pinMode(sht_sda_pin, INPUT_PULLUP);
|
||||
pinMode(sht_scl_pin, OUTPUT);
|
||||
delay(11);
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
digitalWrite(sht_scl_pin, HIGH);
|
||||
digitalWrite(sht_scl_pin, LOW);
|
||||
}
|
||||
boolean success = sht_sendCommand(SHT1X_CMD_SOFT_RESET);
|
||||
delay(11);
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean sht_sendCommand(const byte cmd)
|
||||
{
|
||||
pinMode(sht_sda_pin, OUTPUT);
|
||||
// Transmission Start sequence
|
||||
digitalWrite(sht_sda_pin, HIGH);
|
||||
digitalWrite(sht_scl_pin, HIGH);
|
||||
digitalWrite(sht_sda_pin, LOW);
|
||||
digitalWrite(sht_scl_pin, LOW);
|
||||
digitalWrite(sht_scl_pin, HIGH);
|
||||
digitalWrite(sht_sda_pin, HIGH);
|
||||
digitalWrite(sht_scl_pin, LOW);
|
||||
// Send the command (address must be 000b)
|
||||
shiftOut(sht_sda_pin, sht_scl_pin, MSBFIRST, cmd);
|
||||
// Wait for ACK
|
||||
boolean ackerror = false;
|
||||
digitalWrite(sht_scl_pin, HIGH);
|
||||
pinMode(sht_sda_pin, INPUT_PULLUP);
|
||||
if (digitalRead(sht_sda_pin) != LOW) ackerror = true;
|
||||
digitalWrite(sht_scl_pin, LOW);
|
||||
delayMicroseconds(1); // Give the sensor time to release the data line
|
||||
if (digitalRead(sht_sda_pin) != HIGH) ackerror = true;
|
||||
if (ackerror) {
|
||||
shttype = 0;
|
||||
addLog_P(LOG_LEVEL_DEBUG, PSTR("SHT1X: Sensor did not ACK command"));
|
||||
}
|
||||
return (!ackerror);
|
||||
}
|
||||
|
||||
boolean sht_awaitResult()
|
||||
{
|
||||
// Maximum 320ms for 14 bit measurement
|
||||
for (byte i = 0; i < 16; i++) {
|
||||
if (digitalRead(sht_sda_pin) == LOW) return true;
|
||||
delay(20);
|
||||
}
|
||||
addLog_P(LOG_LEVEL_DEBUG, PSTR("SHT1X: Data not ready"));
|
||||
shttype = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int sht_readData()
|
||||
{
|
||||
int val = 0;
|
||||
|
||||
// Read most significant byte
|
||||
val = shiftIn(sht_sda_pin, sht_scl_pin, 8);
|
||||
val <<= 8;
|
||||
// Send ACK
|
||||
pinMode(sht_sda_pin, OUTPUT);
|
||||
digitalWrite(sht_sda_pin, LOW);
|
||||
digitalWrite(sht_scl_pin, HIGH);
|
||||
digitalWrite(sht_scl_pin, LOW);
|
||||
pinMode(sht_sda_pin, INPUT_PULLUP);
|
||||
// Read least significant byte
|
||||
val |= shiftIn(sht_sda_pin, sht_scl_pin, 8);
|
||||
// Keep DATA pin high to skip CRC
|
||||
digitalWrite(sht_scl_pin, HIGH);
|
||||
digitalWrite(sht_scl_pin, LOW);
|
||||
return val;
|
||||
}
|
||||
|
||||
boolean sht_readTempHum(float &t, float &h)
|
||||
{
|
||||
float tempRaw, humRaw, rhLinear;
|
||||
|
||||
t = NAN;
|
||||
h = NAN;
|
||||
|
||||
if (!sht_reset()) return false;
|
||||
if (!sht_sendCommand(SHT1X_CMD_MEASURE_TEMP)) return false;
|
||||
if (!sht_awaitResult()) return false;
|
||||
tempRaw = sht_readData();
|
||||
// Temperature conversion coefficients from SHT1X datasheet for version 4
|
||||
const float d1 = -39.7; // 3.5V
|
||||
const float d2 = 0.01; // 14-bit
|
||||
t = d1 + (tempRaw * d2);
|
||||
if (!sht_sendCommand(SHT1X_CMD_MEASURE_RH)) return false;
|
||||
if (!sht_awaitResult()) return false;
|
||||
humRaw = sht_readData();
|
||||
// Temperature conversion coefficients from SHT1X datasheet for version 4
|
||||
const float c1 = -2.0468;
|
||||
const float c2 = 0.0367;
|
||||
const float c3 = -1.5955E-6;
|
||||
const float t1 = 0.01;
|
||||
const float t2 = 0.00008;
|
||||
rhLinear = c1 + c2 * humRaw + c3 * humRaw * humRaw;
|
||||
h = (t - 25) * (t1 + t2 * humRaw) + rhLinear;
|
||||
if(!isnan(t) && TEMP_CONVERSION) t = t * 1.8 + 32;
|
||||
return (!isnan(t) && !isnan(h));
|
||||
}
|
||||
|
||||
boolean sht_readCharTempHum(char* temp, char* hum)
|
||||
{
|
||||
float t, h;
|
||||
|
||||
boolean success = sht_readTempHum(t, h);
|
||||
dtostrf(t, 1, TEMP_RESOLUTION &3, temp);
|
||||
dtostrf(h, 1, HUMIDITY_RESOLUTION &3, hum);
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean sht_detect()
|
||||
{
|
||||
if (shttype) return true;
|
||||
|
||||
float t, h;
|
||||
|
||||
sht_sda_pin = pin[GPIO_I2C_SDA];
|
||||
sht_scl_pin = pin[GPIO_I2C_SCL];
|
||||
if (sht_readTempHum(t, h)) {
|
||||
shttype = 1;
|
||||
addLog_P(LOG_LEVEL_DEBUG, PSTR("I2C: SHT1X found"));
|
||||
} else {
|
||||
Wire.begin(sht_sda_pin, sht_scl_pin);
|
||||
shttype = 0;
|
||||
}
|
||||
return shttype;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void sht_mqttPresent(char* svalue, uint16_t ssvalue, uint8_t* djson)
|
||||
{
|
||||
if (!shttype) return;
|
||||
|
||||
char stemp[10], shum[10];
|
||||
if (sht_readCharTempHum(stemp, shum)) {
|
||||
snprintf_P(svalue, ssvalue, PSTR("%s, \"SHT1X\":{\"Temperature\":%s, \"Humidity\":%s}"),
|
||||
svalue, stemp, shum);
|
||||
*djson = 1;
|
||||
#ifdef USE_DOMOTICZ
|
||||
domoticz_sensor2(stemp, shum);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
String sht_webPresent()
|
||||
{
|
||||
String page = "";
|
||||
if (shttype) {
|
||||
char stemp[10], shum[10];
|
||||
if (sht_readCharTempHum(stemp, shum)) {
|
||||
char sensor[80];
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "SHT1X", stemp, (TEMP_CONVERSION) ? 'F' : 'C');
|
||||
page += sensor;
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, "SHT1X", shum);
|
||||
page += sensor;
|
||||
}
|
||||
}
|
||||
return page;
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
#endif // USE_SHT
|
||||
#endif // USE_I2C
|
||||
|
Loading…
Reference in New Issue