mirror of
https://github.com/arendst/Tasmota.git
synced 2025-07-24 11:16:34 +00:00
v5.9.1
5.9.1 20171107 * Add external sensor function pointer interface to enable easy sensor addition * Add support for ADS1115 to be enabled in user_config.h and needs libraries i2cdevlib-Core and i2cdevlib-ADS1115 (#338, #660) * Fix Backup Configuration file download failure by defining proper file size (#1115) * Fix Exception 26 and empty console screen after usage of command WakeupDuration (#1133) * Fix some changed iTead web links in README.md (#1137)
This commit is contained in:
parent
e08d96acc2
commit
fe2d7c63ec
36
README.md
36
README.md
@ -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 **5.9.0** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
|
||||
Current version is **5.9.1** - See [sonoff/_releasenotes.ino](https://github.com/arendst/Sonoff-Tasmota/blob/master/sonoff/_releasenotes.ino) for change information.
|
||||
|
||||
### ATTENTION All versions
|
||||
|
||||
@ -33,23 +33,23 @@ See [Wiki](https://github.com/arendst/Sonoff-Tasmota/wiki) for more information.
|
||||
See [Community](https://groups.google.com/d/forum/sonoffusers) for forum and more user experience.
|
||||
|
||||
The following devices are supported:
|
||||
- [iTead Sonoff Basic](http://sonoff.itead.cc/en/products/sonoff/sonoff-basic)
|
||||
- [iTead Sonoff RF](http://sonoff.itead.cc/en/products/sonoff/sonoff-rf)
|
||||
- [iTead Sonoff SV](https://www.itead.cc/sonoff-sv.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff_th.jpg" width="250" align="right" />
|
||||
- [iTead Sonoff TH10/TH16 with temperature sensor](http://sonoff.itead.cc/en/products/sonoff/sonoff-th)
|
||||
- [iTead Sonoff Dual](http://sonoff.itead.cc/en/products/sonoff/sonoff-dual)
|
||||
- [iTead Sonoff Pow](http://sonoff.itead.cc/en/products/sonoff/sonoff-pow)
|
||||
- [iTead Sonoff 4CH](http://sonoff.itead.cc/en/products/sonoff/sonoff-4ch)
|
||||
- [iTead Sonoff 4CH Pro](http://sonoff.itead.cc/en/products/sonoff/sonoff-4ch-pro)
|
||||
- [iTead S20 Smart Socket](http://sonoff.itead.cc/en/products/residential/s20-socket)
|
||||
- [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 T1](http://sonoff.itead.cc/en/products/residential/sonoff-t1)
|
||||
- [iTead Sonoff SC](http://sonoff.itead.cc/en/products/residential/sonoff-sc)
|
||||
- [iTead Sonoff Led](http://sonoff.itead.cc/en/products/appliances/sonoff-led)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff4ch.jpg" height="250" align="right" />
|
||||
- [iTead Sonoff BN-SZ01 Ceiling Led](http://sonoff.itead.cc/en/products/appliances/bn-sz01)
|
||||
- [iTead Sonoff B1](http://sonoff.itead.cc/en/products/residential/sonoff-b1)
|
||||
- [iTead Sonoff RF Bridge 433](http://sonoff.itead.cc/en/products/appliances/sonoff-rf-bridge-433)
|
||||
- [iTead Sonoff Basic](https://www.itead.cc/smart-home/sonoff-wifi-wireless-switch-1.html)
|
||||
- [iTead Sonoff RF](https://www.itead.cc/smart-home/sonoff-rf.html)
|
||||
- [iTead Sonoff SV](https://www.itead.cc/smart-home/sonoff-sv.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff_th.jpg" width="250" align="right" />
|
||||
- [iTead Sonoff TH10/TH16 with temperature sensor](https://www.itead.cc/smart-home/sonoff-th.html)
|
||||
- [iTead Sonoff Dual](https://www.itead.cc/smart-home/sonoff-dual.html)
|
||||
- [iTead Sonoff Pow](https://www.itead.cc/smart-home/sonoff-pow.html)
|
||||
- [iTead Sonoff 4CH](https://www.itead.cc/smart-home/sonoff-4ch.html)
|
||||
- [iTead Sonoff 4CH Pro](https://www.itead.cc/smart-home/sonoff-4ch-pro.html)
|
||||
- [iTead S20 Smart Socket](https://www.itead.cc/smart-socket.html)
|
||||
- [iTead Slampher](https://www.itead.cc/slampher.html)
|
||||
- [iTead Sonoff Touch](https://www.itead.cc/sonoff-touch-eu-local.html)
|
||||
- [iTead Sonoff T1](https://www.itead.cc/sonoff-t1.html)
|
||||
- [iTead Sonoff SC](https://www.itead.cc/sonoff-sc.html)
|
||||
- [iTead Sonoff Led](https://www.itead.cc/sonoff-led.html)<img src="https://github.com/arendst/arendst.github.io/blob/master/media/sonoff4ch.jpg" height="250" align="right" />
|
||||
- [iTead Sonoff BN-SZ01 Ceiling Led](https://www.itead.cc/bn-sz01.html)
|
||||
- [iTead Sonoff B1](https://www.itead.cc/sonoff-b1.html)
|
||||
- [iTead Sonoff RF Bridge 433](https://www.itead.cc/sonoff-rf-bridge-433.html)
|
||||
- [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)
|
||||
|
40
lib/I2Cdevlib-ADS1115/.library.json
Normal file
40
lib/I2Cdevlib-ADS1115/.library.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "I2Cdevlib-ADS1115",
|
||||
"repository": {
|
||||
"url": "https://github.com/jrowberg/i2cdevlib.git",
|
||||
"type": "git"
|
||||
},
|
||||
"platforms": [
|
||||
"atmelavr"
|
||||
],
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"dependencies": {
|
||||
"frameworks": "arduino",
|
||||
"name": "I2Cdevlib-Core"
|
||||
},
|
||||
"export": {
|
||||
"include": "Arduino/ADS1115"
|
||||
},
|
||||
"version": "3b4c8bda90",
|
||||
"authors": [
|
||||
{
|
||||
"maintainer": false,
|
||||
"name": "Jeff Rowberg",
|
||||
"url": "https://github.com/jrowberg",
|
||||
"email": "jeff@rowberg.net"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"i2c",
|
||||
"comparator",
|
||||
"reference",
|
||||
"pga",
|
||||
"oscillator",
|
||||
"mux",
|
||||
"i2cdevlib"
|
||||
],
|
||||
"id": 95,
|
||||
"description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference"
|
||||
}
|
649
lib/I2Cdevlib-ADS1115/ADS1115.cpp
Normal file
649
lib/I2Cdevlib-ADS1115/ADS1115.cpp
Normal file
@ -0,0 +1,649 @@
|
||||
// I2Cdev library collection - ADS1115 I2C device class
|
||||
// Based on Texas Instruments ADS1113/4/5 datasheet, May 2009 (SBAS444B, revised October 2009)
|
||||
// Note that the ADS1115 uses 16-bit registers, not 8-bit registers.
|
||||
// 8/2/2011 by Jeff Rowberg <jeff@rowberg.net>
|
||||
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
|
||||
//
|
||||
// Changelog:
|
||||
// 2013-05-05 - Add debug information. Rename methods to match datasheet.
|
||||
// 2011-11-06 - added getVoltage, F. Farzanegan
|
||||
// 2011-10-29 - added getDifferentialx() methods, F. Farzanegan
|
||||
// 2011-08-02 - initial release
|
||||
/* ============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2011 Jeff Rowberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
*/
|
||||
|
||||
#include "ADS1115.h"
|
||||
|
||||
/** Default constructor, uses default I2C address.
|
||||
* @see ADS1115_DEFAULT_ADDRESS
|
||||
*/
|
||||
ADS1115::ADS1115() {
|
||||
devAddr = ADS1115_DEFAULT_ADDRESS;
|
||||
}
|
||||
|
||||
/** Specific address constructor.
|
||||
* @param address I2C address
|
||||
* @see ADS1115_DEFAULT_ADDRESS
|
||||
* @see ADS1115_ADDRESS_ADDR_GND
|
||||
* @see ADS1115_ADDRESS_ADDR_VDD
|
||||
* @see ADS1115_ADDRESS_ADDR_SDA
|
||||
* @see ADS1115_ADDRESS_ADDR_SDL
|
||||
*/
|
||||
ADS1115::ADS1115(uint8_t address) {
|
||||
devAddr = address;
|
||||
}
|
||||
|
||||
/** Power on and prepare for general usage.
|
||||
* This device is ready to use automatically upon power-up. It defaults to
|
||||
* single-shot read mode, P0/N1 mux, 2.048v gain, 128 samples/sec, default
|
||||
* comparator with hysterysis, active-low polarity, non-latching comparator,
|
||||
* and comparater-disabled operation.
|
||||
*/
|
||||
void ADS1115::initialize() {
|
||||
setMultiplexer(ADS1115_MUX_P0_N1);
|
||||
setGain(ADS1115_PGA_2P048);
|
||||
setMode(ADS1115_MODE_SINGLESHOT);
|
||||
setRate(ADS1115_RATE_128);
|
||||
setComparatorMode(ADS1115_COMP_MODE_HYSTERESIS);
|
||||
setComparatorPolarity(ADS1115_COMP_POL_ACTIVE_LOW);
|
||||
setComparatorLatchEnabled(ADS1115_COMP_LAT_NON_LATCHING);
|
||||
setComparatorQueueMode(ADS1115_COMP_QUE_DISABLE);
|
||||
}
|
||||
|
||||
/** Verify the I2C connection.
|
||||
* Make sure the device is connected and responds as expected.
|
||||
* @return True if connection is valid, false otherwise
|
||||
*/
|
||||
bool ADS1115::testConnection() {
|
||||
return I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer) == 1;
|
||||
}
|
||||
|
||||
/** Poll the operational status bit until the conversion is finished
|
||||
* Retry at most 'max_retries' times
|
||||
* conversion is finished, then return true;
|
||||
* @see ADS1115_CFG_OS_BIT
|
||||
* @return True if data is available, false otherwise
|
||||
*/
|
||||
bool ADS1115::pollConversion(uint16_t max_retries) {
|
||||
for(uint16_t i = 0; i < max_retries; i++) {
|
||||
if (isConversionReady()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Read differential value based on current MUX configuration.
|
||||
* The default MUX setting sets the device to get the differential between the
|
||||
* AIN0 and AIN1 pins. There are 8 possible MUX settings, but if you are using
|
||||
* all four input pins as single-end voltage sensors, then the default option is
|
||||
* not what you want; instead you will need to set the MUX to compare the
|
||||
* desired AIN* pin with GND. There are shortcut methods (getConversion*) to do
|
||||
* this conveniently, but you can also do it manually with setMultiplexer()
|
||||
* followed by this method.
|
||||
*
|
||||
* In single-shot mode, this register may not have fresh data. You need to write
|
||||
* a 1 bit to the MSB of the CONFIG register to trigger a single read/conversion
|
||||
* before this will be populated with fresh data. This technique is not as
|
||||
* effortless, but it has enormous potential to save power by only running the
|
||||
* comparison circuitry when needed.
|
||||
*
|
||||
* @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger
|
||||
* will be executed and the conversion results will be polled.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversionP0N1();
|
||||
* @see getConversionPON3();
|
||||
* @see getConversionP1N3();
|
||||
* @see getConversionP2N3();
|
||||
* @see getConversionP0GND();
|
||||
* @see getConversionP1GND();
|
||||
* @see getConversionP2GND();
|
||||
* @see getConversionP3GND);
|
||||
* @see setMultiplexer();
|
||||
* @see ADS1115_RA_CONVERSION
|
||||
* @see ADS1115_MUX_P0_N1
|
||||
* @see ADS1115_MUX_P0_N3
|
||||
* @see ADS1115_MUX_P1_N3
|
||||
* @see ADS1115_MUX_P2_N3
|
||||
* @see ADS1115_MUX_P0_NG
|
||||
* @see ADS1115_MUX_P1_NG
|
||||
* @see ADS1115_MUX_P2_NG
|
||||
* @see ADS1115_MUX_P3_NG
|
||||
*/
|
||||
int16_t ADS1115::getConversion(bool triggerAndPoll) {
|
||||
if (triggerAndPoll && devMode == ADS1115_MODE_SINGLESHOT) {
|
||||
triggerConversion();
|
||||
pollConversion(I2CDEV_DEFAULT_READ_TIMEOUT);
|
||||
}
|
||||
I2Cdev::readWord(devAddr, ADS1115_RA_CONVERSION, buffer);
|
||||
return buffer[0];
|
||||
}
|
||||
/** Get AIN0/N1 differential.
|
||||
* This changes the MUX setting to AIN0/N1 if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP0N1() {
|
||||
if (muxMode != ADS1115_MUX_P0_N1) setMultiplexer(ADS1115_MUX_P0_N1);
|
||||
return getConversion();
|
||||
}
|
||||
|
||||
/** Get AIN0/N3 differential.
|
||||
* This changes the MUX setting to AIN0/N3 if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP0N3() {
|
||||
if (muxMode != ADS1115_MUX_P0_N3) setMultiplexer(ADS1115_MUX_P0_N3);
|
||||
return getConversion();
|
||||
}
|
||||
|
||||
/** Get AIN1/N3 differential.
|
||||
* This changes the MUX setting to AIN1/N3 if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP1N3() {
|
||||
if (muxMode != ADS1115_MUX_P1_N3) setMultiplexer(ADS1115_MUX_P1_N3);
|
||||
return getConversion();
|
||||
}
|
||||
|
||||
/** Get AIN2/N3 differential.
|
||||
* This changes the MUX setting to AIN2/N3 if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP2N3() {
|
||||
if (muxMode != ADS1115_MUX_P2_N3) setMultiplexer(ADS1115_MUX_P2_N3);
|
||||
return getConversion();
|
||||
}
|
||||
|
||||
/** Get AIN0/GND differential.
|
||||
* This changes the MUX setting to AIN0/GND if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP0GND() {
|
||||
if (muxMode != ADS1115_MUX_P0_NG) setMultiplexer(ADS1115_MUX_P0_NG);
|
||||
return getConversion();
|
||||
}
|
||||
/** Get AIN1/GND differential.
|
||||
* This changes the MUX setting to AIN1/GND if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP1GND() {
|
||||
if (muxMode != ADS1115_MUX_P1_NG) setMultiplexer(ADS1115_MUX_P1_NG);
|
||||
return getConversion();
|
||||
}
|
||||
/** Get AIN2/GND differential.
|
||||
* This changes the MUX setting to AIN2/GND if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP2GND() {
|
||||
if (muxMode != ADS1115_MUX_P2_NG) setMultiplexer(ADS1115_MUX_P2_NG);
|
||||
return getConversion();
|
||||
}
|
||||
/** Get AIN3/GND differential.
|
||||
* This changes the MUX setting to AIN3/GND if necessary, triggers a new
|
||||
* measurement (also only if necessary), then gets the differential value
|
||||
* currently in the CONVERSION register.
|
||||
* @return 16-bit signed differential value
|
||||
* @see getConversion()
|
||||
*/
|
||||
int16_t ADS1115::getConversionP3GND() {
|
||||
if (muxMode != ADS1115_MUX_P3_NG) setMultiplexer(ADS1115_MUX_P3_NG);
|
||||
return getConversion();
|
||||
}
|
||||
|
||||
/** Get the current voltage reading
|
||||
* Read the current differential and return it multiplied
|
||||
* by the constant for the current gain. mV is returned to
|
||||
* increase the precision of the voltage
|
||||
* @param triggerAndPoll If true (and only in singleshot mode) the conversion trigger
|
||||
* will be executed and the conversion results will be polled.
|
||||
*/
|
||||
float ADS1115::getMilliVolts(bool triggerAndPoll) {
|
||||
switch (pgaMode) {
|
||||
case ADS1115_PGA_6P144:
|
||||
return (getConversion(triggerAndPoll) * ADS1115_MV_6P144);
|
||||
break;
|
||||
case ADS1115_PGA_4P096:
|
||||
return (getConversion(triggerAndPoll) * ADS1115_MV_4P096);
|
||||
break;
|
||||
case ADS1115_PGA_2P048:
|
||||
return (getConversion(triggerAndPoll) * ADS1115_MV_2P048);
|
||||
break;
|
||||
case ADS1115_PGA_1P024:
|
||||
return (getConversion(triggerAndPoll) * ADS1115_MV_1P024);
|
||||
break;
|
||||
case ADS1115_PGA_0P512:
|
||||
return (getConversion(triggerAndPoll) * ADS1115_MV_0P512);
|
||||
break;
|
||||
case ADS1115_PGA_0P256:
|
||||
case ADS1115_PGA_0P256B:
|
||||
case ADS1115_PGA_0P256C:
|
||||
return (getConversion(triggerAndPoll) * ADS1115_MV_0P256);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current multiplier for the PGA setting.
|
||||
*
|
||||
* This may be directly retreived by using getMilliVolts(),
|
||||
* but this causes an independent read. This function could
|
||||
* be used to average a number of reads from the getConversion()
|
||||
* getConversionx() functions and cut downon the number of
|
||||
* floating-point calculations needed.
|
||||
*
|
||||
*/
|
||||
|
||||
float ADS1115::getMvPerCount() {
|
||||
switch (pgaMode) {
|
||||
case ADS1115_PGA_6P144:
|
||||
return ADS1115_MV_6P144;
|
||||
break;
|
||||
case ADS1115_PGA_4P096:
|
||||
return ADS1115_MV_4P096;
|
||||
break;
|
||||
case ADS1115_PGA_2P048:
|
||||
return ADS1115_MV_2P048;
|
||||
break;
|
||||
case ADS1115_PGA_1P024:
|
||||
return ADS1115_MV_1P024;
|
||||
break;
|
||||
case ADS1115_PGA_0P512:
|
||||
return ADS1115_MV_0P512;
|
||||
break;
|
||||
case ADS1115_PGA_0P256:
|
||||
case ADS1115_PGA_0P256B:
|
||||
case ADS1115_PGA_0P256C:
|
||||
return ADS1115_MV_0P256;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// CONFIG register
|
||||
|
||||
/** Get operational status.
|
||||
* @return Current operational status (false for active conversion, true for inactive)
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_OS_BIT
|
||||
*/
|
||||
bool ADS1115::isConversionReady() {
|
||||
I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, buffer);
|
||||
return buffer[0];
|
||||
}
|
||||
/** Trigger a new conversion.
|
||||
* Writing to this bit will only have effect while in power-down mode (no conversions active).
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_OS_BIT
|
||||
*/
|
||||
void ADS1115::triggerConversion() {
|
||||
I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_OS_BIT, 1);
|
||||
}
|
||||
/** Get multiplexer connection.
|
||||
* @return Current multiplexer connection setting
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_MUX_BIT
|
||||
* @see ADS1115_CFG_MUX_LENGTH
|
||||
*/
|
||||
uint8_t ADS1115::getMultiplexer() {
|
||||
I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MUX_BIT, ADS1115_CFG_MUX_LENGTH, buffer);
|
||||
muxMode = (uint8_t)buffer[0];
|
||||
return muxMode;
|
||||
}
|
||||
/** Set multiplexer connection. Continous mode may fill the conversion register
|
||||
* with data before the MUX setting has taken effect. A stop/start of the conversion
|
||||
* is done to reset the values.
|
||||
* @param mux New multiplexer connection setting
|
||||
* @see ADS1115_MUX_P0_N1
|
||||
* @see ADS1115_MUX_P0_N3
|
||||
* @see ADS1115_MUX_P1_N3
|
||||
* @see ADS1115_MUX_P2_N3
|
||||
* @see ADS1115_MUX_P0_NG
|
||||
* @see ADS1115_MUX_P1_NG
|
||||
* @see ADS1115_MUX_P2_NG
|
||||
* @see ADS1115_MUX_P3_NG
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_MUX_BIT
|
||||
* @see ADS1115_CFG_MUX_LENGTH
|
||||
*/
|
||||
void ADS1115::setMultiplexer(uint8_t mux) {
|
||||
if (I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MUX_BIT, ADS1115_CFG_MUX_LENGTH, mux)) {
|
||||
muxMode = mux;
|
||||
if (devMode == ADS1115_MODE_CONTINUOUS) {
|
||||
// Force a stop/start
|
||||
setMode(ADS1115_MODE_SINGLESHOT);
|
||||
getConversion();
|
||||
setMode(ADS1115_MODE_CONTINUOUS);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
/** Get programmable gain amplifier level.
|
||||
* @return Current programmable gain amplifier level
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_PGA_BIT
|
||||
* @see ADS1115_CFG_PGA_LENGTH
|
||||
*/
|
||||
uint8_t ADS1115::getGain() {
|
||||
I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_PGA_BIT, ADS1115_CFG_PGA_LENGTH, buffer);
|
||||
pgaMode=(uint8_t)buffer[0];
|
||||
return pgaMode;
|
||||
}
|
||||
/** Set programmable gain amplifier level.
|
||||
* Continous mode may fill the conversion register
|
||||
* with data before the gain setting has taken effect. A stop/start of the conversion
|
||||
* is done to reset the values.
|
||||
* @param gain New programmable gain amplifier level
|
||||
* @see ADS1115_PGA_6P144
|
||||
* @see ADS1115_PGA_4P096
|
||||
* @see ADS1115_PGA_2P048
|
||||
* @see ADS1115_PGA_1P024
|
||||
* @see ADS1115_PGA_0P512
|
||||
* @see ADS1115_PGA_0P256
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_PGA_BIT
|
||||
* @see ADS1115_CFG_PGA_LENGTH
|
||||
*/
|
||||
void ADS1115::setGain(uint8_t gain) {
|
||||
if (I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_PGA_BIT, ADS1115_CFG_PGA_LENGTH, gain)) {
|
||||
pgaMode = gain;
|
||||
if (devMode == ADS1115_MODE_CONTINUOUS) {
|
||||
// Force a stop/start
|
||||
setMode(ADS1115_MODE_SINGLESHOT);
|
||||
getConversion();
|
||||
setMode(ADS1115_MODE_CONTINUOUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
/** Get device mode.
|
||||
* @return Current device mode
|
||||
* @see ADS1115_MODE_CONTINUOUS
|
||||
* @see ADS1115_MODE_SINGLESHOT
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_MODE_BIT
|
||||
*/
|
||||
bool ADS1115::getMode() {
|
||||
I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, buffer);
|
||||
devMode = buffer[0];
|
||||
return devMode;
|
||||
}
|
||||
/** Set device mode.
|
||||
* @param mode New device mode
|
||||
* @see ADS1115_MODE_CONTINUOUS
|
||||
* @see ADS1115_MODE_SINGLESHOT
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_MODE_BIT
|
||||
*/
|
||||
void ADS1115::setMode(bool mode) {
|
||||
if (I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_MODE_BIT, mode)) {
|
||||
devMode = mode;
|
||||
}
|
||||
}
|
||||
/** Get data rate.
|
||||
* @return Current data rate
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_DR_BIT
|
||||
* @see ADS1115_CFG_DR_LENGTH
|
||||
*/
|
||||
uint8_t ADS1115::getRate() {
|
||||
I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_DR_BIT, ADS1115_CFG_DR_LENGTH, buffer);
|
||||
return (uint8_t)buffer[0];
|
||||
}
|
||||
/** Set data rate.
|
||||
* @param rate New data rate
|
||||
* @see ADS1115_RATE_8
|
||||
* @see ADS1115_RATE_16
|
||||
* @see ADS1115_RATE_32
|
||||
* @see ADS1115_RATE_64
|
||||
* @see ADS1115_RATE_128
|
||||
* @see ADS1115_RATE_250
|
||||
* @see ADS1115_RATE_475
|
||||
* @see ADS1115_RATE_860
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_DR_BIT
|
||||
* @see ADS1115_CFG_DR_LENGTH
|
||||
*/
|
||||
void ADS1115::setRate(uint8_t rate) {
|
||||
I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_DR_BIT, ADS1115_CFG_DR_LENGTH, rate);
|
||||
}
|
||||
/** Get comparator mode.
|
||||
* @return Current comparator mode
|
||||
* @see ADS1115_COMP_MODE_HYSTERESIS
|
||||
* @see ADS1115_COMP_MODE_WINDOW
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_MODE_BIT
|
||||
*/
|
||||
bool ADS1115::getComparatorMode() {
|
||||
I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, buffer);
|
||||
return buffer[0];
|
||||
}
|
||||
/** Set comparator mode.
|
||||
* @param mode New comparator mode
|
||||
* @see ADS1115_COMP_MODE_HYSTERESIS
|
||||
* @see ADS1115_COMP_MODE_WINDOW
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_MODE_BIT
|
||||
*/
|
||||
void ADS1115::setComparatorMode(bool mode) {
|
||||
I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_MODE_BIT, mode);
|
||||
}
|
||||
/** Get comparator polarity setting.
|
||||
* @return Current comparator polarity setting
|
||||
* @see ADS1115_COMP_POL_ACTIVE_LOW
|
||||
* @see ADS1115_COMP_POL_ACTIVE_HIGH
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_POL_BIT
|
||||
*/
|
||||
bool ADS1115::getComparatorPolarity() {
|
||||
I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, buffer);
|
||||
return buffer[0];
|
||||
}
|
||||
/** Set comparator polarity setting.
|
||||
* @param polarity New comparator polarity setting
|
||||
* @see ADS1115_COMP_POL_ACTIVE_LOW
|
||||
* @see ADS1115_COMP_POL_ACTIVE_HIGH
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_POL_BIT
|
||||
*/
|
||||
void ADS1115::setComparatorPolarity(bool polarity) {
|
||||
I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_POL_BIT, polarity);
|
||||
}
|
||||
/** Get comparator latch enabled value.
|
||||
* @return Current comparator latch enabled value
|
||||
* @see ADS1115_COMP_LAT_NON_LATCHING
|
||||
* @see ADS1115_COMP_LAT_LATCHING
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_LAT_BIT
|
||||
*/
|
||||
bool ADS1115::getComparatorLatchEnabled() {
|
||||
I2Cdev::readBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_LAT_BIT, buffer);
|
||||
return buffer[0];
|
||||
}
|
||||
/** Set comparator latch enabled value.
|
||||
* @param enabled New comparator latch enabled value
|
||||
* @see ADS1115_COMP_LAT_NON_LATCHING
|
||||
* @see ADS1115_COMP_LAT_LATCHING
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_LAT_BIT
|
||||
*/
|
||||
void ADS1115::setComparatorLatchEnabled(bool enabled) {
|
||||
I2Cdev::writeBitW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_LAT_BIT, enabled);
|
||||
}
|
||||
/** Get comparator queue mode.
|
||||
* @return Current comparator queue mode
|
||||
* @see ADS1115_COMP_QUE_ASSERT1
|
||||
* @see ADS1115_COMP_QUE_ASSERT2
|
||||
* @see ADS1115_COMP_QUE_ASSERT4
|
||||
* @see ADS1115_COMP_QUE_DISABLE
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_QUE_BIT
|
||||
* @see ADS1115_CFG_COMP_QUE_LENGTH
|
||||
*/
|
||||
uint8_t ADS1115::getComparatorQueueMode() {
|
||||
I2Cdev::readBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_QUE_BIT, ADS1115_CFG_COMP_QUE_LENGTH, buffer);
|
||||
return (uint8_t)buffer[0];
|
||||
}
|
||||
/** Set comparator queue mode.
|
||||
* @param mode New comparator queue mode
|
||||
* @see ADS1115_COMP_QUE_ASSERT1
|
||||
* @see ADS1115_COMP_QUE_ASSERT2
|
||||
* @see ADS1115_COMP_QUE_ASSERT4
|
||||
* @see ADS1115_COMP_QUE_DISABLE
|
||||
* @see ADS1115_RA_CONFIG
|
||||
* @see ADS1115_CFG_COMP_QUE_BIT
|
||||
* @see ADS1115_CFG_COMP_QUE_LENGTH
|
||||
*/
|
||||
void ADS1115::setComparatorQueueMode(uint8_t mode) {
|
||||
I2Cdev::writeBitsW(devAddr, ADS1115_RA_CONFIG, ADS1115_CFG_COMP_QUE_BIT, ADS1115_CFG_COMP_QUE_LENGTH, mode);
|
||||
}
|
||||
|
||||
// *_THRESH registers
|
||||
|
||||
/** Get low threshold value.
|
||||
* @return Current low threshold value
|
||||
* @see ADS1115_RA_LO_THRESH
|
||||
*/
|
||||
int16_t ADS1115::getLowThreshold() {
|
||||
I2Cdev::readWord(devAddr, ADS1115_RA_LO_THRESH, buffer);
|
||||
return buffer[0];
|
||||
}
|
||||
/** Set low threshold value.
|
||||
* @param threshold New low threshold value
|
||||
* @see ADS1115_RA_LO_THRESH
|
||||
*/
|
||||
void ADS1115::setLowThreshold(int16_t threshold) {
|
||||
I2Cdev::writeWord(devAddr, ADS1115_RA_LO_THRESH, threshold);
|
||||
}
|
||||
/** Get high threshold value.
|
||||
* @return Current high threshold value
|
||||
* @see ADS1115_RA_HI_THRESH
|
||||
*/
|
||||
int16_t ADS1115::getHighThreshold() {
|
||||
I2Cdev::readWord(devAddr, ADS1115_RA_HI_THRESH, buffer);
|
||||
return buffer[0];
|
||||
}
|
||||
/** Set high threshold value.
|
||||
* @param threshold New high threshold value
|
||||
* @see ADS1115_RA_HI_THRESH
|
||||
*/
|
||||
void ADS1115::setHighThreshold(int16_t threshold) {
|
||||
I2Cdev::writeWord(devAddr, ADS1115_RA_HI_THRESH, threshold);
|
||||
}
|
||||
|
||||
/** Configures ALERT/RDY pin as a conversion ready pin.
|
||||
* It does this by setting the MSB of the high threshold register to '1' and the MSB
|
||||
* of the low threshold register to '0'. COMP_POL and COMP_QUE bits will be set to '0'.
|
||||
* Note: ALERT/RDY pin requires a pull up resistor.
|
||||
*/
|
||||
void ADS1115::setConversionReadyPinMode() {
|
||||
I2Cdev::writeBitW(devAddr, ADS1115_RA_HI_THRESH, 15, 1);
|
||||
I2Cdev::writeBitW(devAddr, ADS1115_RA_LO_THRESH, 15, 0);
|
||||
setComparatorPolarity(0);
|
||||
setComparatorQueueMode(0);
|
||||
}
|
||||
|
||||
// Create a mask between two bits
|
||||
unsigned createMask(unsigned a, unsigned b) {
|
||||
unsigned mask = 0;
|
||||
for (unsigned i=a; i<=b; i++)
|
||||
mask |= 1 << i;
|
||||
return mask;
|
||||
}
|
||||
|
||||
uint16_t shiftDown(uint16_t extractFrom, int places) {
|
||||
return (extractFrom >> places);
|
||||
}
|
||||
|
||||
|
||||
uint16_t getValueFromBits(uint16_t extractFrom, int high, int length) {
|
||||
int low= high-length +1;
|
||||
uint16_t mask = createMask(low ,high);
|
||||
return shiftDown(extractFrom & mask, low);
|
||||
}
|
||||
|
||||
/** Show all the config register settings
|
||||
*/
|
||||
void ADS1115::showConfigRegister() {
|
||||
I2Cdev::readWord(devAddr, ADS1115_RA_CONFIG, buffer);
|
||||
uint16_t configRegister =buffer[0];
|
||||
|
||||
|
||||
#ifdef ADS1115_SERIAL_DEBUG
|
||||
Serial.print("Register is:");
|
||||
Serial.println(configRegister,BIN);
|
||||
|
||||
Serial.print("OS:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_OS_BIT,1), BIN);
|
||||
Serial.print("MUX:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_MUX_BIT,ADS1115_CFG_MUX_LENGTH), BIN);
|
||||
|
||||
Serial.print("PGA:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_PGA_BIT,ADS1115_CFG_PGA_LENGTH), BIN);
|
||||
|
||||
Serial.print("MODE:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_MODE_BIT,1), BIN);
|
||||
|
||||
Serial.print("DR:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_DR_BIT,ADS1115_CFG_DR_LENGTH), BIN);
|
||||
|
||||
Serial.print("CMP_MODE:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_COMP_MODE_BIT,1), BIN);
|
||||
|
||||
Serial.print("CMP_POL:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_COMP_POL_BIT,1), BIN);
|
||||
|
||||
Serial.print("CMP_LAT:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_COMP_LAT_BIT,1), BIN);
|
||||
|
||||
Serial.print("CMP_QUE:\t");
|
||||
Serial.println(getValueFromBits(configRegister,
|
||||
ADS1115_CFG_COMP_QUE_BIT,ADS1115_CFG_COMP_QUE_LENGTH), BIN);
|
||||
#endif
|
||||
};
|
||||
|
200
lib/I2Cdevlib-ADS1115/ADS1115.h
Normal file
200
lib/I2Cdevlib-ADS1115/ADS1115.h
Normal file
@ -0,0 +1,200 @@
|
||||
// I2Cdev library collection - ADS1115 I2C device class header file
|
||||
// Based on Texas Instruments ADS1113/4/5 datasheet, May 2009 (SBAS444B, revised October 2009)
|
||||
// Note that the ADS1115 uses 16-bit registers, not 8-bit registers.
|
||||
// 8/2/2011 by Jeff Rowberg <jeff@rowberg.net>
|
||||
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
|
||||
//
|
||||
// Changelog:
|
||||
// 2013-05-05 - Add debug information. Clean up Single Shot implementation
|
||||
// 2011-10-29 - added getDifferentialx() methods, F. Farzanegan
|
||||
// 2011-08-02 - initial release
|
||||
|
||||
|
||||
/* ============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2011 Jeff Rowberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
*/
|
||||
|
||||
#ifndef _ADS1115_H_
|
||||
#define _ADS1115_H_
|
||||
|
||||
#include "I2Cdev.h"
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Arduino-style "Serial.print" debug constant (uncomment to enable)
|
||||
// -----------------------------------------------------------------------------
|
||||
//#define ADS1115_SERIAL_DEBUG
|
||||
|
||||
#define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND)
|
||||
#define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC)
|
||||
#define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin
|
||||
#define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin
|
||||
#define ADS1115_DEFAULT_ADDRESS ADS1115_ADDRESS_ADDR_GND
|
||||
|
||||
#define ADS1115_RA_CONVERSION 0x00
|
||||
#define ADS1115_RA_CONFIG 0x01
|
||||
#define ADS1115_RA_LO_THRESH 0x02
|
||||
#define ADS1115_RA_HI_THRESH 0x03
|
||||
|
||||
#define ADS1115_CFG_OS_BIT 15
|
||||
#define ADS1115_CFG_MUX_BIT 14
|
||||
#define ADS1115_CFG_MUX_LENGTH 3
|
||||
#define ADS1115_CFG_PGA_BIT 11
|
||||
#define ADS1115_CFG_PGA_LENGTH 3
|
||||
#define ADS1115_CFG_MODE_BIT 8
|
||||
#define ADS1115_CFG_DR_BIT 7
|
||||
#define ADS1115_CFG_DR_LENGTH 3
|
||||
#define ADS1115_CFG_COMP_MODE_BIT 4
|
||||
#define ADS1115_CFG_COMP_POL_BIT 3
|
||||
#define ADS1115_CFG_COMP_LAT_BIT 2
|
||||
#define ADS1115_CFG_COMP_QUE_BIT 1
|
||||
#define ADS1115_CFG_COMP_QUE_LENGTH 2
|
||||
|
||||
|
||||
#define ADS1115_MUX_P0_N1 0x00 // default
|
||||
#define ADS1115_MUX_P0_N3 0x01
|
||||
#define ADS1115_MUX_P1_N3 0x02
|
||||
#define ADS1115_MUX_P2_N3 0x03
|
||||
#define ADS1115_MUX_P0_NG 0x04
|
||||
#define ADS1115_MUX_P1_NG 0x05
|
||||
#define ADS1115_MUX_P2_NG 0x06
|
||||
#define ADS1115_MUX_P3_NG 0x07
|
||||
|
||||
#define ADS1115_PGA_6P144 0x00
|
||||
#define ADS1115_PGA_4P096 0x01
|
||||
#define ADS1115_PGA_2P048 0x02 // default
|
||||
#define ADS1115_PGA_1P024 0x03
|
||||
#define ADS1115_PGA_0P512 0x04
|
||||
#define ADS1115_PGA_0P256 0x05
|
||||
#define ADS1115_PGA_0P256B 0x06
|
||||
#define ADS1115_PGA_0P256C 0x07
|
||||
|
||||
#define ADS1115_MV_6P144 0.187500
|
||||
#define ADS1115_MV_4P096 0.125000
|
||||
#define ADS1115_MV_2P048 0.062500 // default
|
||||
#define ADS1115_MV_1P024 0.031250
|
||||
#define ADS1115_MV_0P512 0.015625
|
||||
#define ADS1115_MV_0P256 0.007813
|
||||
#define ADS1115_MV_0P256B 0.007813
|
||||
#define ADS1115_MV_0P256C 0.007813
|
||||
|
||||
#define ADS1115_MODE_CONTINUOUS 0x00
|
||||
#define ADS1115_MODE_SINGLESHOT 0x01 // default
|
||||
|
||||
#define ADS1115_RATE_8 0x00
|
||||
#define ADS1115_RATE_16 0x01
|
||||
#define ADS1115_RATE_32 0x02
|
||||
#define ADS1115_RATE_64 0x03
|
||||
#define ADS1115_RATE_128 0x04 // default
|
||||
#define ADS1115_RATE_250 0x05
|
||||
#define ADS1115_RATE_475 0x06
|
||||
#define ADS1115_RATE_860 0x07
|
||||
|
||||
#define ADS1115_COMP_MODE_HYSTERESIS 0x00 // default
|
||||
#define ADS1115_COMP_MODE_WINDOW 0x01
|
||||
|
||||
#define ADS1115_COMP_POL_ACTIVE_LOW 0x00 // default
|
||||
#define ADS1115_COMP_POL_ACTIVE_HIGH 0x01
|
||||
|
||||
#define ADS1115_COMP_LAT_NON_LATCHING 0x00 // default
|
||||
#define ADS1115_COMP_LAT_LATCHING 0x01
|
||||
|
||||
#define ADS1115_COMP_QUE_ASSERT1 0x00
|
||||
#define ADS1115_COMP_QUE_ASSERT2 0x01
|
||||
#define ADS1115_COMP_QUE_ASSERT4 0x02
|
||||
#define ADS1115_COMP_QUE_DISABLE 0x03 // default
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Arduino-style "Serial.print" debug constant (uncomment to enable)
|
||||
// -----------------------------------------------------------------------------
|
||||
//#define ADS1115_SERIAL_DEBUG
|
||||
|
||||
|
||||
class ADS1115 {
|
||||
public:
|
||||
ADS1115();
|
||||
ADS1115(uint8_t address);
|
||||
|
||||
void initialize();
|
||||
bool testConnection();
|
||||
|
||||
// SINGLE SHOT utilities
|
||||
bool pollConversion(uint16_t max_retries);
|
||||
void triggerConversion();
|
||||
|
||||
// Read the current CONVERSION register
|
||||
int16_t getConversion(bool triggerAndPoll=true);
|
||||
|
||||
// Differential
|
||||
int16_t getConversionP0N1();
|
||||
int16_t getConversionP0N3();
|
||||
int16_t getConversionP1N3();
|
||||
int16_t getConversionP2N3();
|
||||
|
||||
// Single-ended
|
||||
int16_t getConversionP0GND();
|
||||
int16_t getConversionP1GND();
|
||||
int16_t getConversionP2GND();
|
||||
int16_t getConversionP3GND();
|
||||
|
||||
// Utility
|
||||
float getMilliVolts(bool triggerAndPoll=true);
|
||||
float getMvPerCount();
|
||||
|
||||
// CONFIG register
|
||||
bool isConversionReady();
|
||||
uint8_t getMultiplexer();
|
||||
void setMultiplexer(uint8_t mux);
|
||||
uint8_t getGain();
|
||||
void setGain(uint8_t gain);
|
||||
bool getMode();
|
||||
void setMode(bool mode);
|
||||
uint8_t getRate();
|
||||
void setRate(uint8_t rate);
|
||||
bool getComparatorMode();
|
||||
void setComparatorMode(bool mode);
|
||||
bool getComparatorPolarity();
|
||||
void setComparatorPolarity(bool polarity);
|
||||
bool getComparatorLatchEnabled();
|
||||
void setComparatorLatchEnabled(bool enabled);
|
||||
uint8_t getComparatorQueueMode();
|
||||
void setComparatorQueueMode(uint8_t mode);
|
||||
void setConversionReadyPinMode();
|
||||
|
||||
// *_THRESH registers
|
||||
int16_t getLowThreshold();
|
||||
void setLowThreshold(int16_t threshold);
|
||||
int16_t getHighThreshold();
|
||||
void setHighThreshold(int16_t threshold);
|
||||
|
||||
// DEBUG
|
||||
void showConfigRegister();
|
||||
|
||||
private:
|
||||
uint8_t devAddr;
|
||||
uint16_t buffer[2];
|
||||
bool devMode;
|
||||
uint8_t muxMode;
|
||||
uint8_t pgaMode;
|
||||
};
|
||||
|
||||
#endif /* _ADS1115_H_ */
|
@ -0,0 +1,91 @@
|
||||
// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class
|
||||
// Example of reading two differential inputs of the ADS1115 and showing the value in mV
|
||||
// 06 May 2013 by Frederick Farzanegan (frederick1@farzanegan.org)
|
||||
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
|
||||
//
|
||||
// Changelog:
|
||||
// 2013-05-13 - initial release
|
||||
|
||||
/* ============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2011 Jeff Rowberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
*/
|
||||
#include "ADS1115.h"
|
||||
|
||||
ADS1115 adc0(ADS1115_DEFAULT_ADDRESS);
|
||||
|
||||
void setup() {
|
||||
Wire.begin(); // join I2C bus
|
||||
Serial.begin(19200); // initialize serial communication
|
||||
Serial.println("Initializing I2C devices...");
|
||||
adc0.initialize(); // initialize ADS1115 16 bit A/D chip
|
||||
|
||||
Serial.println("Testing device connections...");
|
||||
Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed");
|
||||
|
||||
// To get output from this method, you'll need to turn on the
|
||||
//#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file
|
||||
adc0.showConfigRegister();
|
||||
|
||||
// We're going to do continuous sampling
|
||||
adc0.setMode(ADS1115_MODE_CONTINUOUS);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// Sensor is on P0/N1 (pins 4/5)
|
||||
Serial.println("Sensor 1 ************************");
|
||||
// Set the gain (PGA) +/- 1.024v
|
||||
adc0.setGain(ADS1115_PGA_1P024);
|
||||
|
||||
// Get the number of counts of the accumulator
|
||||
Serial.print("Counts for sensor 1 is:");
|
||||
|
||||
// The below method sets the mux and gets a reading.
|
||||
int sensorOneCounts=adc0.getConversionP0N1(); // counts up to 16-bits
|
||||
Serial.println(sensorOneCounts);
|
||||
|
||||
// To turn the counts into a voltage, we can use
|
||||
Serial.print("Voltage for sensor 1 is:");
|
||||
Serial.println(sensorOneCounts*adc0.getMvPerCount());
|
||||
|
||||
Serial.println();
|
||||
|
||||
|
||||
// 2nd sensor is on P2/N3 (pins 6/7)
|
||||
Serial.println("Sensor 2 ************************");
|
||||
// Set the gain (PGA) +/- 0.256v
|
||||
adc0.setGain(ADS1115_PGA_0P256);
|
||||
|
||||
// Manually set the MUX // could have used the getConversionP* above
|
||||
adc0.setMultiplexer(ADS1115_MUX_P2_N3);
|
||||
Serial.print("Counts for sensor 2 is:");
|
||||
Serial.println(adc0.getConversion());
|
||||
|
||||
Serial.print("mVoltage sensor 2 is:");
|
||||
Serial.println(adc0.getMilliVolts()); // Convenience method to calculate voltage
|
||||
|
||||
Serial.println();
|
||||
|
||||
delay(500);
|
||||
}
|
||||
|
110
lib/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino
Normal file
110
lib/I2Cdevlib-ADS1115/examples/ADS1115_single/ADS1115_single.ino
Normal file
@ -0,0 +1,110 @@
|
||||
// I2C device class (I2Cdev) demonstration Arduino sketch for ADS1115 class
|
||||
// Example of reading two differential inputs of the ADS1115 and showing the value in mV
|
||||
// 2016-03-22 by Eadf (https://github.com/eadf)
|
||||
// Updates should (hopefully) always be available at https://github.com/jrowberg/i2cdevlib
|
||||
//
|
||||
// Changelog:
|
||||
// 2016-03-22 - initial release
|
||||
|
||||
/* ============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2011 Jeff Rowberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
*/
|
||||
|
||||
#include "ADS1115.h"
|
||||
|
||||
ADS1115 adc0(ADS1115_DEFAULT_ADDRESS);
|
||||
|
||||
// Wire ADS1115 ALERT/RDY pin to Arduino pin 2
|
||||
const int alertReadyPin = 2;
|
||||
|
||||
void setup() {
|
||||
//I2Cdev::begin(); // join I2C bus
|
||||
Wire.begin();
|
||||
Serial.begin(115200); // initialize serial communication
|
||||
|
||||
Serial.println("Testing device connections...");
|
||||
Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed");
|
||||
|
||||
adc0.initialize(); // initialize ADS1115 16 bit A/D chip
|
||||
|
||||
// We're going to do single shot sampling
|
||||
adc0.setMode(ADS1115_MODE_SINGLESHOT);
|
||||
|
||||
// Slow things down so that we can see that the "poll for conversion" code works
|
||||
adc0.setRate(ADS1115_RATE_8);
|
||||
|
||||
// Set the gain (PGA) +/- 6.144V
|
||||
// Note that any analog input must be higher than –0.3V and less than VDD +0.3
|
||||
adc0.setGain(ADS1115_PGA_6P144);
|
||||
// ALERT/RDY pin will indicate when conversion is ready
|
||||
|
||||
pinMode(alertReadyPin,INPUT_PULLUP);
|
||||
adc0.setConversionReadyPinMode();
|
||||
|
||||
// To get output from this method, you'll need to turn on the
|
||||
//#define ADS1115_SERIAL_DEBUG // in the ADS1115.h file
|
||||
#ifdef ADS1115_SERIAL_DEBUG
|
||||
adc0.showConfigRegister();
|
||||
Serial.print("HighThreshold="); Serial.println(adc0.getHighThreshold(),BIN);
|
||||
Serial.print("LowThreshold="); Serial.println(adc0.getLowThreshold(),BIN);
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Poll the assigned pin for conversion status
|
||||
*/
|
||||
void pollAlertReadyPin() {
|
||||
for (uint32_t i = 0; i<100000; i++)
|
||||
if (!digitalRead(alertReadyPin)) return;
|
||||
Serial.println("Failed to wait for AlertReadyPin, it's stuck high!");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
// The below method sets the mux and gets a reading.
|
||||
adc0.setMultiplexer(ADS1115_MUX_P0_NG);
|
||||
adc0.triggerConversion();
|
||||
pollAlertReadyPin();
|
||||
Serial.print("A0: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t");
|
||||
|
||||
adc0.setMultiplexer(ADS1115_MUX_P1_NG);
|
||||
adc0.triggerConversion();
|
||||
pollAlertReadyPin();
|
||||
Serial.print("A1: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t");
|
||||
|
||||
adc0.setMultiplexer(ADS1115_MUX_P2_NG);
|
||||
adc0.triggerConversion();
|
||||
pollAlertReadyPin();
|
||||
Serial.print("A2: "); Serial.print(adc0.getMilliVolts(false)); Serial.print("mV\t");
|
||||
|
||||
adc0.setMultiplexer(ADS1115_MUX_P3_NG);
|
||||
// Do conversion polling via I2C on this last reading:
|
||||
Serial.print("A3: "); Serial.print(adc0.getMilliVolts(true)); Serial.print("mV");
|
||||
|
||||
Serial.println(digitalRead(alertReadyPin));
|
||||
delay(500);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
18
lib/I2Cdevlib-ADS1115/library.json
Normal file
18
lib/I2Cdevlib-ADS1115/library.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"name": "I2Cdevlib-ADS1115",
|
||||
"keywords": "MUX, PGA, comparator, oscillator, reference, i2cdevlib, i2c",
|
||||
"description": "ADS1115 is 16-Bit ADC with Integrated MUX, PGA, Comparator, Oscillator, and Reference",
|
||||
"include": "Arduino/ADS1115",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/jrowberg/i2cdevlib.git"
|
||||
},
|
||||
"dependencies":
|
||||
{
|
||||
"name": "I2Cdevlib-Core",
|
||||
"frameworks": "arduino"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "atmelavr"
|
||||
}
|
31
lib/I2Cdevlib-Core/.library.json
Normal file
31
lib/I2Cdevlib-Core/.library.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name": "I2Cdevlib-Core",
|
||||
"repository": {
|
||||
"url": "https://github.com/jrowberg/i2cdevlib.git",
|
||||
"type": "git"
|
||||
},
|
||||
"platforms": [
|
||||
"atmelavr"
|
||||
],
|
||||
"frameworks": [
|
||||
"arduino"
|
||||
],
|
||||
"version": "6744ce0ac4",
|
||||
"export": {
|
||||
"include": "Arduino/I2Cdev"
|
||||
},
|
||||
"authors": [
|
||||
{
|
||||
"maintainer": false,
|
||||
"name": "Jeff Rowberg",
|
||||
"url": "https://github.com/jrowberg",
|
||||
"email": "jeff@rowberg.net"
|
||||
}
|
||||
],
|
||||
"keywords": [
|
||||
"i2cdevlib",
|
||||
"i2c"
|
||||
],
|
||||
"id": 11,
|
||||
"description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices."
|
||||
}
|
1457
lib/I2Cdevlib-Core/I2Cdev.cpp
Normal file
1457
lib/I2Cdevlib-Core/I2Cdev.cpp
Normal file
File diff suppressed because it is too large
Load Diff
278
lib/I2Cdevlib-Core/I2Cdev.h
Normal file
278
lib/I2Cdevlib-Core/I2Cdev.h
Normal file
@ -0,0 +1,278 @@
|
||||
// I2Cdev library collection - Main I2C device class header file
|
||||
// Abstracts bit and byte I2C R/W functions into a convenient class
|
||||
// 2013-06-05 by Jeff Rowberg <jeff@rowberg.net>
|
||||
//
|
||||
// Changelog:
|
||||
// 2015-10-30 - simondlevy : support i2c_t3 for Teensy3.1
|
||||
// 2013-05-06 - add Francesco Ferrara's Fastwire v0.24 implementation with small modifications
|
||||
// 2013-05-05 - fix issue with writing bit values to words (Sasquatch/Farzanegan)
|
||||
// 2012-06-09 - fix major issue with reading > 32 bytes at a time with Arduino Wire
|
||||
// - add compiler warnings when using outdated or IDE or limited I2Cdev implementation
|
||||
// 2011-11-01 - fix write*Bits mask calculation (thanks sasquatch @ Arduino forums)
|
||||
// 2011-10-03 - added automatic Arduino version detection for ease of use
|
||||
// 2011-10-02 - added Gene Knight's NBWire TwoWire class implementation with small modifications
|
||||
// 2011-08-31 - added support for Arduino 1.0 Wire library (methods are different from 0.x)
|
||||
// 2011-08-03 - added optional timeout parameter to read* methods to easily change from default
|
||||
// 2011-08-02 - added support for 16-bit registers
|
||||
// - fixed incorrect Doxygen comments on some methods
|
||||
// - added timeout value for read operations (thanks mem @ Arduino forums)
|
||||
// 2011-07-30 - changed read/write function structures to return success or byte counts
|
||||
// - made all methods static for multi-device memory savings
|
||||
// 2011-07-28 - initial release
|
||||
|
||||
/* ============================================
|
||||
I2Cdev device library code is placed under the MIT license
|
||||
Copyright (c) 2013 Jeff Rowberg
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
===============================================
|
||||
*/
|
||||
|
||||
#ifndef _I2CDEV_H_
|
||||
#define _I2CDEV_H_
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// I2C interface implementation setting
|
||||
// -----------------------------------------------------------------------------
|
||||
#ifndef I2CDEV_IMPLEMENTATION
|
||||
#define I2CDEV_IMPLEMENTATION I2CDEV_ARDUINO_WIRE
|
||||
//#define I2CDEV_IMPLEMENTATION I2CDEV_BUILTIN_FASTWIRE
|
||||
#endif // I2CDEV_IMPLEMENTATION
|
||||
|
||||
// comment this out if you are using a non-optimal IDE/implementation setting
|
||||
// but want the compiler to shut up about it
|
||||
#define I2CDEV_IMPLEMENTATION_WARNINGS
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// I2C interface implementation options
|
||||
// -----------------------------------------------------------------------------
|
||||
#define I2CDEV_ARDUINO_WIRE 1 // Wire object from Arduino
|
||||
#define I2CDEV_BUILTIN_NBWIRE 2 // Tweaked Wire object from Gene Knight's NBWire project
|
||||
// ^^^ NBWire implementation is still buggy w/some interrupts!
|
||||
#define I2CDEV_BUILTIN_FASTWIRE 3 // FastWire object from Francesco Ferrara's project
|
||||
#define I2CDEV_I2CMASTER_LIBRARY 4 // I2C object from DSSCircuits I2C-Master Library at https://github.com/DSSCircuits/I2C-Master-Library
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Arduino-style "Serial.print" debug constant (uncomment to enable)
|
||||
// -----------------------------------------------------------------------------
|
||||
//#define I2CDEV_SERIAL_DEBUG
|
||||
|
||||
#ifdef ARDUINO
|
||||
#if ARDUINO < 100
|
||||
#include "WProgram.h"
|
||||
#else
|
||||
#include "Arduino.h"
|
||||
#endif
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
|
||||
#include <Wire.h>
|
||||
#endif
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_I2CMASTER_LIBRARY
|
||||
#include <I2C.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SPARK
|
||||
#include <spark_wiring_i2c.h>
|
||||
#define ARDUINO 101
|
||||
#endif
|
||||
|
||||
|
||||
// 1000ms default read timeout (modify with "I2Cdev::readTimeout = [ms];")
|
||||
#define I2CDEV_DEFAULT_READ_TIMEOUT 1000
|
||||
|
||||
class I2Cdev {
|
||||
public:
|
||||
I2Cdev();
|
||||
|
||||
static int8_t readBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
static int8_t readBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
static int8_t readBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
static int8_t readBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
static int8_t readByte(uint8_t devAddr, uint8_t regAddr, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
static int8_t readWord(uint8_t devAddr, uint8_t regAddr, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
static int8_t readBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
static int8_t readWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data, uint16_t timeout=I2Cdev::readTimeout);
|
||||
|
||||
static bool writeBit(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint8_t data);
|
||||
static bool writeBitW(uint8_t devAddr, uint8_t regAddr, uint8_t bitNum, uint16_t data);
|
||||
static bool writeBits(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint8_t data);
|
||||
static bool writeBitsW(uint8_t devAddr, uint8_t regAddr, uint8_t bitStart, uint8_t length, uint16_t data);
|
||||
static bool writeByte(uint8_t devAddr, uint8_t regAddr, uint8_t data);
|
||||
static bool writeWord(uint8_t devAddr, uint8_t regAddr, uint16_t data);
|
||||
static bool writeBytes(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint8_t *data);
|
||||
static bool writeWords(uint8_t devAddr, uint8_t regAddr, uint8_t length, uint16_t *data);
|
||||
|
||||
static uint16_t readTimeout;
|
||||
};
|
||||
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
|
||||
//////////////////////
|
||||
// FastWire 0.24
|
||||
// This is a library to help faster programs to read I2C devices.
|
||||
// Copyright(C) 2012
|
||||
// Francesco Ferrara
|
||||
//////////////////////
|
||||
|
||||
/* Master */
|
||||
#define TW_START 0x08
|
||||
#define TW_REP_START 0x10
|
||||
|
||||
/* Master Transmitter */
|
||||
#define TW_MT_SLA_ACK 0x18
|
||||
#define TW_MT_SLA_NACK 0x20
|
||||
#define TW_MT_DATA_ACK 0x28
|
||||
#define TW_MT_DATA_NACK 0x30
|
||||
#define TW_MT_ARB_LOST 0x38
|
||||
|
||||
/* Master Receiver */
|
||||
#define TW_MR_ARB_LOST 0x38
|
||||
#define TW_MR_SLA_ACK 0x40
|
||||
#define TW_MR_SLA_NACK 0x48
|
||||
#define TW_MR_DATA_ACK 0x50
|
||||
#define TW_MR_DATA_NACK 0x58
|
||||
|
||||
#define TW_OK 0
|
||||
#define TW_ERROR 1
|
||||
|
||||
class Fastwire {
|
||||
private:
|
||||
static boolean waitInt();
|
||||
|
||||
public:
|
||||
static void setup(int khz, boolean pullup);
|
||||
static byte beginTransmission(byte device);
|
||||
static byte write(byte value);
|
||||
static byte writeBuf(byte device, byte address, byte *data, byte num);
|
||||
static byte readBuf(byte device, byte address, byte *data, byte num);
|
||||
static void reset();
|
||||
static byte stop();
|
||||
};
|
||||
#endif
|
||||
|
||||
#if I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
|
||||
// NBWire implementation based heavily on code by Gene Knight <Gene@Telobot.com>
|
||||
// Originally posted on the Arduino forum at http://arduino.cc/forum/index.php/topic,70705.0.html
|
||||
// Originally offered to the i2cdevlib project at http://arduino.cc/forum/index.php/topic,68210.30.html
|
||||
|
||||
#define NBWIRE_BUFFER_LENGTH 32
|
||||
|
||||
class TwoWire {
|
||||
private:
|
||||
static uint8_t rxBuffer[];
|
||||
static uint8_t rxBufferIndex;
|
||||
static uint8_t rxBufferLength;
|
||||
|
||||
static uint8_t txAddress;
|
||||
static uint8_t txBuffer[];
|
||||
static uint8_t txBufferIndex;
|
||||
static uint8_t txBufferLength;
|
||||
|
||||
// static uint8_t transmitting;
|
||||
static void (*user_onRequest)(void);
|
||||
static void (*user_onReceive)(int);
|
||||
static void onRequestService(void);
|
||||
static void onReceiveService(uint8_t*, int);
|
||||
|
||||
public:
|
||||
TwoWire();
|
||||
void begin();
|
||||
void begin(uint8_t);
|
||||
void begin(int);
|
||||
void beginTransmission(uint8_t);
|
||||
//void beginTransmission(int);
|
||||
uint8_t endTransmission(uint16_t timeout=0);
|
||||
void nbendTransmission(void (*function)(int)) ;
|
||||
uint8_t requestFrom(uint8_t, int, uint16_t timeout=0);
|
||||
//uint8_t requestFrom(int, int);
|
||||
void nbrequestFrom(uint8_t, int, void (*function)(int));
|
||||
void send(uint8_t);
|
||||
void send(uint8_t*, uint8_t);
|
||||
//void send(int);
|
||||
void send(char*);
|
||||
uint8_t available(void);
|
||||
uint8_t receive(void);
|
||||
void onReceive(void (*)(int));
|
||||
void onRequest(void (*)(void));
|
||||
};
|
||||
|
||||
#define TWI_READY 0
|
||||
#define TWI_MRX 1
|
||||
#define TWI_MTX 2
|
||||
#define TWI_SRX 3
|
||||
#define TWI_STX 4
|
||||
|
||||
#define TW_WRITE 0
|
||||
#define TW_READ 1
|
||||
|
||||
#define TW_MT_SLA_NACK 0x20
|
||||
#define TW_MT_DATA_NACK 0x30
|
||||
|
||||
#define CPU_FREQ 16000000L
|
||||
#define TWI_FREQ 100000L
|
||||
#define TWI_BUFFER_LENGTH 32
|
||||
|
||||
/* TWI Status is in TWSR, in the top 5 bits: TWS7 - TWS3 */
|
||||
|
||||
#define TW_STATUS_MASK (_BV(TWS7)|_BV(TWS6)|_BV(TWS5)|_BV(TWS4)|_BV(TWS3))
|
||||
#define TW_STATUS (TWSR & TW_STATUS_MASK)
|
||||
#define TW_START 0x08
|
||||
#define TW_REP_START 0x10
|
||||
#define TW_MT_SLA_ACK 0x18
|
||||
#define TW_MT_SLA_NACK 0x20
|
||||
#define TW_MT_DATA_ACK 0x28
|
||||
#define TW_MT_DATA_NACK 0x30
|
||||
#define TW_MT_ARB_LOST 0x38
|
||||
#define TW_MR_ARB_LOST 0x38
|
||||
#define TW_MR_SLA_ACK 0x40
|
||||
#define TW_MR_SLA_NACK 0x48
|
||||
#define TW_MR_DATA_ACK 0x50
|
||||
#define TW_MR_DATA_NACK 0x58
|
||||
#define TW_ST_SLA_ACK 0xA8
|
||||
#define TW_ST_ARB_LOST_SLA_ACK 0xB0
|
||||
#define TW_ST_DATA_ACK 0xB8
|
||||
#define TW_ST_DATA_NACK 0xC0
|
||||
#define TW_ST_LAST_DATA 0xC8
|
||||
#define TW_SR_SLA_ACK 0x60
|
||||
#define TW_SR_ARB_LOST_SLA_ACK 0x68
|
||||
#define TW_SR_GCALL_ACK 0x70
|
||||
#define TW_SR_ARB_LOST_GCALL_ACK 0x78
|
||||
#define TW_SR_DATA_ACK 0x80
|
||||
#define TW_SR_DATA_NACK 0x88
|
||||
#define TW_SR_GCALL_DATA_ACK 0x90
|
||||
#define TW_SR_GCALL_DATA_NACK 0x98
|
||||
#define TW_SR_STOP 0xA0
|
||||
#define TW_NO_INFO 0xF8
|
||||
#define TW_BUS_ERROR 0x00
|
||||
|
||||
//#define _MMIO_BYTE(mem_addr) (*(volatile uint8_t *)(mem_addr))
|
||||
//#define _SFR_BYTE(sfr) _MMIO_BYTE(_SFR_ADDR(sfr))
|
||||
|
||||
#ifndef sbi // set bit
|
||||
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
|
||||
#endif // sbi
|
||||
|
||||
#ifndef cbi // clear bit
|
||||
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
|
||||
#endif // cbi
|
||||
|
||||
extern TwoWire Wire;
|
||||
|
||||
#endif // I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_NBWIRE
|
||||
|
||||
#endif /* _I2CDEV_H_ */
|
38
lib/I2Cdevlib-Core/keywords.txt
Normal file
38
lib/I2Cdevlib-Core/keywords.txt
Normal file
@ -0,0 +1,38 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For I2Cdev
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
I2Cdev KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
readBit KEYWORD2
|
||||
readBitW KEYWORD2
|
||||
readBits KEYWORD2
|
||||
readBitsW KEYWORD2
|
||||
readByte KEYWORD2
|
||||
readBytes KEYWORD2
|
||||
readWord KEYWORD2
|
||||
readWords KEYWORD2
|
||||
writeBit KEYWORD2
|
||||
writeBitW KEYWORD2
|
||||
writeBits KEYWORD2
|
||||
writeBitsW KEYWORD2
|
||||
writeByte KEYWORD2
|
||||
writeBytes KEYWORD2
|
||||
writeWord KEYWORD2
|
||||
writeWords KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
13
lib/I2Cdevlib-Core/library.json
Normal file
13
lib/I2Cdevlib-Core/library.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "I2Cdevlib-Core",
|
||||
"keywords": "i2cdevlib, i2c",
|
||||
"description": "The I2C Device Library (I2Cdevlib) is a collection of uniform and well-documented classes to provide simple and intuitive interfaces to I2C devices.",
|
||||
"include": "Arduino/I2Cdev",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/jrowberg/i2cdevlib.git"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "atmelavr"
|
||||
}
|
@ -1,4 +1,11 @@
|
||||
/* 5.9.0 20171030
|
||||
/* 5.9.1 20171107
|
||||
* Add external sensor function pointer interface to enable easy sensor addition
|
||||
* Add support for ADS1115 to be enabled in user_config.h and needs libraries i2cdevlib-Core and i2cdevlib-ADS1115 (#338, #660)
|
||||
* Fix Backup Configuration file download failure by defining proper file size (#1115)
|
||||
* Fix Exception 26 and empty console screen after usage of command WakeupDuration (#1133)
|
||||
* Fix some changed iTead web links in README.md (#1137)
|
||||
*
|
||||
* 5.9.0 20171030
|
||||
* Rewrite code (partly) using Google C++ Style Guide (https://google.github.io/styleguide/cppguide.html)
|
||||
* Rewrite code by using command lookup tables and javascript (client side) web page expansions
|
||||
* Change HTML/CSS to enable nicer form field entry
|
||||
|
@ -77,8 +77,9 @@ const char S_JSON_COMMAND_INDEX_NVALUE[] PROGMEM = "{\"%s%d\":%d}";
|
||||
const char S_JSON_COMMAND_INDEX_SVALUE[] PROGMEM = "{\"%s%d\":\"%s\"}";
|
||||
const char S_JSON_COMMAND_INDEX_SVALUE_SVALUE[] PROGMEM = "{\"%s%d\":\"%s%s\"}";
|
||||
|
||||
const char JSON_SNS_TEMPHUM[] PROGMEM =
|
||||
"%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s}";
|
||||
const char JSON_SNS_TEMPHUM[] PROGMEM = "%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s}";
|
||||
|
||||
const char S_LOG_I2C_FOUND_AT[] PROGMEM = D_LOG_I2C "%s " D_FOUND_AT " 0x%x";
|
||||
|
||||
const char S_LOG_HTTP[] PROGMEM = D_LOG_HTTP;
|
||||
const char S_LOG_WIFI[] PROGMEM = D_LOG_WIFI;
|
||||
@ -113,6 +114,13 @@ const char kPrefixes[3][PRFX_MAX_STRING_LENGTH] PROGMEM = {
|
||||
static const char kMonthNames[] = D_MONTH3LIST;
|
||||
|
||||
// webserver.ino
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_TEMP[] PROGMEM = "%s{s}%s " D_TEMPERATURE "{m}%s°%c{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
const char HTTP_SNS_HUM[] PROGMEM = "%s{s}%s " D_HUMIDITY "{m}%s%{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
const char HTTP_SNS_PRESSURE[] PROGMEM = "%s{s}%s " D_PRESSURE "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
const char HTTP_SNS_SEAPRESSURE[] PROGMEM = "%s{s}%s " D_PRESSUREATSEALEVEL "{m}%s " D_UNIT_PRESSURE "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
const char HTTP_SNS_ANALOG[] PROGMEM = "%s{s}%s " D_ANALOG_INPUT "%d{m}%d{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
|
||||
const char S_MAIN_MENU[] PROGMEM = D_MAIN_MENU;
|
||||
const char S_CONFIGURATION[] PROGMEM = D_CONFIGURATION;
|
||||
const char S_CONFIGURE_MODULE[] PROGMEM = D_CONFIGURE_MODULE;
|
||||
@ -128,5 +136,6 @@ const char S_FIRMWARE_UPGRADE[] PROGMEM = D_FIRMWARE_UPGRADE;
|
||||
const char S_CONSOLE[] PROGMEM = D_CONSOLE;
|
||||
const char S_INFORMATION[] PROGMEM = D_INFORMATION;
|
||||
const char S_RESTART[] PROGMEM = D_RESTART;
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
#endif // _I18N_H_
|
@ -216,7 +216,7 @@
|
||||
#define D_SET_BAUDRATE_TO "Baudrate eingestell auf"
|
||||
#define D_RECEIVED_TOPIC "erhaltenes topic"
|
||||
#define D_DATA_SIZE "Datengröße"
|
||||
#define D_ANALOG_INPUT0 "Analog0"
|
||||
#define D_ANALOG_INPUT "Analog"
|
||||
|
||||
#define D_FINGERPRINT "TLS-Fingerabdruck wird verifiziert..."
|
||||
#define D_TLS_CONNECT_FAILED_TO "TLS-Verbindung fehlgeschlagen an"
|
||||
|
@ -216,7 +216,7 @@
|
||||
#define D_SET_BAUDRATE_TO "Set Baudrate to"
|
||||
#define D_RECEIVED_TOPIC "Received Topic"
|
||||
#define D_DATA_SIZE "Data Size"
|
||||
#define D_ANALOG_INPUT0 "Analog0"
|
||||
#define D_ANALOG_INPUT "Analog"
|
||||
|
||||
#define D_FINGERPRINT "Verify TLS fingerprint..."
|
||||
#define D_TLS_CONNECT_FAILED_TO "TLS Connect failed to"
|
||||
|
@ -216,7 +216,7 @@
|
||||
#define D_SET_BAUDRATE_TO "Zet baudrate op"
|
||||
#define D_RECEIVED_TOPIC "Ontvangen topic"
|
||||
#define D_DATA_SIZE "Data lengte"
|
||||
#define D_ANALOG_INPUT0 "Analoog0"
|
||||
#define D_ANALOG_INPUT "Analoog"
|
||||
|
||||
#define D_FINGERPRINT "Controleer TLS vingerafdruk..."
|
||||
#define D_TLS_CONNECT_FAILED_TO "TLS Verbinding mislukt naar"
|
||||
|
@ -216,7 +216,7 @@
|
||||
#define D_SET_BAUDRATE_TO "Ustaw szybkosc transmisji na"
|
||||
#define D_RECEIVED_TOPIC "Otrzymany temat"
|
||||
#define D_DATA_SIZE "Wielkosc danych"
|
||||
#define D_ANALOG_INPUT0 "Wej_analogowe"
|
||||
#define D_ANALOG_INPUT "Wej_analogowe"
|
||||
|
||||
#define D_FINGERPRINT "Weryfikuj odcisk TLS..."
|
||||
#define D_TLS_CONNECT_FAILED_TO "Nieudane polaczenie TLS do"
|
||||
|
@ -90,6 +90,8 @@ typedef unsigned long power_t; // Power (Relay) type
|
||||
#define APP_BAUDRATE 115200 // Default serial baudrate
|
||||
#define MAX_STATUS 11 // Max number of status lines
|
||||
|
||||
#define XSNS_MAX 20 // Max number of allowed Xsns External Sensors (Update xsns_interface.ino if changed)
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Enumeration
|
||||
\*********************************************************************************************/
|
||||
@ -110,6 +112,7 @@ enum Ws2812Color {WS_RED, WS_GREEN, WS_BLUE};
|
||||
enum LightTypes {LT_BASIC, LT_PWM1, LT_PWM2, LT_PWM3, LT_PWM4, LT_PWM5, LT_PWM6, LT_PWM7, LT_NU8, LT_NU9, LT_NU10, LT_WS2812, LT_RGBW, LT_RGBWC};
|
||||
enum LichtSubtypes {LST_NONE, LST_SINGLE, LST_COLDWARM, LST_RGB, LST_RGBW, LST_RGBWC};
|
||||
enum LichtSchemes {LS_POWER, LS_WAKEUP, LS_CYCLEUP, LS_CYCLEDN, LS_RANDOM, LS_MAX};
|
||||
enum XsnsFunctions {FUNC_XSNS_INIT, FUNC_XSNS_PREP, FUNC_XSNS_JSON_APPEND, FUNC_XSNS_MQTT_SHOW, FUNC_XSNS_WEB};
|
||||
|
||||
const uint8_t kDefaultRfCode[9] PROGMEM = { 0x21, 0x16, 0x01, 0x0E, 0x03, 0x48, 0x2E, 0x1A, 0x00 };
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
- Select IDE Tools - Flash Size: "1M (no SPIFFS)"
|
||||
====================================================*/
|
||||
|
||||
#define VERSION 0x05090000 // 5.9.0
|
||||
#define VERSION 0x05090100 // 5.9.1
|
||||
|
||||
// Location specific includes
|
||||
#include "sonoff.h" // Enumaration used in user_config.h
|
||||
@ -183,6 +183,8 @@ uint8_t light_type = 0; // Light types
|
||||
|
||||
boolean mdns_begun = false;
|
||||
|
||||
uint8_t xsns_present = 0; // Number of External Sensors found
|
||||
boolean (*xsns_func_ptr[XSNS_MAX])(byte); // External Sensor Function Pointers for simple implementation of sensors
|
||||
char version[16]; // Version string from VERSION define
|
||||
char my_hostname[33]; // Composed Wifi hostname
|
||||
char mqtt_client[33]; // Composed MQTT Clientname
|
||||
@ -1757,9 +1759,8 @@ void PublishStatus(uint8_t payload)
|
||||
}
|
||||
|
||||
if ((0 == payload) || (10 == payload)) {
|
||||
uint8_t djson = 0;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS10_SENSOR "\":"));
|
||||
MqttShowSensor(&djson);
|
||||
MqttShowSensor();
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
MqttPublishPrefixTopic_P(option, PSTR(D_CMND_STATUS "10"));
|
||||
}
|
||||
@ -1789,62 +1790,23 @@ void MqttShowState()
|
||||
mqtt_data, Settings.sta_active +1, Settings.sta_ssid[Settings.sta_active], WifiGetRssiAsQuality(WiFi.RSSI()), WiFi.BSSIDstr().c_str());
|
||||
}
|
||||
|
||||
void MqttShowSensor(uint8_t* djson)
|
||||
boolean MqttShowSensor()
|
||||
{
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s{\"" D_TIME "\":\"%s\""), mqtt_data, GetDateAndTime().c_str());
|
||||
int json_data_start = strlen(mqtt_data);
|
||||
for (byte i = 0; i < MAX_SWITCHES; i++) {
|
||||
if (pin[GPIO_SWT1 +i] < 99) {
|
||||
boolean swm = ((FOLLOW_INV == Settings.switchmode[i]) || (PUSHBUTTON_INV == Settings.switchmode[i]) || (PUSHBUTTONHOLD_INV == Settings.switchmode[i]));
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_SWITCH "%d\":\"%s\""), mqtt_data, i +1, GetStateText(swm ^ lastwallswitch[i]));
|
||||
*djson = 1;
|
||||
}
|
||||
}
|
||||
MqttShowCounter(djson);
|
||||
#ifndef USE_ADC_VCC
|
||||
if (pin[GPIO_ADC0] < 99) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT0 "\":%d"), mqtt_data, GetAdc0());
|
||||
*djson = 1;
|
||||
}
|
||||
#endif
|
||||
if (SONOFF_SC == Settings.module) {
|
||||
MqttShowSonoffSC(djson);
|
||||
}
|
||||
if (pin[GPIO_DSB] < 99) {
|
||||
#ifdef USE_DS18B20
|
||||
MqttShowDs18b20(djson);
|
||||
#endif // USE_DS18B20
|
||||
#ifdef USE_DS18x20
|
||||
MqttShowDs18x20(djson);
|
||||
#endif // USE_DS18x20
|
||||
}
|
||||
#ifdef USE_DHT
|
||||
if (dht_flg) {
|
||||
MqttShowDht(djson);
|
||||
}
|
||||
#endif // USE_DHT
|
||||
#ifdef USE_I2C
|
||||
if (i2c_flg) {
|
||||
#ifdef USE_SHT
|
||||
MqttShowSht(djson);
|
||||
#endif // USE_SHT
|
||||
#ifdef USE_HTU
|
||||
MqttShowHtu(djson);
|
||||
#endif // USE_HTU
|
||||
#ifdef USE_BMP
|
||||
MqttShowBmp(djson);
|
||||
#endif // USE_BMP
|
||||
#ifdef USE_BH1750
|
||||
MqttShowBh1750(djson);
|
||||
#endif // USE_BH1750
|
||||
#ifdef USE_VEML6070
|
||||
MqttShowVeml6070(djson);
|
||||
#endif // USE_VEML6070
|
||||
}
|
||||
#endif // USE_I2C
|
||||
XsnsCall(FUNC_XSNS_JSON_APPEND);
|
||||
boolean json_data_available = (strlen(mqtt_data) - json_data_start);
|
||||
if (strstr_P(mqtt_data, PSTR(D_TEMPERATURE))) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE_UNIT "\":\"%c\""), mqtt_data, TempUnit());
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
return json_data_available;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
@ -1897,39 +1859,7 @@ void PerformEverySecond()
|
||||
if (Settings.tele_period) {
|
||||
tele_period++;
|
||||
if (tele_period == Settings.tele_period -1) {
|
||||
if (pin[GPIO_DSB] < 99) {
|
||||
#ifdef USE_DS18B20
|
||||
Ds18b20ReadTempPrep();
|
||||
#endif // USE_DS18B20
|
||||
#ifdef USE_DS18x20
|
||||
Ds18x20Search(); // Check for changes in sensors number
|
||||
Ds18x20Convert(); // Start Conversion, takes up to one second
|
||||
#endif // USE_DS18x20
|
||||
}
|
||||
#ifdef USE_DHT
|
||||
if (dht_flg) {
|
||||
DhtReadPrep();
|
||||
}
|
||||
#endif // USE_DHT
|
||||
#ifdef USE_I2C
|
||||
if (i2c_flg) {
|
||||
#ifdef USE_SHT
|
||||
ShtDetect();
|
||||
#endif // USE_SHT
|
||||
#ifdef USE_HTU
|
||||
HtuDetect();
|
||||
#endif // USE_HTU
|
||||
#ifdef USE_BMP
|
||||
BmpDetect();
|
||||
#endif // USE_BMP
|
||||
#ifdef USE_BH1750
|
||||
Bh1750Detect();
|
||||
#endif // USE_BH1750
|
||||
#ifdef USE_VEML6070
|
||||
Veml6070Detect();
|
||||
#endif // USE_VEML6070
|
||||
}
|
||||
#endif // USE_I2C
|
||||
XsnsCall(FUNC_XSNS_PREP);
|
||||
}
|
||||
if (tele_period >= Settings.tele_period) {
|
||||
tele_period = 0;
|
||||
@ -1938,16 +1868,12 @@ void PerformEverySecond()
|
||||
MqttShowState();
|
||||
MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_STATE));
|
||||
|
||||
uint8_t djson = 0;
|
||||
mqtt_data[0] = '\0';
|
||||
MqttShowSensor(&djson);
|
||||
if (djson) {
|
||||
if (MqttShowSensor()) {
|
||||
MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_SENSOR), Settings.flag.mqtt_sensor_retain);
|
||||
}
|
||||
|
||||
if (hlw_flg) {
|
||||
MqttShowHlw8012(1);
|
||||
}
|
||||
XsnsCall(FUNC_XSNS_MQTT_SHOW);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2684,24 +2610,9 @@ void GpioInit()
|
||||
#endif // USE_IR_RECEIVE
|
||||
#endif // USE_IR_REMOTE
|
||||
|
||||
CounterInit();
|
||||
|
||||
hlw_flg = ((pin[GPIO_HLW_SEL] < 99) && (pin[GPIO_HLW_CF1] < 99) && (pin[GPIO_HLW_CF] < 99));
|
||||
if (hlw_flg) {
|
||||
HlwInit();
|
||||
}
|
||||
|
||||
#ifdef USE_DHT
|
||||
if (dht_flg) {
|
||||
DhtInit();
|
||||
}
|
||||
#endif // USE_DHT
|
||||
|
||||
#ifdef USE_DS18x20
|
||||
if (pin[GPIO_DSB] < 99) {
|
||||
Ds18x20Init();
|
||||
}
|
||||
#endif // USE_DS18x20
|
||||
XSnsInit();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
@ -757,6 +757,17 @@ int32_t I2cRead24(uint8_t addr, uint8_t reg)
|
||||
return I2cRead(addr, reg, 3);
|
||||
}
|
||||
|
||||
void I2cWrite8v(uint8_t addr, uint8_t val)
|
||||
{
|
||||
byte x = I2C_RETRY_COUNTER;
|
||||
|
||||
do {
|
||||
Wire.beginTransmission((uint8_t)addr); // start transmission to device
|
||||
Wire.write(val); // write data
|
||||
x--;
|
||||
} while (Wire.endTransmission(true) != 0 && x != 0); // end transmission
|
||||
}
|
||||
|
||||
void I2cWrite8(uint8_t addr, uint8_t reg, uint8_t val)
|
||||
{
|
||||
byte x = I2C_RETRY_COUNTER;
|
||||
@ -1136,16 +1147,6 @@ char TempUnit()
|
||||
return (Settings.flag.temperature_conversion) ? 'F' : 'C';
|
||||
}
|
||||
|
||||
uint16_t GetAdc0()
|
||||
{
|
||||
uint16_t alr = 0;
|
||||
for (byte i = 0; i < 32; i++) {
|
||||
alr += analogRead(A0);
|
||||
delay(1);
|
||||
}
|
||||
return alr >> 5;
|
||||
}
|
||||
|
||||
double FastPrecisePow(double a, double b)
|
||||
{
|
||||
// https://martin.ankerl.com/2012/01/25/optimized-approximative-pow-in-c-and-cpp/
|
||||
@ -1233,8 +1234,66 @@ int GetCommandCode(char* destination, size_t destination_size, const char* needl
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef USE_ADC_VCC
|
||||
/*********************************************************************************************\
|
||||
* ADC support
|
||||
\*********************************************************************************************/
|
||||
|
||||
void AdcShow(boolean json)
|
||||
{
|
||||
uint16_t analog = 0;
|
||||
for (byte i = 0; i < 32; i++) {
|
||||
analog += analogRead(A0);
|
||||
delay(1);
|
||||
}
|
||||
analog >>= 5;
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_ANALOG_INPUT "0\":%d"), mqtt_data, analog);
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "", 0, analog);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_02
|
||||
|
||||
boolean Xsns02(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (pin[GPIO_ADC0] < 99) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
// case FUNC_XSNS_PREP:
|
||||
// break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
AdcShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
AdcShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif // USE_ADC_VCC
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Syslog
|
||||
*
|
||||
* Example:
|
||||
* snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_LOG "Any value %d"), value);
|
||||
* AddLog(LOG_LEVEL_DEBUG);
|
||||
*
|
||||
\*********************************************************************************************/
|
||||
|
||||
void Syslog()
|
||||
|
@ -163,14 +163,15 @@
|
||||
// -- Sensor code selection -----------------------
|
||||
#define USE_ADC_VCC // Display Vcc in Power status. Disable for use as Analog input on selected devices
|
||||
|
||||
//#define USE_DS18x20 // Optional using OneWire library for multiple DS18B20 and/or DS18S20 (+2k code)
|
||||
//#define USE_DS18x20 // Optional for multiple DS18B20 and/or DS18S20 sensors using library OneWire (+2k code)
|
||||
|
||||
#define USE_I2C // I2C using library wire (+10k code, 0.2k mem) - Disable by //
|
||||
#define USE_SHT // Add I2C emulating code for SHT1X sensor
|
||||
#define USE_HTU // Add I2C code for HTU21/SI7013/SI7020/SI7021 sensor
|
||||
#define USE_BMP // Add I2C code for BMP/BME280 sensor
|
||||
#define USE_BH1750 // Add I2C code for BH1750 sensor
|
||||
// #define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0.5k code)
|
||||
#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_ADS1115 // Add I2C code for ADS1x15 16 bit A/D converter using library i2cdevlib-Core and i2cdevlib-ADS1115 (+2k code)
|
||||
|
||||
#define USE_IR_REMOTE // Send IR remote commands using library IRremoteESP8266 and ArduinoJson (+3k code, 0.3k mem)
|
||||
// #define USE_IR_HVAC // Support for HVAC system using IR (+2k code)
|
||||
|
@ -60,7 +60,8 @@ const char HTTP_HEAD[] PROGMEM =
|
||||
"x=new XMLHttpRequest();"
|
||||
"x.onreadystatechange=function(){"
|
||||
"if(x.readyState==4&&x.status==200){"
|
||||
"document.getElementById('l1').innerHTML=x.responseText;"
|
||||
"var s=x.responseText.replace(/{s}/g,\"<tr><th>\").replace(/{m}/g,\"</th><td>\").replace(/{e}/g,\"</td></tr>\").replace(/{t}/g,\"%'><div style='text-align:center;font-weight:\");"
|
||||
"document.getElementById('l1').innerHTML=s;"
|
||||
"}"
|
||||
"};"
|
||||
"x.open('GET','ay'+a,true);"
|
||||
@ -274,20 +275,6 @@ const char HTTP_TABLE100[] PROGMEM =
|
||||
"<table style='width:100%'>";
|
||||
const char HTTP_COUNTER[] PROGMEM =
|
||||
"<br/><div id='t' name='t' style='text-align:center;'></div>";
|
||||
const char HTTP_SNS_TEMP[] PROGMEM =
|
||||
"<tr><th>%s " D_TEMPERATURE "</th><td>%s°%c</td></tr>";
|
||||
const char HTTP_SNS_HUM[] PROGMEM =
|
||||
"<tr><th>%s " D_HUMIDITY "</th><td>%s%</td></tr>";
|
||||
const char HTTP_SNS_PRESSURE[] PROGMEM =
|
||||
"<tr><th>%s " D_PRESSURE "</th><td>%s " D_UNIT_PRESSURE "</td></tr>";
|
||||
const char HTTP_SNS_PRESSUREATSEALEVEL[] PROGMEM =
|
||||
"<tr><th>%s " D_PRESSUREATSEALEVEL "</th><td>%s " D_UNIT_PRESSURE "</td></tr>";
|
||||
const char HTTP_SNS_LIGHT[] PROGMEM =
|
||||
"<tr><th>%s " D_LIGHT "</th><td>%d%</td></tr>";
|
||||
const char HTTP_SNS_NOISE[] PROGMEM =
|
||||
"<tr><th>%s " D_NOISE "</th><td>%d%</td></tr>";
|
||||
const char HTTP_SNS_DUST[] PROGMEM =
|
||||
"<tr><th>%s " D_AIR_QUALITY "</th><td>%d%</td></tr>";
|
||||
const char HTTP_END[] PROGMEM =
|
||||
"</div>"
|
||||
"</body>"
|
||||
@ -520,68 +507,23 @@ void HandleAjaxStatusRefresh()
|
||||
ExecuteCommand(svalue);
|
||||
}
|
||||
|
||||
String tpage = "";
|
||||
tpage += WebShowCounter();
|
||||
#ifndef USE_ADC_VCC
|
||||
if (pin[GPIO_ADC0] < 99) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("<tr><th>" D_ANALOG_INPUT0 "</th><td>%d</td></tr>"), GetAdc0());
|
||||
tpage += svalue;
|
||||
}
|
||||
#endif
|
||||
if (hlw_flg) {
|
||||
tpage += WebShowHlw();
|
||||
}
|
||||
if (SONOFF_SC == Settings.module) {
|
||||
tpage += WebShowSonoffSc();
|
||||
}
|
||||
#ifdef USE_DS18B20
|
||||
if (pin[GPIO_DSB] < 99) {
|
||||
tpage += WebShowDs18b20();
|
||||
}
|
||||
#endif // USE_DS18B20
|
||||
#ifdef USE_DS18x20
|
||||
if (pin[GPIO_DSB] < 99) {
|
||||
tpage += WebShowDs18x20();
|
||||
}
|
||||
#endif // USE_DS18x20
|
||||
#ifdef USE_DHT
|
||||
if (dht_flg) {
|
||||
tpage += WebShowDht();
|
||||
}
|
||||
#endif // USE_DHT
|
||||
#ifdef USE_I2C
|
||||
if (i2c_flg) {
|
||||
#ifdef USE_SHT
|
||||
tpage += WebShowSht();
|
||||
#endif
|
||||
#ifdef USE_HTU
|
||||
tpage += WebShowHtu();
|
||||
#endif
|
||||
#ifdef USE_BMP
|
||||
tpage += WebShowBmp();
|
||||
#endif
|
||||
#ifdef USE_BH1750
|
||||
tpage += WebShowBh1750();
|
||||
#endif
|
||||
#ifdef USE_VEML6070
|
||||
tpage += WebShowVeml6070();
|
||||
#endif
|
||||
}
|
||||
#endif // USE_I2C
|
||||
String page = "";
|
||||
if (tpage.length() > 0) {
|
||||
mqtt_data[0] = '\0';
|
||||
XsnsCall(FUNC_XSNS_WEB);
|
||||
if (strlen(mqtt_data)) {
|
||||
page += FPSTR(HTTP_TABLE100);
|
||||
page += tpage;
|
||||
page += mqtt_data;
|
||||
page += F("</table>");
|
||||
}
|
||||
char line[160];
|
||||
char line[80];
|
||||
if (devices_present) {
|
||||
page += FPSTR(HTTP_TABLE100);
|
||||
page += F("<tr>");
|
||||
uint8_t fsize = (devices_present < 5) ? 70 - (devices_present * 8) : 32;
|
||||
for (byte idx = 1; idx <= devices_present; idx++) {
|
||||
snprintf_P(svalue, sizeof(svalue), PSTR("%d"), bitRead(power, idx -1));
|
||||
snprintf_P(line, sizeof(line), PSTR("<td style='width:%d%'><div style='text-align:center;font-weight:%s;font-size:%dpx'>%s</div></td>"),
|
||||
// snprintf_P(line, sizeof(line), PSTR("<td style='width:%d%'><div style='text-align:center;font-weight:%s;font-size:%dpx'>%s</div></td>"),
|
||||
snprintf_P(line, sizeof(line), PSTR("<td style='width:%d{t}%s;font-size:%dpx'>%s</div></td>"), // {t} = %'><div style='text-align:center;font-weight:
|
||||
100 / devices_present, (bitRead(power, idx -1)) ? "bold" : "normal", fsize, (devices_present < 5) ? GetStateText(bitRead(power, idx -1)) : svalue);
|
||||
page += line;
|
||||
}
|
||||
@ -978,14 +920,14 @@ void HandleBackupConfiguration()
|
||||
uint8_t buffer[sizeof(Settings)];
|
||||
|
||||
WiFiClient myClient = WebServer->client();
|
||||
WebServer->setContentLength(4096);
|
||||
WebServer->setContentLength(sizeof(buffer));
|
||||
|
||||
char attachment[100];
|
||||
snprintf_P(attachment, sizeof(attachment), PSTR("attachment; filename=Config_%s_%s.dmp"),
|
||||
Settings.friendlyname[0], version);
|
||||
WebServer->sendHeader(F("Content-Disposition"), attachment);
|
||||
WebServer->send(200, FPSTR(HDR_CTYPE_STREAM), "");
|
||||
memcpy(buffer, &Settings, sizeof(Settings));
|
||||
memcpy(buffer, &Settings, sizeof(buffer));
|
||||
buffer[0] = CONFIG_FILE_SIGN;
|
||||
buffer[1] = (!CONFIG_FILE_XOR)?0:1;
|
||||
if (buffer[1]) {
|
||||
|
@ -899,7 +899,7 @@ boolean LightCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_le
|
||||
Settings.light_wakeup = payload;
|
||||
light_wakeup_active = 0;
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, Settings.light_wakeup);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), S_JSON_COMMAND_NVALUE, command, Settings.light_wakeup);
|
||||
}
|
||||
else if (CMND_UNDOCA == command_code) { // Theos legacy status
|
||||
LightGetColor(1, scolor);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Sonoff-Tasmota
|
||||
xsns_01_counter.ino - Counter sensors (water meters, electricity meters etc.) sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Maarten Damen and Theo Arends
|
||||
|
||||
@ -68,6 +68,8 @@ void CounterSaveState()
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void CounterInit()
|
||||
{
|
||||
typedef void (*function) () ;
|
||||
@ -81,57 +83,66 @@ void CounterInit()
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_COUNTER[] PROGMEM =
|
||||
"%s{s}" D_COUNTER "%d{m}%s%s{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void MqttShowCounter(uint8_t* djson)
|
||||
void CounterShow(boolean json)
|
||||
{
|
||||
char stemp[16];
|
||||
char counter[16];
|
||||
|
||||
byte dsxflg = 0;
|
||||
for (byte i = 0; i < MAX_COUNTERS; i++) {
|
||||
if (pin[GPIO_CNTR1 +i] < 99) {
|
||||
if (bitRead(Settings.pulse_counter_type, i)) {
|
||||
dtostrfd((double)RtcSettings.pulse_counter[i] / 1000, 3, stemp);
|
||||
dtostrfd((double)RtcSettings.pulse_counter[i] / 1000, 3, counter);
|
||||
} else {
|
||||
dsxflg++;
|
||||
dtostrfd(RtcSettings.pulse_counter[i], 0, stemp);
|
||||
dtostrfd(RtcSettings.pulse_counter[i], 0, counter);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_COUNTER "%d\":%s"), mqtt_data, i +1, stemp);
|
||||
*djson = 1;
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_COUNTER "%d\":%s"), mqtt_data, i +1, counter);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (1 == dsxflg) {
|
||||
DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]);
|
||||
dsxflg++;
|
||||
}
|
||||
if (1 == dsxflg) {
|
||||
DomoticzSensor(DZ_COUNT, RtcSettings.pulse_counter[i]);
|
||||
dsxflg++;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_COUNTER[] PROGMEM =
|
||||
"<tr><th>" D_COUNTER "%d</th><td>%s%s</td></tr>";
|
||||
|
||||
String WebShowCounter()
|
||||
{
|
||||
String page = "";
|
||||
char stemp[16];
|
||||
char sensor[80];
|
||||
|
||||
for (byte i = 0; i < MAX_COUNTERS; i++) {
|
||||
if (pin[GPIO_CNTR1 +i] < 99) {
|
||||
if (bitRead(Settings.pulse_counter_type, i)) {
|
||||
dtostrfi((double)RtcSettings.pulse_counter[i] / 1000, 3, stemp);
|
||||
} else {
|
||||
dtostrfi(RtcSettings.pulse_counter[i], 0, stemp);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_COUNTER, mqtt_data, i +1, counter, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : "");
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_COUNTER, i+1, stemp, (bitRead(Settings.pulse_counter_type, i)) ? " " D_UNIT_SECOND : "");
|
||||
page += sensor;
|
||||
}
|
||||
}
|
||||
return page;
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_01
|
||||
|
||||
boolean Xsns01(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
switch (function) {
|
||||
case FUNC_XSNS_INIT:
|
||||
CounterInit();
|
||||
break;
|
||||
// case FUNC_XSNS_PREP:
|
||||
// break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
CounterShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
CounterShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
return result;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_hlw8012.ino - sonoff pow HLW8012 energy sensor support for Sonoff-Tasmota
|
||||
xsns_03_hlw8012.ino - sonoff pow HLW8012 energy sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
@ -650,11 +650,20 @@ boolean HlwCommand(char *type, uint16_t index, char *dataBuf, uint16_t data_len,
|
||||
return serviced;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
void HlwMqttStat(byte option)
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_ENERGY_SNS[] PROGMEM =
|
||||
"{s}" D_VOLTAGE "{m}%s " D_UNIT_VOLT "{e}"
|
||||
"{s}" D_CURRENT "{m}%s " D_UNIT_AMPERE "{e}"
|
||||
"{s}" D_POWERUSAGE "{m}%s " D_UNIT_WATT "{e}"
|
||||
"{s}" D_POWER_FACTOR "{m}%s{e}"
|
||||
"{s}" D_ENERGY_TODAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
|
||||
"{s}" D_ENERGY_YESTERDAY "{m}%s " D_UNIT_KILOWATTHOUR "{e}"
|
||||
"{s}" D_ENERGY_TOTAL "{m}%s " D_UNIT_KILOWATTHOUR "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void HlwShow(boolean json, boolean option)
|
||||
{
|
||||
/* option 0 = do not show period energy usage
|
||||
* option 1 = show period energy usage
|
||||
@ -685,17 +694,24 @@ void HlwMqttStat(byte option)
|
||||
dtostrfd(current, 3, scurrent);
|
||||
dtostrfd(power_factor, 2, spower_factor);
|
||||
dtostrfd((float)Settings.hlw_kWhyesterday / 100000000, Settings.flag.energy_resolution, syesterday_energy);
|
||||
snprintf_P(speriod, sizeof(speriod), PSTR(", \"" D_PERIOD "\":%s"), senergy);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_TOTAL "\":%s, \"" D_YESTERDAY "\":%s, \"" D_TODAY "\":%s%s, \"" D_POWERUSAGE "\":%s, \"" D_POWERFACTOR "\":%s, \"" D_VOLTAGE "\":%s, \"" D_CURRENT "\":%s}"),
|
||||
mqtt_data, stotal_energy, syesterday_energy, sdaily_energy, (option) ? speriod : "", swatts, spower_factor, svoltage, scurrent);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(speriod, sizeof(speriod), PSTR(", \"" D_PERIOD "\":%s"), senergy);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s\"" D_TOTAL "\":%s, \"" D_YESTERDAY "\":%s, \"" D_TODAY "\":%s%s, \"" D_POWERUSAGE "\":%s, \"" D_POWERFACTOR "\":%s, \"" D_VOLTAGE "\":%s, \"" D_CURRENT "\":%s}"),
|
||||
mqtt_data, stotal_energy, syesterday_energy, sdaily_energy, (option) ? speriod : "", swatts, spower_factor, svoltage, scurrent);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (option) { // Only send if telemetry
|
||||
dtostrfd(total_energy * 1000, 1, stotal_energy);
|
||||
DomoticzSensorPowerEnergy((uint16_t)watts, stotal_energy); // PowerUsage, EnergyToday
|
||||
DomoticzSensor(DZ_VOLTAGE, svoltage); // Voltage
|
||||
DomoticzSensor(DZ_CURRENT, scurrent); // Current
|
||||
}
|
||||
if (option) { // Only send if telemetry
|
||||
dtostrfd(total_energy * 1000, 1, stotal_energy);
|
||||
DomoticzSensorPowerEnergy((uint16_t)watts, stotal_energy); // PowerUsage, EnergyToday
|
||||
DomoticzSensor(DZ_VOLTAGE, svoltage); // Voltage
|
||||
DomoticzSensor(DZ_CURRENT, scurrent); // Current
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_ENERGY_SNS, svoltage, scurrent, swatts, spower_factor, sdaily_energy, syesterday_energy, stotal_energy);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
void MqttShowHlw8012(byte option)
|
||||
@ -705,54 +721,45 @@ void MqttShowHlw8012(byte option)
|
||||
*/
|
||||
// {"Time":"2017-03-04T13:37:24", "Total":0.013, "Yesterday":0.013, "Today":0.000, "Period":0, "Power":0, "Factor":0.00, "Voltage":0, "Current":0.000}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_TIME "\":\"%s\", "), GetDateAndTime().c_str());
|
||||
HlwMqttStat(option);
|
||||
HlwShow(1, option);
|
||||
MqttPublishPrefixTopic_P(2, PSTR(D_RSLT_ENERGY), Settings.flag.mqtt_sensor_retain);
|
||||
}
|
||||
|
||||
void HlwMqttStatus()
|
||||
{
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("{\"" D_CMND_STATUS D_STATUS8_POWER "\":{"));
|
||||
HlwMqttStat(0);
|
||||
HlwShow(1, 0);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_ENERGY_SNS[] PROGMEM =
|
||||
"<tr><th>" D_VOLTAGE "</th><td>%s " D_UNIT_VOLT "</td></tr>"
|
||||
"<tr><th>" D_CURRENT "</th><td>%s " D_UNIT_AMPERE "</td></tr>"
|
||||
"<tr><th>" D_POWERUSAGE "</th><td>%s " D_UNIT_WATT "</td></tr>"
|
||||
"<tr><th>" D_POWER_FACTOR "</th><td>%s</td></tr>"
|
||||
"<tr><th>" D_ENERGY_TODAY "</th><td>%s " D_UNIT_KILOWATTHOUR "</td></tr>"
|
||||
"<tr><th>" D_ENERGY_YESTERDAY "</th><td>%s " D_UNIT_KILOWATTHOUR "</td></tr>"
|
||||
"<tr><th>" D_ENERGY_TOTAL "</th><td>%s " D_UNIT_KILOWATTHOUR "</td></tr>";
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
String WebShowHlw()
|
||||
#define XSNS_03
|
||||
|
||||
boolean Xsns03(byte function)
|
||||
{
|
||||
float total_energy;
|
||||
float daily_energy;
|
||||
float energy;
|
||||
float watts;
|
||||
float voltage;
|
||||
float current;
|
||||
float power_factor;
|
||||
char stotal_energy[10];
|
||||
char sdaily_energy[10];
|
||||
char swatts[10];
|
||||
char svoltage[10];
|
||||
char scurrent[10];
|
||||
char spower_factor[10];
|
||||
char syesterday_energy[10];
|
||||
char sensor[400];
|
||||
boolean result = false;
|
||||
|
||||
HlwReadEnergy(0, total_energy, daily_energy, energy, watts, voltage, current, power_factor);
|
||||
dtostrfi(total_energy, Settings.flag.energy_resolution, stotal_energy);
|
||||
dtostrfi(daily_energy, Settings.flag.energy_resolution, sdaily_energy);
|
||||
dtostrfi(watts, Settings.flag.wattage_resolution, swatts);
|
||||
dtostrfi(voltage, Settings.flag.voltage_resolution, svoltage);
|
||||
dtostrfi(current, 3, scurrent);
|
||||
dtostrfi(power_factor, 2, spower_factor);
|
||||
dtostrfi((float)Settings.hlw_kWhyesterday / 100000000, Settings.flag.energy_resolution, syesterday_energy);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_ENERGY_SNS, svoltage, scurrent, swatts, spower_factor, sdaily_energy, syesterday_energy, stotal_energy);
|
||||
return String(sensor);
|
||||
}
|
||||
if (hlw_flg) {
|
||||
switch (function) {
|
||||
case FUNC_XSNS_INIT:
|
||||
HlwInit();
|
||||
break;
|
||||
// case FUNC_XSNS_PREP:
|
||||
// break;
|
||||
// case FUNC_XSNS_JSON_APPEND:
|
||||
// break;
|
||||
case FUNC_XSNS_MQTT_SHOW:
|
||||
MqttShowHlw8012(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
HlwShow(0, 0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xdrv_snfsc.ino - sonoff SC support for Sonoff-Tasmota
|
||||
xsns_04_snfsc.ino - sonoff SC support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
@ -101,56 +101,66 @@ void SonoffScSerialInput(char *rcvstat)
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MqttShowSonoffSC(uint8_t* djson)
|
||||
{
|
||||
if (sc_value[0] > 0) {
|
||||
char stemp1[10];
|
||||
char stemp2[10];
|
||||
|
||||
float t = ConvertTemp(sc_value[1]);
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, stemp1);
|
||||
float h = sc_value[0];
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, stemp2);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_LIGHT "\":%d, \"" D_NOISE "\":%d, \"" D_AIRQUALITY "\":%d"),
|
||||
mqtt_data, stemp1, stemp2, sc_value[2], sc_value[3], sc_value[4]);
|
||||
*djson = 1;
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(stemp1, stemp2);
|
||||
DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
}
|
||||
/********************************************************************************************/
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
String WebShowSonoffSc()
|
||||
{
|
||||
String page = "";
|
||||
|
||||
if (sc_value[0] > 0) {
|
||||
char stemp[10];
|
||||
char sensor[80];
|
||||
char scstype[] = "";
|
||||
|
||||
float t = ConvertTemp(sc_value[1]);
|
||||
dtostrfi(t, Settings.flag.temperature_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, scstype, stemp, TempUnit());
|
||||
page += sensor;
|
||||
float h = sc_value[0];
|
||||
dtostrfi(h, Settings.flag.humidity_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, scstype, stemp);
|
||||
page += sensor;
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_LIGHT, scstype, sc_value[2]);
|
||||
page += sensor;
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_NOISE, scstype, sc_value[3]);
|
||||
page += sensor;
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_DUST, scstype, sc_value[4]);
|
||||
page += sensor;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
const char HTTP_SNS_SCPLUS[] PROGMEM =
|
||||
"%s{s}" D_LIGHT "{m}%d%{e}{s}" D_NOISE "{m}%d%{e}{s}" D_AIR_QUALITY "{m}%d%{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void SonoffScShow(boolean json)
|
||||
{
|
||||
if (sc_value[0] > 0) {
|
||||
char temperature[10];
|
||||
char humidity[10];
|
||||
|
||||
float t = ConvertTemp(sc_value[1]);
|
||||
float h = sc_value[0];
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, temperature);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, humidity);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_LIGHT "\":%d, \"" D_NOISE "\":%d, \"" D_AIRQUALITY "\":%d"),
|
||||
mqtt_data, temperature, humidity, sc_value[2], sc_value[3], sc_value[4]);
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
DomoticzSensor(DZ_ILLUMINANCE, sc_value[2]);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "", temperature, TempUnit());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "", humidity);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SCPLUS, mqtt_data, sc_value[2], sc_value[3], sc_value[4]);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_04
|
||||
|
||||
boolean Xsns04(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (SONOFF_SC == Settings.module) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
// case FUNC_XSNS_PREP:
|
||||
// break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
SonoffScShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
SonoffScShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_ds18b20.ino - DS18B20 temperature sensor support for Sonoff-Tasmota
|
||||
xsns_05_ds18b20.ino - DS18B20 temperature sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
@ -181,42 +181,63 @@ boolean Ds18b20ReadTemperature(float &t)
|
||||
return !isnan(t);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
void MqttShowDs18b20(uint8_t* djson)
|
||||
void Ds18b20Show(boolean json)
|
||||
{
|
||||
char stemp1[10];
|
||||
float t;
|
||||
|
||||
if (Ds18b20ReadTemperature(t)) { // Check if read failed
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, stemp1);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18B20\":{\"" D_TEMPERATURE "\":%s}"), mqtt_data, stemp1);
|
||||
*djson = 1;
|
||||
char temperature[10];
|
||||
|
||||
dtostrfi(t, Settings.flag.temperature_resolution, temperature);
|
||||
|
||||
if(json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18B20\":{\"" D_TEMPERATURE "\":%s}"), mqtt_data, temperature);
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_TEMP, stemp1);
|
||||
DomoticzSensor(DZ_TEMP, temperature);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
String WebShowDs18b20()
|
||||
{
|
||||
// Needs TelePeriod to refresh data (Do not do it here as it takes too much time)
|
||||
String page = "";
|
||||
float st;
|
||||
|
||||
if (Ds18b20ReadTemperature(st)) { // Check if read failed
|
||||
char stemp[10];
|
||||
char sensor[80];
|
||||
|
||||
dtostrfi(st, Settings.flag.temperature_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "DS18B20", stemp, TempUnit());
|
||||
page += sensor;
|
||||
}
|
||||
Ds18b20ReadTempPrep();
|
||||
return page;
|
||||
}
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "DS18B20", temperature, TempUnit());
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
if (!json) {
|
||||
Ds18b20ReadTempPrep();
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_05
|
||||
|
||||
boolean Xsns05(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (pin[GPIO_DSB] < 99) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
case FUNC_XSNS_PREP:
|
||||
Ds18b20ReadTempPrep();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
Ds18b20Show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
Ds18b20Show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DS18B20
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_ds18x20.ino - DS18x20 temperature sensor support for Sonoff-Tasmota
|
||||
xsns_05_ds18x20.ino - DS18x20 temperature sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Heiko Krupp and Theo Arends
|
||||
|
||||
@ -143,79 +143,100 @@ boolean Ds18x20Read(uint8_t sensor, float &t)
|
||||
return (!isnan(t));
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
/********************************************************************************************/
|
||||
|
||||
void Ds18x20Type(uint8_t sensor)
|
||||
{
|
||||
strcpy_P(ds18x20_types, PSTR("DS18x20"));
|
||||
switch(ds18x20_address[ds18x20_index[sensor]][0]) {
|
||||
case DS18S20_CHIPID:
|
||||
strcpy_P(ds18x20_types, PSTR("DS18S20"));
|
||||
break;
|
||||
case DS18B20_CHIPID:
|
||||
strcpy_P(ds18x20_types, PSTR("DS18B20"));
|
||||
break;
|
||||
case MAX31850_CHIPID:
|
||||
strcpy_P(ds18x20_types, PSTR("MAX31850"));
|
||||
break;
|
||||
case DS18S20_CHIPID:
|
||||
strcpy_P(ds18x20_types, PSTR("DS18S20"));
|
||||
break;
|
||||
case DS18B20_CHIPID:
|
||||
strcpy_P(ds18x20_types, PSTR("DS18B20"));
|
||||
break;
|
||||
case MAX31850_CHIPID:
|
||||
strcpy_P(ds18x20_types, PSTR("MAX31850"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MqttShowDs18x20(uint8_t* djson)
|
||||
void Ds18x20Show(boolean json)
|
||||
{
|
||||
char stemp1[10];
|
||||
char stemp2[10];
|
||||
char temperature[10];
|
||||
char stemp[10];
|
||||
float t;
|
||||
|
||||
byte dsxflg = 0;
|
||||
for (byte i = 0; i < Ds18x20Sensors(); i++) {
|
||||
if (Ds18x20Read(i, t)) { // Check if read failed
|
||||
Ds18x20Type(i);
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, stemp2);
|
||||
if (!dsxflg) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18x20\":{"), mqtt_data);
|
||||
*djson = 1;
|
||||
stemp1[0] = '\0';
|
||||
}
|
||||
dsxflg++;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_TYPE "\":\"%s\", \"" D_ADDRESS "\":\"%s\", \"" D_TEMPERATURE "\":%s}"),
|
||||
mqtt_data, stemp1, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), stemp2);
|
||||
strcpy(stemp1, ", ");
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, temperature);
|
||||
|
||||
if (json) {
|
||||
if (!dsxflg) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"DS18x20\":{"), mqtt_data);
|
||||
stemp[0] = '\0';
|
||||
}
|
||||
dsxflg++;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"DS%d\":{\"" D_TYPE "\":\"%s\", \"" D_ADDRESS "\":\"%s\", \"" D_TEMPERATURE "\":%s}"),
|
||||
mqtt_data, stemp, i +1, ds18x20_types, Ds18x20Addresses(i).c_str(), temperature);
|
||||
strcpy(stemp, ", ");
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (1 == dsxflg) {
|
||||
DomoticzSensor(DZ_TEMP, stemp2);
|
||||
}
|
||||
if (1 == dsxflg) {
|
||||
DomoticzSensor(DZ_TEMP, temperature);
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
}
|
||||
if (dsxflg) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
String WebShowDs18x20()
|
||||
{
|
||||
String page = "";
|
||||
char stemp[10];
|
||||
char stemp2[16];
|
||||
char sensor[80];
|
||||
float t;
|
||||
|
||||
for (byte i = 0; i < Ds18x20Sensors(); i++) {
|
||||
if (Ds18x20Read(i, t)) { // Check if read failed
|
||||
Ds18x20Type(i);
|
||||
dtostrfi(t, Settings.flag.temperature_resolution, stemp);
|
||||
snprintf_P(stemp2, sizeof(stemp2), PSTR("%s-%d"), ds18x20_types, i +1);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, stemp2, stemp, TempUnit());
|
||||
page += sensor;
|
||||
} else {
|
||||
snprintf_P(stemp, sizeof(stemp), PSTR("%s-%d"), ds18x20_types, i +1);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, stemp, temperature, TempUnit());
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
Ds18x20Search(); // Check for changes in sensors number
|
||||
Ds18x20Convert(); // Start Conversion, takes up to one second
|
||||
return page;
|
||||
}
|
||||
if (json) {
|
||||
if (dsxflg) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
Ds18x20Search(); // Check for changes in sensors number
|
||||
Ds18x20Convert(); // Start Conversion, takes up to one second
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_05
|
||||
|
||||
boolean Xsns05(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (pin[GPIO_DSB] < 99) {
|
||||
switch (function) {
|
||||
case FUNC_XSNS_INIT:
|
||||
Ds18x20Init();
|
||||
break;
|
||||
case FUNC_XSNS_PREP:
|
||||
Ds18x20Search(); // Check for changes in sensors number
|
||||
Ds18x20Convert(); // Start Conversion, takes up to one second
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
Ds18x20Show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
Ds18x20Show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DS18x20
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_dht.ino - DHTxx and AM23xx temperature and humidity sensor support for Sonoff-Tasmota
|
||||
xsns_06_dht.ino - DHTxx and AM23xx temperature and humidity sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
@ -194,6 +194,8 @@ boolean DhtSetup(byte pin, byte type)
|
||||
return success;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
void DhtInit()
|
||||
{
|
||||
dht_max_cycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for reading pulses from DHT sensor.
|
||||
@ -218,54 +220,66 @@ void DhtInit()
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MqttShowDht(uint8_t* djson)
|
||||
void DhtShow(boolean json)
|
||||
{
|
||||
char stemp1[10];
|
||||
char stemp2[10];
|
||||
char temperature[10];
|
||||
char humidity[10];
|
||||
float t;
|
||||
float h;
|
||||
|
||||
byte dsxflg = 0;
|
||||
for (byte i = 0; i < dht_sensors; i++) {
|
||||
if (DhtReadTempHum(i, t, h)) { // Read temperature
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, stemp1);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, stemp2);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, stemp1, stemp2);
|
||||
*djson = 1;
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, temperature);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, humidity);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, Dht[i].stype, temperature, humidity);
|
||||
#ifdef USE_DOMOTICZ
|
||||
if (!dsxflg) {
|
||||
DomoticzTempHumSensor(stemp1, stemp2);
|
||||
dsxflg++;
|
||||
}
|
||||
if (!dsxflg) {
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
dsxflg++;
|
||||
}
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
String WebShowDht()
|
||||
{
|
||||
String page = "";
|
||||
char stemp[10];
|
||||
char sensor[80];
|
||||
float t;
|
||||
float h;
|
||||
|
||||
for (byte i = 0; i < dht_sensors; i++) {
|
||||
if (DhtReadTempHum(i, t, h)) {
|
||||
dtostrfi(t, Settings.flag.temperature_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, Dht[i].stype, stemp, TempUnit());
|
||||
page += sensor;
|
||||
dtostrfi(h, Settings.flag.humidity_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, Dht[i].stype, stemp);
|
||||
page += sensor;
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, Dht[i].stype, temperature, TempUnit());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, Dht[i].stype, humidity);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_06
|
||||
|
||||
boolean Xsns06(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (dht_flg) {
|
||||
switch (function) {
|
||||
case FUNC_XSNS_INIT:
|
||||
DhtInit();
|
||||
break;
|
||||
case FUNC_XSNS_PREP:
|
||||
DhtReadPrep();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
DhtShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
DhtShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_DHT
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota
|
||||
xsns_07_sht1x.ino - SHT1x temperature and sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
@ -159,6 +159,8 @@ boolean ShtReadTempHum(float &t, float &h)
|
||||
return (!isnan(t) && !isnan(h));
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
boolean ShtDetect()
|
||||
{
|
||||
if (sht_type) {
|
||||
@ -180,56 +182,63 @@ boolean ShtDetect()
|
||||
return sht_type;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MqttShowSht(uint8_t* djson)
|
||||
void ShtShow(boolean json)
|
||||
{
|
||||
if (!sht_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
float t;
|
||||
float h;
|
||||
|
||||
if (ShtReadTempHum(t, h)) {
|
||||
char stemp[10];
|
||||
char shum[10];
|
||||
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, stemp);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, shum);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, "SHT1X", stemp, shum);
|
||||
*djson = 1;
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(stemp, shum);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
String WebShowSht()
|
||||
{
|
||||
float t;
|
||||
float h;
|
||||
|
||||
String page = "";
|
||||
if (sht_type) {
|
||||
if (ShtReadTempHum(t, h)) {
|
||||
char stemp[10];
|
||||
char shum[10];
|
||||
char sensor[80];
|
||||
float t;
|
||||
float h;
|
||||
|
||||
dtostrfi(t, Settings.flag.temperature_resolution, stemp);
|
||||
dtostrfi(h, Settings.flag.humidity_resolution, shum);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, "SHT1X", stemp, TempUnit());
|
||||
page += sensor;
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, "SHT1X", shum);
|
||||
page += sensor;
|
||||
if (ShtReadTempHum(t, h)) {
|
||||
char temperature[10];
|
||||
char humidity[10];
|
||||
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, temperature);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, humidity);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, "SHT1X", temperature, humidity);
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, "SHT1X", temperature, TempUnit());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, "SHT1X", humidity);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_07
|
||||
|
||||
boolean Xsns07(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
case FUNC_XSNS_PREP:
|
||||
ShtDetect();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
ShtShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
ShtShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_SHT
|
||||
#endif // USE_I2C
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_htu21.ino - HTU21 temperature and humidity sensor support for Sonoff-Tasmota
|
||||
xsns_08_htu21.ino - HTU21 temperature and humidity sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Heiko Krupp and Theo Arends
|
||||
|
||||
@ -205,6 +205,8 @@ float HtuCompensatedHumidity(float humidity, float temperature)
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
uint8_t HtuDetect()
|
||||
{
|
||||
if (htu_type) {
|
||||
@ -243,7 +245,7 @@ uint8_t HtuDetect()
|
||||
delay_humidity=23;
|
||||
}
|
||||
if (success) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), htu_types, htu_address);
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, htu_types, htu_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
} else {
|
||||
htu_type = 0;
|
||||
@ -251,52 +253,62 @@ uint8_t HtuDetect()
|
||||
return success;
|
||||
}
|
||||
|
||||
void HtuShow(boolean json)
|
||||
{
|
||||
if (htu_type) {
|
||||
char temperature[10];
|
||||
char humidity[10];
|
||||
|
||||
float t = HtuReadTemperature();
|
||||
float h = HtuReadHumidity();
|
||||
h = HtuCompensatedHumidity(h, t);
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, temperature);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, humidity);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, temperature, humidity);
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(temperature, humidity);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, htu_types, temperature, TempUnit());
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, htu_types, humidity);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MqttShowHtu(uint8_t* djson)
|
||||
#define XSNS_08
|
||||
|
||||
boolean Xsns08(byte function)
|
||||
{
|
||||
if (!htu_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
char stemp1[10];
|
||||
char stemp2[10];
|
||||
|
||||
float t = HtuReadTemperature();
|
||||
float h = HtuReadHumidity();
|
||||
h = HtuCompensatedHumidity(h, t);
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, stemp1);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, stemp2);
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), JSON_SNS_TEMPHUM, mqtt_data, htu_types, stemp1, stemp2);
|
||||
*djson = 1;
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumSensor(stemp1, stemp2);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
case FUNC_XSNS_PREP:
|
||||
HtuDetect();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
HtuShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
String WebShowHtu()
|
||||
{
|
||||
String page = "";
|
||||
if (htu_type) {
|
||||
char stemp[10];
|
||||
char sensor[80];
|
||||
|
||||
float t_htu21 = HtuReadTemperature();
|
||||
float h_htu21 = HtuReadHumidity();
|
||||
h_htu21 = HtuCompensatedHumidity(h_htu21, t_htu21);
|
||||
dtostrfi(t_htu21, Settings.flag.temperature_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, htu_types, stemp, TempUnit());
|
||||
page += sensor;
|
||||
dtostrfi(h_htu21, Settings.flag.humidity_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, htu_types, stemp);
|
||||
page += sensor;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
case FUNC_XSNS_WEB:
|
||||
HtuShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_HTU
|
||||
#endif // USE_I2C
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_bmp.ino - BMP pressure, temperature and humidity sensor support for Sonoff-Tasmota
|
||||
xsns_09_bmp.ino - BMP pressure, temperature and humidity sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Heiko Krupp and Theo Arends
|
||||
|
||||
@ -369,6 +369,8 @@ double BmpReadHumidity(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
boolean BmpDetect()
|
||||
{
|
||||
if (bmp_type) {
|
||||
@ -398,7 +400,7 @@ boolean BmpDetect()
|
||||
strcpy_P(bmp_types, PSTR("BME280"));
|
||||
}
|
||||
if (success) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), bmp_types, bmp_address);
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, bmp_types, bmp_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
else {
|
||||
@ -407,75 +409,80 @@ boolean BmpDetect()
|
||||
return success;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MqttShowBmp(uint8_t *djson)
|
||||
void BmpShow(boolean json)
|
||||
{
|
||||
if (!bmp_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
char temperature[10];
|
||||
char pressure[10];
|
||||
char humidity[10];
|
||||
char sea_pressure[10];
|
||||
char sealevel[40];
|
||||
|
||||
double t = BmpReadTemperature();
|
||||
double p = BmpReadPressure();
|
||||
double h = BmpReadHumidity();
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, temperature);
|
||||
dtostrfd(p, Settings.flag.pressure_resolution, pressure);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, humidity);
|
||||
|
||||
dtostrfd(bmp_sealevel, Settings.flag.pressure_resolution, sea_pressure);
|
||||
snprintf_P(sealevel, sizeof(sealevel), PSTR(", \"" D_PRESSUREATSEALEVEL "\":%s"), sea_pressure);
|
||||
if (BME280_CHIPID == bmp_type) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_PRESSURE "\":%s%s}"),
|
||||
mqtt_data, bmp_types, temperature, humidity, pressure, (Settings.altitude != 0) ? sealevel : "");
|
||||
}
|
||||
else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_PRESSURE "\":%s%s}"),
|
||||
mqtt_data, bmp_types, temperature, pressure, (Settings.altitude != 0) ? sealevel : "");
|
||||
}
|
||||
*djson = 1;
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumPressureSensor(temperature, humidity, pressure);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
String WebShowBmp()
|
||||
{
|
||||
String page = "";
|
||||
if (bmp_type) {
|
||||
char stemp[10];
|
||||
char sensor[80];
|
||||
char temperature[10];
|
||||
char pressure[10];
|
||||
char humidity[10];
|
||||
char sea_pressure[10];
|
||||
char sealevel[40];
|
||||
|
||||
double t = BmpReadTemperature();
|
||||
double p = BmpReadPressure();
|
||||
double h = BmpReadHumidity();
|
||||
dtostrfi(t, Settings.flag.temperature_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_TEMP, bmp_types, stemp, TempUnit());
|
||||
page += sensor;
|
||||
if (BME280_CHIPID == bmp_type) {
|
||||
dtostrfi(h, Settings.flag.humidity_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_HUM, bmp_types, stemp);
|
||||
page += sensor;
|
||||
}
|
||||
dtostrfi(p, Settings.flag.pressure_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSURE, bmp_types, stemp);
|
||||
page += sensor;
|
||||
if (Settings.altitude != 0) {
|
||||
dtostrfi(bmp_sealevel, Settings.flag.pressure_resolution, stemp);
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_PRESSUREATSEALEVEL, bmp_types, stemp);
|
||||
page += sensor;
|
||||
dtostrfd(t, Settings.flag.temperature_resolution, temperature);
|
||||
dtostrfd(p, Settings.flag.pressure_resolution, pressure);
|
||||
dtostrfd(h, Settings.flag.humidity_resolution, humidity);
|
||||
dtostrfd(bmp_sealevel, Settings.flag.pressure_resolution, sea_pressure);
|
||||
|
||||
if (json) {
|
||||
snprintf_P(sealevel, sizeof(sealevel), PSTR(", \"" D_PRESSUREATSEALEVEL "\":%s"), sea_pressure);
|
||||
if (BME280_CHIPID == bmp_type) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_HUMIDITY "\":%s, \"" D_PRESSURE "\":%s%s}"),
|
||||
mqtt_data, bmp_types, temperature, humidity, pressure, (Settings.altitude != 0) ? sealevel : "");
|
||||
}
|
||||
else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_TEMPERATURE "\":%s, \"" D_PRESSURE "\":%s%s}"),
|
||||
mqtt_data, bmp_types, temperature, pressure, (Settings.altitude != 0) ? sealevel : "");
|
||||
}
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzTempHumPressureSensor(temperature, humidity, pressure);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_TEMP, mqtt_data, bmp_types, temperature, TempUnit());
|
||||
if (BME280_CHIPID == bmp_type) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_HUM, mqtt_data, bmp_types, humidity);
|
||||
}
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_PRESSURE, mqtt_data, bmp_types, pressure);
|
||||
if (Settings.altitude != 0) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_SEAPRESSURE, mqtt_data, bmp_types, sea_pressure);
|
||||
}
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return page;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_09
|
||||
|
||||
boolean Xsns09(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
case FUNC_XSNS_PREP:
|
||||
BmpDetect();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
BmpShow(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
BmpShow(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_BMP
|
||||
#endif // USE_I2C
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_bh1750.ino - BH1750 ambient light sensor support for Sonoff-Tasmota
|
||||
xsns_10_bh1750.ino - BH1750 ambient light sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
@ -30,7 +30,6 @@
|
||||
|
||||
uint8_t bh1750_address;
|
||||
uint8_t bh1750_type = 0;
|
||||
char bh1750_types[7];
|
||||
|
||||
uint16_t Bh1750ReadLux()
|
||||
{
|
||||
@ -41,6 +40,8 @@ uint16_t Bh1750ReadLux()
|
||||
return value;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
boolean Bh1750Detect()
|
||||
{
|
||||
if (bh1750_type) {
|
||||
@ -63,10 +64,9 @@ boolean Bh1750Detect()
|
||||
if (!status) {
|
||||
success = true;
|
||||
bh1750_type = 1;
|
||||
strcpy_P(bh1750_types, PSTR("BH1750"));
|
||||
}
|
||||
if (success) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), bh1750_types, bh1750_address);
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "BH1750", bh1750_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
} else {
|
||||
bh1750_type = 0;
|
||||
@ -74,39 +74,58 @@ boolean Bh1750Detect()
|
||||
return success;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MqttShowBh1750(uint8_t* djson)
|
||||
{
|
||||
if (!bh1750_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t l = Bh1750ReadLux();
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_ILLUMINANCE "\":%d}"), mqtt_data, bh1750_types, l);
|
||||
*djson = 1;
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_ILLUMINANCE, l);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_ILLUMINANCE[] PROGMEM =
|
||||
"<tr><th>BH1750 " D_ILLUMINANCE "</th><td>%d " D_UNIT_LUX "</td></tr>";
|
||||
|
||||
String WebShowBh1750()
|
||||
{
|
||||
String page = "";
|
||||
if (bh1750_type) {
|
||||
char sensor[80];
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ILLUMINANCE, Bh1750ReadLux());
|
||||
page += sensor;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
"%s{s}BH1750 " D_ILLUMINANCE "{m}%d " D_UNIT_LUX "{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void Bh1750Show(boolean json)
|
||||
{
|
||||
if (bh1750_type) {
|
||||
uint16_t illuminance = Bh1750ReadLux();
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"BH1750\":{\"" D_ILLUMINANCE "\":%d}"), mqtt_data, illuminance);
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_ILLUMINANCE, illuminance);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ILLUMINANCE, mqtt_data, illuminance);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_10
|
||||
|
||||
boolean Xsns10(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
case FUNC_XSNS_PREP:
|
||||
Bh1750Detect();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
Bh1750Show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
Bh1750Show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_BH1750
|
||||
#endif // USE_I2C
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
xsns_veml6070.ino - VEML6070 ultra violet light sensor support for Sonoff-Tasmota
|
||||
xsns_11_veml6070.ino - VEML6070 ultra violet light sensor support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends
|
||||
|
||||
@ -44,9 +44,11 @@ uint16_t Veml6070ReadUv()
|
||||
}
|
||||
uvi |= Wire.read();
|
||||
|
||||
return uvi;
|
||||
return uvi;
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
boolean Veml6070Detect()
|
||||
{
|
||||
if (veml6070_type) {
|
||||
@ -67,7 +69,7 @@ boolean Veml6070Detect()
|
||||
strcpy_P(veml6070_types, PSTR("VEML6070"));
|
||||
}
|
||||
if (success) {
|
||||
snprintf_P(log_data, sizeof(log_data), PSTR(D_LOG_I2C "%s " D_FOUND_AT " 0x%x"), veml6070_types, veml6070_address);
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, veml6070_types, veml6070_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
} else {
|
||||
veml6070_type = 0;
|
||||
@ -75,39 +77,59 @@ boolean Veml6070Detect()
|
||||
return success;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Presentation
|
||||
\*********************************************************************************************/
|
||||
|
||||
void MqttShowVeml6070(uint8_t* djson)
|
||||
{
|
||||
if (!veml6070_type) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t uv = Veml6070ReadUv();
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_UV_LEVEL "\":%d}"), mqtt_data, veml6070_types, uv);
|
||||
*djson = 1;
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_ILLUMINANCE, uv);
|
||||
#endif // USE_DOMOTICZ
|
||||
}
|
||||
|
||||
#ifdef USE_WEBSERVER
|
||||
const char HTTP_SNS_ULTRAVIOLET[] PROGMEM =
|
||||
"<tr><th>VEML6070 " D_UV_LEVEL "</th><td>%d</td></tr>";
|
||||
|
||||
String WebShowVeml6070()
|
||||
{
|
||||
String page = "";
|
||||
if (veml6070_type) {
|
||||
char sensor[80];
|
||||
snprintf_P(sensor, sizeof(sensor), HTTP_SNS_ULTRAVIOLET, Veml6070ReadUv());
|
||||
page += sensor;
|
||||
}
|
||||
return page;
|
||||
}
|
||||
"%s{s}VEML6070 " D_UV_LEVEL "{m}%d{e}"; // {s} = <tr><th>, {m} = </th><td>, {e} = </td></tr>
|
||||
#endif // USE_WEBSERVER
|
||||
|
||||
void Veml6070Show(boolean json)
|
||||
{
|
||||
if (veml6070_type) {
|
||||
uint16_t uvlevel = Veml6070ReadUv();
|
||||
|
||||
if (json) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"%s\":{\"" D_UV_LEVEL "\":%d}"), mqtt_data, veml6070_types, uvlevel);
|
||||
#ifdef USE_DOMOTICZ
|
||||
DomoticzSensor(DZ_ILLUMINANCE, uvlevel);
|
||||
#endif // USE_DOMOTICZ
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ULTRAVIOLET, mqtt_data, uvlevel);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_11
|
||||
|
||||
boolean Xsns11(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
case FUNC_XSNS_PREP:
|
||||
Veml6070Detect();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
Veml6070Show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
Veml6070Show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_VEML6070
|
||||
#endif // USE_I2C
|
||||
|
166
sonoff/xsns_12_ads1115.ino
Normal file
166
sonoff/xsns_12_ads1115.ino
Normal file
@ -0,0 +1,166 @@
|
||||
/*
|
||||
xsns_12_ads1115.ino - ADS1x15 A/D Converter support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Stefan Bode and Theo Arends
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_I2C
|
||||
#ifdef USE_ADS1115
|
||||
/*********************************************************************************************\
|
||||
* ADS1115 - 4 channel 16BIT A/D converter
|
||||
*
|
||||
* Required library: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/ADS1115
|
||||
*
|
||||
* The ADC input range (or gain) can be changed via the following
|
||||
* functions, but be careful never to exceed VDD +0.3V max, or to
|
||||
* exceed the upper and lower limits if you adjust the input range!
|
||||
* Setting these values incorrectly may destroy your ADC!
|
||||
* ADS1015 ADS1115
|
||||
* ------- -------
|
||||
* ads.setGain(GAIN_TWOTHIRDS); // 2/3x gain +/- 6.144V 1 bit = 3mV 0.1875mV (default)
|
||||
* ads.setGain(GAIN_ONE); // 1x gain +/- 4.096V 1 bit = 2mV 0.125mV
|
||||
* ads.setGain(GAIN_TWO); // 2x gain +/- 2.048V 1 bit = 1mV 0.0625mV
|
||||
* ads.setGain(GAIN_FOUR); // 4x gain +/- 1.024V 1 bit = 0.5mV 0.03125mV
|
||||
* ads.setGain(GAIN_EIGHT); // 8x gain +/- 0.512V 1 bit = 0.25mV 0.015625mV
|
||||
* ads.setGain(GAIN_SIXTEEN); // 16x gain +/- 0.256V 1 bit = 0.125mV 0.0078125mV
|
||||
\*********************************************************************************************/
|
||||
|
||||
#include <ADS1115.h>
|
||||
|
||||
ADS1115 adc0;
|
||||
|
||||
uint8_t ads1115_address;
|
||||
uint8_t ads1115_type = 0;
|
||||
|
||||
uint8_t ads1115_addresses[] = {
|
||||
ADS1115_ADDRESS_ADDR_GND, // address pin low (GND)
|
||||
ADS1115_ADDRESS_ADDR_VDD, // address pin high (VCC)
|
||||
ADS1115_ADDRESS_ADDR_SDA, // address pin tied to SDA pin
|
||||
ADS1115_ADDRESS_ADDR_SCL // address pin tied to SCL pin
|
||||
};
|
||||
|
||||
int16_t Ads1115GetConversion(byte channel)
|
||||
{
|
||||
switch (channel) {
|
||||
case 0:
|
||||
adc0.getConversionP0GND();
|
||||
break;
|
||||
case 1:
|
||||
adc0.getConversionP1GND();
|
||||
break;
|
||||
case 2:
|
||||
adc0.getConversionP2GND();
|
||||
break;
|
||||
case 3:
|
||||
adc0.getConversionP3GND();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/********************************************************************************************/
|
||||
|
||||
boolean Ads1115Detect()
|
||||
{
|
||||
if (ads1115_type) {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t status;
|
||||
boolean success = false;
|
||||
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
ads1115_address = ads1115_addresses[i];
|
||||
ADS1115 adc0(ads1115_address);
|
||||
if (adc0.testConnection()) {
|
||||
adc0.initialize();
|
||||
adc0.setGain(ADS1115_PGA_2P048); // Set the gain (PGA) +/-4.096V
|
||||
adc0.setRate(ADS1115_RATE_860);
|
||||
adc0.setMode(ADS1115_MODE_CONTINUOUS);
|
||||
success = true;
|
||||
ads1115_type = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (success) {
|
||||
snprintf_P(log_data, sizeof(log_data), S_LOG_I2C_FOUND_AT, "ADS1115", ads1115_address);
|
||||
AddLog(LOG_LEVEL_DEBUG);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void Ads1115Show(boolean json)
|
||||
{
|
||||
if (ads1115_type) {
|
||||
char stemp[10];
|
||||
|
||||
byte dsxflg = 0;
|
||||
for (byte i = 0; i < 4; i++) {
|
||||
int16_t adc_value = Ads1115GetConversion(i);
|
||||
|
||||
if (json) {
|
||||
if (!dsxflg ) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s, \"ADS1115\":{"), mqtt_data);
|
||||
stemp[0] = '\0';
|
||||
}
|
||||
dsxflg++;
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s%s\"" D_ANALOG_INPUT "%d\":%d"), mqtt_data, stemp, i, adc_value);
|
||||
strcpy(stemp, ", ");
|
||||
#ifdef USE_WEBSERVER
|
||||
} else {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), HTTP_SNS_ANALOG, mqtt_data, "ADS1115", i, adc_value);
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
if (json) {
|
||||
if (dsxflg) {
|
||||
snprintf_P(mqtt_data, sizeof(mqtt_data), PSTR("%s}"), mqtt_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Interface
|
||||
\*********************************************************************************************/
|
||||
|
||||
#define XSNS_12
|
||||
|
||||
boolean Xsns12(byte function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (i2c_flg) {
|
||||
switch (function) {
|
||||
// case FUNC_XSNS_INIT:
|
||||
// break;
|
||||
case FUNC_XSNS_PREP:
|
||||
Ads1115Detect();
|
||||
break;
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
Ads1115Show(1);
|
||||
break;
|
||||
#ifdef USE_WEBSERVER
|
||||
case FUNC_XSNS_WEB:
|
||||
Ads1115Show(0);
|
||||
break;
|
||||
#endif // USE_WEBSERVER
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // USE_ADS1115
|
||||
#endif // USE_I2C
|
131
sonoff/xsns_interface.ino
Normal file
131
sonoff/xsns_interface.ino
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
xsns_interface.ino - External sensor interface support for Sonoff-Tasmota
|
||||
|
||||
Copyright (C) 2017 Theo Arends inspired by ESPEasy
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
void XSnsInit()
|
||||
{
|
||||
for (byte i = 0; i < XSNS_MAX; i++) {
|
||||
xsns_func_ptr[i] = NULL;
|
||||
}
|
||||
xsns_present = 0;
|
||||
|
||||
#ifdef XSNS_01
|
||||
xsns_func_ptr[xsns_present++] = &Xsns01;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_02
|
||||
xsns_func_ptr[xsns_present++] = &Xsns02;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_03
|
||||
xsns_func_ptr[xsns_present++] = &Xsns03;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_04
|
||||
xsns_func_ptr[xsns_present++] = &Xsns04;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_05
|
||||
xsns_func_ptr[xsns_present++] = &Xsns05;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_06
|
||||
xsns_func_ptr[xsns_present++] = &Xsns06;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_07
|
||||
xsns_func_ptr[xsns_present++] = &Xsns07;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_08
|
||||
xsns_func_ptr[xsns_present++] = &Xsns08;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_09
|
||||
xsns_func_ptr[xsns_present++] = &Xsns09;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_10
|
||||
xsns_func_ptr[xsns_present++] = &Xsns10;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_11
|
||||
xsns_func_ptr[xsns_present++] = &Xsns11;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_12
|
||||
xsns_func_ptr[xsns_present++] = &Xsns12;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_13
|
||||
xsns_func_ptr[xsns_present++] = &Xsns13;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_14
|
||||
xsns_func_ptr[xsns_present++] = &Xsns14;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_15
|
||||
xsns_func_ptr[xsns_present++] = &Xsns15;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_16
|
||||
xsns_func_ptr[xsns_present++] = &Xsns16;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_17
|
||||
xsns_func_ptr[xsns_present++] = &Xsns17;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_18
|
||||
xsns_func_ptr[xsns_present++] = &Xsns18;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_19
|
||||
xsns_func_ptr[xsns_present++] = &Xsns19;
|
||||
#endif
|
||||
|
||||
#ifdef XSNS_20
|
||||
xsns_func_ptr[xsns_present++] = &Xsns20;
|
||||
#endif
|
||||
|
||||
XsnsCall(FUNC_XSNS_INIT);
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Function call to all xsns
|
||||
\*********************************************************************************************/
|
||||
|
||||
boolean XsnsCall(byte Function)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
switch (Function) {
|
||||
case FUNC_XSNS_INIT:
|
||||
case FUNC_XSNS_PREP:
|
||||
case FUNC_XSNS_JSON_APPEND:
|
||||
case FUNC_XSNS_MQTT_SHOW:
|
||||
case FUNC_XSNS_WEB:
|
||||
for (byte x = 0; x < xsns_present; x++) {
|
||||
xsns_func_ptr[x](Function);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user