mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Merge branch 'mega' of https://github.com/letscontrolit/ESPEasy into mega
This commit is contained in:
@@ -809,7 +809,7 @@ static uint8_t bin2bcd(uint8_t val) { return val + 6 * (val / 10); }
|
||||
|
||||
boolean RTC_DS1307::begin(TwoWire *wireInstance) {
|
||||
RTCWireBus = wireInstance;
|
||||
RTCWireBus->begin();
|
||||
//RTCWireBus->begin();
|
||||
RTCWireBus->beginTransmission(DS1307_ADDRESS);
|
||||
if (RTCWireBus->endTransmission() == 0)
|
||||
return true;
|
||||
@@ -1054,7 +1054,7 @@ DateTime RTC_Micros::now() {
|
||||
|
||||
boolean RTC_PCF8523::begin(TwoWire *wireInstance) {
|
||||
RTCWireBus = wireInstance;
|
||||
RTCWireBus->begin();
|
||||
//RTCWireBus->begin();
|
||||
RTCWireBus->beginTransmission(PCF8523_ADDRESS);
|
||||
if (RTCWireBus->endTransmission() == 0)
|
||||
return true;
|
||||
@@ -1403,7 +1403,7 @@ void RTC_PCF8523::calibrate(Pcf8523OffsetMode mode, int8_t offset) {
|
||||
|
||||
boolean RTC_PCF8563::begin(TwoWire *wireInstance) {
|
||||
RTCWireBus = wireInstance;
|
||||
RTCWireBus->begin();
|
||||
//RTCWireBus->begin();
|
||||
RTCWireBus->beginTransmission(PCF8563_ADDRESS);
|
||||
if (RTCWireBus->endTransmission() == 0)
|
||||
return true;
|
||||
@@ -1565,7 +1565,7 @@ static uint8_t dowToDS3231(uint8_t d) { return d == 0 ? 7 : d; }
|
||||
|
||||
boolean RTC_DS3231::begin(TwoWire *wireInstance) {
|
||||
RTCWireBus = wireInstance;
|
||||
RTCWireBus->begin();
|
||||
//RTCWireBus->begin();
|
||||
RTCWireBus->beginTransmission(DS3231_ADDRESS);
|
||||
if (RTCWireBus->endTransmission() == 0)
|
||||
return true;
|
||||
|
||||
@@ -28,6 +28,8 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <time.h>
|
||||
|
||||
TinyGPSPlus::TinyGPSPlus()
|
||||
: parity(0)
|
||||
, isChecksumTerm(false)
|
||||
|
||||
@@ -147,11 +147,13 @@ platform = espressif32@1.12.4
|
||||
platform = espressif32@2.1.0
|
||||
build_flags =
|
||||
|
||||
|
||||
[core_esp32_3_3_2]
|
||||
platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/esp32-arduino-lib-builder/releases/download/424/framework-arduinoespressif32-master-cdcf92440.tar.gz
|
||||
platform = espressif32 @ 3.3.2
|
||||
platform_packages = framework-arduinoespressif32
|
||||
build_flags = -DESP32_STAGE
|
||||
|
||||
|
||||
[core_esp32_3_3_2_esp32s2]
|
||||
platform = https://github.com/platformio/platform-espressif32.git#feature/arduino-idf-master
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/v.2.0-post/framework-arduinoespressif32_i2c.zip
|
||||
@@ -163,7 +165,6 @@ platform = espressif32@3.0.0
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/1.0.5-rc6/esp32-1.0.5-rc6.zip
|
||||
|
||||
|
||||
|
||||
[core_esp32_stage]
|
||||
platform = espressif32
|
||||
platform_packages = framework-arduinoespressif32 @ https://github.com/Jason2866/arduino-esp32/releases/download/v.2.0-post/framework-arduinoespressif32_i2c.zip
|
||||
|
||||
@@ -50,6 +50,7 @@ build_flags = ${esp32_common.build_flags}
|
||||
board = esp32-s2-saola-1
|
||||
extra_scripts = ${esp32_common.extra_scripts}
|
||||
pre:tools/pio/pre_custom_esp32.py
|
||||
platform = ${core_esp32_3_3_2_esp32s2.platform}
|
||||
platform_packages = ${core_esp32_3_3_2_esp32s2.platform_packages}
|
||||
|
||||
|
||||
|
||||
+254
-244
@@ -1,40 +1,41 @@
|
||||
#include "_Plugin_Helper.h"
|
||||
|
||||
#ifdef USES_P013
|
||||
//#######################################################################################################
|
||||
//############################### Plugin 013: HC-SR04, RCW-0001, etc. ###################################
|
||||
//#######################################################################################################
|
||||
|
||||
// #######################################################################################################
|
||||
// ############################### Plugin 013: HC-SR04, RCW-0001, etc. ###################################
|
||||
// #######################################################################################################
|
||||
|
||||
|
||||
#define PLUGIN_013
|
||||
#define PLUGIN_ID_013 13
|
||||
#define PLUGIN_NAME_013 "Position - HC-SR04, RCW-0001, etc."
|
||||
#define PLUGIN_VALUENAME1_013 "Distance"
|
||||
# define PLUGIN_013
|
||||
# define PLUGIN_ID_013 13
|
||||
# define PLUGIN_NAME_013 "Position - HC-SR04, RCW-0001, etc."
|
||||
# define PLUGIN_VALUENAME1_013 "Distance"
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <map>
|
||||
#include <NewPingESP8266.h>
|
||||
# include <Arduino.h>
|
||||
# include <map>
|
||||
# include <NewPingESP8266.h>
|
||||
|
||||
// PlugIn specific defines
|
||||
// operatingMode
|
||||
#define OPMODE_VALUE (0)
|
||||
#define OPMODE_STATE (1)
|
||||
# define OPMODE_VALUE (0)
|
||||
# define OPMODE_STATE (1)
|
||||
|
||||
// measuringUnit
|
||||
#define UNIT_CM (0)
|
||||
#define UNIT_INCH (1)
|
||||
# define UNIT_CM (0)
|
||||
# define UNIT_INCH (1)
|
||||
|
||||
// filterType
|
||||
#define FILTER_NONE (0)
|
||||
#define FILTER_MEDIAN (1)
|
||||
# define FILTER_NONE (0)
|
||||
# define FILTER_MEDIAN (1)
|
||||
|
||||
// map of sensors
|
||||
std::map<unsigned int, std::shared_ptr<NewPingESP8266> > P_013_sensordefs;
|
||||
|
||||
// Forward declaration
|
||||
const __FlashStringHelper * Plugin_013_getErrorStatusString(taskIndex_t taskIndex);
|
||||
const __FlashStringHelper* Plugin_013_getErrorStatusString(taskIndex_t taskIndex);
|
||||
|
||||
boolean Plugin_013(uint8_t function, struct EventStruct *event, String& string)
|
||||
boolean Plugin_013(uint8_t function, struct EventStruct *event, String& string)
|
||||
{
|
||||
static uint8_t switchstate[TASKS_MAX];
|
||||
boolean success = false;
|
||||
@@ -42,273 +43,278 @@ boolean Plugin_013(uint8_t function, struct EventStruct *event, String& string)
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_013;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_013;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = Sensor_VType::SENSOR_TYPE_SINGLE;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 1;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_013);
|
||||
break;
|
||||
}
|
||||
{
|
||||
string = F(PLUGIN_NAME_013);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_013));
|
||||
break;
|
||||
}
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_013));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEGPIONAMES:
|
||||
{
|
||||
event->String1 = formatGpioName_output(F("Trigger"));
|
||||
event->String2 = formatGpioName_input(F("Echo, 5V"));
|
||||
break;
|
||||
}
|
||||
{
|
||||
event->String1 = formatGpioName_output(F("Trigger"));
|
||||
event->String2 = formatGpioName_input(F("Echo, 5V"));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t threshold = PCONFIG(1);
|
||||
int16_t max_distance = PCONFIG(2);
|
||||
int16_t measuringUnit = PCONFIG(3);
|
||||
int16_t filterType = PCONFIG(4);
|
||||
int16_t filterSize = PCONFIG(5);
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t threshold = PCONFIG(1);
|
||||
int16_t max_distance = PCONFIG(2);
|
||||
int16_t measuringUnit = PCONFIG(3);
|
||||
int16_t filterType = PCONFIG(4);
|
||||
int16_t filterSize = PCONFIG(5);
|
||||
|
||||
// default filtersize = 5
|
||||
if (filterSize == 0) {
|
||||
filterSize = 5;
|
||||
PCONFIG(5) = filterSize;
|
||||
}
|
||||
|
||||
|
||||
String strUnit = (measuringUnit == UNIT_CM) ? F("cm") : F("inch");
|
||||
|
||||
{
|
||||
const __FlashStringHelper * optionsOpMode[2];
|
||||
int optionValuesOpMode[2] = { 0, 1 };
|
||||
optionsOpMode[0] = F("Value");
|
||||
optionsOpMode[1] = F("State");
|
||||
addFormSelector(F("Mode"), F("p013_mode"), 2, optionsOpMode, optionValuesOpMode, operatingMode);
|
||||
}
|
||||
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
{
|
||||
addFormNumericBox(F("Threshold"), F("p013_threshold"), threshold);
|
||||
addUnit(strUnit);
|
||||
}
|
||||
addFormNumericBox(F("Max Distance"), F("p013_max_distance"), max_distance, 0, 500);
|
||||
addUnit(strUnit);
|
||||
|
||||
{
|
||||
const __FlashStringHelper * optionsUnit[2];
|
||||
int optionValuesUnit[2] = { 0, 1 };
|
||||
optionsUnit[0] = F("Metric");
|
||||
optionsUnit[1] = F("Imperial");
|
||||
addFormSelector(F("Unit"), F("p013_Unit"), 2, optionsUnit, optionValuesUnit, measuringUnit);
|
||||
}
|
||||
|
||||
{
|
||||
const __FlashStringHelper * optionsFilter[2];
|
||||
int optionValuesFilter[2] = { 0, 1 };
|
||||
optionsFilter[0] = F("None");
|
||||
optionsFilter[1] = F("Median");
|
||||
addFormSelector(F("Filter"), F("p013_FilterType"), 2, optionsFilter, optionValuesFilter, filterType);
|
||||
}
|
||||
|
||||
// enable filtersize option if filter is used,
|
||||
if (filterType != FILTER_NONE)
|
||||
addFormNumericBox(F("Number of Pings"), F("p013_FilterSize"), filterSize, 2, 20);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
// default filtersize = 5
|
||||
if (filterSize == 0) {
|
||||
filterSize = 5;
|
||||
PCONFIG(5) = filterSize;
|
||||
}
|
||||
|
||||
|
||||
String strUnit = (measuringUnit == UNIT_CM) ? F("cm") : F("inch");
|
||||
|
||||
{
|
||||
const __FlashStringHelper *optionsOpMode[2];
|
||||
int optionValuesOpMode[2] = { 0, 1 };
|
||||
optionsOpMode[0] = F("Value");
|
||||
optionsOpMode[1] = F("State");
|
||||
addFormSelector(F("Mode"), F("p013_mode"), 2, optionsOpMode, optionValuesOpMode, operatingMode);
|
||||
}
|
||||
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
{
|
||||
addFormNumericBox(F("Threshold"), F("p013_threshold"), threshold);
|
||||
addUnit(strUnit);
|
||||
}
|
||||
addFormNumericBox(F("Max Distance"), F("p013_max_distance"), max_distance, 0, 500);
|
||||
addUnit(strUnit);
|
||||
|
||||
{
|
||||
const __FlashStringHelper *optionsUnit[2];
|
||||
int optionValuesUnit[2] = { 0, 1 };
|
||||
optionsUnit[0] = F("Metric");
|
||||
optionsUnit[1] = F("Imperial");
|
||||
addFormSelector(F("Unit"), F("p013_Unit"), 2, optionsUnit, optionValuesUnit, measuringUnit);
|
||||
}
|
||||
|
||||
{
|
||||
const __FlashStringHelper *optionsFilter[2];
|
||||
int optionValuesFilter[2] = { 0, 1 };
|
||||
optionsFilter[0] = F("None");
|
||||
optionsFilter[1] = F("Median");
|
||||
addFormSelector(F("Filter"), F("p013_FilterType"), 2, optionsFilter, optionValuesFilter, filterType);
|
||||
}
|
||||
|
||||
// enable filtersize option if filter is used,
|
||||
if (filterType != FILTER_NONE) {
|
||||
addFormNumericBox(F("Number of Pings"), F("p013_FilterSize"), filterSize, 2, 20);
|
||||
}
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t filterType = PCONFIG(4);
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t filterType = PCONFIG(4);
|
||||
|
||||
PCONFIG(0) = getFormItemInt(F("p013_mode"));
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
PCONFIG(1) = getFormItemInt(F("p013_threshold"));
|
||||
PCONFIG(2) = getFormItemInt(F("p013_max_distance"));
|
||||
PCONFIG(0) = getFormItemInt(F("p013_mode"));
|
||||
|
||||
PCONFIG(3) = getFormItemInt(F("p013_Unit"));
|
||||
PCONFIG(4) = getFormItemInt(F("p013_FilterType"));
|
||||
if (filterType != FILTER_NONE)
|
||||
PCONFIG(5) = getFormItemInt(F("p013_FilterSize"));
|
||||
if (operatingMode == OPMODE_STATE) {
|
||||
PCONFIG(1) = getFormItemInt(F("p013_threshold"));
|
||||
}
|
||||
PCONFIG(2) = getFormItemInt(F("p013_max_distance"));
|
||||
|
||||
success = true;
|
||||
break;
|
||||
PCONFIG(3) = getFormItemInt(F("p013_Unit"));
|
||||
PCONFIG(4) = getFormItemInt(F("p013_FilterType"));
|
||||
|
||||
if (filterType != FILTER_NONE) {
|
||||
PCONFIG(5) = getFormItemInt(F("p013_FilterSize"));
|
||||
}
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
int16_t max_distance = PCONFIG(2);
|
||||
int16_t measuringUnit = PCONFIG(3);
|
||||
int16_t filterType = PCONFIG(4);
|
||||
int16_t filterSize = PCONFIG(5);
|
||||
|
||||
int8_t Plugin_013_TRIG_Pin = CONFIG_PIN1;
|
||||
int8_t Plugin_013_IRQ_Pin = CONFIG_PIN2;
|
||||
int16_t max_distance_cm = (measuringUnit == UNIT_CM) ? max_distance : static_cast<float>(max_distance) * 2.54f;
|
||||
|
||||
// create sensor instance and add to std::map
|
||||
P_013_sensordefs.erase(event->TaskIndex);
|
||||
P_013_sensordefs[event->TaskIndex] =
|
||||
std::shared_ptr<NewPingESP8266>(new NewPingESP8266(Plugin_013_TRIG_Pin, Plugin_013_IRQ_Pin, max_distance_cm));
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex + 1;
|
||||
log += F(" TrigPin: ");
|
||||
log += Plugin_013_TRIG_Pin;
|
||||
log += F(" IRQ_Pin: ");
|
||||
log += Plugin_013_IRQ_Pin;
|
||||
log += F(" max dist ");
|
||||
log += (measuringUnit == UNIT_CM) ? F("[cm]: ") : F("[inch]: ");
|
||||
log += max_distance;
|
||||
log += F(" max echo: ");
|
||||
log += P_013_sensordefs[event->TaskIndex]->getMaxEchoTime();
|
||||
log += F(" Filter: ");
|
||||
|
||||
if (filterType == FILTER_NONE) {
|
||||
log += F("none");
|
||||
}
|
||||
else
|
||||
if (filterType == FILTER_MEDIAN) {
|
||||
log += F("Median size: ");
|
||||
log += filterSize;
|
||||
}
|
||||
else {
|
||||
log += F("invalid!");
|
||||
}
|
||||
log += F(" nr_tasks: ");
|
||||
log += P_013_sensordefs.size();
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
// FIXME TD-er: What kind of nonsense code is this?
|
||||
unsigned long tmpmillis = millis();
|
||||
unsigned long tmpmicros = micros();
|
||||
delay(100);
|
||||
long millispassed = timePassedSince(tmpmillis);
|
||||
long microspassed = usecPassedSince(tmpmicros);
|
||||
|
||||
String log = F("ULTRASONIC : micros() test: ");
|
||||
log += millispassed;
|
||||
log += F(" msec, ");
|
||||
log += microspassed;
|
||||
log += F(" usec, ");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_EXIT:
|
||||
{
|
||||
P_013_sensordefs.erase(event->TaskIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ: // If we select value mode, read and send the value based on global timer
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t measuringUnit = PCONFIG(3);
|
||||
|
||||
if (operatingMode == OPMODE_VALUE)
|
||||
{
|
||||
int16_t max_distance = PCONFIG(2);
|
||||
int16_t measuringUnit = PCONFIG(3);
|
||||
int16_t filterType = PCONFIG(4);
|
||||
int16_t filterSize = PCONFIG(5);
|
||||
|
||||
int8_t Plugin_013_TRIG_Pin = CONFIG_PIN1;
|
||||
int8_t Plugin_013_IRQ_Pin = CONFIG_PIN2;
|
||||
int16_t max_distance_cm = (measuringUnit == UNIT_CM) ? max_distance : static_cast<float>(max_distance) * 2.54f;
|
||||
|
||||
// create sensor instance and add to std::map
|
||||
P_013_sensordefs.erase(event->TaskIndex);
|
||||
P_013_sensordefs[event->TaskIndex] =
|
||||
std::shared_ptr<NewPingESP8266> (new NewPingESP8266(Plugin_013_TRIG_Pin, Plugin_013_IRQ_Pin, max_distance_cm));
|
||||
const float value = Plugin_013_read(event->TaskIndex);
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" TrigPin: ");
|
||||
log += Plugin_013_TRIG_Pin;
|
||||
log += F(" IRQ_Pin: ");
|
||||
log += Plugin_013_IRQ_Pin;
|
||||
log += F(" max dist ");
|
||||
log += (measuringUnit == UNIT_CM) ? F("[cm]: ") : F("[inch]: ");
|
||||
log += max_distance;
|
||||
log += F(" max echo: ");
|
||||
log += P_013_sensordefs[event->TaskIndex]->getMaxEchoTime();
|
||||
log += F(" Filter: ");
|
||||
if (filterType == FILTER_NONE)
|
||||
log += F("none");
|
||||
else
|
||||
if (filterType == FILTER_MEDIAN) {
|
||||
log += F("Median size: ");
|
||||
log += filterSize;
|
||||
}
|
||||
else
|
||||
log += F("invalid!");
|
||||
log += F(" nr_tasks: ");
|
||||
log += P_013_sensordefs.size();
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
log += event->TaskIndex + 1;
|
||||
log += F(" Distance: ");
|
||||
log += formatUserVarNoCheck(event->TaskIndex, 0);
|
||||
log += (measuringUnit == UNIT_CM) ? F(" cm ") : F(" inch ");
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
// FIXME TD-er: What kind of nonsense code is this?
|
||||
unsigned long tmpmillis = millis();
|
||||
unsigned long tmpmicros = micros();
|
||||
delay(100);
|
||||
long millispassed = timePassedSince(tmpmillis);
|
||||
long microspassed = usecPassedSince(tmpmicros);
|
||||
|
||||
String log = F("ULTRASONIC : micros() test: ");
|
||||
log += millispassed;
|
||||
log += F(" msec, ");
|
||||
log += microspassed;
|
||||
log += F(" usec, ");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_EXIT:
|
||||
{
|
||||
P_013_sensordefs.erase(event->TaskIndex);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ: // If we select value mode, read and send the value based on global timer
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t measuringUnit = PCONFIG(3);
|
||||
|
||||
if (operatingMode == OPMODE_VALUE)
|
||||
{
|
||||
const float value = Plugin_013_read(event->TaskIndex);
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" Distance: ");
|
||||
log += formatUserVarNoCheck(event->TaskIndex, 0);
|
||||
log += (measuringUnit == UNIT_CM) ? F(" cm ") : F(" inch ");
|
||||
if (value == NO_ECHO)
|
||||
{
|
||||
log += F(" Error: ");
|
||||
log += Plugin_013_getErrorStatusString(event->TaskIndex);
|
||||
}
|
||||
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
if (value == NO_ECHO)
|
||||
{
|
||||
log += F(" Error: ");
|
||||
log += Plugin_013_getErrorStatusString(event->TaskIndex);
|
||||
}
|
||||
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND: // If we select state mode, do more frequent checks and send only state changes
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t threshold = PCONFIG(1);
|
||||
{
|
||||
int16_t operatingMode = PCONFIG(0);
|
||||
int16_t threshold = PCONFIG(1);
|
||||
|
||||
if (operatingMode == OPMODE_STATE)
|
||||
{
|
||||
uint8_t state = 0;
|
||||
float value = Plugin_013_read(event->TaskIndex);
|
||||
if (value != NO_ECHO)
|
||||
{
|
||||
if (value < threshold)
|
||||
state = 1;
|
||||
if (state != switchstate[event->TaskIndex])
|
||||
{
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
log += F(" state: ");
|
||||
log += state;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
switchstate[event->TaskIndex] = state;
|
||||
UserVar[event->BaseVarIndex] = state;
|
||||
event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH;
|
||||
sendData(event);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex +1;
|
||||
if (operatingMode == OPMODE_STATE) {
|
||||
uint8_t state = 0;
|
||||
float value = Plugin_013_read(event->TaskIndex);
|
||||
|
||||
if ((value != NO_ECHO) && (value < threshold)) {
|
||||
state = 1;
|
||||
}
|
||||
|
||||
if (state != switchstate[event->TaskIndex]) {
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("ULTRASONIC : TaskNr: ");
|
||||
log += event->TaskIndex + 1;
|
||||
|
||||
if (value != NO_ECHO) {
|
||||
log += F(" state: ");
|
||||
log += state;
|
||||
} else {
|
||||
log += F(" Error: ");
|
||||
log += Plugin_013_getErrorStatusString(event->TaskIndex);
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
switchstate[event->TaskIndex] = state;
|
||||
UserVar[event->BaseVarIndex] = state;
|
||||
event->sensorType = Sensor_VType::SENSOR_TYPE_SWITCH;
|
||||
sendData(event);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
float Plugin_013_read(taskIndex_t taskIndex)
|
||||
|
||||
/*********************************************************************/
|
||||
{
|
||||
if (P_013_sensordefs.count(taskIndex) == 0)
|
||||
if (P_013_sensordefs.count(taskIndex) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[taskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[taskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[taskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[taskIndex][5];
|
||||
int16_t max_distance = Settings.TaskDevicePluginConfig[taskIndex][2];
|
||||
int16_t measuringUnit = Settings.TaskDevicePluginConfig[taskIndex][3];
|
||||
int16_t filterType = Settings.TaskDevicePluginConfig[taskIndex][4];
|
||||
int16_t filterSize = Settings.TaskDevicePluginConfig[taskIndex][5];
|
||||
int16_t max_distance_cm = (measuringUnit == UNIT_CM) ? max_distance : static_cast<float>(max_distance) * 2.54f;
|
||||
|
||||
unsigned int echoTime = 0;
|
||||
@@ -324,18 +330,22 @@ float Plugin_013_read(taskIndex_t taskIndex)
|
||||
addLog(LOG_LEVEL_ERROR, F("invalid Filter Type setting!"));
|
||||
}
|
||||
|
||||
if (measuringUnit == UNIT_CM)
|
||||
if (measuringUnit == UNIT_CM) {
|
||||
return NewPingESP8266::convert_cm_F(echoTime);
|
||||
else
|
||||
}
|
||||
else {
|
||||
return NewPingESP8266::convert_in_F(echoTime);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************/
|
||||
const __FlashStringHelper * Plugin_013_getErrorStatusString(taskIndex_t taskIndex)
|
||||
const __FlashStringHelper* Plugin_013_getErrorStatusString(taskIndex_t taskIndex)
|
||||
|
||||
/*********************************************************************/
|
||||
{
|
||||
if (P_013_sensordefs.count(taskIndex) == 0)
|
||||
if (P_013_sensordefs.count(taskIndex) == 0) {
|
||||
return F("invalid taskindex");
|
||||
}
|
||||
|
||||
switch ((P_013_sensordefs[taskIndex])->getErrorState()) {
|
||||
case NewPingESP8266::STATUS_SENSOR_READY: {
|
||||
@@ -369,7 +379,7 @@ const __FlashStringHelper * Plugin_013_getErrorStatusString(taskIndex_t taskInde
|
||||
default: {
|
||||
return F("unknown error");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // USES_P013
|
||||
|
||||
@@ -151,6 +151,10 @@ bool ETHConnected() {
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
if (EthEventData.last_eth_connect_attempt_moment.isSet() &&
|
||||
EthEventData.last_eth_connect_attempt_moment.millisPassedSince() < 5000) {
|
||||
return false;
|
||||
}
|
||||
setNetworkMedium(NetworkMedium_t::WIFI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ void AttemptWiFiConnect() {
|
||||
WiFiEventData.markWiFiTurnOn();
|
||||
|
||||
if (WiFi_AP_Candidates.getNext(WiFiScanAllowed())) {
|
||||
const WiFi_AP_Candidate& candidate = WiFi_AP_Candidates.getCurrent();
|
||||
const WiFi_AP_Candidate candidate = WiFi_AP_Candidates.getCurrent();
|
||||
|
||||
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
|
||||
String log = F("WIFI : Connecting ");
|
||||
@@ -403,7 +403,7 @@ void AttemptWiFiConnect() {
|
||||
SetWiFiTXpower(tx_pwr, candidate.rssi);
|
||||
// Start connect attempt now, so no longer needed to attempt new connection.
|
||||
WiFiEventData.wifiConnectAttemptNeeded = false;
|
||||
if (candidate.allowQuickConnect()) {
|
||||
if (candidate.allowQuickConnect() && !candidate.isHidden) {
|
||||
WiFi.begin(candidate.ssid.c_str(), candidate.key.c_str(), candidate.channel, candidate.bssid.mac);
|
||||
} else {
|
||||
WiFi.begin(candidate.ssid.c_str(), candidate.key.c_str());
|
||||
@@ -470,7 +470,7 @@ bool checkAndResetWiFi() {
|
||||
|
||||
switch(status) {
|
||||
case STATION_GOT_IP:
|
||||
if (WiFi.RSSI() < 0 && NetworkLocalIP().isSet()) {
|
||||
if (WiFi.RSSI() < 0 && WiFi.localIP().isSet()) {
|
||||
//if (WiFi.channel() == WiFiEventData.usedChannel || WiFiEventData.usedChannel == 0) {
|
||||
// This is a valid status, no need to reset
|
||||
return false;
|
||||
@@ -484,7 +484,7 @@ bool checkAndResetWiFi() {
|
||||
break;
|
||||
case STATION_IDLE:
|
||||
case STATION_CONNECTING:
|
||||
if (!WiFiEventData.last_wifi_connect_attempt_moment.timeoutReached(15000)) {
|
||||
if (WiFiEventData.last_wifi_connect_attempt_moment.isSet() && !WiFiEventData.last_wifi_connect_attempt_moment.timeoutReached(15000)) {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
@@ -496,7 +496,7 @@ bool checkAndResetWiFi() {
|
||||
return false;
|
||||
//}
|
||||
}
|
||||
if (!WiFiEventData.last_wifi_connect_attempt_moment.timeoutReached(15000)) {
|
||||
if (WiFiEventData.last_wifi_connect_attempt_moment.isSet() && !WiFiEventData.last_wifi_connect_attempt_moment.timeoutReached(15000)) {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -246,13 +246,13 @@ void processDisconnect() {
|
||||
}
|
||||
|
||||
|
||||
bool mustRestartWiFi = Settings.WiFiRestart_connection_lost();
|
||||
bool mustRestartWiFi = true; //Settings.WiFiRestart_connection_lost();
|
||||
if (WiFiEventData.lastConnectedDuration_us > 0 && (WiFiEventData.lastConnectedDuration_us / 1000) < 5000) {
|
||||
mustRestartWiFi = true;
|
||||
}
|
||||
|
||||
WifiDisconnect(); // Needed or else node may not reconnect reliably.
|
||||
if (mustRestartWiFi) {
|
||||
WifiDisconnect(); // Needed or else node may not reconnect reliably.
|
||||
delay(100);
|
||||
setWifiMode(WIFI_OFF);
|
||||
initWiFi();
|
||||
|
||||
@@ -224,6 +224,14 @@ void ESPEasy_setup()
|
||||
logMemUsageAfter(F("LoadSettings()"));
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_NO_RAM_TRACKER
|
||||
checkRAM(F("hardwareInit"));
|
||||
#endif // ifndef BUILD_NO_RAM_TRACKER
|
||||
hardwareInit();
|
||||
#ifndef BUILD_NO_RAM_TRACKER
|
||||
logMemUsageAfter(F("hardwareInit()"));
|
||||
#endif
|
||||
|
||||
node_time.restoreFromRTC();
|
||||
|
||||
Settings.UseRTOSMultitasking = false; // For now, disable it, we experience heap corruption.
|
||||
@@ -244,7 +252,8 @@ void ESPEasy_setup()
|
||||
|
||||
// This ensures, that changing WIFI OR ETHERNET MODE happens properly only after reboot. Changing without reboot would not be a good idea.
|
||||
// This only works after LoadSettings();
|
||||
setNetworkMedium(Settings.NetworkMedium);
|
||||
// Do not call setNetworkMedium here as that may try to clean up settings.
|
||||
active_network_medium = Settings.NetworkMedium;
|
||||
#endif // ifdef HAS_ETHERNET
|
||||
|
||||
if (active_network_medium == NetworkMedium_t::WIFI) {
|
||||
@@ -309,14 +318,6 @@ void ESPEasy_setup()
|
||||
Serial.setDebugOutput(true);
|
||||
}
|
||||
|
||||
#ifndef BUILD_NO_RAM_TRACKER
|
||||
checkRAM(F("hardwareInit"));
|
||||
#endif // ifndef BUILD_NO_RAM_TRACKER
|
||||
hardwareInit();
|
||||
#ifndef BUILD_NO_RAM_TRACKER
|
||||
logMemUsageAfter(F("hardwareInit()"));
|
||||
#endif
|
||||
|
||||
|
||||
timermqtt_interval = 250; // Interval for checking MQTT
|
||||
timerAwakeFromDeepSleep = millis();
|
||||
|
||||
@@ -239,7 +239,7 @@ void prepare_I2C_by_taskIndex(taskIndex_t taskIndex, deviceIndex_t DeviceIndex)
|
||||
#endif
|
||||
|
||||
if (bitRead(Settings.I2C_Flags[taskIndex], I2C_FLAGS_SLOW_SPEED)) {
|
||||
I2CSelectClockSpeed(true); // Set to slow
|
||||
I2CSelectLowClockSpeed(); // Set to slow
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ void post_I2C_by_taskIndex(taskIndex_t taskIndex, deviceIndex_t DeviceIndex) {
|
||||
#endif
|
||||
|
||||
if (bitRead(Settings.I2C_Flags[taskIndex], I2C_FLAGS_SLOW_SPEED)) {
|
||||
I2CSelectClockSpeed(false); // Reset
|
||||
I2CSelectHighClockSpeed(); // Reset
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include "../Globals/Settings.h"
|
||||
#include "../Globals/TimeZone.h"
|
||||
|
||||
#include "../Helpers/Hardware.h"
|
||||
#include "../Helpers/Misc.h"
|
||||
#include "../Helpers/Networking.h"
|
||||
#include "../Helpers/Numerical.h"
|
||||
@@ -723,6 +724,7 @@ bool ESPEasy_time::ExtRTC_get(uint32_t &unixtime)
|
||||
case ExtTimeSource_e::DS1307:
|
||||
{
|
||||
#ifdef USE_EXT_RTC
|
||||
I2CSelect_Max100kHz_ClockSpeed(); // Only supports upto 100 kHz
|
||||
RTC_DS1307 rtc;
|
||||
if (!rtc.begin()) {
|
||||
// Not found
|
||||
@@ -815,6 +817,7 @@ bool ESPEasy_time::ExtRTC_set(uint32_t unixtime)
|
||||
case ExtTimeSource_e::DS1307:
|
||||
{
|
||||
#ifdef USE_EXT_RTC
|
||||
I2CSelect_Max100kHz_ClockSpeed(); // Only supports upto 100 kHz
|
||||
RTC_DS1307 rtc;
|
||||
if (rtc.begin()) {
|
||||
rtc.adjust(DateTime(unixtime));
|
||||
|
||||
@@ -183,12 +183,12 @@ void hardwareInit()
|
||||
|
||||
void initI2C() {
|
||||
// configure hardware pins according to eeprom settings.
|
||||
if (Settings.isI2CEnabled())
|
||||
if (!Settings.isI2CEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, F("INIT : I2C"));
|
||||
I2CSelectClockSpeed(false); // Set normal clock speed
|
||||
I2CSelectHighClockSpeed(); // Set normal clock speed
|
||||
|
||||
if (Settings.WireClockStretchLimit)
|
||||
{
|
||||
@@ -237,19 +237,36 @@ void initI2C() {
|
||||
}
|
||||
}
|
||||
|
||||
void I2CSelectClockSpeed(bool setLowSpeed) {
|
||||
void I2CSelectHighClockSpeed() {
|
||||
I2CSelectClockSpeed(Settings.I2C_clockSpeed);
|
||||
}
|
||||
|
||||
void I2CSelectLowClockSpeed() {
|
||||
I2CSelectClockSpeed(Settings.I2C_clockSpeed_Slow);
|
||||
}
|
||||
|
||||
void I2CSelect_Max100kHz_ClockSpeed() {
|
||||
if (Settings.I2C_clockSpeed <= 100000) {
|
||||
I2CSelectHighClockSpeed();
|
||||
} else if (Settings.I2C_clockSpeed_Slow <= 100000) {
|
||||
I2CSelectLowClockSpeed();
|
||||
} else {
|
||||
I2CSelectClockSpeed(100000);
|
||||
}
|
||||
}
|
||||
|
||||
void I2CSelectClockSpeed(uint32_t clockFreq) {
|
||||
static uint32_t lastI2CClockSpeed = 0;
|
||||
const uint32_t newI2CClockSpeed = setLowSpeed ? Settings.I2C_clockSpeed_Slow : Settings.I2C_clockSpeed;
|
||||
if (newI2CClockSpeed == lastI2CClockSpeed) {
|
||||
if (clockFreq == lastI2CClockSpeed) {
|
||||
// No need to change the clock speed.
|
||||
return;
|
||||
}
|
||||
lastI2CClockSpeed = newI2CClockSpeed;
|
||||
lastI2CClockSpeed = clockFreq;
|
||||
#ifdef ESP32
|
||||
Wire.begin(Settings.Pin_i2c_sda, Settings.Pin_i2c_scl, newI2CClockSpeed);
|
||||
Wire.begin(Settings.Pin_i2c_sda, Settings.Pin_i2c_scl, clockFreq);
|
||||
#else
|
||||
Wire.begin(Settings.Pin_i2c_sda, Settings.Pin_i2c_scl);
|
||||
Wire.setClock(newI2CClockSpeed);
|
||||
Wire.setClock(clockFreq);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,10 @@ void hardwareInit();
|
||||
|
||||
void initI2C();
|
||||
|
||||
void I2CSelectClockSpeed(bool setLowSpeed);
|
||||
void I2CSelectHighClockSpeed();
|
||||
void I2CSelectLowClockSpeed();
|
||||
void I2CSelect_Max100kHz_ClockSpeed();
|
||||
void I2CSelectClockSpeed(uint32_t clockFreq);
|
||||
|
||||
#ifdef FEATURE_I2CMULTIPLEXER
|
||||
bool isI2CMultiplexerEnabled();
|
||||
|
||||
@@ -36,11 +36,12 @@ void WiFi_AP_CandidatesList::load_knownCredentials() {
|
||||
while (!done) {
|
||||
if (get_SSID_key(index, ssid, key)) {
|
||||
known.emplace_back(index, ssid, key);
|
||||
if (index == WIFI_CUSTOM_DEPLOYMENT_KEY_INDEX ||
|
||||
index == WIFI_CUSTOM_SUPPORT_KEY_INDEX) {
|
||||
known.back().lowPriority = true;
|
||||
} else if (index == WIFI_CREDENTIALS_FALLBACK_SSID_INDEX) {
|
||||
known.back().isEmergencyFallback = true;
|
||||
if (SettingsIndexMatchCustomCredentials(index)) {
|
||||
if (SettingsIndexMatchEmergencyFallback(index)) {
|
||||
known.back().isEmergencyFallback = true;
|
||||
} else {
|
||||
known.back().lowPriority = true;
|
||||
}
|
||||
}
|
||||
++index;
|
||||
} else {
|
||||
@@ -189,10 +190,18 @@ bool WiFi_AP_CandidatesList::getNext(bool scanAllowed) {
|
||||
}
|
||||
|
||||
if (mustPop) {
|
||||
known_it = known.begin();
|
||||
if (!candidates.empty()) {
|
||||
candidates.pop_front();
|
||||
if (currentCandidate.isHidden) {
|
||||
// We tried to connect to hidden SSIDs in 1 run, so pop all hidden candidates.
|
||||
for (auto cand_it = candidates.begin(); cand_it != candidates.end() && cand_it->isHidden; ) {
|
||||
cand_it = candidates.erase(cand_it);
|
||||
}
|
||||
} else {
|
||||
if (!candidates.empty()) {
|
||||
candidates.pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
known_it = known.begin();
|
||||
}
|
||||
return currentCandidate.usable();
|
||||
}
|
||||
@@ -258,9 +267,15 @@ bool WiFi_AP_CandidatesList::SettingsIndexMatchCustomCredentials(uint8_t index)
|
||||
{
|
||||
return (WIFI_CUSTOM_DEPLOYMENT_KEY_INDEX == index ||
|
||||
WIFI_CUSTOM_SUPPORT_KEY_INDEX == index ||
|
||||
WIFI_CREDENTIALS_FALLBACK_SSID_INDEX == index);
|
||||
SettingsIndexMatchEmergencyFallback(index));
|
||||
}
|
||||
|
||||
bool WiFi_AP_CandidatesList::SettingsIndexMatchEmergencyFallback(uint8_t index)
|
||||
{
|
||||
return (WIFI_CREDENTIALS_FALLBACK_SSID_INDEX == index);
|
||||
}
|
||||
|
||||
|
||||
void WiFi_AP_CandidatesList::loadCandidatesFromScanned() {
|
||||
if (candidates.size() > 1) {
|
||||
// Do not mess with the current candidates order if > 1 present
|
||||
|
||||
@@ -58,6 +58,8 @@ struct WiFi_AP_CandidatesList {
|
||||
|
||||
static bool SettingsIndexMatchCustomCredentials(uint8_t index);
|
||||
|
||||
static bool SettingsIndexMatchEmergencyFallback(uint8_t index);
|
||||
|
||||
private:
|
||||
|
||||
// Pick the possible
|
||||
|
||||
@@ -113,7 +113,7 @@ void handle_i2cscanner_json() {
|
||||
|
||||
int nDevices = 0;
|
||||
|
||||
I2CSelectClockSpeed(true); // Always scan in low speed to also find old/slow devices
|
||||
I2CSelect_Max100kHz_ClockSpeed(); // Always scan in low speed to also find old/slow devices
|
||||
#ifdef FEATURE_I2CMULTIPLEXER
|
||||
i2c_addresses_t mainBusDevices;
|
||||
mainBusDevices.resize(128);
|
||||
@@ -135,7 +135,7 @@ void handle_i2cscanner_json() {
|
||||
I2CMultiplexerOff();
|
||||
}
|
||||
#endif
|
||||
I2CSelectClockSpeed(false); // Reset bus to standard speed
|
||||
I2CSelectHighClockSpeed(); // Reset bus to standard speed
|
||||
|
||||
json_close(true);
|
||||
TXBuffer.endStream();
|
||||
@@ -386,7 +386,7 @@ void handle_i2cscanner() {
|
||||
|
||||
if (Settings.isI2CEnabled()) {
|
||||
int nDevices = 0;
|
||||
I2CSelectClockSpeed(true); // Scan bus using low speed
|
||||
I2CSelect_Max100kHz_ClockSpeed(); // Scan bus using low speed
|
||||
#ifdef FEATURE_I2CMULTIPLEXER
|
||||
i2c_addresses_t mainBusDevices;
|
||||
mainBusDevices.resize(128);
|
||||
@@ -408,7 +408,7 @@ void handle_i2cscanner() {
|
||||
I2CMultiplexerOff();
|
||||
}
|
||||
#endif
|
||||
I2CSelectClockSpeed(false); // By default the bus is in standard speed
|
||||
I2CSelectHighClockSpeed(); // By default the bus is in standard speed
|
||||
|
||||
if (nDevices == 0) {
|
||||
addHtml(F("<TR>No I2C devices found"));
|
||||
|
||||
Reference in New Issue
Block a user