mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-28 04:07:47 +00:00
Compare commits
149
Commits
v2.0
...
mega-20180213
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d7134e6b87 | ||
|
|
8dc1924059 | ||
|
|
a7b77b6008 | ||
|
|
649305a2dd | ||
|
|
2371b0f315 | ||
|
|
59b7768722 | ||
|
|
b320c2a1e2 | ||
|
|
b85010006b | ||
|
|
749c8cd931 | ||
|
|
eb2dbb5b90 | ||
|
|
d87cd7eafe | ||
|
|
58bb62cc1a | ||
|
|
201d013230 | ||
|
|
9a77b1727c | ||
|
|
f0d35527df | ||
|
|
9cbaa4d7e7 | ||
|
|
af4ad9fbcb | ||
|
|
8bdfa656de | ||
|
|
952bf68b93 | ||
|
|
13f73c0156 | ||
|
|
b32212b061 | ||
|
|
cae3baf71e | ||
|
|
27db33f1bd | ||
|
|
b96e12f217 | ||
|
|
ad8e229c06 | ||
|
|
0ec7085022 | ||
|
|
913cd67eee | ||
|
|
2586b94e28 | ||
|
|
b811b13483 | ||
|
|
c149888bed | ||
|
|
8aea298854 | ||
|
|
5617fbe0a0 | ||
|
|
6a643da8ee | ||
|
|
ee568a76c1 | ||
|
|
beaf077b06 | ||
|
|
e36a9f163e | ||
|
|
17f0f6637a | ||
|
|
0ec770fc51 | ||
|
|
9da5f465d1 | ||
|
|
5230a4fe4f | ||
|
|
b236887718 | ||
|
|
cbca4c3efa | ||
|
|
a67f92176f | ||
|
|
3922827fad | ||
|
|
4b298d6e31 | ||
|
|
c0c65364e5 | ||
|
|
5f89698308 | ||
|
|
5821377b6c | ||
|
|
a6ea35ef9c | ||
|
|
fe9a579dc3 | ||
|
|
ed7f597b3d | ||
|
|
6700030d7c | ||
|
|
f45c7650de | ||
|
|
a36ee65865 | ||
|
|
dfb5b8a4c5 | ||
|
|
9d3dd49e9d | ||
|
|
0833029c82 | ||
|
|
71cf207bf7 | ||
|
|
3d3a035822 | ||
|
|
af3bf5217d | ||
|
|
11f47f26e6 | ||
|
|
f7b37306aa | ||
|
|
8b3d8f6ad4 | ||
|
|
b5cad22afd | ||
|
|
407dae03ca | ||
|
|
c17e683834 | ||
|
|
311abeabd0 | ||
|
|
04f27e0d03 | ||
|
|
fc5103de8d | ||
|
|
14b6345277 | ||
|
|
9a70037e32 | ||
|
|
8ce1aa0092 | ||
|
|
d2e2522c07 | ||
|
|
4a212302e0 | ||
|
|
993dd7ade3 | ||
|
|
d544fc84e8 | ||
|
|
e6dba4456c | ||
|
|
d2777a9b15 | ||
|
|
c7d12bb798 | ||
|
|
ef912a4484 | ||
|
|
b4debd9559 | ||
|
|
d7277649dd | ||
|
|
33ec7e5240 | ||
|
|
d62b692b3b | ||
|
|
493bfd56b9 | ||
|
|
abbfa24ca6 | ||
|
|
fae1edc859 | ||
|
|
a9a741f775 | ||
|
|
c0d482e4fc | ||
|
|
b5cabdc775 | ||
|
|
c71a43c3a6 | ||
|
|
cd01283ac6 | ||
|
|
7ce1077bd6 | ||
|
|
f9701d1c7b | ||
|
|
e764830113 | ||
|
|
9646457b50 | ||
|
|
7346e55e0d | ||
|
|
ae38a8cb4f | ||
|
|
df46a4a5fc | ||
|
|
7c6797a141 | ||
|
|
83abac8c5e | ||
|
|
5ba6b2f335 | ||
|
|
0d4ba7c6f1 | ||
|
|
a1fc351183 | ||
|
|
33a6c39fc4 | ||
|
|
f853f6ef25 | ||
|
|
7a2d114360 | ||
|
|
0157f387ee | ||
|
|
c23be231e1 | ||
|
|
00f5c36919 | ||
|
|
c960175ec1 | ||
|
|
e456604436 | ||
|
|
ac4657e77f | ||
|
|
3817427e79 | ||
|
|
0200b3c63e | ||
|
|
972a1a5703 | ||
|
|
73c22176b8 | ||
|
|
4db036f350 | ||
|
|
52223f0a20 | ||
|
|
907ad0faf6 | ||
|
|
887e10c947 | ||
|
|
b4c463e452 | ||
|
|
66ba9b1f46 | ||
|
|
7db50811ba | ||
|
|
17d20705ff | ||
|
|
e3bd782a42 | ||
|
|
b073379fff | ||
|
|
b89d8ff946 | ||
|
|
22ad971c8e | ||
|
|
ab06cc3703 | ||
|
|
8a5cc5f2bd | ||
|
|
6919baf23c | ||
|
|
ddedb215c4 | ||
|
|
08d4d817f6 | ||
|
|
e8bdcfbaf2 | ||
|
|
743fb4494e | ||
|
|
0a4bc7fad6 | ||
|
|
49d0b16324 | ||
|
|
de479d6188 | ||
|
|
3fd3e13dc7 | ||
|
|
d7d913d439 | ||
|
|
5c4ae3820b | ||
|
|
38774a20c6 | ||
|
|
9fc58bb4df | ||
|
|
ca936ca42f | ||
|
|
840fb6b647 | ||
|
|
c80b5d6d78 | ||
|
|
40067c514f | ||
|
|
139ae36d3e |
@@ -26,6 +26,8 @@ Also there are more people on the forum that can help you with support.
|
||||
|
||||
* Incomplete or unstable plugins should have a PLUGIN_BUILD_DEV #ifdef around them. Also add [DEVELOPMENT] to the name.
|
||||
|
||||
* New plugins that seem to be working correctly should have a PLUGIN_BUILD_TESTING around until they are tested enough.
|
||||
* Do not modify any of the variables passed to your PLUGIN_WRITE handler.
|
||||
|
||||
* New plugins that seem to be working correctly should have a PLUGIN_BUILD_TESTING around until they are tested enough. Also add [TESTING] to the name
|
||||
|
||||
* Also see our general guidelines at: https://www.letscontrolit.com/wiki/index.php/ESPEasyDevelopmentGuidelines
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ install:
|
||||
- pip install -U platformio
|
||||
|
||||
script:
|
||||
- cppcheck --enable=warning src/*.ino -q --force -I src --include=src/ESPEasy.ino --error-exitcode=1
|
||||
# - cppcheck --enable=warning src/*.ino -q --force -I src --include=src/ESPEasy.ino --error-exitcode=1
|
||||
# - ./memanalyzer.py ~/.platformio/packages/toolchain-xtensa/bin/xtensa-lx106-elf-objdump
|
||||
- PLATFORMIO_BUILD_FLAGS="-D CONTINUOUS_INTEGRATION" platformio run -s
|
||||
|
||||
|
||||
@@ -1,44 +1,36 @@
|
||||
# ESPEasy (v2.0 stable branch)
|
||||
# ESPEasy (development branch)
|
||||
|
||||
Build status: [](https://travis-ci.org/letscontrolit/ESPEasy)
|
||||
Build status: [](https://travis-ci.org/letscontrolit/ESPEasy)
|
||||
|
||||
Introduction and wiki: https://www.letscontrolit.com/wiki/index.php/ESPEasy#Introduction
|
||||
|
||||
**v2.0**
|
||||
:warning:This is the stable branch for the next upcoming ESPeasy release (2.0.0).:warning:
|
||||
**MEGA**
|
||||
:warning:This is the development branch of ESPEasy. All new untested features go into this branch. If you want to do a bugfix, do it on the stable branch, we will merge the fix to the development branch as well.:warning:
|
||||
|
||||
If you're living on the edge and want the latest features and bugs, go to the development branch: https://github.com/letscontrolit/ESPEasy/tree/mega
|
||||
|
||||
If you're a developer: Bug fixes go into this v2.0 branch, we will merge them back to the development branch.
|
||||
Next stable branch: https://github.com/letscontrolit/ESPEasy/tree/v2.0 (bug fixes only, since oct 2017))
|
||||
|
||||
Check here to learn how to use this branch and help us improving ESPEasy: http://www.letscontrolit.com/wiki/index.php/ESPEasy#Source_code_development
|
||||
|
||||
## Versions
|
||||
|
||||
* v2.0-YYYYMMDD: These are the nightly builds. Once a day this is automaticly released whenever there are new changes. (this replaces the manual v2.0-devX release system)
|
||||
* v2.0.0-betaX: as soon as we THINK everything is fixed, we start beta testing.
|
||||
* v2.0.0-rcX: release candidates (almost stable)
|
||||
* v2.0.0: This will be the first stable release. After this we will use more standard numbering. Next bugfix release will probably be 2.0.1.
|
||||
## Automated binary releases
|
||||
|
||||
## Firmware binary releases
|
||||
Every night our build-bot will build a new binary release: https://github.com/letscontrolit/ESPEasy/releases
|
||||
|
||||
Binary development releases are here: https://github.com/letscontrolit/ESPEasy/releases
|
||||
The releases are named something like 'mega-20180102' (last number is the build date)
|
||||
|
||||
Depending on your needs, we release different types of files.
|
||||
|
||||
This uses version v2.0-20181001 as an example.
|
||||
Depending on your needs, we release different types of files:
|
||||
|
||||
Firmware name | Hardware | Included plugins |
|
||||
----------------------------------------------|-------------------------|-----------------------------|
|
||||
ESPEasy_v2.0-20181001_normal_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable |
|
||||
ESPEasy_v2.0-20181001_test_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable + Test |
|
||||
ESPEasy_v2.0-20181001_dev_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable + Test + Development |
|
||||
ESPEasy_v2.0-20181001_normal_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable |
|
||||
ESPEasy_v2.0-20181001_test_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable + Test |
|
||||
ESPEasy_v2.0-20181001_dev_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable + Test + Development |
|
||||
ESPEasy_v2.0-20181001_normal_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable |
|
||||
ESPEasy_v2.0-20181001_test_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable + Test |
|
||||
ESPEasy_v2.0-20181001_dev_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable + Test + Development |
|
||||
ESPEasy_mega-20180102_normal_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable |
|
||||
ESPEasy_mega-20180102_test_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable + Test |
|
||||
ESPEasy_mega-20180102_dev_ESP8266_1024.bin | ESP8266 with 1Mb flash | Stable + Test + Development |
|
||||
ESPEasy_mega-20180102_normal_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable |
|
||||
ESPEasy_mega-20180102_test_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable + Test |
|
||||
ESPEasy_mega-20180102_dev_ESP8266_4096.bin | ESP8266 with 4Mb flash | Stable + Test + Development |
|
||||
ESPEasy_mega-20180102_normal_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable |
|
||||
ESPEasy_mega-20180102_test_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable + Test |
|
||||
ESPEasy_mega-20180102_dev_ESP8285_1024.bin | ESP8285 with 1Mb flash | Stable + Test + Development |
|
||||
|
||||
## More info
|
||||
|
||||
|
||||
+22
-14
@@ -1,24 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION=$(git describe)
|
||||
echo "Creating release archives for $VERSION ..."
|
||||
#binaries
|
||||
|
||||
#ESP_Easy_v[version]-[build type]-dev[dev number]-ESP[chip type]-[size].bin
|
||||
#Naming convention:
|
||||
# ESP_Easy_[github version]_[plugin set]_[chip type]_[flash memory].bin
|
||||
|
||||
#cp .pioenvs/mini_512/firmware.bin dist/"ESPEasy_$VERSION""_mini_512.bin"
|
||||
|
||||
cp .pioenvs/normal_ESP8266_1024/firmware.bin dist/"ESP_Easy_$VERSION""_normal_ESP8266_1024.bin"
|
||||
cp .pioenvs/normal_ESP8266_4096/firmware.bin dist/"ESP_Easy_$VERSION""_normal_ESP8266_4096.bin"
|
||||
cp .pioenvs/normal_ESP8285_1024/firmware.bin dist/"ESP_Easy_$VERSION""_normal_ESP8285_1024.bin"
|
||||
for ENV in \
|
||||
normal_ESP8266_1024 \
|
||||
normal_ESP8266_4096 \
|
||||
normal_ESP8285_1024 \
|
||||
test_ESP8266_1024\
|
||||
test_ESP8266_4096\
|
||||
test_ESP8285_1024\
|
||||
dev_ESP8266_1024\
|
||||
dev_ESP8266_4096\
|
||||
dev_ESP8285_1024;\
|
||||
do
|
||||
echo
|
||||
echo "### Deploying environment $ENV for version $VERSION"
|
||||
BIN=.pioenvs/$ENV/firmware.bin
|
||||
python2 crc2.py $BIN
|
||||
cp $BIN dist/"ESP_Easy_$VERSION""_$ENV.bin"
|
||||
done
|
||||
|
||||
cp .pioenvs/test_ESP8266_1024/firmware.bin dist/"ESP_Easy_$VERSION""_test_ESP8266_1024.bin"
|
||||
cp .pioenvs/test_ESP8266_4096/firmware.bin dist/"ESP_Easy_$VERSION""_test_ESP8266_4096.bin"
|
||||
cp .pioenvs/test_ESP8285_1024/firmware.bin dist/"ESP_Easy_$VERSION""_test_ESP8285_1024.bin"
|
||||
|
||||
cp .pioenvs/dev_ESP8266_1024/firmware.bin dist/"ESP_Easy_$VERSION""_dev_ESP8266_1024.bin"
|
||||
cp .pioenvs/dev_ESP8266_4096/firmware.bin dist/"ESP_Easy_$VERSION""_dev_ESP8266_4096.bin"
|
||||
cp .pioenvs/dev_ESP8285_1024/firmware.bin dist/"ESP_Easy_$VERSION""_dev_ESP8285_1024.bin"
|
||||
|
||||
#create a source structure that is the same as the original ESPEasy project (and works with the howto on the wiki)
|
||||
rm -rf dist/Source 2>/dev/null
|
||||
@@ -28,4 +33,7 @@ cp -r src dist/Source/
|
||||
cp platformio.ini dist/Source/
|
||||
|
||||
cd dist
|
||||
|
||||
echo
|
||||
echo "### Creating zip archive"
|
||||
zip ../ESPEasy_$VERSION.zip -r .
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
|
||||
|
||||
import sys
|
||||
import binascii
|
||||
import struct
|
||||
import md5
|
||||
MD5DUMMY = "MD5_MD5_MD5_MD5_BoundariesOfTheSegmentsGoHere..."
|
||||
MemorySegmentStart,MemorySegmentEnd,MemoryContent=[],[],[]
|
||||
|
||||
##################################################################
|
||||
# this subroutine shows the segments of a part
|
||||
##################################################################
|
||||
def showSegments (fileContent,offset):
|
||||
global MemorySegmentStart, MemorySegmentEnd, MemoryContent
|
||||
header = struct.unpack("ii", fileContent[offset:offset+8])
|
||||
herestr =""
|
||||
MemorySegmentStart.append(struct.pack("I",header[0]))
|
||||
MemorySegmentEnd.append(struct.pack("I",header[0]+header[1]))
|
||||
MemoryContent.append(fileContent[offset+8:offset+8+header[1]])
|
||||
if fileContent.find( MD5DUMMY, offset+8, offset+8+header[1]) >0 :
|
||||
herestr= " <-- CRC is here."
|
||||
print ("SEGMENT "+ str(len(MemorySegmentStart)-1)+ ": memory position: " + hex(header[0])+" to " + hex(header[0]+header[1]) + " length: " + hex(header[1])+herestr)
|
||||
#print ("first byte positoin in file: " + hex( offset+8))
|
||||
#print ("last byte postion in file: " + hex(offset+8+header[1]-1))
|
||||
return (8+offset+ header[1]); # return start of next segment
|
||||
|
||||
##################################################################
|
||||
# this subroutine shows the parts of a binary file
|
||||
##################################################################
|
||||
def showParts(fileContent, offset):
|
||||
header = struct.unpack("BBBBi", fileContent[offset:offset+8])
|
||||
print ('\n\nBINARY PART\nSegments: ') + (hex(header[1]))
|
||||
nextpos =offset+8
|
||||
for x in range (0,header[1]):
|
||||
nextpos = showSegments(fileContent,nextpos)
|
||||
nextSegmentOffset = (fileContent.find("\xe9", nextpos))
|
||||
return nextSegmentOffset
|
||||
|
||||
##################################################################
|
||||
# MAIN
|
||||
##################################################################
|
||||
|
||||
#if len(sys.argv) !=2 :
|
||||
# print ("please give a filename")
|
||||
# k=input("press close to exit")
|
||||
# sys.exit(1)
|
||||
FileName = sys.argv[1]#"C:/ArduinoPortable/sketchbooks/build/sketch_jan15a.ino.bin"
|
||||
#FileName = "C:/ArduinoPortable/sketchbooks/build/sketch_jan15a.ino.bin"
|
||||
print( "\n\nReplacing dummy MD5 checksum in .bin file")
|
||||
|
||||
|
||||
|
||||
with open(FileName, mode='rb') as file: # b is important -> binary
|
||||
nextpos =0;
|
||||
fileContent = file.read()
|
||||
while nextpos >=0:
|
||||
nextpos = showParts(fileContent,nextpos)
|
||||
|
||||
startArray,endArray,hashString = "","",""
|
||||
includeStr = "hash includes segments:"
|
||||
# memory sections:
|
||||
# 0: bootloader (not readable)
|
||||
# 1: program memory (SPI flash)
|
||||
# 2: unknown but stable
|
||||
# 3: RAM (initialized by bin file. Can be read but changes as you go :-( )
|
||||
# 4: RAM
|
||||
|
||||
for i in (1,2 ): # use only stable segments, must be 4 in total. We use 2.
|
||||
startArray =startArray + MemorySegmentStart[i]
|
||||
endArray = endArray + MemorySegmentEnd[i]
|
||||
hashString =hashString + MemoryContent[i]
|
||||
with open(FileName+str(i), mode='wb') as file: # b is important -> binary
|
||||
file.write(MemoryContent[i])
|
||||
includeStr = includeStr +" "+ str(i)
|
||||
print (includeStr)
|
||||
# IMPORTANT: pad array with zeros if you use only 3 segments (see above)
|
||||
while len(startArray) < 16 :
|
||||
startArray =startArray + struct.pack("I",0)
|
||||
endArray = endArray + struct.pack("I",0)
|
||||
# debug print (binascii.hexlify(startArray))
|
||||
# debug print (binascii.hexlify(endArray))
|
||||
if (len(endArray) + len (startArray)) != 32 :
|
||||
print("ERROR: please make sure you add / remove padding if you change the semgents.")
|
||||
|
||||
if fileContent.find( MD5DUMMY) < 0:
|
||||
print("ERROR: MD5 dummy not found in binary")
|
||||
else:
|
||||
hashString=hashString.replace (MD5DUMMY,"",1)
|
||||
m = md5.new()
|
||||
m.update (hashString) #use segment 1
|
||||
md5hash = m.digest()
|
||||
print("MD5 hash: "+ m.hexdigest())
|
||||
print("\nwriting output file:\n" + FileName)
|
||||
with open(FileName, mode='wb') as file: # b is important -> binary
|
||||
file.write(fileContent.replace(MD5DUMMY,md5hash+startArray+endArray))
|
||||
#k=input("press close to exit")
|
||||
Vendored
+444
-100
@@ -1,62 +1,114 @@
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180212 (since v2.0-20180209)
|
||||
Changes in release mega-20180213 (since mega-20180212)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Mon Feb 12 04:00:22 CET 2018
|
||||
Release date: Tue Feb 13 04:00:09 CET 2018
|
||||
|
||||
Gijs Noorlander (1):
|
||||
ESPEasy release bot (3):
|
||||
automaticly updated release notes for v2.0-20180206
|
||||
automaticly updated release notes for v2.0-20180209
|
||||
automaticly updated release notes for v2.0-20180212
|
||||
|
||||
Edwin Eefting (1):
|
||||
make blynk stuff compile again
|
||||
|
||||
Gijs Noorlander (10):
|
||||
[Issue #831] Use DOUT flash mode (#834)
|
||||
[#804] Degree symbol for non-framed OLED display (#835)
|
||||
Blynk controler (re-implementation of PR#92) (#837)
|
||||
[issue #839] Add command support for setting contrast for OLED Framed (#841)
|
||||
[P001 Switch] Fix a mixup in previous fix for switch (#845)
|
||||
[v2.0] Fix compile errors on ESP32 (#848)
|
||||
Bugfix/oled framed less memory (#859)
|
||||
Formatting user vars (re-do of PR#482) + enabled check OpenHabMQTT (#851)
|
||||
[issue #825] Change labels and password form for Thingspeak controller (#849)
|
||||
[MQTT] Allow for background tests while waiting for wifi (#860)
|
||||
|
||||
soif (1):
|
||||
Henri de Jong (1):
|
||||
Added support for pioneer ir signals (#844)
|
||||
|
||||
soif (2):
|
||||
Add Device Name in /json page (#815)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180209 (since v2.0-20180206)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Feb 9 04:00:26 CET 2018
|
||||
P012 - Fix/handle lines exceeding LCD width + allow to clear line b4 print (#852)
|
||||
|
||||
wdonker (1):
|
||||
Add trigger for rulesprocessing (#826)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180206 (since v2.0-20180203)
|
||||
Changes in release mega-20180212 (since mega-20180209)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Feb 6 05:00:21 CET 2018
|
||||
Release date: Mon Feb 12 04:00:09 CET 2018
|
||||
|
||||
mvdbro (1):
|
||||
Fix compile errors on ESP32
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180209 (since mega-20180206)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Feb 9 04:00:15 CET 2018
|
||||
|
||||
Andrey (1):
|
||||
Added HIGH-Z state options for GPIO command (#833)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180206 (since mega-20180203)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Feb 6 05:00:10 CET 2018
|
||||
|
||||
ESPEasy release bot (2):
|
||||
automaticly updated release notes for v2.0-20180202
|
||||
automaticly updated release notes for v2.0-20180203
|
||||
|
||||
Gijs Noorlander (3):
|
||||
Backport OLED framed from mega + support special characters (#818)
|
||||
[issue #817] Added mail header to SMTP (#820)
|
||||
[issue #727] Proper user interface to set DST rules (#823)
|
||||
|
||||
Grovkillen (1):
|
||||
Update README.md
|
||||
|
||||
s0170071 (1):
|
||||
Add compile time (#811)
|
||||
|
||||
soif (1):
|
||||
All Advanced Settings as 'DEFAULT_' Defines (#813)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180203 (since v2.0-20180202)
|
||||
Changes in release mega-20180203 (since mega-20180202)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sat Feb 3 05:00:20 CET 2018
|
||||
Release date: Sat Feb 3 05:00:11 CET 2018
|
||||
|
||||
Grovkillen (1):
|
||||
Update README.md
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180202 (since v2.0-20180130)
|
||||
Changes in release mega-20180202 (since mega-20180130)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Feb 2 05:00:23 CET 2018
|
||||
Release date: Fri Feb 2 05:00:12 CET 2018
|
||||
|
||||
DatuX (2):
|
||||
DatuX (3):
|
||||
Update README.md
|
||||
Update README.md
|
||||
Update README.md
|
||||
|
||||
Gijs Noorlander (3):
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180130
|
||||
|
||||
Edwin Eefting (1):
|
||||
Add CRC checks to all binaries when building a release with travis. fixes #779
|
||||
|
||||
Gijs Noorlander (4):
|
||||
[Mega] Fix pointer arithmetic on void pointers for CRC computations (#795)
|
||||
[issue #794] Add longpulse_ms command (#796)
|
||||
[v2.0] Resource friendly string replacement (#798)
|
||||
[issue #739] Reconnect MQTT when Unit Name has changed. (#803)
|
||||
@@ -70,10 +122,13 @@ soif (5):
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180130 (since v2.0-20180126)
|
||||
Changes in release mega-20180130 (since mega-20180126)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 30 05:00:23 CET 2018
|
||||
Release date: Tue Jan 30 05:00:12 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180126
|
||||
|
||||
Edwin Eefting (1):
|
||||
forgot to commit last framed oled display fix
|
||||
@@ -85,22 +140,33 @@ Gijs Noorlander (3):
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180126 (since v2.0-20180124)
|
||||
Changes in release mega-20180126 (since mega-20180124)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Jan 26 05:00:22 CET 2018
|
||||
Release date: Fri Jan 26 05:00:11 CET 2018
|
||||
|
||||
Gijs Noorlander (3):
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180124
|
||||
|
||||
Gijs Noorlander (5):
|
||||
[Mega] Allow compile with 2.4.0 core library (#772)
|
||||
[issue #759] Disable Senseair ABC due to firmware issues (#771)
|
||||
[V2.0] Allow IRremoteESP8266 to be built with core 2.4.0 (#773)
|
||||
[Mega] Force 2.3.0 for all builds and add an option for 2.4.0 core (#775)
|
||||
Update _C007.ino (#774) (#776)
|
||||
|
||||
josemariaaraujo (1):
|
||||
Update _C007.ino (#774)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180124 (since v2.0-20180123)
|
||||
Changes in release mega-20180124 (since mega-20180123)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Jan 24 05:00:19 CET 2018
|
||||
Release date: Wed Jan 24 05:00:09 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180123
|
||||
|
||||
Edwin Eefting (1):
|
||||
fix #718. also update display on save and removed graphical boot logo to conserve space. also fixes #713. (web interface will be non repsonsive during scrolling now, but there is no easy fix for that)
|
||||
@@ -108,12 +174,19 @@ Edwin Eefting (1):
|
||||
Gijs Noorlander (1):
|
||||
[issue #758] P029 MQTT helper does not log anymore (#764)
|
||||
|
||||
s0170071 (2):
|
||||
Broken comment (#766)
|
||||
Space (#767)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180123 (since v2.0-20180122)
|
||||
Changes in release mega-20180123 (since mega-20180122)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 23 05:00:20 CET 2018
|
||||
Release date: Tue Jan 23 05:00:10 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180122
|
||||
|
||||
Edwin Eefting (5):
|
||||
test suite: now possible to run all tests at once. fixes
|
||||
@@ -125,12 +198,30 @@ Edwin Eefting (5):
|
||||
Gijs Noorlander (1):
|
||||
Central function for system variable replacement (#757)
|
||||
|
||||
s0170071 (1):
|
||||
CRC on settings and security settings and progmem (#720)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180122 (since v2.0-20180121)
|
||||
Changes in release mega-20180122 (since mega-20180119)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Mon Jan 22 05:00:19 CET 2018
|
||||
Release date: Mon Jan 22 05:00:08 CET 2018
|
||||
|
||||
ESPEasy release bot (3):
|
||||
automaticly updated release notes for v2.0-20180119
|
||||
automaticly updated release notes for v2.0-20180120
|
||||
automaticly updated release notes for v2.0-20180121
|
||||
|
||||
Edwin Eefting (8):
|
||||
test suite: added dht22
|
||||
added QUAD to c002. fixed getBearing and SENSOR_TYPE_WIND.
|
||||
test suite: started on testcase to test all sensor types via the dummy plugin
|
||||
test suite: generelized controller testing in test005
|
||||
cleaned up nodo logging. fixed domotics SENSOR_TYPE_WIND inconsistency
|
||||
test suite: fixed issues, started working on nodo
|
||||
test suite: lots of refactoring and fixing
|
||||
test suite: fixes. testing boot gpio states
|
||||
|
||||
Gijs Noorlander (2):
|
||||
[issue #745] Set IPaddress to 0.0.0.0 when read from empty string (#754)
|
||||
@@ -138,49 +229,35 @@ Gijs Noorlander (2):
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180121 (since v2.0-20180120)
|
||||
Changes in release mega-20180119 (since mega-20180118)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sun Jan 21 05:00:12 CET 2018
|
||||
Release date: Fri Jan 19 05:00:07 CET 2018
|
||||
|
||||
Edwin Eefting (5):
|
||||
test suite: generelized controller testing in test005
|
||||
cleaned up nodo logging. fixed domotics SENSOR_TYPE_WIND inconsistency
|
||||
test suite: fixed issues, started working on nodo
|
||||
test suite: lots of refactoring and fixing
|
||||
test suite: fixes. testing boot gpio states
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180120 (since v2.0-20180119)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sat Jan 20 05:00:12 CET 2018
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180118
|
||||
|
||||
Edwin Eefting (2):
|
||||
added QUAD to c002. fixed getBearing and SENSOR_TYPE_WIND.
|
||||
test suite: started on testcase to test all sensor types via the dummy plugin
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180119 (since v2.0-20180118)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Jan 19 05:00:18 CET 2018
|
||||
|
||||
Edwin Eefting (2):
|
||||
test suite domoticz mqtt + found few fixmes
|
||||
test suite: added dht22
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180118 (since v2.0-20180116)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Jan 18 05:00:19 CET 2018
|
||||
|
||||
Edwin Eefting (1):
|
||||
refactoring test suite controller stuff
|
||||
test suite domoticz mqtt + found few fixmes
|
||||
|
||||
jctual (1):
|
||||
DHT plugin update (#736)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180118 (since mega-20180117)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Jan 18 05:00:07 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180116
|
||||
|
||||
Edwin Eefting (3):
|
||||
made test resumable and importable
|
||||
now supports powercycle to test for bugs like #719
|
||||
added fixme
|
||||
|
||||
Gijs Noorlander (2):
|
||||
[issue 733] Fix for negative values on MQTT import (#735)
|
||||
@@ -188,45 +265,74 @@ Gijs Noorlander (2):
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180116 (since v2.0-20180113)
|
||||
Changes in release mega-20180117 (since mega-20180116)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 16 05:00:21 CET 2018
|
||||
Release date: Wed Jan 17 05:00:08 CET 2018
|
||||
|
||||
Edwin Eefting (3):
|
||||
Edwin Eefting (1):
|
||||
fix #719 (initial ds18b20 value after power on 85 degrees)
|
||||
|
||||
papperone (1):
|
||||
merge with main branch (#648)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180116 (since mega-20180114)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 16 05:00:11 CET 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180113
|
||||
|
||||
Edwin Eefting (2):
|
||||
testsuite: working on generic http/mqtt controller emulatior receiving
|
||||
fixed custom build path
|
||||
made test resumable and importable
|
||||
now supports powercycle to test for bugs like #719
|
||||
|
||||
Gijs Noorlander (1):
|
||||
[AutoDST] Added Auto DST (Bugfix/v2.0 issue569) (#726)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180113 (since v2.0-20180112)
|
||||
Changes in release mega-20180114 (since mega-20180113)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sat Jan 13 05:00:20 CET 2018
|
||||
Release date: Sun Jan 14 05:00:08 CET 2018
|
||||
|
||||
Edwin Eefting (5):
|
||||
release bot fixes
|
||||
dont make same release twice
|
||||
dont make same release twice
|
||||
s0170071 (1):
|
||||
preparations for lwip2 (#707)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-20180113 (since mega-20180112)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Sat Jan 13 05:00:10 CET 2018
|
||||
|
||||
Edwin Eefting (2):
|
||||
ESPEasy v2.0 only supports compiling under arduino core 2.3.0 to prevent issues like #705 when people use Arduino IDE to compile with arduino core 2.4.0
|
||||
testsuite: working on generic http/mqtt controller emulatior receiving
|
||||
fix version number
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180112 (since v2.0-20180111)
|
||||
Changes in release mega-20180112 (since mega-20180111)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Fri Jan 12 01:56:54 CET 2018
|
||||
Release date: Fri Jan 12 02:05:49 CET 2018
|
||||
|
||||
Edwin Eefting (4):
|
||||
ESPEasy release bot (1):
|
||||
automaticly updated release notes for v2.0-20180111
|
||||
|
||||
Edwin Eefting (8):
|
||||
added http server emulation and domotics http to testsuite
|
||||
first http domoticz test works
|
||||
testsuite requirements
|
||||
fixed releasebot issues with multiple branches
|
||||
automaticly updated release notes for v2.0-20180112
|
||||
release bot fixes
|
||||
dont make same release twice
|
||||
dont make same release twice
|
||||
|
||||
Gijs Noorlander (2):
|
||||
[Issue 699] Incorrect shown device name (#700)
|
||||
@@ -234,36 +340,274 @@ Gijs Noorlander (2):
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180111 (since mega-20180111)
|
||||
Changes in release mega-20180111 (since v2.0-20180110)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Thu Jan 11 05:00:18 CET 2018
|
||||
Release date: Thu Jan 11 05:00:08 CET 2018
|
||||
|
||||
Alexander Schulz (1):
|
||||
improvement: Configurable number of tasks for "Devices" page (TASKS_P…
|
||||
|
||||
BadWolf42 (1):
|
||||
Dallas Plugin enhanced : no more "delay()" (#488)
|
||||
|
||||
Bartłomiej Zimoń (1):
|
||||
Update _C002.ino (#645)
|
||||
|
||||
DaM (1):
|
||||
[Domoticz HTTP] Compatibility fix for BMP280 (#636)
|
||||
|
||||
ESPEasy release bot (5):
|
||||
created releasebot script
|
||||
automaticly updated release notes for mega-01022018
|
||||
automaticly updated release notes for mega-01032018
|
||||
changed date format of nightly builds
|
||||
automaticly updated release notes for mega-20180104
|
||||
|
||||
Edwin Eefting (22):
|
||||
keep TASKS_PER_PAGE at default value of 4
|
||||
fix plugin id (starting with a 0 makes it octal in c++ :( )
|
||||
fix warnings
|
||||
fixed bug in oled upstream lib
|
||||
test fixes
|
||||
smooth out testing code
|
||||
esptest stuff
|
||||
fix travis build errors. disable cpp checking for now
|
||||
set lcd to NULL by default. #584
|
||||
fix illegal string manipulations in PLUGIN_WRITE for some plugins. fixes #347 and #460
|
||||
fix #588. parseTemplate() now only checks enabled taskes for [] macros
|
||||
testing for ds18b20
|
||||
updated travis link to reflect v2.0
|
||||
changed readme to reflect mega branch and automated builds
|
||||
updates version numbering documentation
|
||||
changed devicecombobox handling to save a lot of memory on device page. fixes #654 #676 and could be triggered by #683 in some cases.
|
||||
oops...somehow git did made some changes :(
|
||||
copied test-stuff from mega to v2.0 to do some testing
|
||||
analysed some code and added comments
|
||||
test suite fixes
|
||||
added frame oled test
|
||||
working on http mocker for test suite
|
||||
|
||||
GHolli (1):
|
||||
Cosmetics: fixing typos. (#628)
|
||||
|
||||
Gijs Noorlander (14):
|
||||
P028 to support both BME280 and BMP280 to reduce resource usage (#481)
|
||||
Single function for format to user defined number decimals (#482)
|
||||
OLED framed improve header footer (#495)
|
||||
[SSD1306] Feature/oled 1306 library upgrade (#501)
|
||||
[MH-Z19] Allow for B-version and add filtering (#525)
|
||||
Support both SSD1306 and SH1106 OLED in OLED_Framed plugin (#509)
|
||||
[LCD plugin] Added check of LCD object before dereferencing it (#584)
|
||||
[P039 Thermocouple] Handling negative values and proper error logging (#586)
|
||||
Reduce iRAM usage for plugins using SoftwareSerial (#631)
|
||||
[Security] Add IP-based filtering to web interface and http-commands. (#653)
|
||||
[SDS011] Allow the sensor to sleep to extend sensor lifetime (#668)
|
||||
[CPPcheck] v2.0 ControllerSettingsStruct some variables not initialized (#692)
|
||||
Merge/v2.0 dev13 to mega (#695)
|
||||
[v2.0_kamstrup] Plugin configuration does not load (#697)
|
||||
|
||||
Grovkillen (6):
|
||||
Added categories... (#552)
|
||||
Changed bin file names to be more descriptive. (#597)
|
||||
Move "TTP229 keypad" and "Encoder" plugin from "testing" to "normal" (#619)
|
||||
Updated ESPTOOLS.exe from 0.4.6 to 0.4.12 (#627)
|
||||
Updated "/pinstates" page: Made the plugin number column display "P001" instead of "1" and "P012" instead of "12".
|
||||
Update README.md
|
||||
|
||||
M0ebiu5 (1):
|
||||
P022_PCA9685 added change frequency - P038_NeoPixel added RGBW strips (SK6812) (#638)
|
||||
|
||||
Michael (2):
|
||||
WebServer.ino: enhance handle_SDfilelist() (#507)
|
||||
src/Hardware.ino: make it possible to use GPIO-0 (D3) as Pin_sd_cs (#508)
|
||||
|
||||
Sen Haerens (1):
|
||||
Enhanced system info layout (#624)
|
||||
|
||||
SightofSilence (1):
|
||||
Add System Variable for day, month and year / Fix for "Calculate" function to recognize minus-sign (#485)
|
||||
|
||||
SloMusti (1):
|
||||
implemewnted web activity timer tracker (#462)
|
||||
|
||||
Tomasz Torcz (1):
|
||||
retain MQTT LWT messages (#516)
|
||||
|
||||
denisfrench (1):
|
||||
Set MQTT clientid to %sysname% +/- Settings.Unit (#431) (#436)
|
||||
|
||||
fensoft (1):
|
||||
added #define FEATURE_SD (permit a flash size reduction of ~10k) (#568)
|
||||
|
||||
hatzlhoffer (1):
|
||||
added new display size 128x32 (#545)
|
||||
|
||||
krikk (1):
|
||||
added support for the TSL2591 Sensor based on Adafruit Library (#661)
|
||||
|
||||
mvdbro (8):
|
||||
First preparations for ESP32
|
||||
ESP32 IRAM/Deepsleep
|
||||
ESP32 Rules/ADC/PWM
|
||||
ESP32 fix FreeRAM reporting
|
||||
ESP32 Enabled OTA
|
||||
ESP32 fix UDP instability
|
||||
ESP32 fixed chunked HTTP transfer
|
||||
Fix #599
|
||||
|
||||
papperone (3):
|
||||
Plugin 073 - 7-segment display plugin TM1637/MAX7219
|
||||
Update _P073_7DGT.ino (#553)
|
||||
deleted GPIO notes referring to 75HC595 not supported (#591)
|
||||
|
||||
paulv888 (1):
|
||||
usesID = true (#666)
|
||||
|
||||
s0170071 (2):
|
||||
split IP addrress (#605)
|
||||
fix chunking (#649)
|
||||
|
||||
sakinit (1):
|
||||
Fix p1 wifi gateway module (#587)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release v2.0-20180110 (since mega-20180104)
|
||||
Changes in release mega-20180104 (since mega-01032018)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Wed Jan 10 16:14:23 CET 2018
|
||||
Release date: Thu Jan 4 03:13:01 UTC 2018
|
||||
|
||||
ESPEasy release bot (1):
|
||||
added releasebot to v2.0 branch
|
||||
changed date format of nightly builds
|
||||
|
||||
Edwin Eefting (5):
|
||||
changed readme title
|
||||
readme updates
|
||||
actually ignore MQTT messages that are too big.
|
||||
moved mqtt stuff outside of backgroundtasks(). fixes #683 in my test scenario
|
||||
fixed plugin id of "Communication - Kamstrup Multical 401". (accidental octal notation)
|
||||
|
||||
Gijs Noorlander (4):
|
||||
[switch] Fixed switch behavior and default settings. (#675)
|
||||
[Flash info] Detailed flash information (#678)
|
||||
Bugfix/v2.0 crash switch (#682)
|
||||
[Adafruit MPR121] Change deprecated name setThreshholds to setThresholds (#685)
|
||||
-------------------------------------------------
|
||||
Changes in release mega-01032018 (since mega-01022018)
|
||||
-------------------------------------------------
|
||||
|
||||
chunter1 (1):
|
||||
ABC calibration feature added (#606)
|
||||
Release date: Wed Jan 3 04:00:06 UTC 2018
|
||||
|
||||
Edwin Eefting (4):
|
||||
updated readme to reflect new binary names
|
||||
updated travis link to reflect v2.0
|
||||
updated travis link to reflect v2.0
|
||||
changed readme to reflect mega branch and automated builds
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
Changes in release mega-01022018 (since v2.0.0-dev13)
|
||||
-------------------------------------------------
|
||||
|
||||
Release date: Tue Jan 2 23:32:50 UTC 2018
|
||||
|
||||
Alexander Schulz (1):
|
||||
improvement: Configurable number of tasks for "Devices" page (TASKS_P…
|
||||
|
||||
BadWolf42 (1):
|
||||
Dallas Plugin enhanced : no more "delay()" (#488)
|
||||
|
||||
Bartłomiej Zimoń (1):
|
||||
Update _C002.ino (#645)
|
||||
|
||||
DaM (1):
|
||||
[Domoticz HTTP] Compatibility fix for BMP280 (#636)
|
||||
|
||||
ESPEasy release bot (1):
|
||||
created releasebot script
|
||||
|
||||
Edwin Eefting (12):
|
||||
keep TASKS_PER_PAGE at default value of 4
|
||||
fix plugin id (starting with a 0 makes it octal in c++ :( )
|
||||
fix warnings
|
||||
fixed bug in oled upstream lib
|
||||
test fixes
|
||||
smooth out testing code
|
||||
esptest stuff
|
||||
fix travis build errors. disable cpp checking for now
|
||||
set lcd to NULL by default. #584
|
||||
fix illegal string manipulations in PLUGIN_WRITE for some plugins. fixes #347 and #460
|
||||
fix #588. parseTemplate() now only checks enabled taskes for [] macros
|
||||
testing for ds18b20
|
||||
|
||||
GHolli (1):
|
||||
Cosmetics: fixing typos. (#628)
|
||||
|
||||
Gijs Noorlander (11):
|
||||
P028 to support both BME280 and BMP280 to reduce resource usage (#481)
|
||||
Single function for format to user defined number decimals (#482)
|
||||
OLED framed improve header footer (#495)
|
||||
[SSD1306] Feature/oled 1306 library upgrade (#501)
|
||||
[MH-Z19] Allow for B-version and add filtering (#525)
|
||||
Support both SSD1306 and SH1106 OLED in OLED_Framed plugin (#509)
|
||||
[LCD plugin] Added check of LCD object before dereferencing it (#584)
|
||||
[P039 Thermocouple] Handling negative values and proper error logging (#586)
|
||||
Reduce iRAM usage for plugins using SoftwareSerial (#631)
|
||||
[Security] Add IP-based filtering to web interface and http-commands. (#653)
|
||||
[SDS011] Allow the sensor to sleep to extend sensor lifetime (#668)
|
||||
|
||||
Grovkillen (5):
|
||||
Added categories... (#552)
|
||||
Changed bin file names to be more descriptive. (#597)
|
||||
Move "TTP229 keypad" and "Encoder" plugin from "testing" to "normal" (#619)
|
||||
Updated ESPTOOLS.exe from 0.4.6 to 0.4.12 (#627)
|
||||
Updated "/pinstates" page: Made the plugin number column display "P001" instead of "1" and "P012" instead of "12".
|
||||
|
||||
M0ebiu5 (1):
|
||||
P022_PCA9685 added change frequency - P038_NeoPixel added RGBW strips (SK6812) (#638)
|
||||
|
||||
Michael (2):
|
||||
WebServer.ino: enhance handle_SDfilelist() (#507)
|
||||
src/Hardware.ino: make it possible to use GPIO-0 (D3) as Pin_sd_cs (#508)
|
||||
|
||||
Sen Haerens (1):
|
||||
Enhanced system info layout (#624)
|
||||
|
||||
SightofSilence (1):
|
||||
Add System Variable for day, month and year / Fix for "Calculate" function to recognize minus-sign (#485)
|
||||
|
||||
SloMusti (1):
|
||||
implemewnted web activity timer tracker (#462)
|
||||
|
||||
Tomasz Torcz (1):
|
||||
retain MQTT LWT messages (#516)
|
||||
|
||||
denisfrench (1):
|
||||
Set MQTT clientid to %sysname% +/- Settings.Unit (#431) (#436)
|
||||
|
||||
fensoft (1):
|
||||
added #define FEATURE_SD (permit a flash size reduction of ~10k) (#568)
|
||||
|
||||
hatzlhoffer (1):
|
||||
added new display size 128x32 (#545)
|
||||
|
||||
krikk (1):
|
||||
added support for the TSL2591 Sensor based on Adafruit Library (#661)
|
||||
|
||||
mvdbro (8):
|
||||
First preparations for ESP32
|
||||
ESP32 IRAM/Deepsleep
|
||||
ESP32 Rules/ADC/PWM
|
||||
ESP32 fix FreeRAM reporting
|
||||
ESP32 Enabled OTA
|
||||
ESP32 fix UDP instability
|
||||
ESP32 fixed chunked HTTP transfer
|
||||
Fix #599
|
||||
|
||||
papperone (3):
|
||||
Plugin 073 - 7-segment display plugin TM1637/MAX7219
|
||||
Update _P073_7DGT.ino (#553)
|
||||
deleted GPIO notes referring to 75HC595 not supported (#591)
|
||||
|
||||
paulv888 (1):
|
||||
usesID = true (#666)
|
||||
|
||||
s0170071 (2):
|
||||
split IP addrress (#605)
|
||||
fix chunking (#649)
|
||||
|
||||
sakinit (1):
|
||||
Fix p1 wifi gateway module (#587)
|
||||
|
||||
|
||||
-------------------------------------------------
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software< /span>
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and
|
||||
* extended sensor support to include color, voltage and current */
|
||||
|
||||
#ifndef _ADAFRUIT_SENSOR_H
|
||||
#define _ADAFRUIT_SENSOR_H
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#else
|
||||
#include "WProgram.h"
|
||||
#endif
|
||||
|
||||
/* Intentionally modeled after sensors.h in the Android API:
|
||||
* https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */
|
||||
|
||||
/* Constants */
|
||||
#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */
|
||||
#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */
|
||||
#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */
|
||||
#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH)
|
||||
#define SENSORS_MAGFIELD_EARTH_MAX (60.0F) /**< Maximum magnetic field on Earth's surface */
|
||||
#define SENSORS_MAGFIELD_EARTH_MIN (30.0F) /**< Minimum magnetic field on Earth's surface */
|
||||
#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) /**< Average sea level pressure is 1013.25 hPa */
|
||||
#define SENSORS_DPS_TO_RADS (0.017453293F) /**< Degrees/s to rad/s multiplier */
|
||||
#define SENSORS_GAUSS_TO_MICROTESLA (100) /**< Gauss to micro-Tesla multiplier */
|
||||
|
||||
/** Sensor types */
|
||||
typedef enum
|
||||
{
|
||||
SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */
|
||||
SENSOR_TYPE_MAGNETIC_FIELD = (2),
|
||||
SENSOR_TYPE_ORIENTATION = (3),
|
||||
SENSOR_TYPE_GYROSCOPE = (4),
|
||||
SENSOR_TYPE_LIGHT = (5),
|
||||
SENSOR_TYPE_PRESSURE = (6),
|
||||
SENSOR_TYPE_PROXIMITY = (8),
|
||||
SENSOR_TYPE_GRAVITY = (9),
|
||||
SENSOR_TYPE_LINEAR_ACCELERATION = (10), /**< Acceleration not including gravity */
|
||||
SENSOR_TYPE_ROTATION_VECTOR = (11),
|
||||
SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
|
||||
SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
|
||||
SENSOR_TYPE_VOLTAGE = (15),
|
||||
SENSOR_TYPE_CURRENT = (16),
|
||||
SENSOR_TYPE_COLOR = (17)
|
||||
} sensors_type_t;
|
||||
|
||||
/** struct sensors_vec_s is used to return a vector in a common format. */
|
||||
typedef struct {
|
||||
union {
|
||||
float v[3];
|
||||
struct {
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
/* Orientation sensors */
|
||||
struct {
|
||||
float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */
|
||||
float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */
|
||||
float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */
|
||||
};
|
||||
};
|
||||
int8_t status;
|
||||
uint8_t reserved[3];
|
||||
} sensors_vec_t;
|
||||
|
||||
/** struct sensors_color_s is used to return color data in a common format. */
|
||||
typedef struct {
|
||||
union {
|
||||
float c[3];
|
||||
/* RGB color space */
|
||||
struct {
|
||||
float r; /**< Red component */
|
||||
float g; /**< Green component */
|
||||
float b; /**< Blue component */
|
||||
};
|
||||
};
|
||||
uint32_t rgba; /**< 24-bit RGBA value */
|
||||
} sensors_color_t;
|
||||
|
||||
/* Sensor event (36 bytes) */
|
||||
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
|
||||
typedef struct
|
||||
{
|
||||
int32_t version; /**< must be sizeof(struct sensors_event_t) */
|
||||
int32_t sensor_id; /**< unique sensor identifier */
|
||||
int32_t type; /**< sensor type */
|
||||
int32_t reserved0; /**< reserved */
|
||||
int32_t timestamp; /**< time is in milliseconds */
|
||||
union
|
||||
{
|
||||
float data[4];
|
||||
sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */
|
||||
sensors_vec_t magnetic; /**< magnetic vector values are in micro-Tesla (uT) */
|
||||
sensors_vec_t orientation; /**< orientation values are in degrees */
|
||||
sensors_vec_t gyro; /**< gyroscope values are in rad/s */
|
||||
float temperature; /**< temperature is in degrees centigrade (Celsius) */
|
||||
float distance; /**< distance in centimeters */
|
||||
float light; /**< light in SI lux units */
|
||||
float pressure; /**< pressure in hectopascal (hPa) */
|
||||
float relative_humidity; /**< relative humidity in percent */
|
||||
float current; /**< current in milliamps (mA) */
|
||||
float voltage; /**< voltage in volts (V) */
|
||||
sensors_color_t color; /**< color in RGB component values */
|
||||
};
|
||||
} sensors_event_t;
|
||||
|
||||
/* Sensor details (40 bytes) */
|
||||
/** struct sensor_s is used to describe basic information about a specific sensor. */
|
||||
typedef struct
|
||||
{
|
||||
char name[12]; /**< sensor name */
|
||||
int32_t version; /**< version of the hardware + driver */
|
||||
int32_t sensor_id; /**< unique sensor identifier */
|
||||
int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */
|
||||
float max_value; /**< maximum value of this sensor's value in SI units */
|
||||
float min_value; /**< minimum value of this sensor's value in SI units */
|
||||
float resolution; /**< smallest difference between two values reported by this sensor */
|
||||
int32_t min_delay; /**< min delay in microseconds between events. zero = not a constant rate */
|
||||
} sensor_t;
|
||||
|
||||
class Adafruit_Sensor {
|
||||
public:
|
||||
// Constructor(s)
|
||||
Adafruit_Sensor() {}
|
||||
virtual ~Adafruit_Sensor() {}
|
||||
|
||||
// These must be defined by the subclass
|
||||
virtual void enableAutoRange(bool enabled) {};
|
||||
virtual bool getEvent(sensors_event_t*) = 0;
|
||||
virtual void getSensor(sensor_t*) = 0;
|
||||
|
||||
private:
|
||||
bool _autoRange;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,221 @@
|
||||
# Adafruit Unified Sensor Driver #
|
||||
|
||||
Many small embedded systems exist to collect data from sensors, analyse the data, and either take an appropriate action or send that sensor data to another system for processing.
|
||||
|
||||
One of the many challenges of embedded systems design is the fact that parts you used today may be out of production tomorrow, or system requirements may change and you may need to choose a different sensor down the road.
|
||||
|
||||
Creating new drivers is a relatively easy task, but integrating them into existing systems is both error prone and time consuming since sensors rarely use the exact same units of measurement.
|
||||
|
||||
By reducing all data to a single **sensors\_event\_t** 'type' and settling on specific, **standardised SI units** for each sensor family the same sensor types return values that are comparable with any other similar sensor. This enables you to switch sensor models with very little impact on the rest of the system, which can help mitigate some of the risks and problems of sensor availability and code reuse.
|
||||
|
||||
The unified sensor abstraction layer is also useful for data-logging and data-transmission since you only have one well-known type to log or transmit over the air or wire.
|
||||
|
||||
## Unified Sensor Drivers ##
|
||||
|
||||
The following drivers are based on the Adafruit Unified Sensor Driver:
|
||||
|
||||
**Accelerometers**
|
||||
- [Adafruit\_ADXL345](https://github.com/adafruit/Adafruit_ADXL345)
|
||||
- [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
|
||||
- [Adafruit\_MMA8451\_Library](https://github.com/adafruit/Adafruit_MMA8451_Library)
|
||||
|
||||
**Gyroscope**
|
||||
- [Adafruit\_L3GD20\_U](https://github.com/adafruit/Adafruit_L3GD20_U)
|
||||
|
||||
**Light**
|
||||
- [Adafruit\_TSL2561](https://github.com/adafruit/Adafruit_TSL2561)
|
||||
- [Adafruit\_TSL2591\_Library](https://github.com/adafruit/Adafruit_TSL2591_Library)
|
||||
|
||||
**Magnetometers**
|
||||
- [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
|
||||
- [Adafruit\_HMC5883\_Unified](https://github.com/adafruit/Adafruit_HMC5883_Unified)
|
||||
|
||||
**Barometric Pressure**
|
||||
- [Adafruit\_BMP085\_Unified](https://github.com/adafruit/Adafruit_BMP085_Unified)
|
||||
- [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library)
|
||||
|
||||
**Humidity & Temperature**
|
||||
- [DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library)
|
||||
|
||||
**Orientation**
|
||||
- [Adafruit_BNO055](https://github.com/adafruit/Adafruit_BNO055)
|
||||
|
||||
## How Does it Work? ##
|
||||
|
||||
Any driver that supports the Adafruit unified sensor abstraction layer will implement the Adafruit\_Sensor base class. There are two main typedefs and one enum defined in Adafruit_Sensor.h that are used to 'abstract' away the sensor details and values:
|
||||
|
||||
**Sensor Types (sensors\_type\_t)**
|
||||
|
||||
These pre-defined sensor types are used to properly handle the two related typedefs below, and allows us determine what types of units the sensor uses, etc.
|
||||
|
||||
```
|
||||
/** Sensor types */
|
||||
typedef enum
|
||||
{
|
||||
SENSOR_TYPE_ACCELEROMETER = (1),
|
||||
SENSOR_TYPE_MAGNETIC_FIELD = (2),
|
||||
SENSOR_TYPE_ORIENTATION = (3),
|
||||
SENSOR_TYPE_GYROSCOPE = (4),
|
||||
SENSOR_TYPE_LIGHT = (5),
|
||||
SENSOR_TYPE_PRESSURE = (6),
|
||||
SENSOR_TYPE_PROXIMITY = (8),
|
||||
SENSOR_TYPE_GRAVITY = (9),
|
||||
SENSOR_TYPE_LINEAR_ACCELERATION = (10),
|
||||
SENSOR_TYPE_ROTATION_VECTOR = (11),
|
||||
SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
|
||||
SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
|
||||
SENSOR_TYPE_VOLTAGE = (15),
|
||||
SENSOR_TYPE_CURRENT = (16),
|
||||
SENSOR_TYPE_COLOR = (17)
|
||||
} sensors_type_t;
|
||||
```
|
||||
|
||||
**Sensor Details (sensor\_t)**
|
||||
|
||||
This typedef describes the specific capabilities of this sensor, and allows us to know what sensor we are using beneath the abstraction layer.
|
||||
|
||||
```
|
||||
/* Sensor details (40 bytes) */
|
||||
/** struct sensor_s is used to describe basic information about a specific sensor. */
|
||||
typedef struct
|
||||
{
|
||||
char name[12];
|
||||
int32_t version;
|
||||
int32_t sensor_id;
|
||||
int32_t type;
|
||||
float max_value;
|
||||
float min_value;
|
||||
float resolution;
|
||||
int32_t min_delay;
|
||||
} sensor_t;
|
||||
```
|
||||
|
||||
The individual fields are intended to be used as follows:
|
||||
|
||||
- **name**: The sensor name or ID, up to a maximum of twelve characters (ex. "MPL115A2")
|
||||
- **version**: The version of the sensor HW and the driver to allow us to differentiate versions of the board or driver
|
||||
- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network
|
||||
- **type**: The sensor type, based on **sensors\_type\_t** in sensors.h
|
||||
- **max\_value**: The maximum value that this sensor can return (in the appropriate SI unit)
|
||||
- **min\_value**: The minimum value that this sensor can return (in the appropriate SI unit)
|
||||
- **resolution**: The smallest difference between two values that this sensor can report (in the appropriate SI unit)
|
||||
- **min\_delay**: The minimum delay in microseconds between two sensor events, or '0' if there is no constant sensor rate
|
||||
|
||||
**Sensor Data/Events (sensors\_event\_t)**
|
||||
|
||||
This typedef is used to return sensor data from any sensor supported by the abstraction layer, using standard SI units and scales.
|
||||
|
||||
```
|
||||
/* Sensor event (36 bytes) */
|
||||
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
|
||||
typedef struct
|
||||
{
|
||||
int32_t version;
|
||||
int32_t sensor_id;
|
||||
int32_t type;
|
||||
int32_t reserved0;
|
||||
int32_t timestamp;
|
||||
union
|
||||
{
|
||||
float data[4];
|
||||
sensors_vec_t acceleration;
|
||||
sensors_vec_t magnetic;
|
||||
sensors_vec_t orientation;
|
||||
sensors_vec_t gyro;
|
||||
float temperature;
|
||||
float distance;
|
||||
float light;
|
||||
float pressure;
|
||||
float relative_humidity;
|
||||
float current;
|
||||
float voltage;
|
||||
sensors_color_t color;
|
||||
};
|
||||
} sensors_event_t;
|
||||
```
|
||||
It includes the following fields:
|
||||
|
||||
- **version**: Contain 'sizeof(sensors\_event\_t)' to identify which version of the API we're using in case this changes in the future
|
||||
- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network (must match the sensor\_id value in the corresponding sensor\_t enum above!)
|
||||
- **type**: the sensor type, based on **sensors\_type\_t** in sensors.h
|
||||
- **timestamp**: time in milliseconds when the sensor value was read
|
||||
- **data[4]**: An array of four 32-bit values that allows us to encapsulate any type of sensor data via a simple union (further described below)
|
||||
|
||||
**Required Functions**
|
||||
|
||||
In addition to the two standard types and the sensor type enum, all drivers based on Adafruit_Sensor must also implement the following two functions:
|
||||
|
||||
```
|
||||
bool getEvent(sensors_event_t*);
|
||||
```
|
||||
Calling this function will populate the supplied sensors\_event\_t reference with the latest available sensor data. You should call this function as often as you want to update your data.
|
||||
|
||||
```
|
||||
void getSensor(sensor_t*);
|
||||
```
|
||||
Calling this function will provide some basic information about the sensor (the sensor name, driver version, min and max values, etc.
|
||||
|
||||
**Standardised SI values for sensors\_event\_t**
|
||||
|
||||
A key part of the abstraction layer is the standardisation of values on SI units of a particular scale, which is accomplished via the data[4] union in sensors\_event\_t above. This 16 byte union includes fields for each main sensor type, and uses the following SI units and scales:
|
||||
|
||||
- **acceleration**: values are in **meter per second per second** (m/s^2)
|
||||
- **magnetic**: values are in **micro-Tesla** (uT)
|
||||
- **orientation**: values are in **degrees**
|
||||
- **gyro**: values are in **rad/s**
|
||||
- **temperature**: values in **degrees centigrade** (Celsius)
|
||||
- **distance**: values are in **centimeters**
|
||||
- **light**: values are in **SI lux** units
|
||||
- **pressure**: values are in **hectopascal** (hPa)
|
||||
- **relative\_humidity**: values are in **percent**
|
||||
- **current**: values are in **milliamps** (mA)
|
||||
- **voltage**: values are in **volts** (V)
|
||||
- **color**: values are in 0..1.0 RGB channel luminosity and 32-bit RGBA format
|
||||
|
||||
## The Unified Driver Abstraction Layer in Practice ##
|
||||
|
||||
Using the unified sensor abstraction layer is relatively easy once a compliant driver has been created.
|
||||
|
||||
Every compliant sensor can now be read using a single, well-known 'type' (sensors\_event\_t), and there is a standardised way of interrogating a sensor about its specific capabilities (via sensor\_t).
|
||||
|
||||
An example of reading the [TSL2561](https://github.com/adafruit/Adafruit_TSL2561) light sensor can be seen below:
|
||||
|
||||
```
|
||||
Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345);
|
||||
...
|
||||
/* Get a new sensor event */
|
||||
sensors_event_t event;
|
||||
tsl.getEvent(&event);
|
||||
|
||||
/* Display the results (light is measured in lux) */
|
||||
if (event.light)
|
||||
{
|
||||
Serial.print(event.light); Serial.println(" lux");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* If event.light = 0 lux the sensor is probably saturated
|
||||
and no reliable data could be generated! */
|
||||
Serial.println("Sensor overload");
|
||||
}
|
||||
```
|
||||
|
||||
Similarly, we can get the basic technical capabilities of this sensor with the following code:
|
||||
|
||||
```
|
||||
sensor_t sensor;
|
||||
|
||||
sensor_t sensor;
|
||||
tsl.getSensor(&sensor);
|
||||
|
||||
/* Display the sensor details */
|
||||
Serial.println("------------------------------------");
|
||||
Serial.print ("Sensor: "); Serial.println(sensor.name);
|
||||
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
|
||||
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
|
||||
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux");
|
||||
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux");
|
||||
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux");
|
||||
Serial.println("------------------------------------");
|
||||
Serial.println("");
|
||||
```
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Adafruit Unified Sensor
|
||||
version=1.0.2
|
||||
author=Adafruit <info@adafruit.com>
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Required for all Adafruit Unified Sensor based libraries.
|
||||
paragraph=A unified sensor abstraction layer used by many Adafruit sensor libraries.
|
||||
category=Sensors
|
||||
url=https://github.com/adafruit/Adafruit_Sensor
|
||||
architectures=*
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
Thank you for opening an issue on an Adafruit Arduino library repository. To
|
||||
improve the speed of resolution please review the following guidelines and
|
||||
common troubleshooting steps below before creating the issue:
|
||||
|
||||
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
|
||||
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
|
||||
something isn't working as expected. In many cases the problem is a common issue
|
||||
that you will more quickly receive help from the forum community. GitHub issues
|
||||
are meant for known defects in the code. If you don't know if there is a defect
|
||||
in the code then start with troubleshooting on the forum first.
|
||||
|
||||
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
|
||||
check all of the steps and commands to run have been followed. Consult the
|
||||
forum if you're unsure or have questions about steps in a guide/tutorial.
|
||||
|
||||
- **For Arduino projects check these very common issues to ensure they don't apply**:
|
||||
|
||||
- For uploading sketches or communicating with the board make sure you're using
|
||||
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
|
||||
very hard to tell the difference between a data and charge cable! Try using the
|
||||
cable with other devices or swapping to another cable to confirm it is not
|
||||
the problem.
|
||||
|
||||
- **Be sure you are supplying adequate power to the board.** Check the specs of
|
||||
your board and plug in an external power supply. In many cases just
|
||||
plugging a board into your computer is not enough to power it and other
|
||||
peripherals.
|
||||
|
||||
- **Double check all soldering joints and connections.** Flakey connections
|
||||
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
|
||||
|
||||
- **Ensure you are using an official Arduino or Adafruit board.** We can't
|
||||
guarantee a clone board will have the same functionality and work as expected
|
||||
with this code and don't support them.
|
||||
|
||||
If you're sure this issue is a defect in the code and checked the steps above
|
||||
please fill in the following fields to provide enough troubleshooting information.
|
||||
You may delete the guideline and text above to just leave the following details:
|
||||
|
||||
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
|
||||
|
||||
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
|
||||
VERSION HERE**
|
||||
|
||||
- List the steps to reproduce the problem below (if possible attach a sketch or
|
||||
copy the sketch code in too): **LIST REPRO STEPS BELOW**
|
||||
@@ -0,0 +1,26 @@
|
||||
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
|
||||
Before you open the request please review the following guidelines and tips to
|
||||
help it be more easily integrated:
|
||||
|
||||
- **Describe the scope of your change--i.e. what the change does and what parts
|
||||
of the code were modified.** This will help us understand any risks of integrating
|
||||
the code.
|
||||
|
||||
- **Describe any known limitations with your change.** For example if the change
|
||||
doesn't apply to a supported platform of the library please mention it.
|
||||
|
||||
- **Please run any tests or examples that can exercise your modified code.** We
|
||||
strive to not break users of the code and running tests/examples helps with this
|
||||
process.
|
||||
|
||||
Thank you again for contributing! We will try to test and integrate the change
|
||||
as soon as we can, but be aware we have many GitHub repositories to manage and
|
||||
can't immediately respond to every request. There is no need to bump or check in
|
||||
on a pull request (it will clutter the discussion of the request).
|
||||
|
||||
Also don't be worried if the request is closed or not integrated--sometimes the
|
||||
priorities of Adafruit's GitHub code (education, ease of use) might not match the
|
||||
priorities of the pull request. Don't fret, the open source community thrives on
|
||||
forks and GitHub makes it easy to keep your changes in a forked repo.
|
||||
|
||||
After reviewing the guidelines above you can delete this text from the pull request.
|
||||
@@ -0,0 +1,504 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file Adafruit_TSL2591.cpp
|
||||
@author KT0WN (adafruit.com)
|
||||
|
||||
This is a library for the Adafruit TSL2591 breakout board
|
||||
This library works with the Adafruit TSL2591 breakout
|
||||
----> https://www.adafruit.com/products/1980
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use I2C to communicate
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2014 Adafruit Industries
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
#if defined(ESP8266) || defined(ESP32)
|
||||
#include <pgmspace.h>
|
||||
#else
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
#if defined(__AVR__)
|
||||
#include <util/delay.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Adafruit_TSL2591.h"
|
||||
|
||||
Adafruit_TSL2591::Adafruit_TSL2591(int32_t sensorID)
|
||||
{
|
||||
_initialized = false;
|
||||
_integration = TSL2591_INTEGRATIONTIME_100MS;
|
||||
_gain = TSL2591_GAIN_MED;
|
||||
_sensorID = sensorID;
|
||||
|
||||
// we cant do wire initialization till later, because we havent loaded Wire yet
|
||||
}
|
||||
|
||||
boolean Adafruit_TSL2591::begin(void)
|
||||
{
|
||||
Wire.begin();
|
||||
|
||||
/*
|
||||
for (uint8_t i=0; i<0x20; i++)
|
||||
{
|
||||
uint8_t id = read8(0x12);
|
||||
Serial.print("$"); Serial.print(i, HEX);
|
||||
Serial.print(" = 0x"); Serial.println(read8(i), HEX);
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t id = read8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_ID);
|
||||
if (id == 0x50 )
|
||||
{
|
||||
// Serial.println("Found Adafruit_TSL2591");
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
|
||||
// Set default integration time and gain
|
||||
setTiming(_integration);
|
||||
setGain(_gain);
|
||||
|
||||
// Note: by default, the device is in power down mode on bootup
|
||||
disable();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::enable(void)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the device by setting the control bit to 0x01
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWERON | TSL2591_ENABLE_AEN | TSL2591_ENABLE_AIEN | TSL2591_ENABLE_NPIEN);
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::disable(void)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the device by setting the control bit to 0x00
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_ENABLE, TSL2591_ENABLE_POWEROFF);
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::setGain(tsl2591Gain_t gain)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
_gain = gain;
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, _integration | _gain);
|
||||
disable();
|
||||
}
|
||||
|
||||
tsl2591Gain_t Adafruit_TSL2591::getGain()
|
||||
{
|
||||
return _gain;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::setTiming(tsl2591IntegrationTime_t integration)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
_integration = integration;
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CONTROL, _integration | _gain);
|
||||
disable();
|
||||
}
|
||||
|
||||
tsl2591IntegrationTime_t Adafruit_TSL2591::getTiming()
|
||||
{
|
||||
return _integration;
|
||||
}
|
||||
|
||||
float Adafruit_TSL2591::calculateLuxf(uint16_t ch0, uint16_t ch1)
|
||||
{
|
||||
float atime, again;
|
||||
float cpl, lux1, lux2, lux;
|
||||
uint32_t chan0, chan1;
|
||||
|
||||
// Check for overflow conditions first
|
||||
if ((ch0 == 0xFFFF) | (ch1 == 0xFFFF))
|
||||
{
|
||||
// Signal an overflow
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Note: This algorithm is based on preliminary coefficients
|
||||
// provided by AMS and may need to be updated in the future
|
||||
|
||||
switch (_integration)
|
||||
{
|
||||
case TSL2591_INTEGRATIONTIME_100MS :
|
||||
atime = 100.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_200MS :
|
||||
atime = 200.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_300MS :
|
||||
atime = 300.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_400MS :
|
||||
atime = 400.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_500MS :
|
||||
atime = 500.0F;
|
||||
break;
|
||||
case TSL2591_INTEGRATIONTIME_600MS :
|
||||
atime = 600.0F;
|
||||
break;
|
||||
default: // 100ms
|
||||
atime = 100.0F;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (_gain)
|
||||
{
|
||||
case TSL2591_GAIN_LOW :
|
||||
again = 1.0F;
|
||||
break;
|
||||
case TSL2591_GAIN_MED :
|
||||
again = 25.0F;
|
||||
break;
|
||||
case TSL2591_GAIN_HIGH :
|
||||
again = 428.0F;
|
||||
break;
|
||||
case TSL2591_GAIN_MAX :
|
||||
again = 9876.0F;
|
||||
break;
|
||||
default:
|
||||
again = 1.0F;
|
||||
break;
|
||||
}
|
||||
|
||||
// cpl = (ATIME * AGAIN) / DF
|
||||
cpl = (atime * again) / TSL2591_LUX_DF;
|
||||
|
||||
lux1 = (((float) ch0 - (float) ch1)) * (1.0F - ((float) ch1 / (float) ch0)) / cpl;//( (float)ch0 - (TSL2591_LUX_COEFB * (float)ch1) ) / cpl;
|
||||
lux2 = ((TSL2591_LUX_COEFC * (float) ch0) - (TSL2591_LUX_COEFD * (float) ch1)) / cpl;
|
||||
lux = lux1 > lux2 ? lux1 : lux2;
|
||||
|
||||
// Alternate lux calculation
|
||||
//lux = ( (float)ch0 - ( 1.7F * (float)ch1 ) ) / cpl;
|
||||
|
||||
// Signal I2C had no errors
|
||||
return lux;
|
||||
}
|
||||
|
||||
uint32_t Adafruit_TSL2591::calculateLux(uint16_t ch0, uint16_t ch1)
|
||||
{
|
||||
return (uint32_t) calculateLuxf(ch0, ch1);
|
||||
}
|
||||
|
||||
uint32_t Adafruit_TSL2591::getFullLuminosity (void)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the device
|
||||
enable();
|
||||
|
||||
// Wait x ms for ADC to complete
|
||||
for (uint8_t d=0; d<=_integration; d++)
|
||||
{
|
||||
delay(120);
|
||||
}
|
||||
|
||||
uint32_t x;
|
||||
uint16_t y;
|
||||
y |= read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW);
|
||||
x = read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW);
|
||||
x <<= 16;
|
||||
x |= y;
|
||||
|
||||
disable();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16_t Adafruit_TSL2591::getLuminosity (uint8_t channel)
|
||||
{
|
||||
uint32_t x = getFullLuminosity();
|
||||
|
||||
if (channel == TSL2591_FULLSPECTRUM)
|
||||
{
|
||||
// Reads two byte value from channel 0 (visible + infrared)
|
||||
return (x & 0xFFFF);
|
||||
}
|
||||
else if (channel == TSL2591_INFRARED)
|
||||
{
|
||||
// Reads two byte value from channel 1 (infrared)
|
||||
return (x >> 16);
|
||||
}
|
||||
else if (channel == TSL2591_VISIBLE)
|
||||
{
|
||||
// Reads all and subtracts out just the visible!
|
||||
return ( (x & 0xFFFF) - (x >> 16));
|
||||
}
|
||||
|
||||
// unknown channel!
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAILTL, lowerThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAILTH, lowerThreshold >> 8);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAIHTL, upperThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_NPAIHTH, upperThreshold >> 8);
|
||||
disable();
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold, tsl2591Persist_t persist)
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_PERSIST_FILTER, persist);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AILTL, lowerThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AILTH, lowerThreshold >> 8);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AIHTL, upperThreshold);
|
||||
write8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_THRESHOLD_AIHTH, upperThreshold >> 8);
|
||||
disable();
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::clearInterrupt()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enable();
|
||||
write8(TSL2591_CLEAR_INT);
|
||||
disable();
|
||||
}
|
||||
|
||||
|
||||
uint8_t Adafruit_TSL2591::getStatus()
|
||||
{
|
||||
if (!_initialized)
|
||||
{
|
||||
if (!begin())
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Enable the device
|
||||
enable();
|
||||
uint8_t x;
|
||||
x = read8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_STATUS);
|
||||
disable();
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
uint8_t Adafruit_TSL2591::read8(uint8_t reg)
|
||||
{
|
||||
uint8_t x;
|
||||
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(TSL2591_ADDR, 1);
|
||||
#if ARDUINO >= 100
|
||||
x = Wire.read();
|
||||
#else
|
||||
x = Wire.receive();
|
||||
#endif
|
||||
// while (! Wire.available());
|
||||
// return Wire.read();
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16_t Adafruit_TSL2591::read16(uint8_t reg)
|
||||
{
|
||||
uint16_t x;
|
||||
uint16_t t;
|
||||
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
|
||||
Wire.requestFrom(TSL2591_ADDR, 2);
|
||||
#if ARDUINO >= 100
|
||||
t = Wire.read();
|
||||
x = Wire.read();
|
||||
#else
|
||||
t = Wire.receive();
|
||||
x = Wire.receive();
|
||||
#endif
|
||||
x <<= 8;
|
||||
x |= t;
|
||||
return x;
|
||||
}
|
||||
|
||||
void Adafruit_TSL2591::write8 (uint8_t reg, uint8_t value)
|
||||
{
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
Wire.write(value);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
Wire.send(value);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
|
||||
void Adafruit_TSL2591::write8 (uint8_t reg)
|
||||
{
|
||||
Wire.beginTransmission(TSL2591_ADDR);
|
||||
#if ARDUINO >= 100
|
||||
Wire.write(reg);
|
||||
#else
|
||||
Wire.send(reg);
|
||||
#endif
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Gets the most recent sensor event
|
||||
*/
|
||||
/**************************************************************************/
|
||||
bool Adafruit_TSL2591::getEvent(sensors_event_t *event)
|
||||
{
|
||||
uint16_t ir, full;
|
||||
uint32_t lum = getFullLuminosity();
|
||||
/* Early silicon seems to have issues when there is a sudden jump in */
|
||||
/* light levels. :( To work around this for now sample the sensor 2x */
|
||||
lum = getFullLuminosity();
|
||||
ir = lum >> 16;
|
||||
full = lum & 0xFFFF;
|
||||
|
||||
/* Clear the event */
|
||||
memset(event, 0, sizeof(sensors_event_t));
|
||||
|
||||
event->version = sizeof(sensors_event_t);
|
||||
event->sensor_id = _sensorID;
|
||||
event->type = SENSOR_TYPE_LIGHT;
|
||||
event->timestamp = millis();
|
||||
|
||||
/* Calculate the actual lux value */
|
||||
/* 0 = sensor overflow (too much light) */
|
||||
event->light = calculateLux(full, ir);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Gets the sensor_t data
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void Adafruit_TSL2591::getSensor(sensor_t *sensor)
|
||||
{
|
||||
/* Clear the sensor_t object */
|
||||
memset(sensor, 0, sizeof(sensor_t));
|
||||
|
||||
/* Insert the sensor name in the fixed length char array */
|
||||
strncpy (sensor->name, "TSL2591", sizeof(sensor->name) - 1);
|
||||
sensor->name[sizeof(sensor->name)- 1] = 0;
|
||||
sensor->version = 1;
|
||||
sensor->sensor_id = _sensorID;
|
||||
sensor->type = SENSOR_TYPE_LIGHT;
|
||||
sensor->min_delay = 0;
|
||||
sensor->max_value = 88000.0;
|
||||
sensor->min_value = 0.0;
|
||||
sensor->resolution = 1.0;
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@file Adafruit_TSL2591.h
|
||||
@author KT0WN (adafruit.com)
|
||||
|
||||
This is a library for the Adafruit TSL2591 breakout board
|
||||
This library works with the Adafruit TSL2591 breakout
|
||||
----> https://www.adafruit.com/products/1980
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These chips use I2C to communicate
|
||||
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2014 Adafruit Industries
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef _TSL2591_H_
|
||||
#define _TSL2591_H_
|
||||
|
||||
#if ARDUINO >= 100
|
||||
#include <Arduino.h>
|
||||
#else
|
||||
#include <WProgram.h>
|
||||
#endif
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include <Wire.h>
|
||||
|
||||
#define TSL2591_VISIBLE (2) // channel 0 - channel 1
|
||||
#define TSL2591_INFRARED (1) // channel 1
|
||||
#define TSL2591_FULLSPECTRUM (0) // channel 0
|
||||
|
||||
#define TSL2591_ADDR (0x29)
|
||||
#define TSL2591_READBIT (0x01)
|
||||
|
||||
#define TSL2591_COMMAND_BIT (0xA0) // 1010 0000: bits 7 and 5 for 'command normal'
|
||||
#define TSL2591_CLEAR_INT (0xE7)
|
||||
#define TSL2591_TEST_INT (0xE4)
|
||||
#define TSL2591_WORD_BIT (0x20) // 1 = read/write word (rather than byte)
|
||||
#define TSL2591_BLOCK_BIT (0x10) // 1 = using block read/write
|
||||
|
||||
#define TSL2591_ENABLE_POWEROFF (0x00)
|
||||
#define TSL2591_ENABLE_POWERON (0x01)
|
||||
#define TSL2591_ENABLE_AEN (0x02) // ALS Enable. This field activates ALS function. Writing a one activates the ALS. Writing a zero disables the ALS.
|
||||
#define TSL2591_ENABLE_AIEN (0x10) // ALS Interrupt Enable. When asserted permits ALS interrupts to be generated, subject to the persist filter.
|
||||
#define TSL2591_ENABLE_NPIEN (0x80) // No Persist Interrupt Enable. When asserted NP Threshold conditions will generate an interrupt, bypassing the persist filter
|
||||
|
||||
#define TSL2591_LUX_DF (408.0F)
|
||||
#define TSL2591_LUX_COEFB (1.64F) // CH0 coefficient
|
||||
#define TSL2591_LUX_COEFC (0.59F) // CH1 coefficient A
|
||||
#define TSL2591_LUX_COEFD (0.86F) // CH2 coefficient B
|
||||
|
||||
enum
|
||||
{
|
||||
TSL2591_REGISTER_ENABLE = 0x00,
|
||||
TSL2591_REGISTER_CONTROL = 0x01,
|
||||
TSL2591_REGISTER_THRESHOLD_AILTL = 0x04, // ALS low threshold lower byte
|
||||
TSL2591_REGISTER_THRESHOLD_AILTH = 0x05, // ALS low threshold upper byte
|
||||
TSL2591_REGISTER_THRESHOLD_AIHTL = 0x06, // ALS high threshold lower byte
|
||||
TSL2591_REGISTER_THRESHOLD_AIHTH = 0x07, // ALS high threshold upper byte
|
||||
TSL2591_REGISTER_THRESHOLD_NPAILTL = 0x08, // No Persist ALS low threshold lower byte
|
||||
TSL2591_REGISTER_THRESHOLD_NPAILTH = 0x09, // etc
|
||||
TSL2591_REGISTER_THRESHOLD_NPAIHTL = 0x0A,
|
||||
TSL2591_REGISTER_THRESHOLD_NPAIHTH = 0x0B,
|
||||
TSL2591_REGISTER_PERSIST_FILTER = 0x0C,
|
||||
TSL2591_REGISTER_PACKAGE_PID = 0x11,
|
||||
TSL2591_REGISTER_DEVICE_ID = 0x12,
|
||||
TSL2591_REGISTER_DEVICE_STATUS = 0x13,
|
||||
TSL2591_REGISTER_CHAN0_LOW = 0x14,
|
||||
TSL2591_REGISTER_CHAN0_HIGH = 0x15,
|
||||
TSL2591_REGISTER_CHAN1_LOW = 0x16,
|
||||
TSL2591_REGISTER_CHAN1_HIGH = 0x17
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSL2591_INTEGRATIONTIME_100MS = 0x00,
|
||||
TSL2591_INTEGRATIONTIME_200MS = 0x01,
|
||||
TSL2591_INTEGRATIONTIME_300MS = 0x02,
|
||||
TSL2591_INTEGRATIONTIME_400MS = 0x03,
|
||||
TSL2591_INTEGRATIONTIME_500MS = 0x04,
|
||||
TSL2591_INTEGRATIONTIME_600MS = 0x05,
|
||||
}
|
||||
tsl2591IntegrationTime_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
// bit 7:4: 0
|
||||
TSL2591_PERSIST_EVERY = 0x00, // Every ALS cycle generates an interrupt
|
||||
TSL2591_PERSIST_ANY = 0x01, // Any value outside of threshold range
|
||||
TSL2591_PERSIST_2 = 0x02, // 2 consecutive values out of range
|
||||
TSL2591_PERSIST_3 = 0x03, // 3 consecutive values out of range
|
||||
TSL2591_PERSIST_5 = 0x04, // 5 consecutive values out of range
|
||||
TSL2591_PERSIST_10 = 0x05, // 10 consecutive values out of range
|
||||
TSL2591_PERSIST_15 = 0x06, // 15 consecutive values out of range
|
||||
TSL2591_PERSIST_20 = 0x07, // 20 consecutive values out of range
|
||||
TSL2591_PERSIST_25 = 0x08, // 25 consecutive values out of range
|
||||
TSL2591_PERSIST_30 = 0x09, // 30 consecutive values out of range
|
||||
TSL2591_PERSIST_35 = 0x0A, // 35 consecutive values out of range
|
||||
TSL2591_PERSIST_40 = 0x0B, // 40 consecutive values out of range
|
||||
TSL2591_PERSIST_45 = 0x0C, // 45 consecutive values out of range
|
||||
TSL2591_PERSIST_50 = 0x0D, // 50 consecutive values out of range
|
||||
TSL2591_PERSIST_55 = 0x0E, // 55 consecutive values out of range
|
||||
TSL2591_PERSIST_60 = 0x0F, // 60 consecutive values out of range
|
||||
}
|
||||
tsl2591Persist_t;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
TSL2591_GAIN_LOW = 0x00, // low gain (1x)
|
||||
TSL2591_GAIN_MED = 0x10, // medium gain (25x)
|
||||
TSL2591_GAIN_HIGH = 0x20, // medium gain (428x)
|
||||
TSL2591_GAIN_MAX = 0x30, // max gain (9876x)
|
||||
}
|
||||
tsl2591Gain_t;
|
||||
|
||||
class Adafruit_TSL2591 : public Adafruit_Sensor
|
||||
{
|
||||
public:
|
||||
Adafruit_TSL2591(int32_t sensorID = -1);
|
||||
|
||||
boolean begin ( void );
|
||||
void enable ( void );
|
||||
void disable ( void );
|
||||
void write8 ( uint8_t r);
|
||||
void write8 ( uint8_t r, uint8_t v );
|
||||
uint16_t read16 ( uint8_t reg );
|
||||
uint8_t read8 ( uint8_t reg );
|
||||
|
||||
uint32_t calculateLux ( uint16_t ch0, uint16_t ch1 );
|
||||
float calculateLuxf ( uint16_t ch0, uint16_t ch1 );
|
||||
void setGain ( tsl2591Gain_t gain );
|
||||
void setTiming ( tsl2591IntegrationTime_t integration );
|
||||
uint16_t getLuminosity (uint8_t channel );
|
||||
uint32_t getFullLuminosity ( );
|
||||
|
||||
tsl2591IntegrationTime_t getTiming();
|
||||
tsl2591Gain_t getGain();
|
||||
|
||||
// Interrupt
|
||||
void clearInterrupt(void);
|
||||
void registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold);
|
||||
void registerInterrupt(uint16_t lowerThreshold, uint16_t upperThreshold, tsl2591Persist_t persist);
|
||||
uint8_t getStatus();
|
||||
|
||||
/* Unified Sensor API Functions */
|
||||
bool getEvent ( sensors_event_t* );
|
||||
void getSensor ( sensor_t* );
|
||||
|
||||
private:
|
||||
tsl2591IntegrationTime_t _integration;
|
||||
tsl2591Gain_t _gain;
|
||||
int32_t _sensorID;
|
||||
|
||||
boolean _initialized;
|
||||
};
|
||||
#endif
|
||||
@@ -0,0 +1,9 @@
|
||||
This is an Arduino library for the TSL2591 digital luminosity (light) sensors.
|
||||
|
||||
Pick one up at http://www.adafruit.com/products/1980
|
||||
|
||||
To download. click the DOWNLOADS button in the top right corner, rename the uncompressed folder Adafruit_TSL2591. Check that the Adafruit_TSL2591 folder contains Adafruit_TSL2591.cpp and Adafruit_TSL2591.h
|
||||
|
||||
Place the Adafruit_TSL2591 library folder your <arduinosketchfolder>/libraries/ folder. You may need to create the libraries subfolder if its your first library. Restart the IDE.
|
||||
|
||||
You'll also need the Adafruit_Sensor library from https://github.com/adafruit/Adafruit_Sensor
|
||||
@@ -0,0 +1,200 @@
|
||||
/* TSL2591 Digital Light Sensor */
|
||||
/* Dynamic Range: 600M:1 */
|
||||
/* Maximum Lux: 88K */
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include "Adafruit_TSL2591.h"
|
||||
|
||||
// Example for demonstrating the TSL2591 library - public domain!
|
||||
|
||||
// connect SCL to analog 5
|
||||
// connect SDA to analog 4
|
||||
// connect Vin to 3.3-5V DC
|
||||
// connect GROUND to common ground
|
||||
|
||||
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Displays some basic information on this sensor from the unified
|
||||
sensor API sensor_t type (see Adafruit_Sensor for more information)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void displaySensorDetails(void)
|
||||
{
|
||||
sensor_t sensor;
|
||||
tsl.getSensor(&sensor);
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.print (F("Sensor: ")); Serial.println(sensor.name);
|
||||
Serial.print (F("Driver Ver: ")); Serial.println(sensor.version);
|
||||
Serial.print (F("Unique ID: ")); Serial.println(sensor.sensor_id);
|
||||
Serial.print (F("Max Value: ")); Serial.print(sensor.max_value); Serial.println(F(" lux"));
|
||||
Serial.print (F("Min Value: ")); Serial.print(sensor.min_value); Serial.println(F(" lux"));
|
||||
Serial.print (F("Resolution: ")); Serial.print(sensor.resolution); Serial.println(F(" lux"));
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.println(F(""));
|
||||
delay(500);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Configures the gain and integration time for the TSL2591
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void configureSensor(void)
|
||||
{
|
||||
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
|
||||
//tsl.setGain(TSL2591_GAIN_LOW); // 1x gain (bright light)
|
||||
tsl.setGain(TSL2591_GAIN_MED); // 25x gain
|
||||
// tsl.setGain(TSL2591_GAIN_HIGH); // 428x gain
|
||||
|
||||
// Changing the integration time gives you a longer time over which to sense light
|
||||
// longer timelines are slower, but are good in very low light situtations!
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); // shortest integration time (bright light)
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // longest integration time (dim light)
|
||||
|
||||
/* Display the gain and integration time for reference sake */
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.print (F("Gain: "));
|
||||
tsl2591Gain_t gain = tsl.getGain();
|
||||
switch(gain)
|
||||
{
|
||||
case TSL2591_GAIN_LOW:
|
||||
Serial.println(F("1x (Low)"));
|
||||
break;
|
||||
case TSL2591_GAIN_MED:
|
||||
Serial.println(F("25x (Medium)"));
|
||||
break;
|
||||
case TSL2591_GAIN_HIGH:
|
||||
Serial.println(F("428x (High)"));
|
||||
break;
|
||||
case TSL2591_GAIN_MAX:
|
||||
Serial.println(F("9876x (Max)"));
|
||||
break;
|
||||
}
|
||||
Serial.print (F("Timing: "));
|
||||
Serial.print((tsl.getTiming() + 1) * 100, DEC);
|
||||
Serial.println(F(" ms"));
|
||||
Serial.println(F("------------------------------------"));
|
||||
Serial.println(F(""));
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Program entry point for the Arduino sketch
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
Serial.println(F("Starting Adafruit TSL2591 Test!"));
|
||||
|
||||
if (tsl.begin())
|
||||
{
|
||||
Serial.println(F("Found a TSL2591 sensor"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println(F("No sensor found ... check your wiring?"));
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Display some basic information on this sensor */
|
||||
displaySensorDetails();
|
||||
|
||||
/* Configure the sensor */
|
||||
configureSensor();
|
||||
|
||||
// Now we're ready to get readings ... move on to loop()!
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Shows how to perform a basic read on visible, full spectrum or
|
||||
infrared light (returns raw 16-bit ADC values)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void simpleRead(void)
|
||||
{
|
||||
// Simple data read example. Just read the infrared, fullspecrtrum diode
|
||||
// or 'visible' (difference between the two) channels.
|
||||
// This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
|
||||
uint16_t x = tsl.getLuminosity(TSL2591_VISIBLE);
|
||||
//uint16_t x = tsl.getLuminosity(TSL2591_FULLSPECTRUM);
|
||||
//uint16_t x = tsl.getLuminosity(TSL2591_INFRARED);
|
||||
|
||||
Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
|
||||
Serial.print(F("Luminosity: "));
|
||||
Serial.println(x, DEC);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Show how to read IR and Full Spectrum at once and convert to lux
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void advancedRead(void)
|
||||
{
|
||||
// More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
|
||||
// That way you can do whatever math and comparisons you want!
|
||||
uint32_t lum = tsl.getFullLuminosity();
|
||||
uint16_t ir, full;
|
||||
ir = lum >> 16;
|
||||
full = lum & 0xFFFF;
|
||||
Serial.print(F("[ ")); Serial.print(millis()); Serial.print(F(" ms ] "));
|
||||
Serial.print(F("IR: ")); Serial.print(ir); Serial.print(F(" "));
|
||||
Serial.print(F("Full: ")); Serial.print(full); Serial.print(F(" "));
|
||||
Serial.print(F("Visible: ")); Serial.print(full - ir); Serial.print(F(" "));
|
||||
Serial.print(F("Lux: ")); Serial.println(tsl.calculateLux(full, ir));
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Performs a read using the Adafruit Unified Sensor API.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void unifiedSensorAPIRead(void)
|
||||
{
|
||||
/* Get a new sensor event */
|
||||
sensors_event_t event;
|
||||
tsl.getEvent(&event);
|
||||
|
||||
/* Display the results (light is measured in lux) */
|
||||
Serial.print(F("[ ")); Serial.print(event.timestamp); Serial.print(F(" ms ] "));
|
||||
if ((event.light == 0) |
|
||||
(event.light > 4294966000.0) |
|
||||
(event.light <-4294966000.0))
|
||||
{
|
||||
/* If event.light = 0 lux the sensor is probably saturated */
|
||||
/* and no reliable data could be generated! */
|
||||
/* if event.light is +/- 4294967040 there was a float over/underflow */
|
||||
Serial.println(F("Invalid data (adjust gain or timing)"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.print(event.light); Serial.println(F(" lux"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Arduino loop function, called once 'setup' is complete (your own code
|
||||
should go here)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void loop(void)
|
||||
{
|
||||
//simpleRead();
|
||||
advancedRead();
|
||||
// unifiedSensorAPIRead();
|
||||
|
||||
delay(500);
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
/* TSL2591 Digital Light Sensor, example with (simple) interrupt support */
|
||||
/* Dynamic Range: 600M:1 */
|
||||
/* Maximum Lux: 88K */
|
||||
|
||||
/* This example shows how the interrupt system on the TLS2591
|
||||
* can be used to detect a meaningful change in light levels.
|
||||
*
|
||||
* Two thresholds can be set:
|
||||
*
|
||||
* Lower Threshold - Any light sample on CHAN0 below this value
|
||||
* will trigger an interrupt
|
||||
* Upper Threshold - Any light sample on CHAN0 above this value
|
||||
* will trigger an interrupt
|
||||
*
|
||||
* If CHAN0 (full light) crosses below the low threshold specified,
|
||||
* or above the higher threshold, an interrupt is asserted on the interrupt
|
||||
* pin. The use of the HW pin is optional, though, since the change can
|
||||
* also be detected in software by looking at the status byte via
|
||||
* tsl.getStatus().
|
||||
*
|
||||
* An optional third parameter can be used in the .registerInterrupt
|
||||
* function to indicate the number of samples that must stay outside
|
||||
* the threshold window before the interrupt fires, providing some basic
|
||||
* debouncing of light level data.
|
||||
*
|
||||
* For example, the following code will fire an interrupt on any and every
|
||||
* sample outside the window threshold (meaning a sample below 100 or above
|
||||
* 1500 on CHAN0 or FULL light):
|
||||
*
|
||||
* tsl.registerInterrupt(100, 1500, TSL2591_PERSIST_ANY);
|
||||
*
|
||||
* This code would require five consecutive changes before the interrupt
|
||||
* fires though (see tls2591Persist_t in Adafruit_TLS2591.h for possible
|
||||
* values):
|
||||
*
|
||||
* tsl.registerInterrupt(100, 1500, TSL2591_PERSIST_5);
|
||||
*/
|
||||
|
||||
#include <Wire.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include "Adafruit_TSL2591.h"
|
||||
|
||||
// Example for demonstrating the TSL2591 library - public domain!
|
||||
|
||||
// connect SCL to analog 5
|
||||
// connect SDA to analog 4
|
||||
// connect Vin to 3.3-5V DC
|
||||
// connect GROUND to common ground
|
||||
|
||||
// Interrupt thresholds and persistance
|
||||
#define TLS2591_INT_THRESHOLD_LOWER (100)
|
||||
#define TLS2591_INT_THRESHOLD_UPPER (1500)
|
||||
//#define TLS2591_INT_PERSIST (TSL2591_PERSIST_ANY) // Fire on any valid change
|
||||
#define TLS2591_INT_PERSIST (TSL2591_PERSIST_60) // Require at least 60 samples to fire
|
||||
|
||||
Adafruit_TSL2591 tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Displays some basic information on this sensor from the unified
|
||||
sensor API sensor_t type (see Adafruit_Sensor for more information)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void displaySensorDetails(void)
|
||||
{
|
||||
sensor_t sensor;
|
||||
tsl.getSensor(&sensor);
|
||||
Serial.println("------------------------------------");
|
||||
Serial.print ("Sensor: "); Serial.println(sensor.name);
|
||||
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
|
||||
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
|
||||
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux");
|
||||
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux");
|
||||
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux");
|
||||
Serial.println("------------------------------------");
|
||||
Serial.println("");
|
||||
delay(500);
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Configures the gain and integration time for the TSL2591
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void configureSensor(void)
|
||||
{
|
||||
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
|
||||
//tsl.setGain(TSL2591_GAIN_LOW); // 1x gain (bright light)
|
||||
tsl.setGain(TSL2591_GAIN_MED); // 25x gain
|
||||
// tsl.setGain(TSL2591_GAIN_HIGH); // 428x gain
|
||||
|
||||
// Changing the integration time gives you a longer time over which to sense light
|
||||
// longer timelines are slower, but are good in very low light situtations!
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); // shortest integration time (bright light)
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // longest integration time (dim light)
|
||||
|
||||
/* Display the gain and integration time for reference sake */
|
||||
Serial.println("------------------------------------");
|
||||
Serial.print ("Gain: ");
|
||||
tsl2591Gain_t gain = tsl.getGain();
|
||||
switch (gain)
|
||||
{
|
||||
case TSL2591_GAIN_LOW:
|
||||
Serial.println("1x (Low)");
|
||||
break;
|
||||
case TSL2591_GAIN_MED:
|
||||
Serial.println("25x (Medium)");
|
||||
break;
|
||||
case TSL2591_GAIN_HIGH:
|
||||
Serial.println("428x (High)");
|
||||
break;
|
||||
case TSL2591_GAIN_MAX:
|
||||
Serial.println("9876x (Max)");
|
||||
break;
|
||||
}
|
||||
Serial.print ("Timing: ");
|
||||
Serial.print((tsl.getTiming() + 1) * 100, DEC);
|
||||
Serial.println(" ms");
|
||||
Serial.println("------------------------------------");
|
||||
Serial.println("");
|
||||
|
||||
/* Setup the SW interrupt to trigger between 100 and 1500 lux */
|
||||
/* Threshold values are defined at the top of this sketch */
|
||||
tsl.clearInterrupt();
|
||||
tsl.registerInterrupt(TLS2591_INT_THRESHOLD_LOWER,
|
||||
TLS2591_INT_THRESHOLD_UPPER,
|
||||
TLS2591_INT_PERSIST);
|
||||
|
||||
/* Display the interrupt threshold window */
|
||||
Serial.print("Interrupt Threshold Window: -");
|
||||
Serial.print(TLS2591_INT_THRESHOLD_LOWER, DEC);
|
||||
Serial.print(" to +");
|
||||
Serial.println(TLS2591_INT_THRESHOLD_LOWER, DEC);
|
||||
Serial.println("");
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Program entry point for the Arduino sketch
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void setup(void)
|
||||
{
|
||||
Serial.begin(9600);
|
||||
|
||||
// Enable this line for Flora, Zero and Feather boards with no FTDI chip
|
||||
// Waits for the serial port to connect before sending data out
|
||||
// while (!Serial) { delay(1); }
|
||||
|
||||
Serial.println("Starting Adafruit TSL2591 interrupt Test!");
|
||||
|
||||
if (tsl.begin())
|
||||
{
|
||||
Serial.println("Found a TSL2591 sensor");
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("No sensor found ... check your wiring?");
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Display some basic information on this sensor */
|
||||
displaySensorDetails();
|
||||
|
||||
/* Configure the sensor (including the interrupt threshold) */
|
||||
configureSensor();
|
||||
|
||||
// Now we're ready to get readings ... move on to loop()!
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Show how to read IR and Full Spectrum at once and convert to lux
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void advancedRead(void)
|
||||
{
|
||||
// More advanced data read example. Read 32 bits with top 16 bits IR, bottom 16 bits full spectrum
|
||||
// That way you can do whatever math and comparisons you want!
|
||||
uint32_t lum = tsl.getFullLuminosity();
|
||||
uint16_t ir, full;
|
||||
ir = lum >> 16;
|
||||
full = lum & 0xFFFF;
|
||||
Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.print("IR: "); Serial.print(ir); Serial.print(" ");
|
||||
Serial.print("Full: "); Serial.print(full); Serial.print(" ");
|
||||
Serial.print("Visible: "); Serial.print(full - ir); Serial.print(" ");
|
||||
Serial.print("Lux: "); Serial.println(tsl.calculateLux(full, ir));
|
||||
}
|
||||
|
||||
|
||||
void getStatus(void)
|
||||
{
|
||||
uint8_t x = tsl.getStatus();
|
||||
// bit 4: ALS Interrupt occured
|
||||
// bit 5: No-persist Interrupt occurence
|
||||
if (x & 0x10) {
|
||||
Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.println("ALS Interrupt occured");
|
||||
}
|
||||
if (x & 0x20) {
|
||||
Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.println("No-persist Interrupt occured");
|
||||
}
|
||||
|
||||
// Serial.print("[ "); Serial.print(millis()); Serial.print(" ms ] ");
|
||||
Serial.print("Status: ");
|
||||
Serial.println(x, BIN);
|
||||
tsl.clearInterrupt();
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*
|
||||
Arduino loop function, called once 'setup' is complete (your own code
|
||||
should go here)
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void loop(void)
|
||||
{
|
||||
advancedRead();
|
||||
getStatus();
|
||||
delay(500);
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=Adafruit TSL2591 Library
|
||||
version=1.0.2
|
||||
author=Adafruit
|
||||
maintainer=Adafruit <info@adafruit.com>
|
||||
sentence=Library for the TSL2591 digital luminosity (light) sensors.
|
||||
paragraph=Library for the TSL2591 digital luminosity (light) sensors.
|
||||
category=Sensors
|
||||
url=https://github.com/adafruit/Adafruit_TSL2591_Library
|
||||
architectures=*
|
||||
@@ -168,6 +168,51 @@ void ICACHE_FLASH_ATTR IRsend::sendNEC (unsigned long data, int nbits,
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR IRsend::sendPioneer (unsigned long data, int nbits,
|
||||
unsigned int repeat, unsigned long secondData) {
|
||||
// Details about timings can be found at:
|
||||
// http://www.sbprojects.com/knowledge/ir/nec.php
|
||||
// More about the pioneer format:
|
||||
// http://www.adrian-kingston.com/IRFormatPioneer.htm
|
||||
|
||||
// Set IR carrier frequency
|
||||
enableIROut(40);
|
||||
IRtimer usecs = IRtimer();
|
||||
|
||||
for (unsigned int i = 0; i <= repeat; i++) {
|
||||
usecs.reset();
|
||||
// Header
|
||||
mark(PIONEER_HDR_MARK);
|
||||
space(PIONEER_HDR_SPACE);
|
||||
|
||||
sendData(PIONEER_BIT_MARK, PIONEER_ONE_SPACE, PIONEER_BIT_MARK, PIONEER_ZERO_SPACE,
|
||||
data, nbits, true);
|
||||
|
||||
// Footer
|
||||
mark(PIONEER_BIT_MARK);
|
||||
space(PIONEER_ONE_SPACE);
|
||||
// Gap till next command.
|
||||
space(max(0ul, PIONEER_MIN_COMMAND_LENGTH - usecs.elapsed()));
|
||||
|
||||
// Some Pioneer signals have two 32 bit commands
|
||||
if (secondData) {
|
||||
usecs.reset();
|
||||
// Header
|
||||
mark(PIONEER_HDR_MARK);
|
||||
space(PIONEER_HDR_SPACE);
|
||||
|
||||
sendData(PIONEER_BIT_MARK, PIONEER_ONE_SPACE, PIONEER_BIT_MARK, PIONEER_ZERO_SPACE,
|
||||
secondData, nbits, true);
|
||||
|
||||
// Footer
|
||||
mark(PIONEER_BIT_MARK);
|
||||
space(PIONEER_ONE_SPACE);
|
||||
// Gap till next command.
|
||||
space(max(0ul, PIONEER_MIN_COMMAND_LENGTH - usecs.elapsed()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ICACHE_FLASH_ATTR IRsend::sendLG (unsigned long data, int nbits,
|
||||
unsigned int repeat) {
|
||||
// Args:
|
||||
|
||||
@@ -53,6 +53,7 @@ enum decode_type_t {
|
||||
RC5,
|
||||
RC6,
|
||||
NEC,
|
||||
PIONEER,
|
||||
SONY,
|
||||
PANASONIC,
|
||||
JVC,
|
||||
@@ -92,6 +93,7 @@ public:
|
||||
#define REPEAT 0xffffffff
|
||||
|
||||
#define SEND_PROTOCOL_NEC case NEC: sendNEC(data, nbits); break;
|
||||
#define SEND_PROTOCOL_PIONEER case PIONEER: sendPioneer(data, nbits, 1, 0ul); break;
|
||||
#define SEND_PROTOCOL_SONY case SONY: sendSony(data, nbits); break;
|
||||
#define SEND_PROTOCOL_RC5 case RC5: sendRC5(data, nbits); break;
|
||||
#define SEND_PROTOCOL_RC6 case RC6: sendRC6(data, nbits); break;
|
||||
@@ -162,6 +164,7 @@ public:
|
||||
void send(int type, unsigned long data, int nbits) {
|
||||
switch (type) {
|
||||
SEND_PROTOCOL_NEC
|
||||
SEND_PROTOCOL_PIONEER
|
||||
SEND_PROTOCOL_SONY
|
||||
SEND_PROTOCOL_RC5
|
||||
SEND_PROTOCOL_RC6
|
||||
@@ -179,6 +182,7 @@ public:
|
||||
void sendCOOLIX(unsigned long data, int nbits);
|
||||
void sendWhynter(unsigned long data, int nbits);
|
||||
void sendNEC(unsigned long data, int nbits=32, unsigned int repeat=0);
|
||||
void sendPioneer(unsigned long data, int nbits=32, unsigned int repeat=0, unsigned long secondData=0ul);
|
||||
void sendLG(unsigned long data, int nbits=28, unsigned int repeat=0);
|
||||
// sendSony() should typically be called with repeat=2 as Sony devices
|
||||
// expect the code to be sent at least 3 times. (code + 2 repeats = 3 codes)
|
||||
|
||||
@@ -60,6 +60,14 @@
|
||||
#define NEC_RPT_SPACE 2250
|
||||
#define NEC_MIN_COMMAND_LENGTH 108000UL
|
||||
|
||||
#define PIONEER_HDR_MARK 8000
|
||||
#define PIONEER_HDR_SPACE 4000
|
||||
#define PIONEER_BIT_MARK 500
|
||||
#define PIONEER_ONE_SPACE 1500
|
||||
#define PIONEER_ZERO_SPACE 500
|
||||
#define PIONEER_RPT_SPACE 2250
|
||||
#define PIONEER_MIN_COMMAND_LENGTH 90000UL
|
||||
|
||||
// Timings based on http://www.sbprojects.com/knowledge/ir/sirc.php
|
||||
#define SONY_HDR_MARK 2400
|
||||
#define SONY_HDR_SPACE 600
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
#include <SensorSerial.h>
|
||||
|
||||
|
||||
SensorSerial::SensorSerial(int receivePin, int transmitPin, bool inverse_logic, unsigned int buffSize) : SoftwareSerial(receivePin, transmitPin, inverse_logic, buffSize)
|
||||
SensorSerial::SensorSerial(int receivePin, int transmitPin, bool inverse_logic, unsigned int buffSize) : ESPeasySoftwareSerial(receivePin, transmitPin, inverse_logic, buffSize)
|
||||
{
|
||||
//boolean sws = isValidGPIOpin(receivePin);
|
||||
_hw = receivePin < 0;
|
||||
@@ -37,7 +37,7 @@ void SensorSerial::begin(long speed)
|
||||
if (_hw)
|
||||
Serial.begin(speed);
|
||||
else
|
||||
SoftwareSerial::begin(speed);
|
||||
ESPeasySoftwareSerial::begin(speed);
|
||||
}
|
||||
|
||||
int SensorSerial::peek()
|
||||
@@ -45,7 +45,7 @@ int SensorSerial::peek()
|
||||
if (_hw)
|
||||
return Serial.peek();
|
||||
else
|
||||
return SoftwareSerial::peek();
|
||||
return ESPeasySoftwareSerial::peek();
|
||||
}
|
||||
|
||||
size_t SensorSerial::write(uint8_t byte)
|
||||
@@ -53,7 +53,7 @@ size_t SensorSerial::write(uint8_t byte)
|
||||
if (_hw)
|
||||
return Serial.write(byte);
|
||||
else
|
||||
return SoftwareSerial::write(byte);
|
||||
return ESPeasySoftwareSerial::write(byte);
|
||||
}
|
||||
|
||||
int SensorSerial::read()
|
||||
@@ -61,7 +61,7 @@ int SensorSerial::read()
|
||||
if (_hw)
|
||||
return Serial.read();
|
||||
else
|
||||
return SoftwareSerial::read();
|
||||
return ESPeasySoftwareSerial::read();
|
||||
}
|
||||
|
||||
int SensorSerial::available()
|
||||
@@ -69,7 +69,7 @@ int SensorSerial::available()
|
||||
if (_hw)
|
||||
return Serial.available();
|
||||
else
|
||||
return SoftwareSerial::available();
|
||||
return ESPeasySoftwareSerial::available();
|
||||
}
|
||||
|
||||
void SensorSerial::flush()
|
||||
@@ -77,5 +77,5 @@ void SensorSerial::flush()
|
||||
if (_hw)
|
||||
Serial.flush();
|
||||
else
|
||||
SoftwareSerial::flush();
|
||||
ESPeasySoftwareSerial::flush();
|
||||
}
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
#define _SENSORSERIAL_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include <SoftwareSerial.h>
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
class SensorSerial : public SoftwareSerial
|
||||
class SensorSerial : public ESPeasySoftwareSerial
|
||||
{
|
||||
public:
|
||||
SensorSerial(int receivePin, int transmitPin = -1, bool inverse_logic = false, unsigned int buffSize = 64);
|
||||
|
||||
+116
-29
@@ -25,7 +25,7 @@
|
||||
|
||||
#include "jkSDS011.h"
|
||||
|
||||
CjkSDS011::CjkSDS011(int16_t pinRX, int16_t pinTX) : _serial(pinRX, pinTX)
|
||||
CjkSDS011::CjkSDS011(int16_t pinRX, int16_t pinTX)
|
||||
{
|
||||
_sws = ! ( pinRX < 0 || pinRX == 3 );
|
||||
_pm2_5 = NAN;
|
||||
@@ -35,43 +35,131 @@ CjkSDS011::CjkSDS011(int16_t pinRX, int16_t pinTX) : _serial(pinRX, pinTX)
|
||||
_pm10_avr = 0;
|
||||
_avr = 0;
|
||||
_data.SetPacketLength(10);
|
||||
_command.SetPacketLength(19);
|
||||
_working_period = -1;
|
||||
_sleepmode_active = false;
|
||||
_serial = new ESPeasySoftwareSerial(pinRX, pinTX);
|
||||
_serial->begin(9600);
|
||||
}
|
||||
|
||||
_serial.begin(9600);
|
||||
CjkSDS011::~CjkSDS011() {
|
||||
delete _serial;
|
||||
}
|
||||
|
||||
void CjkSDS011::SendCommand(byte byte1, byte byte2, byte byte3) {
|
||||
_command[0] = 0xAA; // Head
|
||||
_command[1] = 0xB4; // Command ID
|
||||
_command[2] = byte1; // Data Byte 1
|
||||
_command[3] = byte2; // Data Byte 2
|
||||
_command[4] = byte3; // Data Byte 3
|
||||
_command[5] = 0; // Data Byte 4
|
||||
_command[6] = 0; // Data Byte 5
|
||||
_command[7] = 0; // Data Byte 6
|
||||
_command[8] = 0; // Data Byte 7
|
||||
_command[9] = 0; // Data Byte 8
|
||||
_command[10] = 0; // Data Byte 9
|
||||
_command[11] = 0; // Data Byte 10
|
||||
_command[12] = 0; // Data Byte 11
|
||||
_command[13] = 0; // Data Byte 12
|
||||
_command[14] = 0; // Data Byte 13
|
||||
_command[15] = 0xFF; // Device ID byte 1, FF: All sensor response
|
||||
_command[16] = 0xFF; // Device ID byte 2, FF: All sensor response
|
||||
|
||||
byte checksum = 0;
|
||||
for (byte i=2; i< 17; ++i) {
|
||||
checksum += _command[i];
|
||||
}
|
||||
_command[17] = checksum; // Checksum
|
||||
_command[18] = 0xAB; // Tail
|
||||
|
||||
for (int i = 0; i < 19; ++i) {
|
||||
_serial->write(_command[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void CjkSDS011::SetSleepMode(bool enabled) {
|
||||
byte databyte3 = enabled ? 0 : 1;
|
||||
SendCommand(6, 1, databyte3);
|
||||
}
|
||||
|
||||
void CjkSDS011::SetWorkingPeriod(int minutes) {
|
||||
// Data byte 1: 8
|
||||
// Data byte 2: 0: query the current mode
|
||||
// 1: set mode
|
||||
// Data byte 3: 0:continuous(default)
|
||||
// 1-30minute:work 30 seconds and sleep n*60-30 seconds
|
||||
if (minutes < 0 || minutes > 30) return;
|
||||
// Working period is stored in the flash of the sensor. Only write to change.
|
||||
const int currentWorkingPeriod = GetWorkingPeriod();
|
||||
if (minutes != currentWorkingPeriod)
|
||||
SendCommand(8, 1, minutes);
|
||||
}
|
||||
|
||||
int CjkSDS011::GetWorkingPeriod() {
|
||||
// Data byte 1: 8
|
||||
// Data byte 2: 0: query the current mode
|
||||
// 1: set mode
|
||||
// Data byte 3: 0:continuous(default)
|
||||
// 1-30minute:work 30 seconds and sleep n*60-30 seconds
|
||||
SendCommand(8, 0, 0);
|
||||
Process();
|
||||
return _working_period;
|
||||
}
|
||||
|
||||
void CjkSDS011::ParseCommandReply() {
|
||||
switch(_data[2]) {
|
||||
case 6: // Enable/Disable sleep mode.
|
||||
if (_data[3] == 0)
|
||||
_sleepmode_active = _data[4];
|
||||
break;
|
||||
case 8: // Set/Get working period
|
||||
if (_data[3] == 0)
|
||||
_working_period = _data[4];
|
||||
break;
|
||||
default:
|
||||
// Not implemented.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CjkSDS011::Process()
|
||||
{
|
||||
while (_serial.available())
|
||||
while (_serial->available())
|
||||
{
|
||||
_data.AddData(_serial.read());
|
||||
_data.AddData(_serial->read());
|
||||
|
||||
if (_data[0] == 0xAA && _data[9] == 0xAB && (_data[1] == 0xC0 || _data[1] == 0xCF)) // correct packet frame?
|
||||
if (_data[0] == 0xAA && _data[9] == 0xAB) // correct packet frame?
|
||||
{
|
||||
byte checksum = 0;
|
||||
for (byte i=2; i<= 7; i++)
|
||||
checksum += _data[i];
|
||||
checksum += _data[i];
|
||||
if (checksum != _data[8])
|
||||
continue;
|
||||
|
||||
if (_data[1] == 0xC0) // SDS011 or SDS018?
|
||||
{
|
||||
_pm2_5 = (float)((_data[3] << 8) | _data[2]) * 0.1;
|
||||
_pm10_ = (float)((_data[5] << 8) | _data[4]) * 0.1;
|
||||
_available = true;
|
||||
switch(_data[1]) {
|
||||
case 0xC0: // SDS011 or SDS018?
|
||||
_pm2_5 = (float)((_data[3] << 8) | _data[2]) * 0.1;
|
||||
_pm10_ = (float)((_data[5] << 8) | _data[4]) * 0.1;
|
||||
_available = true;
|
||||
break;
|
||||
case 0xCF: // SDS198?
|
||||
_pm2_5 = (float)((_data[5] << 8) | _data[4]);
|
||||
_pm10_ = (float)((_data[3] << 8) | _data[2]);
|
||||
_available = true;
|
||||
break;
|
||||
case 0xC5: // Reply on command ID 0xB4
|
||||
ParseCommandReply();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if (_data[1] == 0xCF) // SDS198?
|
||||
{
|
||||
_pm2_5 = (float)((_data[5] << 8) | _data[4]);
|
||||
_pm10_ = (float)((_data[3] << 8) | _data[2]);
|
||||
_available = true;
|
||||
if (_available) {
|
||||
_pm2_5avr += _pm2_5;
|
||||
_pm10_avr += _pm10_;
|
||||
_avr++;
|
||||
_data.Clear();
|
||||
return;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
|
||||
_pm2_5avr += _pm2_5;
|
||||
_pm10_avr += _pm10_;
|
||||
_avr++;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +171,7 @@ boolean CjkSDS011::available()
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CjkSDS011::ReadAverage(float &pm25, float &pm10)
|
||||
boolean CjkSDS011::ReadAverage(float &pm25, float &pm10)
|
||||
{
|
||||
if (_avr)
|
||||
{
|
||||
@@ -92,10 +180,9 @@ void CjkSDS011::ReadAverage(float &pm25, float &pm10)
|
||||
_pm2_5avr = 0;
|
||||
_pm10_avr = 0;
|
||||
_avr = 0;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
pm25 = NAN;
|
||||
pm10 = NAN;
|
||||
}
|
||||
pm25 = NAN;
|
||||
pm10 = NAN;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -27,13 +27,15 @@
|
||||
#define _jkSDS011_H_
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "SensorSerial.h"
|
||||
//#include "SensorSerial.h"
|
||||
#include "SensorSerialBuffer.h"
|
||||
#include "ESPeasySoftwareSerial.h"
|
||||
|
||||
class CjkSDS011
|
||||
{
|
||||
public:
|
||||
CjkSDS011(int16_t pinRX, int16_t pinTX);
|
||||
virtual ~CjkSDS011();
|
||||
|
||||
void Process();
|
||||
|
||||
@@ -42,11 +44,28 @@ public:
|
||||
float GetPM2_5() { return _pm2_5; };
|
||||
float GetPM10_() { return _pm10_; };
|
||||
|
||||
void ReadAverage(float &pm25, float &pm10);
|
||||
// Return true when there are valid samples.
|
||||
boolean ReadAverage(float &pm25, float &pm10);
|
||||
|
||||
void SetSleepMode(bool enabled);
|
||||
|
||||
// Set interval to get new data, 0 .. 30 minutes.
|
||||
// Minutes = 0 => continous mode.
|
||||
// The setting is still effective after power off(factory default is continuous measurement)
|
||||
void SetWorkingPeriod(int minutes);
|
||||
|
||||
// Get the working period in minutes (0 = continuous reading)
|
||||
// Negative return value indicates error during communication.
|
||||
int GetWorkingPeriod();
|
||||
|
||||
private:
|
||||
SensorSerial _serial;
|
||||
void SendCommand(byte byte1, byte byte2, byte byte3);
|
||||
void ParseCommandReply();
|
||||
|
||||
// SensorSerial _serial;
|
||||
ESPeasySoftwareSerial *_serial;
|
||||
CSensorSerialBuffer _data;
|
||||
CSensorSerialBuffer _command;
|
||||
float _pm2_5;
|
||||
float _pm10_;
|
||||
float _pm2_5avr;
|
||||
@@ -54,6 +73,8 @@ private:
|
||||
uint16_t _avr;
|
||||
boolean _available;
|
||||
boolean _sws;
|
||||
int _working_period;
|
||||
boolean _sleepmode_active;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
|
||||
ESPeasySoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266.
|
||||
Copyright (c) 2015-2016 Peter Lerup. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
// The Arduino standard GPIO routines are not enough,
|
||||
// must use some from the Espressif SDK as well
|
||||
extern "C" {
|
||||
#include "gpio.h"
|
||||
}
|
||||
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
#define MAX_PIN 15
|
||||
#define USABLE_PINS 10
|
||||
#define NR_CONCURRENT_SOFT_SERIALS 3
|
||||
|
||||
// As the Arduino attachInterrupt has no parameter, lists of objects
|
||||
// and callbacks corresponding to each possible GPIO pins have to be defined
|
||||
static ESPeasySoftwareSerial *ObjList[NR_CONCURRENT_SOFT_SERIALS];
|
||||
static uint8_t PinControllerMap[NR_CONCURRENT_SOFT_SERIALS]={}; // Zero all elements
|
||||
|
||||
void ICACHE_RAM_ATTR sws_isr_0() { ObjList[0]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_1() { ObjList[1]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_2() { ObjList[2]->rxRead(); };
|
||||
/*void ICACHE_RAM_ATTR sws_isr_3() { ObjList[3]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_4() { ObjList[4]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_5() { ObjList[5]->rxRead(); };
|
||||
// Pin 6 to 11 can not be used
|
||||
void ICACHE_RAM_ATTR sws_isr_12() { ObjList[6]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_13() { ObjList[7]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_14() { ObjList[8]->rxRead(); };
|
||||
void ICACHE_RAM_ATTR sws_isr_15() { ObjList[9]->rxRead(); };
|
||||
*/
|
||||
|
||||
static void (*ISRList[NR_CONCURRENT_SOFT_SERIALS])() = {
|
||||
sws_isr_0,
|
||||
sws_isr_1,
|
||||
sws_isr_2 /*,
|
||||
sws_isr_3,
|
||||
sws_isr_4,
|
||||
sws_isr_5,
|
||||
// Pin 6 to 11 can not be used
|
||||
sws_isr_12,
|
||||
sws_isr_13,
|
||||
sws_isr_14,
|
||||
sws_isr_15
|
||||
*/
|
||||
};
|
||||
|
||||
ESPeasySoftwareSerial::ESPeasySoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic, uint16_t buffSize) {
|
||||
m_rxValid = m_txValid = m_txEnableValid = false;
|
||||
m_buffer = NULL;
|
||||
m_invert = inverse_logic;
|
||||
if (isValidGPIOpin(receivePin)) {
|
||||
m_rxPin = receivePin;
|
||||
m_buffSize = buffSize;
|
||||
m_buffer = (uint8_t*)malloc(m_buffSize);
|
||||
if (m_buffer != NULL) {
|
||||
m_rxValid = true;
|
||||
m_inPos = m_outPos = 0;
|
||||
pinMode(m_rxPin, INPUT);
|
||||
const uint8_t index = pinToIndex(m_rxPin);
|
||||
if (index == NR_CONCURRENT_SOFT_SERIALS) {
|
||||
return; // Not possible to add software Serial.
|
||||
}
|
||||
ObjList[index] = this;
|
||||
enableRx(true);
|
||||
}
|
||||
}
|
||||
if (isValidGPIOpin(transmitPin)) {
|
||||
m_txValid = true;
|
||||
m_txPin = transmitPin;
|
||||
pinMode(m_txPin, OUTPUT);
|
||||
digitalWrite(m_txPin, !m_invert);
|
||||
}
|
||||
// Default speed
|
||||
begin(9600);
|
||||
}
|
||||
|
||||
ESPeasySoftwareSerial::~ESPeasySoftwareSerial() {
|
||||
enableRx(false);
|
||||
if (m_rxValid) {
|
||||
const uint8_t index = pinToIndex(m_rxPin);
|
||||
if (index < NR_CONCURRENT_SOFT_SERIALS) {
|
||||
PinControllerMap[index] = 0;
|
||||
ObjList[index] = NULL;
|
||||
}
|
||||
}
|
||||
if (m_buffer)
|
||||
free(m_buffer);
|
||||
}
|
||||
|
||||
bool ESPeasySoftwareSerial::isValidGPIOpin(uint8_t pin) {
|
||||
if (pin >= 0 && pin <= 5) {
|
||||
return true;
|
||||
}
|
||||
if (pin >= 12 && pin <= MAX_PIN) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t ESPeasySoftwareSerial::pinToIndex(uint8_t pin) {
|
||||
// Pin will be stored in the map, only "1" will be added,
|
||||
// to allow simple initialize to 0 and still use GPIO-0.
|
||||
const uint8_t stored_pin = pin + 1;
|
||||
for (unsigned i = 0; i < NR_CONCURRENT_SOFT_SERIALS; ++i) {
|
||||
if (PinControllerMap[i] == stored_pin) return i;
|
||||
}
|
||||
// Not found, add as first free option.
|
||||
for (unsigned i = 0; i < NR_CONCURRENT_SOFT_SERIALS; ++i) {
|
||||
if (PinControllerMap[i] == 0) {
|
||||
PinControllerMap[i] = stored_pin;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
// No more controllers available.
|
||||
return NR_CONCURRENT_SOFT_SERIALS;
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::begin(long speed) {
|
||||
// Use getCycleCount() loop to get as exact timing as possible
|
||||
m_bitTime = ESP.getCpuFreqMHz()*1000000/speed;
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::setTransmitEnablePin(uint8_t transmitEnablePin) {
|
||||
if (isValidGPIOpin(transmitEnablePin)) {
|
||||
m_txEnableValid = true;
|
||||
m_txEnablePin = transmitEnablePin;
|
||||
pinMode(m_txEnablePin, OUTPUT);
|
||||
digitalWrite(m_txEnablePin, LOW);
|
||||
} else {
|
||||
m_txEnableValid = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::enableRx(bool on) {
|
||||
if (m_rxValid) {
|
||||
if (on) {
|
||||
attachInterrupt(m_rxPin, ISRList[pinToIndex(m_rxPin)], m_invert ? RISING : FALLING);
|
||||
} else {
|
||||
detachInterrupt(m_rxPin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ESPeasySoftwareSerial::read() {
|
||||
if (!m_rxValid || (m_inPos == m_outPos)) return -1;
|
||||
uint8_t ch = m_buffer[m_outPos];
|
||||
m_outPos = (m_outPos+1) % m_buffSize;
|
||||
return ch;
|
||||
}
|
||||
|
||||
int ESPeasySoftwareSerial::available() {
|
||||
if (!m_rxValid) return 0;
|
||||
int avail = m_inPos - m_outPos;
|
||||
if (avail < 0) avail += m_buffSize;
|
||||
return avail;
|
||||
}
|
||||
|
||||
#define WAIT { while (ESP.getCycleCount()-start < wait); wait += m_bitTime; }
|
||||
|
||||
size_t ESPeasySoftwareSerial::write(uint8_t b) {
|
||||
if (!m_txValid) return 0;
|
||||
|
||||
if (m_invert) b = ~b;
|
||||
// Disable interrupts in order to get a clean transmit
|
||||
cli();
|
||||
if (m_txEnableValid) digitalWrite(m_txEnablePin, HIGH);
|
||||
unsigned long wait = m_bitTime;
|
||||
digitalWrite(m_txPin, HIGH);
|
||||
unsigned long start = ESP.getCycleCount();
|
||||
// Start bit;
|
||||
digitalWrite(m_txPin, LOW);
|
||||
WAIT;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
digitalWrite(m_txPin, (b & 1) ? HIGH : LOW);
|
||||
WAIT;
|
||||
b >>= 1;
|
||||
}
|
||||
// Stop bit
|
||||
digitalWrite(m_txPin, HIGH);
|
||||
WAIT;
|
||||
if (m_txEnableValid) digitalWrite(m_txEnablePin, LOW);
|
||||
sei();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ESPeasySoftwareSerial::flush() {
|
||||
m_inPos = m_outPos = 0;
|
||||
}
|
||||
|
||||
int ESPeasySoftwareSerial::peek() {
|
||||
if (!m_rxValid || (m_inPos == m_outPos)) return -1;
|
||||
return m_buffer[m_outPos];
|
||||
}
|
||||
|
||||
void ICACHE_RAM_ATTR ESPeasySoftwareSerial::rxRead() {
|
||||
// Advance the starting point for the samples but compensate for the
|
||||
// initial delay which occurs before the interrupt is delivered
|
||||
unsigned long wait = m_bitTime + m_bitTime/3 - 500;
|
||||
unsigned long start = ESP.getCycleCount();
|
||||
uint8_t rec = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
WAIT;
|
||||
rec >>= 1;
|
||||
if (digitalRead(m_rxPin))
|
||||
rec |= 0x80;
|
||||
}
|
||||
if (m_invert) rec = ~rec;
|
||||
// Stop bit
|
||||
WAIT;
|
||||
// Store the received value in the buffer unless we have an overflow
|
||||
uint16_t next = (m_inPos+1) % m_buffSize;
|
||||
if (next != m_inPos) {
|
||||
m_buffer[m_inPos] = rec;
|
||||
m_inPos = next;
|
||||
}
|
||||
// Must clear this bit in the interrupt register,
|
||||
// it gets set even when interrupts are disabled
|
||||
GPIO_REG_WRITE(GPIO_STATUS_W1TC_ADDRESS, 1 << m_rxPin);
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
ESPeasySoftwareSerial.h
|
||||
|
||||
ESPeasySoftwareSerial.cpp - Implementation of the Arduino software serial for ESP8266.
|
||||
Copyright (c) 2015-2016 Peter Lerup. All rights reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#ifndef ESPeasySoftwareSerial_h
|
||||
#define ESPeasySoftwareSerial_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <Stream.h>
|
||||
|
||||
|
||||
// This class is compatible with the corresponding AVR one,
|
||||
// the constructor however has an optional rx buffer size.
|
||||
// Speed up to 115200 can be used.
|
||||
|
||||
|
||||
class ESPeasySoftwareSerial : public Stream
|
||||
{
|
||||
public:
|
||||
ESPeasySoftwareSerial(uint8_t receivePin, uint8_t transmitPin, bool inverse_logic = false, uint16_t buffSize = 64);
|
||||
virtual ~ESPeasySoftwareSerial();
|
||||
|
||||
void begin(long speed);
|
||||
void setTransmitEnablePin(uint8_t transmitEnablePin);
|
||||
|
||||
int peek();
|
||||
|
||||
virtual size_t write(uint8_t byte);
|
||||
virtual int read();
|
||||
virtual int available();
|
||||
virtual void flush();
|
||||
operator bool() {return m_rxValid || m_txValid;}
|
||||
|
||||
// Disable or enable interrupts on the rx pin
|
||||
void enableRx(bool on);
|
||||
|
||||
void rxRead();
|
||||
|
||||
using Print::write;
|
||||
|
||||
private:
|
||||
bool isValidGPIOpin(uint8_t pin);
|
||||
uint8_t pinToIndex(uint8_t pin);
|
||||
|
||||
// Member variables
|
||||
uint8_t m_rxPin, m_txPin, m_txEnablePin;
|
||||
bool m_rxValid, m_txValid, m_txEnableValid;
|
||||
bool m_invert;
|
||||
unsigned long m_bitTime;
|
||||
uint16_t m_inPos, m_outPos;
|
||||
uint16_t m_buffSize;
|
||||
uint8_t *m_buffer;
|
||||
|
||||
};
|
||||
|
||||
// If only one tx or rx wanted then use this as parameter for the unused pin
|
||||
#define SW_SERIAL_UNUSED_PIN -1
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,11 @@
|
||||
# EspESPeasySoftwareSerial
|
||||
|
||||
Implementation of the Arduino software serial library for the ESP8266
|
||||
|
||||
Same functionality as the corresponding AVR library but several instances can be active at the same time.
|
||||
Speed up to 115200 baud is supported. The constructor also has an optional input buffer size.
|
||||
|
||||
Please note that due to the fact that the ESP always have other activities ongoing, there will be some inexactness in interrupt
|
||||
timings. This may lead to bit errors when having heavy data traffic in high baud rates.
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
ESPeasySoftwareSerial swSer(14, 12, false, 256);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
swSer.begin(115200);
|
||||
|
||||
Serial.println("\nSoftware serial test started");
|
||||
|
||||
for (char ch = ' '; ch <= 'z'; ch++) {
|
||||
swSer.write(ch);
|
||||
}
|
||||
swSer.println("");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (swSer.available() > 0) {
|
||||
Serial.write(swSer.read());
|
||||
}
|
||||
while (Serial.available() > 0) {
|
||||
swSer.write(Serial.read());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map for ESPeasySoftwareSerial
|
||||
# (esp8266)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
ESPeasySoftwareSerial KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
begin KEYWORD2
|
||||
read KEYWORD2
|
||||
write KEYWORD2
|
||||
available KEYWORD2
|
||||
flush KEYWORD2
|
||||
overflow KEYWORD2
|
||||
peek KEYWORD2
|
||||
listen KEYWORD2
|
||||
end KEYWORD2
|
||||
isListening KEYWORD2
|
||||
stopListening KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "EspESPeasySoftwareSerial",
|
||||
"version": "3.3.1",
|
||||
"keywords": [
|
||||
"serial", "io", "softwareserial"
|
||||
],
|
||||
"description": "Implementation of the Arduino software serial for ESP8266. Adjusted to reduce memory footprint for ESPeasy",
|
||||
"repository":
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/plerup/espsoftwareserial"
|
||||
},
|
||||
"frameworks": "arduino",
|
||||
"platforms": "espressif8266"
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
name=ESPeasySoftwareSerial
|
||||
version=1.0
|
||||
author=Peter Lerup
|
||||
maintainer=Peter Lerup <peter@lerup.com>
|
||||
sentence=Implementation of the Arduino software serial for ESP8266.
|
||||
paragraph=
|
||||
category=Signal Input/Output
|
||||
url=
|
||||
architectures=esp8266
|
||||
@@ -102,6 +102,16 @@ board = esp12e
|
||||
upload_speed=460800
|
||||
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_TESTING -D PLUGIN_BUILD_DEV
|
||||
|
||||
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 4096k
|
||||
# Use latest ESP8266 core 2.4.0
|
||||
[env:dev_ESP8266_4096_core2_4_0]
|
||||
platform = espressif8266
|
||||
framework = arduino
|
||||
board = esp12e
|
||||
upload_speed=460800
|
||||
build_flags = ${common.build_flags} -Wl,-Tesp8266.flash.4m1m.ld -D PLUGIN_BUILD_TESTING -D PLUGIN_BUILD_DEV
|
||||
|
||||
|
||||
#version with additional plugins (and dependend code) that is in development (probably broken or incomplete) 4096k for esp8285
|
||||
[env:dev_ESP8285_1024]
|
||||
platform = espressif8266@1.5.0
|
||||
|
||||
+64
-4
@@ -127,7 +127,7 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
SendUDPCommand(Par1, (char*)event.c_str(), event.length());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
if (strcasecmp_P(Command, PSTR("sdcard")) == 0)
|
||||
{
|
||||
success = true;
|
||||
@@ -146,6 +146,7 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
Serial.println(fname.c_str());
|
||||
SD.remove((char*)fname.c_str());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("lowmem")) == 0)
|
||||
{
|
||||
@@ -178,6 +179,21 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
delay(60000);
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("accessinfo")) == 0)
|
||||
{
|
||||
success = true;
|
||||
Serial.print(F("Allowed IP range : "));
|
||||
Serial.println(describeAllowedIPrange());
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("clearaccessblock")) == 0)
|
||||
{
|
||||
success = true;
|
||||
clearAccessBlock();
|
||||
Serial.print(F("Allowed IP range : "));
|
||||
Serial.println(describeAllowedIPrange());
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("meminfo")) == 0)
|
||||
{
|
||||
success = true;
|
||||
@@ -387,10 +403,10 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
portUDP.beginPacket(UDP_IP, port.toInt());
|
||||
#if defined(ESP8266)
|
||||
portUDP.write(message.c_str(), message.length());
|
||||
#endif
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
portUDP.write((uint8_t*)message.c_str(), message.length());
|
||||
#endif
|
||||
#endif
|
||||
portUDP.endPacket();
|
||||
}
|
||||
}
|
||||
@@ -429,6 +445,43 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
}
|
||||
}
|
||||
|
||||
// ****************************************
|
||||
// special commands for Blynk
|
||||
// ****************************************
|
||||
|
||||
#ifdef CPLUGIN_012
|
||||
//FIXME: this should go to PLUGIN_WRITE in _C012.ino
|
||||
if (strcasecmp_P(Command, PSTR("BlynkGet")) == 0)
|
||||
{
|
||||
byte first_enabled_blynk_controller = firstEnabledBlynkController();
|
||||
if (first_enabled_blynk_controller == -1) {
|
||||
status = F("Controller not enabled");
|
||||
} else {
|
||||
String strLine = Line;
|
||||
strLine = strLine.substring(9);
|
||||
int index = strLine.indexOf(',');
|
||||
if (index > 0)
|
||||
{
|
||||
int index = strLine.lastIndexOf(',');
|
||||
String blynkcommand = strLine.substring(index+1);
|
||||
float value = 0;
|
||||
if (Blynk_get(blynkcommand, first_enabled_blynk_controller, &value))
|
||||
{
|
||||
UserVar[(VARS_PER_TASK * (Par1 - 1)) + Par2 - 1] = value;
|
||||
}
|
||||
else
|
||||
status = F("Error getting data");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Blynk_get(strLine, first_enabled_blynk_controller))
|
||||
{
|
||||
status = F("Error getting data");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// ****************************************
|
||||
// configure settings commands
|
||||
@@ -506,7 +559,12 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
pinMode(0, INPUT);
|
||||
pinMode(2, INPUT);
|
||||
pinMode(15, INPUT);
|
||||
ESP.reset();
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (strcasecmp_P(Command, PSTR("Restart")) == 0)
|
||||
@@ -585,6 +643,7 @@ void ExecuteCommand(byte source, const char *Line)
|
||||
yield();
|
||||
}
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
void printDirectory(File dir, int numTabs) {
|
||||
while (true) {
|
||||
|
||||
@@ -608,3 +667,4 @@ void printDirectory(File dir, int numTabs) {
|
||||
entry.close();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+4
-3
@@ -138,7 +138,6 @@ void MQTTConnect(int controller_idx)
|
||||
String clientid = F("ESPClient_");
|
||||
clientid += WiFi.macAddress();
|
||||
String subscribeTo = "";
|
||||
|
||||
String LWTTopic = ControllerSettings.Subscribe;
|
||||
LWTTopic.replace(F("/#"), F("/status"));
|
||||
LWTTopic.replace(F("%sysname%"), Settings.Name);
|
||||
@@ -167,14 +166,16 @@ void MQTTConnect(int controller_idx)
|
||||
log += subscribeTo;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
MQTTclient.publish(LWTTopic.c_str(), "Connected");
|
||||
MQTTclient.publish(LWTTopic.c_str(), "Connected", 1);
|
||||
|
||||
statusLED(true);
|
||||
return; // end loop if succesfull
|
||||
}
|
||||
else
|
||||
{
|
||||
log = F("MQTT : Failed to connect to broker");
|
||||
log = F("MQTT : ClientID ");
|
||||
log += clientid;
|
||||
log +=" failed to connected to broker";
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
|
||||
|
||||
+160
-60
@@ -41,7 +41,7 @@
|
||||
|
||||
// Simple Arduino sketch for ESP module, supporting:
|
||||
// =================================================================================
|
||||
// Simple switch inputs and direct GPIO output control to drive relais, mosfets, etc
|
||||
// Simple switch inputs and direct GPIO output control to drive relays, mosfets, etc
|
||||
// Analog input (ESP-7/12 only)
|
||||
// Pulse counters
|
||||
// Dallas OneWire DS18b20 temperature sensors
|
||||
@@ -97,6 +97,9 @@
|
||||
#define DEFAULT_DNS "192.168.0.1" // Enter your DNS
|
||||
#define DEFAULT_GW "192.168.0.1" // Enter your Gateway
|
||||
#define DEFAULT_SUBNET "255.255.255.0" // Enter your Subnet
|
||||
#define DEFAULT_IPRANGE_LOW "0.0.0.0" // Allowed IP range to access webserver
|
||||
#define DEFAULT_IPRANGE_HIGH "255.255.255.255" // Allowed IP range to access webserver
|
||||
#define DEFAULT_IP_BLOCK_LEVEL 1 // 0: ALL_ALLOWED 1: LOCAL_SUBNET_ALLOWED 2: ONLY_IP_RANGE_ALLOWED
|
||||
|
||||
// --- Default Controller ------------------------------------------------------------------------------
|
||||
#define DEFAULT_CONTROLLER false // true or false enabled or disabled, set 1st controller defaults
|
||||
@@ -159,13 +162,18 @@
|
||||
#define FEATURE_ADC_VCC false
|
||||
|
||||
|
||||
//enable Arduino OTA updating.
|
||||
//Note: This adds around 10kb to the firmware size, and 1kb extra ram.
|
||||
// #define FEATURE_ARDUINO_OTA
|
||||
|
||||
//enable mDNS mode (adds about 6kb ram and some bytes IRAM)
|
||||
// #define FEATURE_MDNS
|
||||
#if defined(ESP8266)
|
||||
//enable Arduino OTA updating.
|
||||
//Note: This adds around 10kb to the firmware size, and 1kb extra ram.
|
||||
// #define FEATURE_ARDUINO_OTA
|
||||
|
||||
//enable mDNS mode (adds about 6kb ram and some bytes IRAM)
|
||||
// #define FEATURE_MDNS
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
#define FEATURE_ARDUINO_OTA
|
||||
//#define FEATURE_MDNS
|
||||
#endif
|
||||
|
||||
//enable reporting status to ESPEasy developers.
|
||||
//this informs us of crashes and stability issues.
|
||||
@@ -187,18 +195,21 @@
|
||||
//build all plugins that still are being developed and are broken or incomplete
|
||||
//#define PLUGIN_BUILD_DEV
|
||||
|
||||
//add this if you want SD support (add 10k flash)
|
||||
//#define FEATURE_SD
|
||||
|
||||
// ********************************************************************************
|
||||
// DO NOT CHANGE ANYTHING BELOW THIS LINE
|
||||
// ********************************************************************************
|
||||
#include "core_version.h"
|
||||
#ifndef ARDUINO_ESP8266_RELEASE_2_3_0
|
||||
#error ESPEasy v2.0 only support Arduino core 2.3.0. (Use the ESPEasy development branch to fix this)
|
||||
#endif
|
||||
|
||||
#define ESP_PROJECT_PID 2016110801L
|
||||
#define VERSION 2 // config file version (not ESPEasy version). increase if you make incompatible changes to config system.
|
||||
#define BUILD 20000 // git version 2.0.0
|
||||
#define BUILD_NOTES " - Mega"
|
||||
#define BUILD 20100 // git version 2.1.0
|
||||
#if defined(ESP8266)
|
||||
#define BUILD_NOTES " - Mega"
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
#define BUILD_NOTES " - Mega32"
|
||||
#endif
|
||||
|
||||
#ifndef BUILD_GIT
|
||||
#define BUILD_GIT "(custom)"
|
||||
@@ -211,7 +222,6 @@
|
||||
#define NODE_TYPE_ID_ESP_EASY32_STD 33
|
||||
#define NODE_TYPE_ID_ARDUINO_EASY_STD 65
|
||||
#define NODE_TYPE_ID_NANO_EASY_STD 81
|
||||
#define NODE_TYPE_ID NODE_TYPE_ID_ESP_EASYM_STD
|
||||
|
||||
#define PLUGIN_INIT_ALL 1
|
||||
#define PLUGIN_INIT 2
|
||||
@@ -347,7 +357,6 @@
|
||||
#define DAT_OFFSET_CONTROLLER 28672 // each controller = 1k, 4 max
|
||||
#define DAT_OFFSET_CUSTOM_CONTROLLER 32768 // each custom controller config = 1k, 4 max.
|
||||
|
||||
|
||||
/*
|
||||
To modify the stock configuration without changing this repo file :
|
||||
- define USE_CUSTOM_H as a build flags. ie : export PLATFORMIO_BUILD_FLAGS="'-DUSE_CUSTOM_H'"
|
||||
@@ -358,50 +367,98 @@
|
||||
#include "Custom.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include "core_version.h"
|
||||
#include "ESPEasyTimeTypes.h"
|
||||
#include "lwip/tcp_impl.h"
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <DNSServer.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
#ifdef FEATURE_MDNS
|
||||
#include <ESP8266mDNS.h>
|
||||
#define FS_NO_GLOBALS
|
||||
#if defined(ESP8266)
|
||||
#define NODE_TYPE_ID NODE_TYPE_ID_ESP_EASYM_STD
|
||||
#define FILE_CONFIG "config.dat"
|
||||
#define FILE_SECURITY "security.dat"
|
||||
#define FILE_NOTIFICATION "notification.dat"
|
||||
#define FILE_RULES "rules1.dat"
|
||||
#include <lwip/init.h>
|
||||
#ifndef LWIP_VERSION_MAJOR
|
||||
#error
|
||||
#endif
|
||||
#if LWIP_VERSION_MAJOR == 2
|
||||
// #include <lwip/priv/tcp_priv.h>
|
||||
#else
|
||||
#include <lwip/tcp_impl.h>
|
||||
#endif
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <ESP8266WebServer.h>
|
||||
ESP8266WebServer WebServer(80);
|
||||
#include <DNSServer.h>
|
||||
#include <Servo.h>
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
ESP8266HTTPUpdateServer httpUpdater(true);
|
||||
#ifndef LWIP_OPEN_SRC
|
||||
#define LWIP_OPEN_SRC
|
||||
#endif
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "include/UdpContext.h"
|
||||
#include "limits.h"
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
extern "C" {
|
||||
#include "spi_flash.h"
|
||||
}
|
||||
extern "C" uint32_t _SPIFFS_start;
|
||||
extern "C" uint32_t _SPIFFS_end;
|
||||
extern "C" uint32_t _SPIFFS_page;
|
||||
extern "C" uint32_t _SPIFFS_block;
|
||||
#ifdef FEATURE_MDNS
|
||||
#include <ESP8266mDNS.h>
|
||||
#endif
|
||||
#ifdef FEATURE_ARDUINO_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
bool ArduinoOTAtriggered=false;
|
||||
#endif
|
||||
#define PIN_D_MAX 16
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
#define NODE_TYPE_ID NODE_TYPE_ID_ESP_EASY32_STD
|
||||
#define ICACHE_RAM_ATTR IRAM_ATTR
|
||||
#define FILE_CONFIG "/config.dat"
|
||||
#define FILE_SECURITY "/security.dat"
|
||||
#define FILE_NOTIFICATION "/notification.dat"
|
||||
#define FILE_RULES "/rules1.dat"
|
||||
#include <WiFi.h>
|
||||
#include <ESP32WebServer.h>
|
||||
#include "SPIFFS.h"
|
||||
ESP32WebServer WebServer(80);
|
||||
#ifdef FEATURE_MDNS
|
||||
#include <ESPmDNS.h>
|
||||
#endif
|
||||
#ifdef FEATURE_ARDUINO_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#include <ESPmDNS.h>
|
||||
bool ArduinoOTAtriggered=false;
|
||||
#endif
|
||||
#define PIN_D_MAX 39
|
||||
int8_t ledChannelPin[16];
|
||||
#endif
|
||||
|
||||
#include <WiFiUdp.h>
|
||||
#include <DNSServer.h>
|
||||
#include <Wire.h>
|
||||
#include <SPI.h>
|
||||
#include <PubSubClient.h>
|
||||
// #include <ArduinoJson.h>
|
||||
// #include <LiquidCrystal_I2C.h>
|
||||
#include <Servo.h>
|
||||
#define FS_NO_GLOBALS
|
||||
#include <FS.h>
|
||||
#ifdef FEATURE_SD
|
||||
#include <SD.h>
|
||||
#include <ESP8266HTTPUpdateServer.h>
|
||||
ESP8266HTTPUpdateServer httpUpdater(true);
|
||||
#else
|
||||
using namespace fs;
|
||||
#endif
|
||||
#include <base64.h>
|
||||
#if FEATURE_ADC_VCC
|
||||
ADC_MODE(ADC_VCC);
|
||||
#endif
|
||||
#ifndef LWIP_OPEN_SRC
|
||||
#define LWIP_OPEN_SRC
|
||||
#endif
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/igmp.h"
|
||||
#include "include/UdpContext.h"
|
||||
#include "limits.h"
|
||||
|
||||
extern "C" {
|
||||
#include "user_interface.h"
|
||||
}
|
||||
|
||||
|
||||
#ifdef FEATURE_ARDUINO_OTA
|
||||
#include <ArduinoOTA.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
bool ArduinoOTAtriggered=false;
|
||||
#endif
|
||||
|
||||
|
||||
// Setup DNS, only used if the ESP has no valid WiFi config
|
||||
@@ -417,12 +474,18 @@ WiFiClient mqtt;
|
||||
PubSubClient MQTTclient(mqtt);
|
||||
bool MQTTclient_should_reconnect = true;
|
||||
|
||||
// WebServer
|
||||
ESP8266WebServer WebServer(80);
|
||||
|
||||
// udp protocol stuff (syslog, global sync, node info list, ntp time)
|
||||
WiFiUDP portUDP;
|
||||
|
||||
struct CRCStruct{
|
||||
char compileTimeMD5[16+32+1]= "MD5_MD5_MD5_MD5_BoundariesOfTheSegmentsGoHere...";
|
||||
char compileTime[16]= __TIME__;
|
||||
char compileDate[16]= __DATE__;
|
||||
uint8_t runTimeMD5[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
|
||||
bool checkPassed (void){ return memcmp(compileTimeMD5,runTimeMD5,16)==0 ; }
|
||||
uint32_t numberOfCRCBytes=0;
|
||||
}CRCValues;
|
||||
|
||||
bool WiFiConnected(uint32_t timeout_ms);
|
||||
|
||||
extern "C" {
|
||||
@@ -455,7 +518,12 @@ struct SecurityStruct
|
||||
char ControllerUser[CONTROLLER_MAX][26];
|
||||
char ControllerPassword[CONTROLLER_MAX][64];
|
||||
char Password[26];
|
||||
//its safe to extend this struct, up to 4096 bytes, default values in config are 0
|
||||
byte AllowedIPrangeLow[4]; // TD-er: Use these
|
||||
byte AllowedIPrangeHigh[4];
|
||||
byte IPblockLevel;
|
||||
//its safe to extend this struct, up to 4096 bytes, default values in config are 0. Make sure crc is last
|
||||
uint8_t ProgmemMd5[16]; // crc of the binary that last saved the struct to file.
|
||||
uint8_t md5[16];
|
||||
} SecuritySettings;
|
||||
|
||||
struct SettingsStruct
|
||||
@@ -571,11 +639,16 @@ struct SettingsStruct
|
||||
boolean Pin_status_led_Inversed;
|
||||
boolean deepSleepOnFail;
|
||||
boolean UseValueLogger;
|
||||
boolean ArduinoOTAEnable;
|
||||
uint16_t DST_Start;
|
||||
uint16_t DST_End;
|
||||
|
||||
//its safe to extend this struct, up to several bytes, default values in config are 0
|
||||
//look in misc.ino how config.dat is used because also other stuff is stored in it at different offsets.
|
||||
//TODO: document config.dat somewhere here
|
||||
// make sure crc is the last value in the struct
|
||||
uint8_t ProgmemMd5[16]; // crc of the binary that last saved the struct to file.
|
||||
uint8_t md5[16];
|
||||
} Settings;
|
||||
|
||||
struct ControllerSettingsStruct
|
||||
@@ -903,6 +976,7 @@ unsigned long timer20ms;
|
||||
unsigned long timer1s;
|
||||
unsigned long timerwd;
|
||||
unsigned long lastSend;
|
||||
unsigned long lastWeb;
|
||||
unsigned int NC_Count = 0;
|
||||
unsigned int C_Count = 0;
|
||||
byte cmd_within_mainloop = 0;
|
||||
@@ -943,16 +1017,33 @@ unsigned long dailyResetCounter = 0;
|
||||
|
||||
String eventBuffer = "";
|
||||
|
||||
uint16_t lowestRAM = 0;
|
||||
uint32_t lowestRAM = 0;
|
||||
String lowestRAMfunction = "";
|
||||
|
||||
bool shouldReboot=false;
|
||||
|
||||
// Blynk_get prototype
|
||||
boolean Blynk_get(const String& command, byte controllerIndex,float *data = NULL );
|
||||
|
||||
int firstEnabledBlynkController() {
|
||||
for (byte i = 0; i < CONTROLLER_MAX; ++i) {
|
||||
byte ProtocolIndex = getProtocolIndex(Settings.Protocol[i]);
|
||||
if (Protocol[ProtocolIndex].Number == 12 && Settings.ControllerEnabled[i]) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* SETUP
|
||||
\*********************************************************************************************/
|
||||
void setup()
|
||||
{
|
||||
#if defined(ESP32)
|
||||
for(byte x = 0; x < 16; x++)
|
||||
ledChannelPin[x] = -1;
|
||||
#endif
|
||||
|
||||
lowestRAM = FreeMem();
|
||||
|
||||
@@ -1009,12 +1100,9 @@ void setup()
|
||||
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
|
||||
|
||||
|
||||
fileSystemCheck();
|
||||
progMemMD5check();
|
||||
LoadSettings();
|
||||
|
||||
if (strcasecmp(SecuritySettings.WifiSSID, "ssid") == 0)
|
||||
wifiSetup = true;
|
||||
|
||||
@@ -1265,7 +1353,12 @@ void runOncePerSecond()
|
||||
}
|
||||
case CMD_REBOOT:
|
||||
{
|
||||
ESP.reset();
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
ESP.restart();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1332,12 +1425,16 @@ void runEach30Seconds()
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
sendSysInfoUDP(1);
|
||||
refreshNodeList();
|
||||
|
||||
int enabledMqttController = firstEnabledMQTTController();
|
||||
if (enabledMqttController >= 0) {
|
||||
MQTTCheck(enabledMqttController);
|
||||
}
|
||||
|
||||
#if defined(ESP8266)
|
||||
if (Settings.UseSSDP)
|
||||
SSDP_update();
|
||||
#endif
|
||||
#if FEATURE_ADC_VCC
|
||||
vcc = ESP.getVcc() / 1000.0;
|
||||
#endif
|
||||
@@ -1546,7 +1643,9 @@ void backgroundtasks()
|
||||
}
|
||||
runningBackgroundTasks=true;
|
||||
|
||||
tcpCleanup();
|
||||
#if defined(ESP8266)
|
||||
tcpCleanup();
|
||||
#endif
|
||||
|
||||
if (Settings.UseSerial)
|
||||
if (Serial.available())
|
||||
@@ -1562,7 +1661,8 @@ void backgroundtasks()
|
||||
checkUDP();
|
||||
|
||||
#ifdef FEATURE_ARDUINO_OTA
|
||||
ArduinoOTA.handle();
|
||||
if(Settings.ArduinoOTAEnable)
|
||||
ArduinoOTA.handle();
|
||||
|
||||
//once OTA is triggered, only handle that and dont do other stuff. (otherwise it fails)
|
||||
while (ArduinoOTAtriggered)
|
||||
|
||||
+9
-5
@@ -1,5 +1,5 @@
|
||||
/********************************************************************************************\
|
||||
* Initialize specific hardware setings (only global ones, others are set through devices)
|
||||
* Initialize specific hardware settings (only global ones, others are set through devices)
|
||||
\*********************************************************************************************/
|
||||
|
||||
void hardwareInit()
|
||||
@@ -37,7 +37,9 @@ void hardwareInit()
|
||||
String log = F("INIT : I2C custom clockstretchlimit:");
|
||||
log += Settings.WireClockStretchLimit;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
Wire.setClockStretchLimit(Settings.WireClockStretchLimit);
|
||||
#if defined(ESP8266)
|
||||
Wire.setClockStretchLimit(Settings.WireClockStretchLimit);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +51,7 @@ void hardwareInit()
|
||||
Wire.write(0x83); // command to set pointer
|
||||
Wire.write(17); // pointer value to status byte
|
||||
Wire.endTransmission();
|
||||
|
||||
|
||||
Wire.requestFrom(Settings.WDI2CAddress, (uint8_t)1);
|
||||
if (Wire.available())
|
||||
{
|
||||
@@ -62,7 +64,7 @@ void hardwareInit()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// SPI Init
|
||||
if (Settings.InitSPI)
|
||||
{
|
||||
@@ -77,7 +79,8 @@ void hardwareInit()
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
if (Settings.Pin_sd_cs > 0)
|
||||
#ifdef FEATURE_SD
|
||||
if (Settings.Pin_sd_cs >= 0)
|
||||
{
|
||||
if (SD.begin(Settings.Pin_sd_cs))
|
||||
{
|
||||
@@ -90,6 +93,7 @@ void hardwareInit()
|
||||
addLog(LOG_LEVEL_ERROR, log);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
+313
-87
@@ -3,13 +3,22 @@
|
||||
// this feature is not in all upstream versions yet.
|
||||
// See https://github.com/esp8266/Arduino/issues/1923
|
||||
// and https://github.com/letscontrolit/ESPEasy/issues/253
|
||||
#if defined(ESP8266)
|
||||
#include <md5.h>
|
||||
#endif
|
||||
#if defined(ESP8266)
|
||||
void tcpCleanup()
|
||||
{
|
||||
while(tcp_tw_pcbs!=NULL)
|
||||
{
|
||||
tcp_abort(tcp_tw_pcbs);
|
||||
}
|
||||
#if LWIP_VERSION_MAJOR == 2
|
||||
// is it still needed ?
|
||||
#else
|
||||
while(tcp_tw_pcbs!=NULL)
|
||||
{
|
||||
tcp_abort(tcp_tw_pcbs);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
bool isDeepSleepEnabled()
|
||||
{
|
||||
@@ -67,7 +76,13 @@ void deepSleepStart(int delay)
|
||||
delay = 4294; //max sleep time ~1.2h
|
||||
|
||||
addLog(LOG_LEVEL_INFO, F("SLEEP: Powering down to deepsleep..."));
|
||||
ESP.deepSleep((uint32_t)delay * 1000000, WAKE_RF_DEFAULT);
|
||||
#if defined(ESP8266)
|
||||
ESP.deepSleep((uint32_t)delay * 1000000, WAKE_RF_DEFAULT);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
esp_sleep_enable_timer_wakeup((uint32_t)delay * 1000000);
|
||||
esp_deep_sleep_start();
|
||||
#endif
|
||||
}
|
||||
|
||||
boolean remoteConfig(struct EventStruct *event, String& string)
|
||||
@@ -364,6 +379,9 @@ String getPinStateJSON(boolean search, byte plugin, byte index, String& log, uin
|
||||
/********************************************************************************************\
|
||||
Status LED
|
||||
\*********************************************************************************************/
|
||||
#if defined(ESP32)
|
||||
#define PWMRANGE 1024
|
||||
#endif
|
||||
#define STATUS_PWM_NORMALVALUE (PWMRANGE>>2)
|
||||
#define STATUS_PWM_NORMALFADE (PWMRANGE>>8)
|
||||
#define STATUS_PWM_TRAFFICRISE (PWMRANGE>>1)
|
||||
@@ -421,7 +439,9 @@ void statusLED(boolean traffic)
|
||||
if (Settings.Pin_status_led_Inversed)
|
||||
pwm = PWMRANGE-pwm;
|
||||
|
||||
analogWrite(Settings.Pin_status_led, pwm);
|
||||
#if defined(ESP8266)
|
||||
analogWrite(Settings.Pin_status_led, pwm);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,7 +551,7 @@ String BuildFixes()
|
||||
|
||||
if (Settings.Build < 145)
|
||||
{
|
||||
String fname=F("notification.dat");
|
||||
String fname=F(FILE_NOTIFICATION);
|
||||
fs::File f = SPIFFS.open(fname, "w");
|
||||
SPIFFS_CHECK(f, fname.c_str());
|
||||
|
||||
@@ -557,16 +577,18 @@ void fileSystemCheck()
|
||||
addLog(LOG_LEVEL_INFO, F("FS : Mounting..."));
|
||||
if (SPIFFS.begin())
|
||||
{
|
||||
fs::FSInfo fs_info;
|
||||
SPIFFS.info(fs_info);
|
||||
#if defined(ESP8266)
|
||||
fs::FSInfo fs_info;
|
||||
SPIFFS.info(fs_info);
|
||||
|
||||
String log = F("FS : Mount successful, used ");
|
||||
log=log+fs_info.usedBytes;
|
||||
log=log+F(" bytes of ");
|
||||
log=log+fs_info.totalBytes;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
String log = F("FS : Mount successful, used ");
|
||||
log=log+fs_info.usedBytes;
|
||||
log=log+F(" bytes of ");
|
||||
log=log+fs_info.totalBytes;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
#endif
|
||||
|
||||
fs::File f = SPIFFS.open("config.dat", "r");
|
||||
fs::File f = SPIFFS.open(FILE_CONFIG, "r");
|
||||
if (!f)
|
||||
{
|
||||
ResetFactory();
|
||||
@@ -711,31 +733,135 @@ boolean str2ip(const char *string, byte* IP)
|
||||
return false;
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
check the program memory hash
|
||||
The const MD5_MD5_MD5_MD5_BoundariesOfTheSegmentsGoHere... needs to remain unchanged as it will be replaced by
|
||||
- 16 bytes md5 hash, followed by
|
||||
- 4 * uint32_t start of memory segment 1-4
|
||||
- 4 * uint32_t end of memory segment 1-4
|
||||
currently there are only two segemts included in the hash. Unused segments have start adress 0.
|
||||
Execution time 520kb @80Mhz: 236ms
|
||||
Returns: 0 if hash compare fails, number of checked bytes otherwise.
|
||||
The reference hash is calculated by a .py file and injected into the binary.
|
||||
Caution: currently the hash sits in an unchecked segment. If it ever moves to a checked segment, make sure
|
||||
it is excluded from the calculation !
|
||||
\*********************************************************************************************/
|
||||
#if defined(ARDUINO_ESP8266_RELEASE_2_3_0)
|
||||
void dump (uint32_t addr) { //Seems already included in core 2.4 ...
|
||||
Serial.print (addr, HEX);
|
||||
Serial.print(": ");
|
||||
for (uint32_t a = addr; a < addr + 16; a++)
|
||||
{
|
||||
Serial.print ( pgm_read_byte(a), HEX);
|
||||
Serial.print (" ");
|
||||
}
|
||||
Serial.println("");
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t progMemMD5check(){
|
||||
#define BufSize 10
|
||||
uint32_t calcBuffer[BufSize];
|
||||
CRCValues.numberOfCRCBytes = 0;
|
||||
memcpy (calcBuffer,CRCValues.compileTimeMD5,16); // is there still the dummy in memory ? - the dummy needs to be replaced by the real md5 after linking.
|
||||
if( memcmp (calcBuffer, "MD5_MD5_MD5_",12)==0){ // do not memcmp with CRCdummy directly or it will get optimized away.
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : No program memory checksum found. Check output of crc2.py"));
|
||||
return 0;
|
||||
}
|
||||
MD5Builder md5;
|
||||
md5.begin();
|
||||
for (int l = 0; l<4; l++){ // check max segments, if the pointer is not 0
|
||||
uint32_t *ptrStart = (uint32_t *)&CRCValues.compileTimeMD5[16+l*4];
|
||||
uint32_t *ptrEnd = (uint32_t *)&CRCValues.compileTimeMD5[16+4*4+l*4];
|
||||
if ((*ptrStart) == 0) break; // segment not used.
|
||||
for (uint32_t i = *ptrStart; i< (*ptrEnd) ; i=i+sizeof(calcBuffer)){ // "<" includes last byte
|
||||
for (int buf = 0; buf < BufSize; buf ++){
|
||||
calcBuffer[buf] = pgm_read_dword((uint32_t*)i+buf); // read 4 bytes
|
||||
CRCValues.numberOfCRCBytes+=sizeof(calcBuffer[0]);
|
||||
}
|
||||
md5.add((uint8_t *)&calcBuffer[0],(*ptrEnd-i)<sizeof(calcBuffer) ? (*ptrEnd-i):sizeof(calcBuffer) ); // add buffer to md5. At the end not the whole buffer. md5 ptr to data in ram.
|
||||
}
|
||||
}
|
||||
md5.calculate();
|
||||
md5.getBytes(CRCValues.runTimeMD5);
|
||||
if ( CRCValues.checkPassed()) {
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : program checksum ...OK"));
|
||||
return CRCValues.numberOfCRCBytes;
|
||||
}
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : program checksum ...FAIL"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Save settings to SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String SaveSettings(void)
|
||||
{
|
||||
MD5Builder md5;
|
||||
memcpy( Settings.ProgmemMd5, CRCValues.runTimeMD5, 16);
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&Settings, sizeof(Settings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(Settings.md5);
|
||||
|
||||
String err;
|
||||
err=SaveToFile((char*)"config.dat", 0, (byte*)&Settings, sizeof(struct SettingsStruct));
|
||||
err=SaveToFile((char*)FILE_CONFIG, 0, (byte*)&Settings, sizeof(struct SettingsStruct));
|
||||
if (err.length())
|
||||
return(err);
|
||||
return(err);
|
||||
|
||||
return(SaveToFile((char*)"security.dat", 0, (byte*)&SecuritySettings, sizeof(struct SecurityStruct)));
|
||||
memcpy( SecuritySettings.ProgmemMd5, CRCValues.runTimeMD5, 16);
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&SecuritySettings, sizeof(SecuritySettings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(SecuritySettings.md5);
|
||||
err=SaveToFile((char*)FILE_SECURITY, 0, (byte*)&SecuritySettings, sizeof(struct SecurityStruct));
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Load settings from SPIFFS
|
||||
\*********************************************************************************************/
|
||||
String LoadSettings()
|
||||
{
|
||||
String err;
|
||||
err=LoadFromFile((char*)"config.dat", 0, (byte*)&Settings, sizeof(struct SettingsStruct));
|
||||
uint8_t calculatedMd5[16];
|
||||
MD5Builder md5;
|
||||
|
||||
err=LoadFromFile((char*)FILE_CONFIG, 0, (byte*)&Settings, sizeof( SettingsStruct));
|
||||
if (err.length())
|
||||
return(err);
|
||||
|
||||
return(LoadFromFile((char*)"security.dat", 0, (byte*)&SecuritySettings, sizeof(struct SecurityStruct)));
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&Settings, sizeof(Settings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(calculatedMd5);
|
||||
if (memcmp (calculatedMd5, Settings.md5,16)==0){
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : Settings CRC ...OK"));
|
||||
if (memcmp(Settings.ProgmemMd5, CRCValues.runTimeMD5, 16)!=0)
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : binary has changed since last save of Settings"));
|
||||
}
|
||||
else{
|
||||
addLog(LOG_LEVEL_ERROR, F("CRC : Settings CRC ...FAIL"));
|
||||
}
|
||||
|
||||
|
||||
err=LoadFromFile((char*)FILE_SECURITY, 0, (byte*)&SecuritySettings, sizeof( SecurityStruct));
|
||||
md5.begin();
|
||||
md5.add((uint8_t *)&SecuritySettings, sizeof(SecuritySettings)-16);
|
||||
md5.calculate();
|
||||
md5.getBytes(calculatedMd5);
|
||||
if (memcmp (calculatedMd5, SecuritySettings.md5, 16)==0){
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : SecuritySettings CRC ...OK "));
|
||||
if (memcmp(SecuritySettings.ProgmemMd5,CRCValues.runTimeMD5, 16)!=0)
|
||||
addLog(LOG_LEVEL_INFO, F("CRC : binary has changed since last save of Settings"));
|
||||
}
|
||||
else{
|
||||
addLog(LOG_LEVEL_ERROR, F("CRC : SecuritySettings CRC ...FAIL"));
|
||||
}
|
||||
return(err);
|
||||
}
|
||||
|
||||
|
||||
@@ -745,7 +871,7 @@ String LoadSettings()
|
||||
String SaveTaskSettings(byte TaskIndex)
|
||||
{
|
||||
ExtraTaskSettings.TaskIndex = TaskIndex;
|
||||
return(SaveToFile((char*)"config.dat", DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE), (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct)));
|
||||
return(SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE), (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct)));
|
||||
}
|
||||
|
||||
|
||||
@@ -759,7 +885,7 @@ String LoadTaskSettings(byte TaskIndex)
|
||||
return(String());
|
||||
|
||||
String result = "";
|
||||
result = LoadFromFile((char*)"config.dat", DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE), (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct));
|
||||
result = LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE), (byte*)&ExtraTaskSettings, sizeof(struct ExtraTaskSettingsStruct));
|
||||
ExtraTaskSettings.TaskIndex = TaskIndex; // Needed when an empty task was requested
|
||||
return result;
|
||||
}
|
||||
@@ -772,7 +898,7 @@ String SaveCustomTaskSettings(int TaskIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
if (datasize > DAT_TASKS_SIZE)
|
||||
return F("SaveCustomTaskSettings too big");
|
||||
return(SaveToFile((char*)"config.dat", DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE) + DAT_TASKS_CUSTOM_OFFSET, memAddress, datasize));
|
||||
return(SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE) + DAT_TASKS_CUSTOM_OFFSET, memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
@@ -792,7 +918,7 @@ String LoadCustomTaskSettings(int TaskIndex, byte* memAddress, int datasize)
|
||||
{
|
||||
if (datasize > DAT_TASKS_SIZE)
|
||||
return (String(F("LoadCustomTaskSettings too big")));
|
||||
return(LoadFromFile((char*)"config.dat", DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE) + DAT_TASKS_CUSTOM_OFFSET, memAddress, datasize));
|
||||
return(LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_TASKS + (TaskIndex * DAT_TASKS_SIZE) + DAT_TASKS_CUSTOM_OFFSET, memAddress, datasize));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -802,7 +928,7 @@ String SaveControllerSettings(int ControllerIndex, byte* memAddress, int datasiz
|
||||
{
|
||||
if (datasize > DAT_CONTROLLER_SIZE)
|
||||
return F("SaveControllerSettings too big");
|
||||
return SaveToFile((char*)"config.dat", DAT_OFFSET_CONTROLLER + (ControllerIndex * DAT_CONTROLLER_SIZE), memAddress, datasize);
|
||||
return SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_CONTROLLER + (ControllerIndex * DAT_CONTROLLER_SIZE), memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
@@ -814,7 +940,7 @@ String LoadControllerSettings(int ControllerIndex, byte* memAddress, int datasiz
|
||||
if (datasize > DAT_CONTROLLER_SIZE)
|
||||
return F("LoadControllerSettings too big");
|
||||
|
||||
return(LoadFromFile((char*)"config.dat", DAT_OFFSET_CONTROLLER + (ControllerIndex * DAT_CONTROLLER_SIZE), memAddress, datasize));
|
||||
return(LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_CONTROLLER + (ControllerIndex * DAT_CONTROLLER_SIZE), memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
@@ -835,7 +961,7 @@ String SaveCustomControllerSettings(int ControllerIndex,byte* memAddress, int da
|
||||
{
|
||||
if (datasize > DAT_CUSTOM_CONTROLLER_SIZE)
|
||||
return F("SaveCustomControllerSettings too big");
|
||||
return SaveToFile((char*)"config.dat", DAT_OFFSET_CUSTOM_CONTROLLER + (ControllerIndex * DAT_CUSTOM_CONTROLLER_SIZE), memAddress, datasize);
|
||||
return SaveToFile((char*)FILE_CONFIG, DAT_OFFSET_CUSTOM_CONTROLLER + (ControllerIndex * DAT_CUSTOM_CONTROLLER_SIZE), memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
@@ -846,7 +972,7 @@ String LoadCustomControllerSettings(int ControllerIndex,byte* memAddress, int da
|
||||
{
|
||||
if (datasize > DAT_CUSTOM_CONTROLLER_SIZE)
|
||||
return(F("LoadCustomControllerSettings too big"));
|
||||
return(LoadFromFile((char*)"config.dat", DAT_OFFSET_CUSTOM_CONTROLLER + (ControllerIndex * DAT_CUSTOM_CONTROLLER_SIZE), memAddress, datasize));
|
||||
return(LoadFromFile((char*)FILE_CONFIG, DAT_OFFSET_CUSTOM_CONTROLLER + (ControllerIndex * DAT_CUSTOM_CONTROLLER_SIZE), memAddress, datasize));
|
||||
}
|
||||
|
||||
/********************************************************************************************\
|
||||
@@ -856,7 +982,7 @@ String SaveNotificationSettings(int NotificationIndex, byte* memAddress, int dat
|
||||
{
|
||||
if (datasize > DAT_NOTIFICATION_SIZE)
|
||||
return F("SaveNotificationSettings too big");
|
||||
return SaveToFile((char*)"notification.dat", NotificationIndex * DAT_NOTIFICATION_SIZE, memAddress, datasize);
|
||||
return SaveToFile((char*)FILE_NOTIFICATION, NotificationIndex * DAT_NOTIFICATION_SIZE, memAddress, datasize);
|
||||
}
|
||||
|
||||
|
||||
@@ -867,7 +993,7 @@ String LoadNotificationSettings(int NotificationIndex, byte* memAddress, int dat
|
||||
{
|
||||
if (datasize > DAT_NOTIFICATION_SIZE)
|
||||
return(F("LoadNotificationSettings too big"));
|
||||
return(LoadFromFile((char*)"notification.dat", NotificationIndex * DAT_NOTIFICATION_SIZE, memAddress, datasize));
|
||||
return(LoadFromFile((char*)FILE_NOTIFICATION, NotificationIndex * DAT_NOTIFICATION_SIZE, memAddress, datasize));
|
||||
}
|
||||
|
||||
|
||||
@@ -975,9 +1101,14 @@ String LoadFromFile(char* fname, int index, byte* memAddress, int datasize)
|
||||
\*********************************************************************************************/
|
||||
int SpiffsSectors()
|
||||
{
|
||||
uint32_t _sectorStart = ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
uint32_t _sectorEnd = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
return _sectorEnd - _sectorStart;
|
||||
#if defined(ESP8266)
|
||||
uint32_t _sectorStart = ((uint32_t)&_SPIFFS_start - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
uint32_t _sectorEnd = ((uint32_t)&_SPIFFS_end - 0x40200000) / SPI_FLASH_SEC_SIZE;
|
||||
return _sectorEnd - _sectorStart;
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
return 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1025,16 +1156,16 @@ void ResetFactory(void)
|
||||
//pad files with extra zeros for future extensions
|
||||
String fname;
|
||||
|
||||
fname=F("config.dat");
|
||||
fname=F(FILE_CONFIG);
|
||||
InitFile(fname.c_str(), 65536);
|
||||
|
||||
fname=F("security.dat");
|
||||
fname=F(FILE_SECURITY);
|
||||
InitFile(fname.c_str(), 4096);
|
||||
|
||||
fname=F("notification.dat");
|
||||
fname=F(FILE_NOTIFICATION);
|
||||
InitFile(fname.c_str(), 4096);
|
||||
|
||||
fname=F("rules1.txt");
|
||||
fname=F(FILE_RULES);
|
||||
InitFile(fname.c_str(), 0);
|
||||
|
||||
LoadSettings();
|
||||
@@ -1054,6 +1185,11 @@ void ResetFactory(void)
|
||||
strcpy_P(SecuritySettings.WifiKey, PSTR(DEFAULT_KEY));
|
||||
strcpy_P(SecuritySettings.WifiAPKey, PSTR(DEFAULT_AP_KEY));
|
||||
SecuritySettings.Password[0] = 0;
|
||||
// TD-er Reset access control
|
||||
str2ip((char*)DEFAULT_IPRANGE_LOW, SecuritySettings.AllowedIPrangeLow);
|
||||
str2ip((char*)DEFAULT_IPRANGE_HIGH, SecuritySettings.AllowedIPrangeHigh);
|
||||
SecuritySettings.IPblockLevel = DEFAULT_IP_BLOCK_LEVEL;
|
||||
|
||||
Settings.Delay = DEFAULT_DELAY;
|
||||
Settings.Pin_i2c_sda = 4;
|
||||
Settings.Pin_i2c_scl = 5;
|
||||
@@ -1134,7 +1270,12 @@ void ResetFactory(void)
|
||||
WiFi.persistent(true); // use SDK storage of SSID/WPA parameters
|
||||
WiFi.disconnect(); // this will store empty ssid/wpa into sdk storage
|
||||
WiFi.persistent(false); // Do not use SDK storage of SSID/WPA parameters
|
||||
ESP.reset();
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1164,7 +1305,12 @@ void emergencyReset()
|
||||
\*********************************************************************************************/
|
||||
unsigned long FreeMem(void)
|
||||
{
|
||||
return system_get_free_heap_size();
|
||||
#if defined(ESP8266)
|
||||
return system_get_free_heap_size();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
return ESP.getFreeHeap();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1235,6 +1381,7 @@ void addLog(byte loglevel, const char *line)
|
||||
Logging.add(line);
|
||||
}
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
if (loglevelActive(loglevel, Settings.SDLogLevel))
|
||||
{
|
||||
File logFile = SD.open("log.dat", FILE_WRITE);
|
||||
@@ -1242,6 +1389,7 @@ void addLog(byte loglevel, const char *line)
|
||||
logFile.println(line);
|
||||
logFile.close();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1258,7 +1406,12 @@ void delayedReboot(int rebootDelay)
|
||||
rebootDelay--;
|
||||
delay(1000);
|
||||
}
|
||||
ESP.reset();
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
ESP.restart();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1267,15 +1420,20 @@ void delayedReboot(int rebootDelay)
|
||||
\*********************************************************************************************/
|
||||
boolean saveToRTC()
|
||||
{
|
||||
if (!system_rtc_mem_write(RTC_BASE_STRUCT, (byte*)&RTC, sizeof(RTC)) || !readFromRTC())
|
||||
{
|
||||
addLog(LOG_LEVEL_ERROR, F("RTC : Error while writing to RTC"));
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
#if defined(ESP8266)
|
||||
if (!system_rtc_mem_write(RTC_BASE_STRUCT, (byte*)&RTC, sizeof(RTC)) || !readFromRTC())
|
||||
{
|
||||
addLog(LOG_LEVEL_ERROR, F("RTC : Error while writing to RTC"));
|
||||
return(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
boolean ret = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1298,13 +1456,18 @@ void initRTC()
|
||||
\*********************************************************************************************/
|
||||
boolean readFromRTC()
|
||||
{
|
||||
if (!system_rtc_mem_read(RTC_BASE_STRUCT, (byte*)&RTC, sizeof(RTC)))
|
||||
return(false);
|
||||
#if defined(ESP8266)
|
||||
if (!system_rtc_mem_read(RTC_BASE_STRUCT, (byte*)&RTC, sizeof(RTC)))
|
||||
return(false);
|
||||
|
||||
if (RTC.ID1 == 0xAA && RTC.ID2 == 0x55)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
if (RTC.ID1 == 0xAA && RTC.ID2 == 0x55)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
boolean ret = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -1313,12 +1476,17 @@ boolean readFromRTC()
|
||||
\*********************************************************************************************/
|
||||
boolean saveUserVarToRTC()
|
||||
{
|
||||
//addLog(LOG_LEVEL_DEBUG, F("RTCMEM: saveUserVarToRTC"));
|
||||
byte* buffer = (byte*)&UserVar;
|
||||
size_t size = sizeof(UserVar);
|
||||
uint32 sum = getChecksum(buffer, size);
|
||||
boolean ret = system_rtc_mem_write(RTC_BASE_USERVAR, buffer, size);
|
||||
ret &= system_rtc_mem_write(RTC_BASE_USERVAR+(size>>2), (byte*)&sum, 4);
|
||||
#if defined(ESP8266)
|
||||
//addLog(LOG_LEVEL_DEBUG, F("RTCMEM: saveUserVarToRTC"));
|
||||
byte* buffer = (byte*)&UserVar;
|
||||
size_t size = sizeof(UserVar);
|
||||
uint32_t sum = getChecksum(buffer, size);
|
||||
boolean ret = system_rtc_mem_write(RTC_BASE_USERVAR, buffer, size);
|
||||
ret &= system_rtc_mem_write(RTC_BASE_USERVAR+(size>>2), (byte*)&sum, 4);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
boolean ret = false;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1328,34 +1496,58 @@ boolean saveUserVarToRTC()
|
||||
\*********************************************************************************************/
|
||||
boolean readUserVarFromRTC()
|
||||
{
|
||||
//addLog(LOG_LEVEL_DEBUG, F("RTCMEM: readUserVarFromRTC"));
|
||||
byte* buffer = (byte*)&UserVar;
|
||||
size_t size = sizeof(UserVar);
|
||||
boolean ret = system_rtc_mem_read(RTC_BASE_USERVAR, buffer, size);
|
||||
uint32 sumRAM = getChecksum(buffer, size);
|
||||
uint32 sumRTC = 0;
|
||||
ret &= system_rtc_mem_read(RTC_BASE_USERVAR+(size>>2), (byte*)&sumRTC, 4);
|
||||
if (!ret || sumRTC != sumRAM)
|
||||
{
|
||||
addLog(LOG_LEVEL_ERROR, F("RTC : Checksum error on reading RTC user var"));
|
||||
memset(buffer, 0, size);
|
||||
}
|
||||
#if defined(ESP8266)
|
||||
//addLog(LOG_LEVEL_DEBUG, F("RTCMEM: readUserVarFromRTC"));
|
||||
byte* buffer = (byte*)&UserVar;
|
||||
size_t size = sizeof(UserVar);
|
||||
boolean ret = system_rtc_mem_read(RTC_BASE_USERVAR, buffer, size);
|
||||
uint32_t sumRAM = getChecksum(buffer, size);
|
||||
uint32_t sumRTC = 0;
|
||||
ret &= system_rtc_mem_read(RTC_BASE_USERVAR+(size>>2), (byte*)&sumRTC, 4);
|
||||
if (!ret || sumRTC != sumRAM)
|
||||
{
|
||||
addLog(LOG_LEVEL_ERROR, F("RTC : Checksum error on reading RTC user var"));
|
||||
memset(buffer, 0, size);
|
||||
}
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
boolean ret = false;
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint32 getChecksum(byte* buffer, size_t size)
|
||||
uint32_t getChecksum(byte* buffer, size_t size)
|
||||
{
|
||||
uint32 sum = 0x82662342; //some magic to avoid valid checksum on new, uninitialized ESP
|
||||
uint32_t sum = 0x82662342; //some magic to avoid valid checksum on new, uninitialized ESP
|
||||
for (size_t i=0; i<size; i++)
|
||||
sum += buffer[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************************************************************************\
|
||||
Parse string template
|
||||
\*********************************************************************************************/
|
||||
|
||||
// Call this by first declaring a char array of size 20, like:
|
||||
// char strIP[20];
|
||||
// formatIP(ip, strIP);
|
||||
void formatIP(const IPAddress& ip, char (&strIP)[20]) {
|
||||
sprintf_P(strIP, PSTR("%u.%u.%u.%u"), ip[0], ip[1], ip[2], ip[3]);
|
||||
}
|
||||
|
||||
String formatIP(const IPAddress& ip) {
|
||||
char strIP[20];
|
||||
formatIP(ip, strIP);
|
||||
return String(strIP);
|
||||
}
|
||||
|
||||
void formatMAC(const uint8_t* mac, char (&strMAC)[20]) {
|
||||
sprintf_P(strMAC, PSTR("%02X:%02X:%02X:%02X:%02X:%02X"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
}
|
||||
|
||||
String parseTemplate(String &tmpString, byte lineSize)
|
||||
{
|
||||
String newString = "";
|
||||
@@ -1640,7 +1832,7 @@ float pop()
|
||||
if (sp != (globalstack - 1)) // empty
|
||||
return *(sp--);
|
||||
else
|
||||
return(0);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
float apply_operator(char op, float first, float second)
|
||||
@@ -1674,7 +1866,7 @@ int RPNCalculate(char* token)
|
||||
if (token[0] == 0)
|
||||
return 0; // geen moeite doen voor een lege string
|
||||
|
||||
if (is_operator(token[0]))
|
||||
if (is_operator(token[0]) && token[1] == 0)
|
||||
{
|
||||
float second = pop();
|
||||
float first = pop();
|
||||
@@ -1745,7 +1937,7 @@ int Calculate(const char *input, float* result)
|
||||
{
|
||||
const char *strpos = input, *strend = input + strlen(input);
|
||||
char token[25];
|
||||
char c, *TokenPos = token;
|
||||
char c, oc, *TokenPos = token;
|
||||
char stack[32]; // operator stack
|
||||
unsigned int sl = 0; // stack length
|
||||
char sc; // used for record stack element
|
||||
@@ -1753,15 +1945,16 @@ int Calculate(const char *input, float* result)
|
||||
|
||||
//*sp=0; // bug, it stops calculating after 50 times
|
||||
sp = globalstack - 1;
|
||||
|
||||
oc=c=0;
|
||||
while (strpos < strend)
|
||||
{
|
||||
// read one token from the input stream
|
||||
oc = c;
|
||||
c = *strpos;
|
||||
if (c != ' ')
|
||||
{
|
||||
// If the token is a number (identifier), then add it to the token queue.
|
||||
if ((c >= '0' && c <= '9') || c == '.')
|
||||
if ((c >= '0' && c <= '9') || c == '.' || (c == '-' && is_operator(oc)))
|
||||
{
|
||||
*TokenPos = c;
|
||||
++TokenPos;
|
||||
@@ -1893,7 +2086,12 @@ void rulesProcessing(String& event)
|
||||
|
||||
for (byte x = 1; x < RULESETS_MAX + 1; x++)
|
||||
{
|
||||
String fileName = F("rules");
|
||||
#if defined(ESP8266)
|
||||
String fileName = F("rules");
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
String fileName = F("/rules");
|
||||
#endif
|
||||
fileName += x;
|
||||
fileName += F(".txt");
|
||||
if (SPIFFS.exists(fileName))
|
||||
@@ -2331,17 +2529,19 @@ void SendValueLogger(byte TaskIndex)
|
||||
|
||||
addLog(LOG_LEVEL_DEBUG, logger);
|
||||
|
||||
#ifdef FEATURE_SD
|
||||
String filename = F("VALUES.CSV");
|
||||
File logFile = SD.open(filename, FILE_WRITE);
|
||||
if (logFile)
|
||||
logFile.print(logger);
|
||||
logFile.close();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void checkRAM( const __FlashStringHelper* flashString)
|
||||
{
|
||||
uint16_t freeRAM = FreeMem();
|
||||
uint32_t freeRAM = FreeMem();
|
||||
|
||||
if (freeRAM < lowestRAM)
|
||||
{
|
||||
@@ -2368,10 +2568,10 @@ void tone(uint8_t _pin, unsigned int frequency, unsigned long duration) {
|
||||
/********************************************************************************************\
|
||||
Play RTTTL string on specified pin
|
||||
\*********************************************************************************************/
|
||||
void play_rtttl(uint8_t _pin, char *p )
|
||||
void play_rtttl(uint8_t _pin, const char *p )
|
||||
{
|
||||
#define OCTAVE_OFFSET 0
|
||||
// Absolutely no error checking in here
|
||||
// FIXME: Absolutely no error checking in here
|
||||
|
||||
int notes[] = { 0,
|
||||
262, 277, 294, 311, 330, 349, 370, 392, 415, 440, 466, 494,
|
||||
@@ -2550,7 +2750,12 @@ void ArduinoOTAInit()
|
||||
//so dont touch device until restart is complete
|
||||
Serial.println(F("\nOTA : DO NOT RESET OR POWER OFF UNTIL BOOT+FLASH IS COMPLETE."));
|
||||
delay(100);
|
||||
ESP.reset();
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
ESP.restart();
|
||||
#endif
|
||||
});
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
|
||||
@@ -2566,7 +2771,12 @@ void ArduinoOTAInit()
|
||||
else if (error == OTA_END_ERROR) Serial.println(F("End Failed"));
|
||||
|
||||
delay(100);
|
||||
ESP.reset();
|
||||
#if defined(ESP8266)
|
||||
ESP.reset();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
ESP.restart();
|
||||
#endif
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
|
||||
@@ -2614,3 +2824,19 @@ void htmlEscape(String & html)
|
||||
html.replace("<", "<");
|
||||
html.replace(">", ">");
|
||||
}
|
||||
|
||||
// Compute the dew point temperature, given temperature and humidity (temp in Celcius)
|
||||
// Formula: http://www.ajdesigner.com/phphumidity/dewpoint_equation_dewpoint_temperature.php
|
||||
// Td = (f/100)^(1/8) * (112 + 0.9*T) + 0.1*T - 112
|
||||
float compute_dew_point_temp(float temperature, float humidity_percentage) {
|
||||
return pow(humidity_percentage / 100.0, 0.125) *
|
||||
(112.0 + 0.9*temperature) + 0.1*temperature - 112.0;
|
||||
}
|
||||
|
||||
// Compute the humidity given temperature and dew point temperature (temp in Celcius)
|
||||
// Formula: http://www.ajdesigner.com/phphumidity/dewpoint_equation_relative_humidity.php
|
||||
// f = 100 * ((112 - 0.1*T + Td) / (112 + 0.9 * T))^8
|
||||
float compute_humidity_from_dewpoint(float temperature, float dew_temperature) {
|
||||
return 100.0 * pow((112.0 - 0.1 * temperature + dew_temperature) /
|
||||
(112.0 + 0.9 * temperature), 8);
|
||||
}
|
||||
|
||||
+24
-9
@@ -2,6 +2,11 @@
|
||||
// Syslog
|
||||
// UDP system messaging
|
||||
// SSDP
|
||||
#if LWIP_VERSION_MAJOR == 2
|
||||
#define IP2STR(addr) (uint8_t)((uint32_t)addr & 0xFF), (uint8_t)(((uint32_t)addr >> 8) & 0xFF), (uint8_t)(((uint32_t)addr >> 16) & 0xFF), (uint8_t)(((uint32_t)addr >> 24) & 0xFF)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
Syslog client
|
||||
@@ -64,11 +69,17 @@ struct dataStruct
|
||||
/*********************************************************************************************\
|
||||
Check UDP messages (ESPEasy propiertary protocol)
|
||||
\*********************************************************************************************/
|
||||
boolean runningUPDCheck = false;
|
||||
void checkUDP()
|
||||
{
|
||||
if (Settings.UDPPort == 0)
|
||||
return;
|
||||
|
||||
if (runningUPDCheck)
|
||||
return;
|
||||
|
||||
runningUPDCheck = true;
|
||||
|
||||
// UDP events
|
||||
int packetSize = portUDP.parsePacket();
|
||||
if (packetSize)
|
||||
@@ -79,6 +90,7 @@ void checkUDP()
|
||||
if (portUDP.remotePort() == 123)
|
||||
{
|
||||
// unexpected NTP reply, drop for now...
|
||||
runningUPDCheck = false;
|
||||
return;
|
||||
}
|
||||
char packetBuffer[128];
|
||||
@@ -140,9 +152,9 @@ void checkUDP()
|
||||
}
|
||||
|
||||
char macaddress[20];
|
||||
sprintf_P(macaddress, PSTR("%02x:%02x:%02x:%02x:%02x:%02x"), mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
|
||||
char ipaddress[16];
|
||||
sprintf_P(ipaddress, PSTR("%u.%u.%u.%u"), ip[0], ip[1], ip[2], ip[3]);
|
||||
formatMAC(mac, macaddress);
|
||||
char ipaddress[20];
|
||||
formatIP(ip, ipaddress);
|
||||
char log[80];
|
||||
sprintf_P(log, PSTR("UDP : %s,%s,%u"), macaddress, ipaddress, unit);
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
@@ -218,6 +230,10 @@ void checkUDP()
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(ESP32) // testing
|
||||
portUDP.flush();
|
||||
#endif
|
||||
runningUPDCheck = false;
|
||||
}
|
||||
|
||||
|
||||
@@ -418,7 +434,7 @@ void sendSysInfoUDP(byte repeats)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(ESP8266)
|
||||
/********************************************************************************************\
|
||||
Respond to HTTP XML requests for SSDP information
|
||||
\*********************************************************************************************/
|
||||
@@ -427,10 +443,8 @@ void SSDP_schema(WiFiClient &client) {
|
||||
return;
|
||||
}
|
||||
|
||||
IPAddress ip = WiFi.localIP();
|
||||
char str[20];
|
||||
sprintf_P(str, PSTR("%u.%u.%u.%u"), ip[0], ip[1], ip[2], ip[3]);
|
||||
uint32_t chipId = ESP.getChipId();
|
||||
const IPAddress ip = WiFi.localIP();
|
||||
const uint32_t chipId = ESP.getChipId();
|
||||
char uuid[64];
|
||||
sprintf_P(uuid, PSTR("38323636-4558-4dda-9188-cda0e6%02x%02x%02x"),
|
||||
(uint16_t) ((chipId >> 16) & 0xff),
|
||||
@@ -450,7 +464,7 @@ void SSDP_schema(WiFiClient &client) {
|
||||
"<minor>0</minor>"
|
||||
"</specVersion>"
|
||||
"<URLBase>http://");
|
||||
ssdp_schema += str;
|
||||
ssdp_schema += formatIP(ip);
|
||||
ssdp_schema += F(":80/</URLBase>"
|
||||
"<device>"
|
||||
"<deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType>"
|
||||
@@ -755,3 +769,4 @@ bool WiFiConnected(uint32_t timeout_ms) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
+604
-205
File diff suppressed because it is too large
Load Diff
+51
-18
@@ -44,7 +44,12 @@ void WifiAPconfig()
|
||||
|
||||
bool WifiIsAP()
|
||||
{
|
||||
byte wifimode = wifi_get_opmode();
|
||||
#if defined(ESP8266)
|
||||
byte wifimode = wifi_get_opmode();
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
byte wifimode = WiFi.getMode();
|
||||
#endif
|
||||
return(wifimode == 2 || wifimode == 3); //apmode is enabled
|
||||
}
|
||||
|
||||
@@ -82,20 +87,23 @@ boolean WifiConnect(byte connectAttempts)
|
||||
String log = "";
|
||||
char hostname[40];
|
||||
strncpy(hostname, WifiGetHostname().c_str(), sizeof(hostname));
|
||||
wifi_station_set_hostname(hostname);
|
||||
#if defined(ESP8266)
|
||||
wifi_station_set_hostname(hostname);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
WiFi.setHostname(hostname);
|
||||
#endif
|
||||
|
||||
//use static ip?
|
||||
if (Settings.IP[0] != 0 && Settings.IP[0] != 255)
|
||||
{
|
||||
char str[20];
|
||||
sprintf_P(str, PSTR("%u.%u.%u.%u"), Settings.IP[0], Settings.IP[1], Settings.IP[2], Settings.IP[3]);
|
||||
const IPAddress ip = Settings.IP;
|
||||
log = F("IP : Static IP :");
|
||||
log += str;
|
||||
log += ip;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
IPAddress ip = Settings.IP;
|
||||
IPAddress gw = Settings.Gateway;
|
||||
IPAddress subnet = Settings.Subnet;
|
||||
IPAddress dns = Settings.DNS;
|
||||
const IPAddress gw = Settings.Gateway;
|
||||
const IPAddress subnet = Settings.Subnet;
|
||||
const IPAddress dns = Settings.DNS;
|
||||
WiFi.config(ip, gw, subnet, dns);
|
||||
}
|
||||
|
||||
@@ -136,7 +144,7 @@ boolean WifiConnect(byte connectAttempts)
|
||||
|
||||
addLog(LOG_LEVEL_ERROR, F("WIFI : Could not connect to AP!"));
|
||||
|
||||
//everything failed, activate AP mode (will deactivate automaticly after a while if its connected again)
|
||||
//everything failed, activate AP mode (will deactivate automatically after a while if its connected again)
|
||||
WifiAPMode(true);
|
||||
|
||||
return(false);
|
||||
@@ -189,10 +197,7 @@ boolean WifiConnectSSID(char WifiSSID[], char WifiKey[], byte connectAttempts)
|
||||
initTime();
|
||||
}
|
||||
log = F("WIFI : Connected! IP: ");
|
||||
IPAddress ip = WiFi.localIP();
|
||||
char str[20];
|
||||
sprintf_P(str, PSTR("%u.%u.%u.%u"), ip[0], ip[1], ip[2], ip[3]);
|
||||
log += str;
|
||||
log += formatIP(WiFi.localIP());
|
||||
log += F(" (");
|
||||
log += WifiGetHostname();
|
||||
log += F(")");
|
||||
@@ -205,9 +210,11 @@ boolean WifiConnectSSID(char WifiSSID[], char WifiKey[], byte connectAttempts)
|
||||
{
|
||||
// log = F("WIFI : Disconnecting!");
|
||||
// addLog(LOG_LEVEL_INFO, log);
|
||||
ETS_UART_INTR_DISABLE();
|
||||
wifi_station_disconnect();
|
||||
ETS_UART_INTR_ENABLE();
|
||||
#if defined(ESP8266)
|
||||
ETS_UART_INTR_DISABLE();
|
||||
wifi_station_disconnect();
|
||||
ETS_UART_INTR_ENABLE();
|
||||
#endif
|
||||
for (byte x = 0; x < 20; x++)
|
||||
{
|
||||
statusLED(true);
|
||||
@@ -275,7 +282,7 @@ void WifiCheck()
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
{
|
||||
NC_Count++;
|
||||
//give it time to automaticly reconnect
|
||||
//give it time to automatically reconnect
|
||||
if (NC_Count > 2)
|
||||
{
|
||||
WifiConnect(2);
|
||||
@@ -295,3 +302,29 @@ void WifiCheck()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//********************************************************************************
|
||||
// Return subnet range of WiFi.
|
||||
//********************************************************************************
|
||||
bool getSubnetRange(IPAddress& low, IPAddress& high)
|
||||
{
|
||||
if (WifiIsAP()) {
|
||||
// WiFi is active as accesspoint, do not check.
|
||||
return false;
|
||||
}
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
const IPAddress ip = WiFi.localIP();
|
||||
const IPAddress subnet = WiFi.subnetMask();
|
||||
low = ip;
|
||||
high = ip;
|
||||
// Compute subnet range.
|
||||
for (byte i=0; i < 4; ++i) {
|
||||
if (subnet[i] != 255) {
|
||||
low[i] = low[i] & subnet[i];
|
||||
high[i] = high[i] | ~subnet[i];
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
+3
-2
@@ -6,6 +6,7 @@
|
||||
#define CPLUGIN_ID_001 1
|
||||
#define CPLUGIN_NAME_001 "Domoticz HTTP"
|
||||
|
||||
|
||||
boolean CPlugin_001(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
@@ -97,7 +98,7 @@ boolean CPlugin_001(byte function, struct EventStruct *event, String& string)
|
||||
url += F(";");
|
||||
url += humStat(UserVar[event->BaseVarIndex + 1]);
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BMP085
|
||||
case SENSOR_TYPE_TEMP_BARO: // temp + bar used for BMP085 and BMP280
|
||||
url += F("&svalue=");
|
||||
url += formatUserVar(event, 0);
|
||||
url += F(";0;0;");
|
||||
@@ -120,7 +121,7 @@ boolean CPlugin_001(byte function, struct EventStruct *event, String& string)
|
||||
url += F(";");
|
||||
url += humStat(UserVar[event->BaseVarIndex + 1]);
|
||||
url += F(";");
|
||||
url += formatUserVar(event, 2);
|
||||
url += formatUserVar(event, 2);
|
||||
url += F(";0");
|
||||
break;
|
||||
case SENSOR_TYPE_QUAD:
|
||||
|
||||
+13
-13
@@ -208,19 +208,19 @@ boolean CPlugin_002(byte function, struct EventStruct *event, String& string)
|
||||
root[F("svalue")] = values.c_str();
|
||||
// root[F("svalue")] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BME280
|
||||
root[F("nvalue")] = 0;
|
||||
values = formatUserVar(event, 0);
|
||||
values += ";";
|
||||
values += formatUserVar(event, 1);
|
||||
values += ";0;";
|
||||
values += formatUserVar(event, 2);
|
||||
values += ";0";
|
||||
root[F("svalue")] = values.c_str();
|
||||
// values.toCharArray(str, 80);
|
||||
// root[F("svalue")] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_QUAD:
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO: // temp + hum + hum_stat + bar + bar_fore, used for BME280
|
||||
root[F("nvalue")] = 0;
|
||||
values = formatUserVar(event, 0);
|
||||
values += ";";
|
||||
values += formatUserVar(event, 1);
|
||||
values += ";0;";
|
||||
values += formatUserVar(event, 2);
|
||||
values += ";0";
|
||||
root[F("svalue")] = values.c_str();
|
||||
// values.toCharArray(str, 80);
|
||||
// root[F("svalue")] = str;
|
||||
break;
|
||||
case SENSOR_TYPE_QUAD:
|
||||
root[F("nvalue")] = 0;
|
||||
values = formatUserVar(event, 0);
|
||||
values += ";";
|
||||
|
||||
+1
-1
@@ -110,7 +110,7 @@ boolean CPlugin_004(byte function, struct EventStruct *event, String& string)
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
strcpy_P(log, PSTR("HTTP : Success!"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
success = true;
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ boolean CPlugin_005(byte function, struct EventStruct *event, String& string)
|
||||
value = (unsigned long)UserVar[event->BaseVarIndex] + ((unsigned long)UserVar[event->BaseVarIndex + 1] << 16);
|
||||
else
|
||||
value = formatUserVar(event, x);
|
||||
|
||||
MQTTpublish(event->ControllerIndex, tmppubname.c_str(), value.c_str(), Settings.MQTTRetainFlag);
|
||||
String log = F("MQTT : ");
|
||||
log += tmppubname;
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@ boolean CPlugin_007(byte function, struct EventStruct *event, String& string)
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, log);
|
||||
if (line.substring(0, 15) == F("HTTP/1.1 200 OK"))
|
||||
{
|
||||
strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
strcpy_P(log, PSTR("HTTP : Success!"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
success = true;
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ boolean CPlugin_008(byte function, struct EventStruct *event, String& string)
|
||||
Protocol[protocolCount].usesAccount = true;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 80;
|
||||
Protocol[protocolCount].usesID = false;
|
||||
Protocol[protocolCount].usesID = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -136,7 +136,7 @@ boolean HTTPSend(struct EventStruct *event, byte varIndex, float value, unsigned
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, line);
|
||||
if (line.startsWith(F("HTTP/1.1 200 OK")))
|
||||
{
|
||||
// strcpy_P(log, PSTR("HTTP : Succes!"));
|
||||
// strcpy_P(log, PSTR("HTTP : Success!"));
|
||||
// addLog(LOG_LEVEL_DEBUG, log);
|
||||
addLog(LOG_LEVEL_DEBUG, F("HTTP : Success!"));
|
||||
// success = true;
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
- moved on/off translation for SENSOR_TYPE_SWITCH/DIMMER to FHEM module
|
||||
- v1.03
|
||||
- changed http request from GET to POST (RFC conform)
|
||||
- removed obsolet http get url code
|
||||
- removed obsolete http get url code
|
||||
- v1.04
|
||||
- added build options and node_type_id to JSON/device
|
||||
/******************************************************************************/
|
||||
|
||||
+168
@@ -0,0 +1,168 @@
|
||||
//#######################################################################################################
|
||||
//########################### Controller Plugin 012: Blynk #############################################
|
||||
//#######################################################################################################
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define CPLUGIN_012
|
||||
#define CPLUGIN_ID_012 12
|
||||
#define CPLUGIN_NAME_012 "Blynk HTTP [TESTING]"
|
||||
|
||||
boolean CPlugin_012(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case CPLUGIN_PROTOCOL_ADD:
|
||||
{
|
||||
Protocol[++protocolCount].Number = CPLUGIN_ID_012;
|
||||
Protocol[protocolCount].usesMQTT = false;
|
||||
Protocol[protocolCount].usesAccount = false;
|
||||
Protocol[protocolCount].usesPassword = true;
|
||||
Protocol[protocolCount].defaultPort = 8443;
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(CPLUGIN_NAME_012);
|
||||
break;
|
||||
}
|
||||
|
||||
case CPLUGIN_PROTOCOL_SEND:
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
String postDataStr = F("");
|
||||
|
||||
switch (event->sensorType)
|
||||
{
|
||||
case SENSOR_TYPE_SINGLE: // single value sensor, used for Dallas, BH1750, etc
|
||||
success = CPlugin_012_send(event, 1);
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM: // dual value
|
||||
case SENSOR_TYPE_TEMP_BARO:
|
||||
case SENSOR_TYPE_DUAL:
|
||||
success = CPlugin_012_send(event, 2);
|
||||
break;
|
||||
case SENSOR_TYPE_TEMP_HUM_BARO:
|
||||
case SENSOR_TYPE_TRIPLE:
|
||||
success = CPlugin_012_send(event, 3);
|
||||
break;
|
||||
case SENSOR_TYPE_QUAD:
|
||||
success = CPlugin_012_send(event, 4);
|
||||
break;
|
||||
|
||||
case SENSOR_TYPE_SWITCH:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean CPlugin_012_send(struct EventStruct *event, int nrValues) {
|
||||
String postDataStr = F("");
|
||||
boolean success = true;
|
||||
for (int i = 0; i < nrValues && success; ++i) {
|
||||
postDataStr = F("update/V") ;
|
||||
postDataStr += event->idx + i;
|
||||
postDataStr += F("?value=");
|
||||
postDataStr += formatUserVar(event, i);
|
||||
success = Blynk_get(postDataStr, event->ControllerIndex);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
boolean Blynk_get(const String& command, byte controllerIndex, float *data )
|
||||
{
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ControllerSettingsStruct ControllerSettings;
|
||||
LoadControllerSettings(controllerIndex, (byte*)&ControllerSettings, sizeof(ControllerSettings));
|
||||
// Use WiFiClient class to create TCP connections
|
||||
WiFiClient client;
|
||||
if (!ControllerSettings.connectToHost(client))
|
||||
{
|
||||
connectionFailures++;
|
||||
addLog(LOG_LEVEL_ERROR, F("Blynk : connection failed"));
|
||||
return false;
|
||||
}
|
||||
if (connectionFailures)
|
||||
connectionFailures--;
|
||||
|
||||
// We now create a URI for the request
|
||||
char request[300] = {0};
|
||||
sprintf_P(request,
|
||||
PSTR("GET /%s/%s HTTP/1.1\r\n Host: %s \r\n Connection: close\r\n\r\n"),
|
||||
SecuritySettings.ControllerPassword,
|
||||
command.c_str(),
|
||||
ControllerSettings.getHost().c_str());
|
||||
addLog(LOG_LEVEL_DEBUG, request);
|
||||
client.print(request);
|
||||
|
||||
unsigned long timer = millis() + 200;
|
||||
while (!client.available() && !timeOutReached(timer))
|
||||
yield();
|
||||
|
||||
boolean success = false;
|
||||
char log[80] = {0};
|
||||
|
||||
// Read all the lines of the reply from server and log them
|
||||
while (client.available()) {
|
||||
String line;
|
||||
safeReadStringUntil(client, line, '\n');
|
||||
addLog(LOG_LEVEL_DEBUG_MORE, line);
|
||||
// success ?
|
||||
if (line.substring(0, 15) == "HTTP/1.1 200 OK") {
|
||||
strcpy_P(log, PSTR("HTTP : Success"));
|
||||
success = true;
|
||||
}
|
||||
else if (line.substring(0, 24) == "HTTP/1.1 400 Bad Request") {
|
||||
strcpy_P(log, PSTR("HTTP : Unauthorized"));
|
||||
}
|
||||
else if (line.substring(0, 25) == "HTTP/1.1 401 Unauthorized") {
|
||||
strcpy_P(log, PSTR("HTTP : Unauthorized"));
|
||||
}
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
// data only
|
||||
if (data && line.startsWith("["))
|
||||
{
|
||||
String strValue = line;
|
||||
byte pos = strValue.indexOf('"',2);
|
||||
strValue = strValue.substring(2, pos);
|
||||
strValue.trim();
|
||||
float value = strValue.toFloat();
|
||||
*data = value;
|
||||
success = true;
|
||||
|
||||
char value_char[5] = {0};
|
||||
strValue.toCharArray(value_char, 5);
|
||||
sprintf_P(log, PSTR("Blynk get - %s => %s"),command.c_str(), value_char );
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
yield();
|
||||
}
|
||||
strcpy_P(log, PSTR("HTTP : closing connection"));
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
client.flush();
|
||||
client.stop();
|
||||
|
||||
// important - backgroudtasks - free mem
|
||||
timer = millis() + Settings.MessageDelay;
|
||||
while (!timeOutReached(timer))
|
||||
backgroundtasks();
|
||||
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
@@ -45,7 +45,7 @@ boolean NPlugin_002(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
NotificationSettingsStruct NotificationSettings;
|
||||
LoadNotificationSettings(event->NotificationIndex, (byte*)&NotificationSettings, sizeof(NotificationSettings));
|
||||
//this reserves IRAM and uninitalized RAM
|
||||
//this reserves IRAM and uninitialized RAM
|
||||
tone(NotificationSettings.Pin1, 500, 500);
|
||||
success = true;
|
||||
}
|
||||
|
||||
+73
-22
@@ -6,8 +6,10 @@
|
||||
#define PLUGIN_ID_001 1
|
||||
#define PLUGIN_NAME_001 "Switch input - Switch"
|
||||
#define PLUGIN_VALUENAME1_001 "Switch"
|
||||
Servo servo1;
|
||||
Servo servo2;
|
||||
#if defined(ESP8266)
|
||||
Servo servo1;
|
||||
Servo servo2;
|
||||
#endif
|
||||
|
||||
// Make sure the initial default is a switch (value 0)
|
||||
#define PLUGIN_001_TYPE_SWITCH 0
|
||||
@@ -197,11 +199,16 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
if (command == F("gpio"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
if (event->Par1 >= 0 && event->Par1 <= PIN_D_MAX)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
digitalWrite(event->Par1, event->Par2);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
if (event->Par2 == 2) {
|
||||
pinMode(event->Par1, INPUT);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_INPUT, 0);
|
||||
} else {
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
digitalWrite(event->Par1, event->Par2);
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
}
|
||||
log = String(F("SW : GPIO ")) + String(event->Par1) + String(F(" Set to ")) + String(event->Par2);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_001, event->Par1, log, 0));
|
||||
@@ -211,10 +218,11 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
if (command == F("pwm"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
if (event->Par1 >= 0 && event->Par1 <= PIN_D_MAX)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
|
||||
#if defined(ESP8266)
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
#endif
|
||||
if(event->Par3 != 0)
|
||||
{
|
||||
byte prev_mode;
|
||||
@@ -231,12 +239,22 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
curr_value += step_value;
|
||||
int16_t new_value;
|
||||
new_value = (uint16_t)(curr_value >> 12);
|
||||
analogWrite(event->Par1, new_value);
|
||||
#if defined(ESP8266)
|
||||
analogWrite(event->Par1, new_value);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
analogWriteESP32(event->Par1, new_value);
|
||||
#endif
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
analogWrite(event->Par1, event->Par2);
|
||||
#if defined(ESP8266)
|
||||
analogWrite(event->Par1, event->Par2);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
analogWriteESP32(event->Par1, event->Par2);
|
||||
#endif
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_PWM, event->Par2);
|
||||
log = String(F("SW : GPIO ")) + String(event->Par1) + String(F(" Set PWM to ")) + String(event->Par2);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
@@ -247,7 +265,7 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
if (command == F("pulse"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
if (event->Par1 >= 0 && event->Par1 <= PIN_D_MAX)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
digitalWrite(event->Par1, event->Par2);
|
||||
@@ -264,7 +282,7 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean time_in_msec = command == F("longpulse_ms");
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
if (event->Par1 >= 0 && event->Par1 <= PIN_D_MAX)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
digitalWrite(event->Par1, event->Par2);
|
||||
@@ -287,12 +305,16 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
case 1:
|
||||
|
||||
//IRAM: doing servo stuff uses 740 bytes IRAM. (doesnt matter how many instances)
|
||||
servo1.attach(event->Par2);
|
||||
servo1.write(event->Par3);
|
||||
#if defined(ESP8266)
|
||||
servo1.attach(event->Par2);
|
||||
servo1.write(event->Par3);
|
||||
#endif
|
||||
break;
|
||||
case 2:
|
||||
servo2.attach(event->Par2);
|
||||
servo2.write(event->Par3);
|
||||
#if defined(ESP8266)
|
||||
servo2.attach(event->Par2);
|
||||
servo2.write(event->Par3);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
setPinState(PLUGIN_ID_001, event->Par2, PIN_MODE_SERVO, event->Par3);
|
||||
@@ -317,6 +339,7 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
outputstate[event->Par1] = event->Par2;
|
||||
}
|
||||
|
||||
// FIXME: Absolutely no error checking in play_rtttl, until then keep it only in testing
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
//play a tune via a RTTTL string, look at https://www.letscontrolit.com/forum/viewtopic.php?f=4&t=343&hilit=speaker&start=10 for more info.
|
||||
if (command == F("rtttl"))
|
||||
@@ -325,10 +348,11 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
char sng[1024] ="";
|
||||
string.replace("-","#");
|
||||
string.toCharArray(sng, 1024);
|
||||
play_rtttl(event->Par1, sng);
|
||||
// char sng[1024] ="";
|
||||
String tmpString=string;
|
||||
tmpString.replace("-","#");
|
||||
// tmpString.toCharArray(sng, 1024);
|
||||
play_rtttl(event->Par1, tmpString.c_str());
|
||||
setPinState(PLUGIN_ID_001, event->Par1, PIN_MODE_OUTPUT, event->Par2);
|
||||
log = String(F("SW : ")) + string;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
@@ -340,7 +364,7 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
if (command == F("tone"))
|
||||
{
|
||||
success = true;
|
||||
if (event->Par1 >= 0 && event->Par1 <= 16)
|
||||
if (event->Par1 >= 0 && event->Par1 <= PIN_D_MAX)
|
||||
{
|
||||
pinMode(event->Par1, OUTPUT);
|
||||
tone(event->Par1, event->Par2, event->Par3);
|
||||
@@ -365,6 +389,33 @@ boolean Plugin_001(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
#if defined(ESP32)
|
||||
void analogWriteESP32(int pin, int value)
|
||||
{
|
||||
// find existing channel if this pin has been used before
|
||||
int8_t ledChannel = -1;
|
||||
for(byte x = 0; x < 16; x++)
|
||||
if (ledChannelPin[x] == pin)
|
||||
ledChannel = x;
|
||||
|
||||
if(ledChannel == -1) // no channel set for this pin
|
||||
{
|
||||
for(byte x = 0; x < 16; x++) // find free channel
|
||||
if (ledChannelPin[x] == -1)
|
||||
{
|
||||
int freq = 5000;
|
||||
ledChannelPin[x] = pin; // store pin nr
|
||||
ledcSetup(x, freq, 10); // setup channel
|
||||
ledcAttachPin(pin, x); // attach to this pin
|
||||
ledChannel = x;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ledcWrite(ledChannel, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
// TD-er: Needed to fix a mistake in earlier fixes.
|
||||
byte P001_getSwitchType(struct EventStruct *event) {
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
|
||||
+17
-2
@@ -47,6 +47,11 @@ boolean Plugin_002(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
#if defined(ESP32)
|
||||
string += F("<TR><TD>Analog Pin:<TD>");
|
||||
addPinSelect(false, string, "taskdevicepin1", Settings.TaskDevicePin1[event->TaskIndex]);
|
||||
#endif
|
||||
|
||||
addFormCheckBox(string, F("Oversampling"), F("plugin_002_oversampling"), Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
|
||||
addFormSubHeader(string, F("Two Point Calibration"));
|
||||
@@ -85,7 +90,12 @@ boolean Plugin_002(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0]) //Oversampling?
|
||||
{
|
||||
Plugin_002_OversamplingValue += analogRead(A0);
|
||||
#if defined(ESP8266)
|
||||
Plugin_002_OversamplingValue += analogRead(A0);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
Plugin_002_OversamplingValue += analogRead(Settings.TaskDevicePin1[event->TaskIndex]);
|
||||
#endif
|
||||
Plugin_002_OversamplingCount ++;
|
||||
}
|
||||
success = true;
|
||||
@@ -106,7 +116,12 @@ boolean Plugin_002(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
else
|
||||
{
|
||||
int16_t value = analogRead(A0);
|
||||
#if defined(ESP8266)
|
||||
int16_t value = analogRead(A0);
|
||||
#endif
|
||||
#if defined(ESP32)
|
||||
int16_t value = analogRead(Settings.TaskDevicePin1[event->TaskIndex]);
|
||||
#endif
|
||||
UserVar[event->BaseVarIndex] = (float)value;
|
||||
|
||||
log += value;
|
||||
|
||||
+78
-60
@@ -2,6 +2,8 @@
|
||||
// #################################### Plugin 004: TempSensor Dallas DS18B20 ###########################
|
||||
// #######################################################################################################
|
||||
|
||||
// Maxim Integrated (ex Dallas) DS18B20 datasheet : https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf
|
||||
|
||||
#define PLUGIN_004
|
||||
#define PLUGIN_ID_004 4
|
||||
#define PLUGIN_NAME_004 "Environment - DS18b20"
|
||||
@@ -52,9 +54,8 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
|
||||
// get currently saved address
|
||||
for (byte i = 0; i < 8; i++) {
|
||||
for (byte i = 0; i < 8; i++)
|
||||
savedAddress[i] = ExtraTaskSettings.TaskDevicePluginConfigLong[i];
|
||||
}
|
||||
|
||||
// find all suitable devices
|
||||
addRowLabel(string, F("Device Address"));
|
||||
@@ -104,6 +105,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
ExtraTaskSettings.TaskDevicePluginConfigLong[x] = addr[x];
|
||||
|
||||
Plugin_004_DS_setResolution(addr, getFormItemInt(F("plugin_004_res")));
|
||||
Plugin_004_DS_startConvertion(addr);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@@ -115,24 +117,32 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
{
|
||||
if (x != 0)
|
||||
string += "-";
|
||||
string += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
// string += String(ExtraTaskSettings.TaskDevicePluginConfigLong[x], HEX);
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
uint8_t addr[8];
|
||||
Plugin_004_get_addr(addr, event->TaskIndex);
|
||||
Plugin_004_DS_startConvertion(addr);
|
||||
delay(800); //give it time to do intial conversion
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
if (ExtraTaskSettings.TaskDevicePluginConfigLong[0] != 0){
|
||||
uint8_t addr[8];
|
||||
// Load ROM address from tasksettings
|
||||
LoadTaskSettings(event->TaskIndex);
|
||||
for (byte x = 0; x < 8; x++)
|
||||
addr[x] = ExtraTaskSettings.TaskDevicePluginConfigLong[x];
|
||||
Plugin_004_get_addr(addr, event->TaskIndex);
|
||||
|
||||
Plugin_004_DallasPin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
float value = 0;
|
||||
String log = F("DS : Temperature: ");
|
||||
|
||||
if (Plugin_004_DS_readTemp(addr, &value))
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
@@ -144,6 +154,7 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
log += F("Error!");
|
||||
}
|
||||
Plugin_004_DS_startConvertion(addr);
|
||||
|
||||
log += (" (");
|
||||
for (byte x = 0; x < 8; x++)
|
||||
@@ -162,28 +173,53 @@ boolean Plugin_004(byte function, struct EventStruct * event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
void Plugin_004_get_addr(uint8_t addr[], byte TaskIndex)
|
||||
{
|
||||
// Load ROM address from tasksettings
|
||||
LoadTaskSettings(TaskIndex);
|
||||
for (byte x = 0; x < 8; x++)
|
||||
addr[x] = ExtraTaskSettings.TaskDevicePluginConfigLong[x];
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
Dallas Scan bus
|
||||
\*********************************************************************************************/
|
||||
byte Plugin_004_DS_scan(byte getDeviceROM, uint8_t* ROM)
|
||||
{
|
||||
byte tmpaddr[8];
|
||||
byte devCount = 0;
|
||||
Plugin_004_DS_reset();
|
||||
byte tmpaddr[8];
|
||||
byte devCount = 0;
|
||||
Plugin_004_DS_reset();
|
||||
|
||||
Plugin_004_DS_reset_search();
|
||||
while (Plugin_004_DS_search(tmpaddr))
|
||||
{
|
||||
if (getDeviceROM == devCount)
|
||||
for (byte i = 0; i < 8; i++)
|
||||
ROM[i] = tmpaddr[i];
|
||||
devCount++;
|
||||
}
|
||||
return devCount;
|
||||
Plugin_004_DS_reset_search();
|
||||
while (Plugin_004_DS_search(tmpaddr))
|
||||
{
|
||||
if (getDeviceROM == devCount)
|
||||
for (byte i = 0; i < 8; i++)
|
||||
ROM[i] = tmpaddr[i];
|
||||
devCount++;
|
||||
}
|
||||
return devCount;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Dallas Read temperature
|
||||
* Dallas Start Temperature Conversion, expected duration:
|
||||
* 9 bits resolution -> 93.75 ms
|
||||
* 10 bits resolution -> 187.5 ms
|
||||
* 11 bits resolution -> 375 ms
|
||||
* 12 bits resolution -> 750 ms
|
||||
\*********************************************************************************************/
|
||||
void Plugin_004_DS_startConvertion(uint8_t ROM[8])
|
||||
{
|
||||
Plugin_004_DS_reset();
|
||||
Plugin_004_DS_write(0x55); // Choose ROM
|
||||
for (byte i = 0; i < 8; i++)
|
||||
Plugin_004_DS_write(ROM[i]);
|
||||
Plugin_004_DS_write(0x44); // Take temperature mesurement
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Dallas Read temperature from scratchpad
|
||||
\*********************************************************************************************/
|
||||
boolean Plugin_004_DS_readTemp(uint8_t ROM[8], float * value)
|
||||
{
|
||||
@@ -194,20 +230,13 @@ boolean Plugin_004_DS_readTemp(uint8_t ROM[8], float * value)
|
||||
Plugin_004_DS_write(0x55); // Choose ROM
|
||||
for (byte i = 0; i < 8; i++)
|
||||
Plugin_004_DS_write(ROM[i]);
|
||||
Plugin_004_DS_write(0x44);
|
||||
|
||||
delay(800);
|
||||
|
||||
Plugin_004_DS_reset();
|
||||
Plugin_004_DS_write(0x55); // Choose ROM
|
||||
for (byte i = 0; i < 8; i++)
|
||||
Plugin_004_DS_write(ROM[i]);
|
||||
Plugin_004_DS_write(0xBE); // Read scratchpad
|
||||
|
||||
for (byte i = 0; i < 9; i++) // copy 8 bytes
|
||||
for (byte i = 0; i < 9; i++) // read 9 bytes
|
||||
ScratchPad[i] = Plugin_004_DS_read();
|
||||
|
||||
if (Plugin_004_DS_crc8(ScratchPad, 8) != ScratchPad[8])
|
||||
if (!Plugin_004_DS_crc8(ScratchPad))
|
||||
{
|
||||
*value = 0;
|
||||
return false;
|
||||
@@ -222,15 +251,11 @@ boolean Plugin_004_DS_readTemp(uint8_t ROM[8], float * value)
|
||||
{
|
||||
DSTemp = (ScratchPad[1] << 11) | ScratchPad[0] << 3;
|
||||
DSTemp = ((DSTemp & 0xfff0) << 3) - 16 +
|
||||
(
|
||||
((ScratchPad[7] - ScratchPad[6]) << 7) /
|
||||
ScratchPad[7]
|
||||
);
|
||||
(((ScratchPad[7] - ScratchPad[6]) << 7) / ScratchPad[7]);
|
||||
*value = float(DSTemp) * 0.0078125;
|
||||
}
|
||||
|
||||
return true;
|
||||
} // Plugin_004_DS_readTemp
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* Dallas Get Resolution
|
||||
@@ -245,19 +270,15 @@ int Plugin_004_DS_getResolution(uint8_t ROM[8])
|
||||
Plugin_004_DS_reset();
|
||||
Plugin_004_DS_write(0x55); // Choose ROM
|
||||
for (byte i = 0; i < 8; i++)
|
||||
{
|
||||
Plugin_004_DS_write(ROM[i]);
|
||||
}
|
||||
|
||||
Plugin_004_DS_write(0xBE); // Read scratchpad
|
||||
|
||||
for (byte i = 0; i < 9; i++) // copy 8 bytes
|
||||
for (byte i = 0; i < 9; i++) // read 9 bytes
|
||||
ScratchPad[i] = Plugin_004_DS_read();
|
||||
|
||||
if (Plugin_004_DS_crc8(ScratchPad, 8) != ScratchPad[8])
|
||||
{
|
||||
if (!Plugin_004_DS_crc8(ScratchPad))
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (ScratchPad[4])
|
||||
@@ -272,6 +293,7 @@ int Plugin_004_DS_getResolution(uint8_t ROM[8])
|
||||
return 10;
|
||||
|
||||
case 0x1F: // 9 bit
|
||||
default:
|
||||
return 9;
|
||||
}
|
||||
}
|
||||
@@ -291,44 +313,38 @@ boolean Plugin_004_DS_setResolution(uint8_t ROM[8], byte res)
|
||||
Plugin_004_DS_reset();
|
||||
Plugin_004_DS_write(0x55); // Choose ROM
|
||||
for (byte i = 0; i < 8; i++)
|
||||
{
|
||||
Plugin_004_DS_write(ROM[i]);
|
||||
}
|
||||
|
||||
Plugin_004_DS_write(0xBE); // Read scratchpad
|
||||
|
||||
for (byte i = 0; i < 9; i++) // copy 8 bytes
|
||||
for (byte i = 0; i < 9; i++) // read 9 bytes
|
||||
ScratchPad[i] = Plugin_004_DS_read();
|
||||
|
||||
if (Plugin_004_DS_crc8(ScratchPad, 8) != ScratchPad[8])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (!Plugin_004_DS_crc8(ScratchPad))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
switch (res)
|
||||
{
|
||||
case 12:
|
||||
ScratchPad[4] = 0x7F; // 12 bit
|
||||
ScratchPad[4] = 0x7F; // 12 bits
|
||||
break;
|
||||
case 11:
|
||||
ScratchPad[4] = 0x5F; // 11 bit
|
||||
ScratchPad[4] = 0x5F; // 11 bits
|
||||
break;
|
||||
case 10:
|
||||
ScratchPad[4] = 0x3F; // 10 bit
|
||||
ScratchPad[4] = 0x3F; // 10 bits
|
||||
break;
|
||||
case 9:
|
||||
default:
|
||||
ScratchPad[4] = 0x1F; // 9 bit
|
||||
ScratchPad[4] = 0x1F; // 9 bits
|
||||
break;
|
||||
}
|
||||
|
||||
Plugin_004_DS_reset();
|
||||
Plugin_004_DS_write(0x55); // Choose ROM
|
||||
for (byte i = 0; i < 8; i++)
|
||||
{
|
||||
Plugin_004_DS_write(ROM[i]);
|
||||
}
|
||||
|
||||
Plugin_004_DS_write(0x4E); // Write to EEPROM
|
||||
Plugin_004_DS_write(ScratchPad[2]); // high alarm temp
|
||||
@@ -337,9 +353,7 @@ boolean Plugin_004_DS_setResolution(uint8_t ROM[8], byte res)
|
||||
|
||||
Plugin_004_DS_write(0x55); // Choose ROM
|
||||
for (byte i = 0; i < 8; i++)
|
||||
{
|
||||
Plugin_004_DS_write(ROM[i]);
|
||||
}
|
||||
|
||||
// save the newly written values to eeprom
|
||||
Plugin_004_DS_write(0x48);
|
||||
@@ -594,13 +608,17 @@ void Plugin_004_DS_write_bit(uint8_t v)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Plugin_004_DS_crc8(uint8_t * addr, uint8_t len)
|
||||
/*********************************************************************************************\
|
||||
* Dallas Calculate CRC8 and compare it of addr[0-7] and compares it to addr[8]
|
||||
\*********************************************************************************************/
|
||||
boolean Plugin_004_DS_crc8(uint8_t * addr)
|
||||
{
|
||||
uint8_t crc = 0;
|
||||
uint8_t crc = 0;
|
||||
uint8_t len = 8;
|
||||
|
||||
while (len--)
|
||||
{
|
||||
uint8_t inbyte = *addr++;
|
||||
uint8_t inbyte = *addr++; // from 0 to 7
|
||||
for (uint8_t i = 8; i; i--)
|
||||
{
|
||||
uint8_t mix = (crc ^ inbyte) & 0x01;
|
||||
@@ -609,5 +627,5 @@ uint8_t Plugin_004_DS_crc8(uint8_t * addr, uint8_t len)
|
||||
inbyte >>= 1;
|
||||
}
|
||||
}
|
||||
return crc;
|
||||
return crc == *addr; // addr 8
|
||||
}
|
||||
|
||||
+99
-83
@@ -4,7 +4,7 @@
|
||||
|
||||
#define PLUGIN_005
|
||||
#define PLUGIN_ID_005 5
|
||||
#define PLUGIN_NAME_005 "Environment - DHT11/12/22"
|
||||
#define PLUGIN_NAME_005 "Environment - DHT11/12/22 SONOFF2301/7021"
|
||||
#define PLUGIN_VALUENAME1_005 "Temperature"
|
||||
#define PLUGIN_VALUENAME2_005 "Humidity"
|
||||
|
||||
@@ -47,10 +47,10 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
const String options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12") };
|
||||
int indices[] = { 11, 22, 12 };
|
||||
const String options[] = { F("DHT 11"), F("DHT 22"), F("DHT 12"), F("Sonoff am2301"), F("Sonoff si7021") };
|
||||
int indices[] = { 11, 22, 12, 23, 70 };
|
||||
|
||||
addFormSelector(string, F("DHT Type"), F("plugin_005_dhttype"), 3, options, indices, Settings.TaskDevicePluginConfig[event->TaskIndex][0] );
|
||||
addFormSelector(string, F("DHT Type"), F("plugin_005_dhttype"), 5, options, indices, Settings.TaskDevicePluginConfig[event->TaskIndex][0] );
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@@ -67,96 +67,91 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
byte dht_dat[5];
|
||||
byte dht_in;
|
||||
byte i;
|
||||
// byte Retry = 0;
|
||||
boolean error = false;
|
||||
|
||||
byte Par3 = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
Plugin_005_DHT_Pin = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
|
||||
pinMode(Plugin_005_DHT_Pin, OUTPUT);
|
||||
// DHT start condition, pull-down i/o pin for 18ms
|
||||
digitalWrite(Plugin_005_DHT_Pin, LOW); // Pull low
|
||||
delay(18);
|
||||
digitalWrite(Plugin_005_DHT_Pin, HIGH); // Pull high
|
||||
delayMicroseconds(20); // was 40
|
||||
if(Par3 == 11 || Par3 == 22 || Par3 == 12) delay(18);
|
||||
else if (Par3 == 23 ) delayMicroseconds(900);
|
||||
else if (Par3 == 70 ) delayMicroseconds(500);
|
||||
pinMode(Plugin_005_DHT_Pin, INPUT); // change pin to input
|
||||
delayMicroseconds(10);
|
||||
delayMicroseconds(50);
|
||||
|
||||
dht_in = digitalRead(Plugin_005_DHT_Pin);
|
||||
if (!dht_in)
|
||||
error = waitState(0);
|
||||
if(error)
|
||||
{ logError(event, F("DHT : no Reading !"));
|
||||
break;
|
||||
}
|
||||
error = waitState(1);
|
||||
if(error)
|
||||
{ logError(event, F("DHT : no Reading !"));
|
||||
break;
|
||||
}
|
||||
noInterrupts();
|
||||
error = waitState(0);
|
||||
if(error)
|
||||
{ logError(event, F("DHT : no Reading !"));
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
delayMicroseconds(80);
|
||||
dht_in = digitalRead(Plugin_005_DHT_Pin);
|
||||
if (dht_in)
|
||||
{
|
||||
delayMicroseconds(80); // now ready for data reception
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
byte data = Plugin_005_read_dht_dat();
|
||||
if (data != -1)
|
||||
dht_dat[i] = data;
|
||||
else
|
||||
{
|
||||
addLog(LOG_LEVEL_ERROR, F("DHT : protocol timeout!"));
|
||||
error = true;
|
||||
}
|
||||
byte data = Plugin_005_read_dht_dat();
|
||||
if(data == -1)
|
||||
{ logError(event, "DHT : protocol timeout!");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!error)
|
||||
{
|
||||
dht_dat[i] = data;
|
||||
}
|
||||
interrupts();
|
||||
|
||||
// Checksum calculation is a Rollover Checksum by design!
|
||||
byte dht_check_sum = dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]; // check check_sum
|
||||
|
||||
if (dht_dat[4] == dht_check_sum)
|
||||
{
|
||||
float temperature = NAN;
|
||||
float humidity = NAN;
|
||||
|
||||
if (Par3 == 11)
|
||||
{
|
||||
temperature = float(dht_dat[2]); // Temperature
|
||||
humidity = float(dht_dat[0]); // Humidity
|
||||
}
|
||||
else if (Par3 == 12)
|
||||
{
|
||||
temperature = float(dht_dat[2]*10 + (dht_dat[3] & 0x7f)) / 10.0; // Temperature
|
||||
if (dht_dat[3] & 0x80) { temperature = -temperature; } // Negative temperature
|
||||
humidity = float(dht_dat[0]*10+dht_dat[1]) / 10.0; // Humidity
|
||||
}
|
||||
|
||||
if (Par3 == 22)
|
||||
{
|
||||
if (dht_dat[2] & 0x80) // negative temperature
|
||||
temperature = -0.1 * word(dht_dat[2] & 0x7F, dht_dat[3]);
|
||||
else
|
||||
temperature = 0.1 * word(dht_dat[2], dht_dat[3]);
|
||||
humidity = word(dht_dat[0], dht_dat[1]) * 0.1; // Humidity
|
||||
}
|
||||
if (temperature != NAN || humidity != NAN) // According to negated original if, maybe use && instead?
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = temperature;
|
||||
UserVar[event->BaseVarIndex + 1] = humidity;
|
||||
String log = F("DHT : Temperature: ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
log = F("DHT : Humidity: ");
|
||||
log += UserVar[event->BaseVarIndex + 1];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
}
|
||||
} // checksum
|
||||
} // error
|
||||
} // dht
|
||||
} // !dht
|
||||
if(!success)
|
||||
byte dht_check_sum = (dht_dat[0] + dht_dat[1] + dht_dat[2] + dht_dat[3]) & 0xFF; // check check_sum
|
||||
if (dht_dat[4] != dht_check_sum)
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, F("DHT : No reading!"));
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
UserVar[event->BaseVarIndex + 1] = NAN;
|
||||
logError(event, "DHT : checksum error!");
|
||||
break;
|
||||
}
|
||||
|
||||
float temperature = NAN;
|
||||
float humidity = NAN;
|
||||
if (Par3 == 11)
|
||||
{
|
||||
temperature = float(dht_dat[2]); // Temperature
|
||||
humidity = float(dht_dat[0]); // Humidity
|
||||
}
|
||||
else if (Par3 == 12)
|
||||
{
|
||||
temperature = float(dht_dat[2]*10 + (dht_dat[3] & 0x7f)) / 10.0; // Temperature
|
||||
if (dht_dat[3] & 0x80) { temperature = -temperature; } // Negative temperature
|
||||
humidity = float(dht_dat[0]*10+dht_dat[1]) / 10.0; // Humidity
|
||||
}
|
||||
else if (Par3 == 22 || Par3 == 23 || Par3 == 70)
|
||||
{
|
||||
if (dht_dat[2] & 0x80) // negative temperature
|
||||
temperature = -0.1 * word(dht_dat[2] & 0x7F, dht_dat[3]);
|
||||
else
|
||||
temperature = 0.1 * word(dht_dat[2], dht_dat[3]);
|
||||
humidity = 0.1 * word(dht_dat[0], dht_dat[1]); // Humidity
|
||||
}
|
||||
|
||||
if (temperature == NAN || humidity == NAN)
|
||||
{ logError(event, "DHT : invalid NAN reading !");
|
||||
break;
|
||||
}
|
||||
|
||||
UserVar[event->BaseVarIndex] = temperature;
|
||||
UserVar[event->BaseVarIndex + 1] = humidity;
|
||||
String log = F("DHT : Temperature: ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
log = F("DHT : Humidity: ");
|
||||
log += UserVar[event->BaseVarIndex + 1];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -164,6 +159,31 @@ boolean Plugin_005(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************************************\
|
||||
* DHT sub to log an error
|
||||
\*********************************************************************************************/
|
||||
void logError(struct EventStruct *event, String text)
|
||||
{
|
||||
addLog(LOG_LEVEL_INFO, text);
|
||||
UserVar[event->BaseVarIndex] = NAN;
|
||||
UserVar[event->BaseVarIndex + 1] = NAN;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* DHT sub to wait until a pin is in a certiin state
|
||||
\*********************************************************************************************/
|
||||
boolean waitState(int state)
|
||||
{
|
||||
byte counter = 0;
|
||||
while (( digitalRead(Plugin_005_DHT_Pin) != state) && (counter < 100))
|
||||
{
|
||||
delayMicroseconds(1);
|
||||
counter++;
|
||||
}
|
||||
if( counter < 100) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*********************************************************************************************\
|
||||
* DHT sub to get an 8 bit value from the receiving bitstream
|
||||
\*********************************************************************************************/
|
||||
@@ -172,7 +192,6 @@ int Plugin_005_read_dht_dat(void)
|
||||
byte i = 0;
|
||||
byte result = 0;
|
||||
byte counter = 0;
|
||||
//noInterrupts();
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
while ((!digitalRead(Plugin_005_DHT_Pin)) && (counter < 100))
|
||||
@@ -182,10 +201,9 @@ int Plugin_005_read_dht_dat(void)
|
||||
}
|
||||
if (counter >= 100)
|
||||
{
|
||||
//interrupts();
|
||||
return -1;
|
||||
}
|
||||
delayMicroseconds(30);
|
||||
delayMicroseconds(35); // was 30
|
||||
if (digitalRead(Plugin_005_DHT_Pin))
|
||||
result |= (1 << (7 - i));
|
||||
counter = 0;
|
||||
@@ -196,10 +214,8 @@ int Plugin_005_read_dht_dat(void)
|
||||
}
|
||||
if (counter >= 100)
|
||||
{
|
||||
//interrupts();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
//interrupts();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ boolean Plugin_010(byte function, struct EventStruct *event, String& string)
|
||||
optionValuesMode[1] = RESOLUTION_NORMAL;
|
||||
optionValuesMode[2] = RESOLUTION_HIGH;
|
||||
optionValuesMode[3] = RESOLUTION_AUTO_HIGH;
|
||||
addFormSelector(string, F("Measurment mode"), F("plugin_010_mode"), 4, optionsMode, optionValuesMode, choiceMode);
|
||||
addFormSelector(string, F("Measurement mode"), F("plugin_010_mode"), 4, optionsMode, optionValuesMode, choiceMode);
|
||||
|
||||
addFormCheckBox(string, F("Send sensor to sleep"), F("plugin_010_sleep"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
|
||||
|
||||
|
||||
+37
-2
@@ -8,7 +8,7 @@
|
||||
#define PLUGIN_VALUENAME1_022 "PWM"
|
||||
|
||||
#define PLUGIN_022_PCA9685_MODE1 0x00 // location for Mode1 register address
|
||||
#define PCA9685_MODE2 0x01 // location for Mode2 reigster address
|
||||
#define PCA9685_MODE2 0x01 // location for Mode2 register address
|
||||
#define PCA9685_LED0 0x06 // location for start of LED0 registers
|
||||
#define PCA9685_ADDRESS 0x40 // I2C address
|
||||
|
||||
@@ -63,6 +63,16 @@ boolean Plugin_022(byte function, struct EventStruct *event, String& string)
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_022, event->Par1, log, 0));
|
||||
}
|
||||
if (command == F("pcafrq"))
|
||||
{
|
||||
if (!Plugin_022_init) Plugin_022_initialize();
|
||||
success = true;
|
||||
Plugin_022_Frequency(event->Par1);
|
||||
setPinState(PLUGIN_ID_022, 99, PIN_MODE_UNDEFINED, event->Par1);
|
||||
log = String(F("PCA : FREQ ")) + String(event->Par1);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
SendStatus(event->Source, getPinStateJSON(SEARCH_PIN_STATE, PLUGIN_ID_022, 99, log, 0));
|
||||
}
|
||||
|
||||
if (command == F("status"))
|
||||
{
|
||||
@@ -90,6 +100,15 @@ void Plugin_022_writeRegister(int regAddress, byte data) {
|
||||
Wire.endTransmission();
|
||||
}
|
||||
|
||||
uint8_t Plugin_022_readRegister(int regAddress) {
|
||||
uint8_t res = 0;
|
||||
Wire.requestFrom(PCA9685_ADDRESS,1,1);
|
||||
while (Wire.available()) {
|
||||
res = Wire.read();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
//********************************************************************************
|
||||
// PCA9685 write
|
||||
@@ -107,10 +126,26 @@ void Plugin_022_Write(byte Par1, int Par2)
|
||||
Wire.write(highByte(LED_OFF));
|
||||
Wire.endTransmission();
|
||||
}
|
||||
void Plugin_022_Frequency(uint16_t freq)
|
||||
{
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)0x0);
|
||||
freq *= 0.9;
|
||||
// prescale = 25000000 / 4096;
|
||||
uint16_t prescale = 6103;
|
||||
prescale /= freq;
|
||||
prescale -= 1;
|
||||
uint8_t oldmode = Plugin_022_readRegister(0);
|
||||
uint8_t newmode = (oldmode&0x7f) | 0x10;
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)newmode);
|
||||
Plugin_022_writeRegister(0xfe, (byte)prescale); //prescale register
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)oldmode);
|
||||
delayMicroseconds(5000);
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)oldmode | 0xa1);
|
||||
}
|
||||
|
||||
void Plugin_022_initialize()
|
||||
{
|
||||
// default mode is open drain ouput, drive leds connected to VCC
|
||||
// default mode is open drain output, drive leds connected to VCC
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)0x01); // reset the device
|
||||
delay(1);
|
||||
Plugin_022_writeRegister(PLUGIN_022_PCA9685_MODE1, (byte)B10100000); // set up for auto increment
|
||||
|
||||
+270
-124
@@ -15,11 +15,19 @@
|
||||
|
||||
byte Plugin_023_OLED_address = 0x3c;
|
||||
byte Plugin_023_OLED_type = 0;
|
||||
byte Plugin_023_OLED_font_width = 0;
|
||||
|
||||
enum
|
||||
{
|
||||
OLED_64x48 = 0x01,
|
||||
OLED_rotated = 0x02
|
||||
OLED_rotated = 0x02,
|
||||
OLED_128x32 = 0x04
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
Size_normal = 0x01,
|
||||
Size_optimized = 0x02
|
||||
};
|
||||
|
||||
boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
@@ -70,9 +78,14 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
addFormSelector(string, F("Rotation"), F("plugin_023_rotate"), 2, options2, optionValues2, choice2);
|
||||
|
||||
byte choice3 = Settings.TaskDevicePluginConfig[event->TaskIndex][3];
|
||||
String options3[2] = { F("128x64"), F("64x48") };
|
||||
int optionValues3[2] = { 1, 2 };
|
||||
addFormSelector(string, F("Display Size"), F("plugin_023_size"), 2, options3, optionValues3, choice3);
|
||||
String options3[3] = { F("128x64"), F("128x32"), F("64x48") };
|
||||
int optionValues3[3] = { 1, 3, 2 };
|
||||
addFormSelector(string, F("Display Size"), F("plugin_023_size"), 3, options3, optionValues3, choice3);
|
||||
|
||||
byte choice4 = Settings.TaskDevicePluginConfig[event->TaskIndex][4];
|
||||
String options4[2] = { F("Normal"), F("Optimized") };
|
||||
int optionValues4[2] = { 1, 2 };
|
||||
addFormSelector(string, F("Font Width"), F("plugin_023_font_width"), 2, options4, optionValues4, choice4);
|
||||
|
||||
char deviceTemplate[8][64];
|
||||
LoadCustomTaskSettings(event->TaskIndex, (byte*)&deviceTemplate, sizeof(deviceTemplate));
|
||||
@@ -95,6 +108,7 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_023_rotate"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_23_timer"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][3] = getFormItemInt(F("plugin_023_size"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][4] = getFormItemInt(F("plugin_023_font_width"));
|
||||
|
||||
char deviceTemplate[8][64];
|
||||
for (byte varNr = 0; varNr < 8; varNr++)
|
||||
@@ -115,6 +129,16 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
Plugin_023_OLED_type = 0;
|
||||
Plugin_023_OLED_address = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][3] == 3)
|
||||
{
|
||||
Plugin_023_OLED_type = OLED_128x32;
|
||||
}
|
||||
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][4] == 2)
|
||||
{
|
||||
Plugin_023_OLED_font_width = Size_optimized;
|
||||
}
|
||||
|
||||
Plugin_023_StartUp_OLED();
|
||||
Plugin_023_clear_display();
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 2)
|
||||
@@ -210,6 +234,105 @@ boolean Plugin_023(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
const char Plugin_023_myFont_Size[] PROGMEM = {
|
||||
0x05, // SPACE
|
||||
0x05, // !
|
||||
0x07, // "
|
||||
0x08, // #
|
||||
0x08, // $
|
||||
0x08, // %
|
||||
0x08, // &
|
||||
0x06, // '
|
||||
0x06, // (
|
||||
0x06, // )
|
||||
0x08, // *
|
||||
0x08, // +
|
||||
0x05, // ,
|
||||
0x08, // -
|
||||
0x05, // .
|
||||
0x08, // /
|
||||
0x08, // 0
|
||||
0x07, // 1
|
||||
0x08, // 2
|
||||
0x08, // 3
|
||||
0x08, // 4
|
||||
0x08, // 5
|
||||
0x08, // 6
|
||||
0x08, // 7
|
||||
0x08, // 8
|
||||
0x08, // 9
|
||||
0x06, // :
|
||||
0x06, // ;
|
||||
0x07, // <
|
||||
0x08, // =
|
||||
0x07, // >
|
||||
0x08, // ?
|
||||
0x08, // @
|
||||
0x08, // A
|
||||
0x08, // B
|
||||
0x08, // C
|
||||
0x08, // D
|
||||
0x08, // E
|
||||
0x08, // F
|
||||
0x08, // G
|
||||
0x08, // H
|
||||
0x06, // I
|
||||
0x08, // J
|
||||
0x08, // K
|
||||
0x08, // L
|
||||
0x08, // M
|
||||
0x08, // N
|
||||
0x08, // O
|
||||
0x08, // P
|
||||
0x08, // Q
|
||||
0x08, // R
|
||||
0x08, // S
|
||||
0x08, // T
|
||||
0x08, // U
|
||||
0x08, // V
|
||||
0x08, // W
|
||||
0x08, // X
|
||||
0x08, // Y
|
||||
0x08, // Z
|
||||
0x06, // [
|
||||
0x08, // BACKSLASH
|
||||
0x06, // ]
|
||||
0x08, // ^
|
||||
0x08, // _
|
||||
0x06, // `
|
||||
0x08, // a
|
||||
0x08, // b
|
||||
0x07, // c
|
||||
0x08, // d
|
||||
0x08, // e
|
||||
0x07, // f
|
||||
0x08, // g
|
||||
0x08, // h
|
||||
0x05, // i
|
||||
0x06, // j
|
||||
0x07, // k
|
||||
0x06, // l
|
||||
0x08, // m
|
||||
0x07, // n
|
||||
0x07, // o
|
||||
0x07, // p
|
||||
0x07, // q
|
||||
0x07, // r
|
||||
0x07, // s
|
||||
0x06, // t
|
||||
0x07, // u
|
||||
0x08, // v
|
||||
0x08, // w
|
||||
0x08, // x
|
||||
0x07, // y
|
||||
0x08, // z
|
||||
0x06, // {
|
||||
0x05, // |
|
||||
0x06, // }
|
||||
0x08, // ~
|
||||
0x08 // DEL
|
||||
};
|
||||
|
||||
// Perform some specific changes for OLED display
|
||||
String P023_parseTemplate(String &tmpString, byte lineSize) {
|
||||
String result = parseTemplate(tmpString, lineSize);
|
||||
@@ -222,102 +345,102 @@ String P023_parseTemplate(String &tmpString, byte lineSize) {
|
||||
|
||||
|
||||
const char Plugin_023_myFont[][8] PROGMEM = {
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, 0x00},
|
||||
{0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x00},
|
||||
{0x00, 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 0x00},
|
||||
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x2A, 0x1C, 0x2A, 0x08, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00},
|
||||
{0x00, 0xA0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00},
|
||||
{0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00},
|
||||
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x00, 0x00},
|
||||
{0x00, 0x22, 0x41, 0x49, 0x49, 0x36, 0x00, 0x00},
|
||||
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x00},
|
||||
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x00},
|
||||
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00, 0x00},
|
||||
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03, 0x00, 0x00},
|
||||
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00},
|
||||
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0xAC, 0x6C, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06, 0x00, 0x00},
|
||||
{0x00, 0x32, 0x49, 0x79, 0x41, 0x3E, 0x00, 0x00},
|
||||
{0x00, 0x7E, 0x09, 0x09, 0x09, 0x7E, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00},
|
||||
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 0x00},
|
||||
{0x00, 0x3E, 0x41, 0x41, 0x51, 0x72, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, 0x00},
|
||||
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 0x00},
|
||||
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 0x00},
|
||||
{0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00},
|
||||
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, 0x00, 0x00},
|
||||
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 0x00},
|
||||
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 0x00},
|
||||
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 0x00},
|
||||
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x00},
|
||||
{0x00, 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, 0x00},
|
||||
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x41, 0x7F, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00},
|
||||
{0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00},
|
||||
{0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, 0x00, 0x00},
|
||||
{0x00, 0x38, 0x44, 0x44, 0x28, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, 0x00, 0x00},
|
||||
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x80, 0x84, 0x7D, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, 0x00, 0x00},
|
||||
{0x00, 0x7C, 0x08, 0x04, 0x7C, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00},
|
||||
{0x00, 0xFC, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x18, 0x24, 0x24, 0xFC, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x7C, 0x08, 0x04, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x48, 0x54, 0x54, 0x24, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x04, 0x7F, 0x44, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x3C, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, 0x00},
|
||||
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, 0x00},
|
||||
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00},
|
||||
{0x00, 0x1C, 0xA0, 0xA0, 0x7C, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x00},
|
||||
{0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x41, 0x36, 0x08, 0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x00},
|
||||
{0x00, 0x02, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00}
|
||||
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // SPACE
|
||||
{0x00, 0x00, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00}, // !
|
||||
{0x00, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00}, // "
|
||||
{0x00, 0x14, 0x7F, 0x14, 0x7F, 0x14, 0x00, 0x00}, // #
|
||||
{0x00, 0x24, 0x2A, 0x7F, 0x2A, 0x12, 0x00, 0x00}, // $
|
||||
{0x00, 0x23, 0x13, 0x08, 0x64, 0x62, 0x00, 0x00}, // %
|
||||
{0x00, 0x36, 0x49, 0x55, 0x22, 0x50, 0x00, 0x00}, // &
|
||||
{0x00, 0x00, 0x05, 0x03, 0x00, 0x00, 0x00, 0x00}, // '
|
||||
{0x00, 0x1C, 0x22, 0x41, 0x00, 0x00, 0x00, 0x00}, // (
|
||||
{0x00, 0x41, 0x22, 0x1C, 0x00, 0x00, 0x00, 0x00}, // )
|
||||
{0x00, 0x08, 0x2A, 0x1C, 0x2A, 0x08, 0x00, 0x00}, // *
|
||||
{0x00, 0x08, 0x08, 0x3E, 0x08, 0x08, 0x00, 0x00}, // +
|
||||
{0x00, 0xA0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // ,
|
||||
{0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00}, // -
|
||||
{0x00, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00}, // .
|
||||
{0x00, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00, 0x00}, // /
|
||||
{0x00, 0x3E, 0x51, 0x49, 0x45, 0x3E, 0x00, 0x00}, // 0
|
||||
{0x00, 0x00, 0x42, 0x7F, 0x40, 0x00, 0x00, 0x00}, // 1
|
||||
{0x00, 0x62, 0x51, 0x49, 0x49, 0x46, 0x00, 0x00}, // 2
|
||||
{0x00, 0x22, 0x41, 0x49, 0x49, 0x36, 0x00, 0x00}, // 3
|
||||
{0x00, 0x18, 0x14, 0x12, 0x7F, 0x10, 0x00, 0x00}, // 4
|
||||
{0x00, 0x27, 0x45, 0x45, 0x45, 0x39, 0x00, 0x00}, // 5
|
||||
{0x00, 0x3C, 0x4A, 0x49, 0x49, 0x30, 0x00, 0x00}, // 6
|
||||
{0x00, 0x01, 0x71, 0x09, 0x05, 0x03, 0x00, 0x00}, // 7
|
||||
{0x00, 0x36, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00}, // 8
|
||||
{0x00, 0x06, 0x49, 0x49, 0x29, 0x1E, 0x00, 0x00}, // 9
|
||||
{0x00, 0x00, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00}, // :
|
||||
{0x00, 0x00, 0xAC, 0x6C, 0x00, 0x00, 0x00, 0x00}, // ;
|
||||
{0x00, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00, 0x00}, // <
|
||||
{0x00, 0x14, 0x14, 0x14, 0x14, 0x14, 0x00, 0x00}, // =
|
||||
{0x00, 0x41, 0x22, 0x14, 0x08, 0x00, 0x00, 0x00}, // >
|
||||
{0x00, 0x02, 0x01, 0x51, 0x09, 0x06, 0x00, 0x00}, // ?
|
||||
{0x00, 0x32, 0x49, 0x79, 0x41, 0x3E, 0x00, 0x00}, // @
|
||||
{0x00, 0x7E, 0x09, 0x09, 0x09, 0x7E, 0x00, 0x00}, // A
|
||||
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x36, 0x00, 0x00}, // B
|
||||
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x22, 0x00, 0x00}, // C
|
||||
{0x00, 0x7F, 0x41, 0x41, 0x22, 0x1C, 0x00, 0x00}, // D
|
||||
{0x00, 0x7F, 0x49, 0x49, 0x49, 0x41, 0x00, 0x00}, // E
|
||||
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x01, 0x00, 0x00}, // F
|
||||
{0x00, 0x3E, 0x41, 0x41, 0x51, 0x72, 0x00, 0x00}, // G
|
||||
{0x00, 0x7F, 0x08, 0x08, 0x08, 0x7F, 0x00, 0x00}, // H
|
||||
{0x00, 0x41, 0x7F, 0x41, 0x00, 0x00, 0x00, 0x00}, // I
|
||||
{0x00, 0x20, 0x40, 0x41, 0x3F, 0x01, 0x00, 0x00}, // J
|
||||
{0x00, 0x7F, 0x08, 0x14, 0x22, 0x41, 0x00, 0x00}, // K
|
||||
{0x00, 0x7F, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00}, // L
|
||||
{0x00, 0x7F, 0x02, 0x0C, 0x02, 0x7F, 0x00, 0x00}, // M
|
||||
{0x00, 0x7F, 0x04, 0x08, 0x10, 0x7F, 0x00, 0x00}, // N
|
||||
{0x00, 0x3E, 0x41, 0x41, 0x41, 0x3E, 0x00, 0x00}, // O
|
||||
{0x00, 0x7F, 0x09, 0x09, 0x09, 0x06, 0x00, 0x00}, // P
|
||||
{0x00, 0x3E, 0x41, 0x51, 0x21, 0x5E, 0x00, 0x00}, // Q
|
||||
{0x00, 0x7F, 0x09, 0x19, 0x29, 0x46, 0x00, 0x00}, // R
|
||||
{0x00, 0x26, 0x49, 0x49, 0x49, 0x32, 0x00, 0x00}, // S
|
||||
{0x00, 0x01, 0x01, 0x7F, 0x01, 0x01, 0x00, 0x00}, // T
|
||||
{0x00, 0x3F, 0x40, 0x40, 0x40, 0x3F, 0x00, 0x00}, // U
|
||||
{0x00, 0x1F, 0x20, 0x40, 0x20, 0x1F, 0x00, 0x00}, // V
|
||||
{0x00, 0x3F, 0x40, 0x38, 0x40, 0x3F, 0x00, 0x00}, // W
|
||||
{0x00, 0x63, 0x14, 0x08, 0x14, 0x63, 0x00, 0x00}, // X
|
||||
{0x00, 0x03, 0x04, 0x78, 0x04, 0x03, 0x00, 0x00}, // Y
|
||||
{0x00, 0x61, 0x51, 0x49, 0x45, 0x43, 0x00, 0x00}, // Z
|
||||
{0x00, 0x7F, 0x41, 0x41, 0x00, 0x00, 0x00, 0x00}, // [
|
||||
{0x00, 0x02, 0x04, 0x08, 0x10, 0x20, 0x00, 0x00}, // BACKSLASH
|
||||
{0x00, 0x41, 0x41, 0x7F, 0x00, 0x00, 0x00, 0x00}, // ]
|
||||
{0x00, 0x04, 0x02, 0x01, 0x02, 0x04, 0x00, 0x00}, // ^
|
||||
{0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00}, // _
|
||||
{0x00, 0x01, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00}, // `
|
||||
{0x00, 0x20, 0x54, 0x54, 0x54, 0x78, 0x00, 0x00}, // a
|
||||
{0x00, 0x7F, 0x48, 0x44, 0x44, 0x38, 0x00, 0x00}, // b
|
||||
{0x00, 0x38, 0x44, 0x44, 0x28, 0x00, 0x00, 0x00}, // c
|
||||
{0x00, 0x38, 0x44, 0x44, 0x48, 0x7F, 0x00, 0x00}, // d
|
||||
{0x00, 0x38, 0x54, 0x54, 0x54, 0x18, 0x00, 0x00}, // e
|
||||
{0x00, 0x08, 0x7E, 0x09, 0x02, 0x00, 0x00, 0x00}, // f
|
||||
{0x00, 0x18, 0xA4, 0xA4, 0xA4, 0x7C, 0x00, 0x00}, // g
|
||||
{0x00, 0x7F, 0x08, 0x04, 0x04, 0x78, 0x00, 0x00}, // h
|
||||
{0x00, 0x00, 0x7D, 0x00, 0x00, 0x00, 0x00, 0x00}, // i
|
||||
{0x00, 0x80, 0x84, 0x7D, 0x00, 0x00, 0x00, 0x00}, // j
|
||||
{0x00, 0x7F, 0x10, 0x28, 0x44, 0x00, 0x00, 0x00}, // k
|
||||
{0x00, 0x41, 0x7F, 0x40, 0x00, 0x00, 0x00, 0x00}, // l
|
||||
{0x00, 0x7C, 0x04, 0x18, 0x04, 0x78, 0x00, 0x00}, // m
|
||||
{0x00, 0x7C, 0x08, 0x04, 0x7C, 0x00, 0x00, 0x00}, // n
|
||||
{0x00, 0x38, 0x44, 0x44, 0x38, 0x00, 0x00, 0x00}, // o
|
||||
{0x00, 0xFC, 0x24, 0x24, 0x18, 0x00, 0x00, 0x00}, // p
|
||||
{0x00, 0x18, 0x24, 0x24, 0xFC, 0x00, 0x00, 0x00}, // q
|
||||
{0x00, 0x00, 0x7C, 0x08, 0x04, 0x00, 0x00, 0x00}, // r
|
||||
{0x00, 0x48, 0x54, 0x54, 0x24, 0x00, 0x00, 0x00}, // s
|
||||
{0x00, 0x04, 0x7F, 0x44, 0x00, 0x00, 0x00, 0x00}, // t
|
||||
{0x00, 0x3C, 0x40, 0x40, 0x7C, 0x00, 0x00, 0x00}, // u
|
||||
{0x00, 0x1C, 0x20, 0x40, 0x20, 0x1C, 0x00, 0x00}, // v
|
||||
{0x00, 0x3C, 0x40, 0x30, 0x40, 0x3C, 0x00, 0x00}, // w
|
||||
{0x00, 0x44, 0x28, 0x10, 0x28, 0x44, 0x00, 0x00}, // x
|
||||
{0x00, 0x1C, 0xA0, 0xA0, 0x7C, 0x00, 0x00, 0x00}, // y
|
||||
{0x00, 0x44, 0x64, 0x54, 0x4C, 0x44, 0x00, 0x00}, // z
|
||||
{0x00, 0x08, 0x36, 0x41, 0x00, 0x00, 0x00, 0x00}, // {
|
||||
{0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00}, // |
|
||||
{0x00, 0x41, 0x36, 0x08, 0x00, 0x00, 0x00, 0x00}, // }
|
||||
{0x00, 0x02, 0x01, 0x01, 0x02, 0x01, 0x00, 0x00}, // ~
|
||||
{0x00, 0x02, 0x05, 0x05, 0x02, 0x00, 0x00, 0x00} // DEL
|
||||
};
|
||||
|
||||
static void Plugin_023_reset_display(void)
|
||||
@@ -444,9 +567,20 @@ static void Plugin_023_sendStrXY(const char *string, int X, int Y)
|
||||
{
|
||||
Plugin_023_setXY(X, Y);
|
||||
unsigned char i = 0;
|
||||
unsigned char font_width = 0;
|
||||
|
||||
while (*string)
|
||||
{
|
||||
for (i = 0; i < 8; i++)
|
||||
switch (Plugin_023_OLED_font_width)
|
||||
{
|
||||
case Size_optimized:
|
||||
font_width = pgm_read_byte(&(Plugin_023_myFont_Size[*string - 0x20]));
|
||||
break;
|
||||
default:
|
||||
font_width = 8;
|
||||
}
|
||||
|
||||
for (i = 0; i < font_width; i++)
|
||||
{
|
||||
Plugin_023_SendChar(pgm_read_byte(Plugin_023_myFont[*string - 0x20] + i));
|
||||
}
|
||||
@@ -457,35 +591,47 @@ static void Plugin_023_sendStrXY(const char *string, int X, int Y)
|
||||
|
||||
static void Plugin_023_init_OLED(void)
|
||||
{
|
||||
Plugin_023_sendcommand(0xae); //display off
|
||||
Plugin_023_sendcommand(0xa6); //Set Normal Display (default)
|
||||
Plugin_023_sendcommand(0xAE); //DISPLAYOFF
|
||||
Plugin_023_sendcommand(0xD5); //SETDISPLAYCLOCKDIV
|
||||
Plugin_023_sendcommand(0x80); // the suggested ratio 0x80
|
||||
Plugin_023_sendcommand(0xA8); //SSD1306_SETMULTIPLEX
|
||||
Plugin_023_sendcommand(0x3F);
|
||||
Plugin_023_sendcommand(0xD3); //SETDISPLAYOFFSET
|
||||
Plugin_023_sendcommand(0x0); //no offset
|
||||
Plugin_023_sendcommand(0x40 | 0x0); //SETSTARTLINE
|
||||
Plugin_023_sendcommand(0x8D); //CHARGEPUMP
|
||||
unsigned char multiplex;
|
||||
unsigned char compins;
|
||||
switch (Plugin_023_OLED_type)
|
||||
{
|
||||
case OLED_128x32:
|
||||
multiplex = 0x1F;
|
||||
compins = 0x02;
|
||||
break;
|
||||
default:
|
||||
multiplex = 0x3F;
|
||||
compins = 0x12;
|
||||
}
|
||||
|
||||
Plugin_023_sendcommand(0xAE); //display off
|
||||
Plugin_023_sendcommand(0xD5); //SETDISPLAYCLOCKDIV
|
||||
Plugin_023_sendcommand(0x80); // the suggested ratio 0x80
|
||||
Plugin_023_sendcommand(0xA8); //SSD1306_SETMULTIPLEX
|
||||
Plugin_023_sendcommand(multiplex); //0x1F if 128x32, 0x3F if others (e.g. 128x64)
|
||||
Plugin_023_sendcommand(0xD3); //SETDISPLAYOFFSET
|
||||
Plugin_023_sendcommand(0x00); //no offset
|
||||
Plugin_023_sendcommand(0x40 | 0x0); //SETSTARTLINE
|
||||
Plugin_023_sendcommand(0x8D); //CHARGEPUMP
|
||||
Plugin_023_sendcommand(0x14);
|
||||
Plugin_023_sendcommand(0x20); //MEMORYMODE
|
||||
Plugin_023_sendcommand(0x00); //0x0 act like ks0108
|
||||
Plugin_023_sendcommand(0xA0);
|
||||
Plugin_023_sendcommand(0xC0);
|
||||
Plugin_023_sendcommand(0xDA); //0xDA
|
||||
Plugin_023_sendcommand(0x12); //COMSCANDEC
|
||||
Plugin_023_sendcommand(0x81); //SETCONTRAS
|
||||
Plugin_023_sendcommand(0x20); //MEMORYMODE
|
||||
Plugin_023_sendcommand(0x00); //0x0 act like ks0108
|
||||
Plugin_023_sendcommand(0xA0); //128x32 ???
|
||||
Plugin_023_sendcommand(0xC0); //128x32 ???
|
||||
Plugin_023_sendcommand(0xDA); //COMPINS
|
||||
Plugin_023_sendcommand(compins); //0x02 if 128x32, 0x12 if others (e.g. 128x64)
|
||||
Plugin_023_sendcommand(0x81); //SETCONTRAS
|
||||
Plugin_023_sendcommand(0xCF);
|
||||
Plugin_023_sendcommand(0xd9); //SETPRECHARGE
|
||||
Plugin_023_sendcommand(0xD9); //SETPRECHARGE
|
||||
Plugin_023_sendcommand(0xF1);
|
||||
Plugin_023_sendcommand(0xDB); //SETVCOMDETECT
|
||||
Plugin_023_sendcommand(0xDB); //SETVCOMDETECT
|
||||
Plugin_023_sendcommand(0x40);
|
||||
Plugin_023_sendcommand(0xA4); //DISPLAYALLON_RESUME
|
||||
Plugin_023_sendcommand(0xA6); //NORMALDISPLAY
|
||||
Plugin_023_sendcommand(0xA4); //DISPLAYALLON_RESUME
|
||||
Plugin_023_sendcommand(0xA6); //NORMALDISPLAY
|
||||
|
||||
Plugin_023_clear_display();
|
||||
Plugin_023_sendcommand(0x2e); // stop scroll
|
||||
Plugin_023_sendcommand(0x2E); // stop scroll
|
||||
Plugin_023_sendcommand(0x20); //Set Memory Addressing Mode
|
||||
Plugin_023_sendcommand(0x00); //Set Memory Addressing Mode ab Horizontal addressing mode
|
||||
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ boolean Plugin_026(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
String options[9];
|
||||
String options[10];
|
||||
options[0] = F("Uptime");
|
||||
options[1] = F("Free RAM");
|
||||
options[2] = F("Wifi RSSI");
|
||||
@@ -50,7 +50,8 @@ boolean Plugin_026(byte function, struct EventStruct *event, String& string)
|
||||
options[6] = F("IP 2.Octet");
|
||||
options[7] = F("IP 3.Octet");
|
||||
options[8] = F("IP 4.Octet");
|
||||
addFormSelector(string, F("Indicator"), F("plugin_026"), 9, options, NULL, choice);
|
||||
options[9] = F("Web activity");
|
||||
addFormSelector(string, F("Indicator"), F("plugin_026"), 10, options, NULL, choice);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@@ -117,6 +118,11 @@ boolean Plugin_026(byte function, struct EventStruct *event, String& string)
|
||||
value = WiFi.localIP()[3];
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
{
|
||||
value = (millis()-lastWeb)/1000; // respond in seconds
|
||||
break;
|
||||
}
|
||||
}
|
||||
UserVar[event->BaseVarIndex] = value;
|
||||
String log = F("SYS : ");
|
||||
|
||||
+341
-122
@@ -2,54 +2,57 @@
|
||||
//#################### Plugin 028 BME280 I2C Temp/Hum/Barometric Pressure Sensor #######################
|
||||
//#######################################################################################################
|
||||
|
||||
//#include <math.h>
|
||||
|
||||
#define PLUGIN_028
|
||||
#define PLUGIN_ID_028 28
|
||||
#define PLUGIN_NAME_028 "Environment - BME280"
|
||||
#define PLUGIN_NAME_028 "Environment - BMx280"
|
||||
#define PLUGIN_VALUENAME1_028 "Temperature"
|
||||
#define PLUGIN_VALUENAME2_028 "Humidity"
|
||||
#define PLUGIN_VALUENAME3_028 "Pressure"
|
||||
|
||||
enum
|
||||
{
|
||||
BME280_REGISTER_DIG_T1 = 0x88,
|
||||
BME280_REGISTER_DIG_T2 = 0x8A,
|
||||
BME280_REGISTER_DIG_T3 = 0x8C,
|
||||
#define PLUGIN_028_BME280_DEVICE "BME280"
|
||||
#define PLUGIN_028_BMP280_DEVICE "BMP280"
|
||||
|
||||
BME280_REGISTER_DIG_P1 = 0x8E,
|
||||
BME280_REGISTER_DIG_P2 = 0x90,
|
||||
BME280_REGISTER_DIG_P3 = 0x92,
|
||||
BME280_REGISTER_DIG_P4 = 0x94,
|
||||
BME280_REGISTER_DIG_P5 = 0x96,
|
||||
BME280_REGISTER_DIG_P6 = 0x98,
|
||||
BME280_REGISTER_DIG_P7 = 0x9A,
|
||||
BME280_REGISTER_DIG_P8 = 0x9C,
|
||||
BME280_REGISTER_DIG_P9 = 0x9E,
|
||||
// Minimal interval in msec.
|
||||
#define BMx280_MEASUREMENT_INTERVAL_MSEC 50000
|
||||
|
||||
BME280_REGISTER_DIG_H1 = 0xA1,
|
||||
BME280_REGISTER_DIG_H2 = 0xE1,
|
||||
BME280_REGISTER_DIG_H3 = 0xE3,
|
||||
BME280_REGISTER_DIG_H4 = 0xE4,
|
||||
BME280_REGISTER_DIG_H5 = 0xE5,
|
||||
BME280_REGISTER_DIG_H6 = 0xE7,
|
||||
#define BMx280_REGISTER_DIG_T1 0x88
|
||||
#define BMx280_REGISTER_DIG_T2 0x8A
|
||||
#define BMx280_REGISTER_DIG_T3 0x8C
|
||||
|
||||
BME280_REGISTER_CHIPID = 0xD0,
|
||||
BME280_REGISTER_VERSION = 0xD1,
|
||||
BME280_REGISTER_SOFTRESET = 0xE0,
|
||||
#define BMx280_REGISTER_DIG_P1 0x8E
|
||||
#define BMx280_REGISTER_DIG_P2 0x90
|
||||
#define BMx280_REGISTER_DIG_P3 0x92
|
||||
#define BMx280_REGISTER_DIG_P4 0x94
|
||||
#define BMx280_REGISTER_DIG_P5 0x96
|
||||
#define BMx280_REGISTER_DIG_P6 0x98
|
||||
#define BMx280_REGISTER_DIG_P7 0x9A
|
||||
#define BMx280_REGISTER_DIG_P8 0x9C
|
||||
#define BMx280_REGISTER_DIG_P9 0x9E
|
||||
|
||||
BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0
|
||||
#define BMx280_REGISTER_DIG_H1 0xA1
|
||||
#define BMx280_REGISTER_DIG_H2 0xE1
|
||||
#define BMx280_REGISTER_DIG_H3 0xE3
|
||||
#define BMx280_REGISTER_DIG_H4 0xE4
|
||||
#define BMx280_REGISTER_DIG_H5 0xE5
|
||||
#define BMx280_REGISTER_DIG_H6 0xE7
|
||||
|
||||
BME280_REGISTER_CONTROLHUMID = 0xF2,
|
||||
BME280_REGISTER_STATUS = 0xF3,
|
||||
BME280_REGISTER_CONTROL = 0xF4,
|
||||
BME280_REGISTER_CONFIG = 0xF5,
|
||||
BME280_REGISTER_PRESSUREDATA = 0xF7,
|
||||
BME280_REGISTER_TEMPDATA = 0xFA,
|
||||
BME280_REGISTER_HUMIDDATA = 0xFD,
|
||||
#define BMx280_REGISTER_CHIPID 0xD0
|
||||
#define BMx280_REGISTER_VERSION 0xD1
|
||||
#define BMx280_REGISTER_SOFTRESET 0xE0
|
||||
|
||||
BME280_CONTROL_SETTING = 0x25, // Oversampling: 1x P, 1x T, forced
|
||||
BME280_CONTROL_SETTING_HUMIDITY = 0x01, // Oversampling: 1x H
|
||||
BME280_CONFIG_SETTING = 0xA0, // Tstandby 1000ms, filter off, 3-wire SPI Disable
|
||||
};
|
||||
#define BMx280_REGISTER_CAL26 0xE1 // R calibration stored in 0xE1-0xF0
|
||||
|
||||
#define BMx280_REGISTER_CONTROLHUMID 0xF2
|
||||
#define BMx280_REGISTER_STATUS 0xF3
|
||||
#define BMx280_REGISTER_CONTROL 0xF4
|
||||
#define BMx280_REGISTER_CONFIG 0xF5
|
||||
#define BMx280_REGISTER_PRESSUREDATA 0xF7
|
||||
#define BMx280_REGISTER_TEMPDATA 0xFA
|
||||
#define BMx280_REGISTER_HUMIDDATA 0xFD
|
||||
|
||||
#define BME280_CONTROL_SETTING_HUMIDITY 0x02 // Oversampling: 2x H
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@@ -76,14 +79,99 @@ typedef struct
|
||||
} bme280_calib_data;
|
||||
|
||||
bme280_calib_data _bme280_calib[2];
|
||||
boolean Plugin_028_init[2] = {false, false};
|
||||
int Plugin_28_i2c_addresses[2] = { 0x76, 0x77 };
|
||||
|
||||
uint8_t _i2caddr;
|
||||
int32_t _sensorID;
|
||||
int32_t t_fine;
|
||||
|
||||
static float last_hum_val[2] = {0.0, 0.0};
|
||||
static float last_press_val[2] = {0.0, 0.0};
|
||||
static float last_temp_val[2] = {0.0, 0.0};
|
||||
static float last_dew_temp_val[2] = {0.0, 0.0};
|
||||
static unsigned long last_measurement[2] = {0, 0};
|
||||
|
||||
enum BMx_ChipId {
|
||||
Unknown_DEVICE = 0,
|
||||
BMP280_DEVICE_SAMPLE1 = 0x56,
|
||||
BMP280_DEVICE_SAMPLE2 = 0x57,
|
||||
BMP280_DEVICE = 0x58,
|
||||
BME280_DEVICE = 0x60
|
||||
};
|
||||
|
||||
BMx_ChipId _sensorID[2] = {Unknown_DEVICE, Unknown_DEVICE};
|
||||
|
||||
byte Plugin_028_get_config_settings() {
|
||||
const uint8_t idx = Plugin_028_device_index(_i2caddr);
|
||||
switch (_sensorID[idx]) {
|
||||
case BMP280_DEVICE_SAMPLE1:
|
||||
case BMP280_DEVICE_SAMPLE2:
|
||||
case BMP280_DEVICE: return 0x28; // Tstandby 62.5ms, filter 4, 3-wire SPI Disable
|
||||
case BME280_DEVICE: return 0x28; // Tstandby 62.5ms, filter 4, 3-wire SPI Disable
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
byte Plugin_028_get_control_settings() {
|
||||
const uint8_t idx = Plugin_028_device_index(_i2caddr);
|
||||
switch (_sensorID[idx]) {
|
||||
case BMP280_DEVICE_SAMPLE1:
|
||||
case BMP280_DEVICE_SAMPLE2:
|
||||
case BMP280_DEVICE: return 0x93; // Oversampling: 8x P, 8x T, normal mode
|
||||
case BME280_DEVICE: return 0x93; // Oversampling: 8x P, 8x T, normal mode
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
String Plugin_028_getFullDeviceName() {
|
||||
const uint8_t idx = Plugin_028_device_index(_i2caddr);
|
||||
String devicename = Plugin_028_getDeviceName();
|
||||
if (_sensorID[idx] == BMP280_DEVICE_SAMPLE1 ||
|
||||
_sensorID[idx] == BMP280_DEVICE_SAMPLE2)
|
||||
{
|
||||
devicename += F(" sample");
|
||||
}
|
||||
return devicename;
|
||||
}
|
||||
|
||||
String Plugin_028_getDeviceName() {
|
||||
const uint8_t idx = Plugin_028_device_index(_i2caddr);
|
||||
switch (_sensorID[idx]) {
|
||||
case BMP280_DEVICE_SAMPLE1:
|
||||
case BMP280_DEVICE_SAMPLE2:
|
||||
case BMP280_DEVICE: return PLUGIN_028_BMP280_DEVICE;
|
||||
case BME280_DEVICE: return PLUGIN_028_BME280_DEVICE;
|
||||
default: return F("Unknown");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
boolean Plugin_028_hasHumidity() {
|
||||
const uint8_t idx = Plugin_028_device_index(_i2caddr);
|
||||
switch (_sensorID[idx]) {
|
||||
case BMP280_DEVICE_SAMPLE1:
|
||||
case BMP280_DEVICE_SAMPLE2:
|
||||
case BMP280_DEVICE: return false;
|
||||
case BME280_DEVICE: return true;
|
||||
default: return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t Plugin_028_read8(byte reg, bool * is_ok = NULL); // Declaration
|
||||
|
||||
boolean Plugin_028_init[2] = {false, false};
|
||||
uint8_t Plugin_028_i2c_addr(struct EventStruct *event) {
|
||||
_i2caddr = (uint8_t)Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
if (_i2caddr != Plugin_28_i2c_addresses[0] && _i2caddr != Plugin_28_i2c_addresses[1]) {
|
||||
// Set to default address
|
||||
_i2caddr = Plugin_28_i2c_addresses[0];
|
||||
}
|
||||
return _i2caddr;
|
||||
}
|
||||
|
||||
uint8_t Plugin_028_device_index(const uint8_t i2cAddress) {
|
||||
return i2cAddress & 0x1; //Addresses are 0x76 and 0x77 so we may use it this way
|
||||
}
|
||||
|
||||
boolean Plugin_028(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
@@ -123,68 +211,80 @@ boolean Plugin_028(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
byte choice = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
/*
|
||||
String options[2];
|
||||
options[0] = F("0x76 - default settings (SDO Low)");
|
||||
options[1] = F("0x77 - alternate settings (SDO HIGH)");
|
||||
*/
|
||||
int optionValues[2] = { 0x76, 0x77 };
|
||||
addFormSelectorI2C(string, F("plugin_028_bme280_i2c"), 2, optionValues, choice);
|
||||
const uint8_t i2cAddress = Plugin_028_i2c_addr(event);
|
||||
addFormSelectorI2C(string, F("plugin_028_bme280_i2c"), 2, Plugin_28_i2c_addresses, i2cAddress);
|
||||
const uint8_t idx = Plugin_028_device_index(i2cAddress);
|
||||
if (_sensorID[idx] != Unknown_DEVICE) {
|
||||
String detectedString = F("Detected: ");
|
||||
detectedString += Plugin_028_getFullDeviceName();
|
||||
addUnit(string, detectedString);
|
||||
}
|
||||
addFormNote(string, F("SDO Low=0x76, High=0x77"));
|
||||
|
||||
addFormNumericBox(string, F("Altitude"), F("plugin_028_bme280_elev"), Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
|
||||
addUnit(string, F("m"));
|
||||
|
||||
addFormNumericBox(string, F("Temperature offset"), F("plugin_028_bme280_tempoffset"), Settings.TaskDevicePluginConfig[event->TaskIndex][2]);
|
||||
addUnit(string, F("x 0.1C"));
|
||||
String offsetNote = F("Offset in units of 0.1 degree Celcius");
|
||||
if (Plugin_028_hasHumidity()) {
|
||||
offsetNote += F(" (also correct humidity)");
|
||||
}
|
||||
addFormNote(string, offsetNote);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_028_bme280_i2c"));
|
||||
const uint8_t i2cAddress = getFormItemInt(F("plugin_028_bme280_i2c"));
|
||||
Plugin_028_check(i2cAddress); // Check id device is present
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = i2cAddress;
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_028_bme280_elev"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_028_bme280_tempoffset"));
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
uint8_t idx = Settings.TaskDevicePluginConfig[event->TaskIndex][0] & 0x1; //Addresses are 0x76 and 0x77 so we may use it this way
|
||||
Plugin_028_init[idx] &= Plugin_028_check(Settings.TaskDevicePluginConfig[event->TaskIndex][0]); // Check id device is present
|
||||
Plugin_028_init[idx] &= (Plugin_028_read8(BME280_REGISTER_CONTROL) == BME280_CONTROL_SETTING); // Check if the coefficients are still valid
|
||||
|
||||
if (!Plugin_028_init[idx])
|
||||
{
|
||||
Plugin_028_init[idx] = Plugin_028_begin(Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
delay(65); //May be needed here as well to fix first wrong measurement?
|
||||
const uint8_t i2cAddress = Plugin_028_i2c_addr(event);
|
||||
const uint8_t idx = Plugin_028_device_index(i2cAddress);
|
||||
const float tempOffset = Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 10.0;
|
||||
if (!Plugin_028_update_measurements(i2cAddress, tempOffset)) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Plugin_028_init[idx])
|
||||
{
|
||||
UserVar[event->BaseVarIndex] = Plugin_028_readTemperature(idx);
|
||||
UserVar[event->BaseVarIndex + 1] = ((float)Plugin_028_readHumidity(idx));
|
||||
int elev = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
if (elev)
|
||||
{
|
||||
UserVar[event->BaseVarIndex + 2] = Plugin_028_pressureElevation((float)Plugin_028_readPressure(idx) / 100, elev);
|
||||
} else {
|
||||
UserVar[event->BaseVarIndex + 2] = ((float)Plugin_028_readPressure(idx)) / 100;
|
||||
}
|
||||
String log = F("BME : Address: 0x");
|
||||
log += String(_i2caddr,HEX);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
log = F("BME : Temperature: ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
log = F("BME : Humidity: ");
|
||||
UserVar[event->BaseVarIndex] = last_temp_val[idx];
|
||||
UserVar[event->BaseVarIndex + 1] = last_hum_val[idx];
|
||||
const int elev = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
if (elev) {
|
||||
UserVar[event->BaseVarIndex + 2] = Plugin_028_pressureElevation(last_press_val[idx], elev);
|
||||
} else {
|
||||
UserVar[event->BaseVarIndex + 2] = last_press_val[idx];
|
||||
}
|
||||
String log;
|
||||
log.reserve(40); // Prevent re-allocation
|
||||
log = Plugin_028_getDeviceName();
|
||||
log += F(" : Address: 0x");
|
||||
log += String(_i2caddr,HEX);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
log = Plugin_028_getDeviceName();
|
||||
log += F(" : Temperature: ");
|
||||
log += UserVar[event->BaseVarIndex];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
if (Plugin_028_hasHumidity()) {
|
||||
log = Plugin_028_getDeviceName();
|
||||
log += F(" : Humidity: ");
|
||||
log += UserVar[event->BaseVarIndex + 1];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
log = F("BME : Barometric Pressure: ");
|
||||
log += UserVar[event->BaseVarIndex + 2];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
}
|
||||
log = Plugin_028_getDeviceName();
|
||||
log += F(" : Barometric Pressure: ");
|
||||
log += UserVar[event->BaseVarIndex + 2];
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -192,18 +292,125 @@ boolean Plugin_028(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
// Only perform the measurements with big interval to prevent the sensor from warming up.
|
||||
bool Plugin_028_update_measurements(uint8_t i2cAddress, float tempOffset) {
|
||||
const uint8_t idx = Plugin_028_device_index(i2cAddress);
|
||||
const unsigned long current_time = millis();
|
||||
if ((last_measurement[idx] > BMx280_MEASUREMENT_INTERVAL_MSEC) &&
|
||||
(current_time < (last_measurement[idx] + BMx280_MEASUREMENT_INTERVAL_MSEC)) &&
|
||||
(current_time > last_measurement[idx])) {
|
||||
// Timeout has not yet been reached.
|
||||
return false;
|
||||
}
|
||||
Plugin_028_init[idx] &= Plugin_028_check(i2cAddress); // Check id device is present
|
||||
if (!Plugin_028_init[idx]) {
|
||||
Plugin_028_init[idx] = Plugin_028_begin(i2cAddress);
|
||||
}
|
||||
|
||||
if (Plugin_028_init[idx]) {
|
||||
last_measurement[idx] = current_time;
|
||||
// Set the Sensor in sleep to be make sure that the following configs will be stored
|
||||
Plugin_028_write8(BMx280_REGISTER_CONTROL, 0x00);
|
||||
if (Plugin_028_hasHumidity()) {
|
||||
Plugin_028_write8(BMx280_REGISTER_CONTROLHUMID, BME280_CONTROL_SETTING_HUMIDITY);
|
||||
}
|
||||
Plugin_028_write8(BMx280_REGISTER_CONFIG, Plugin_028_get_config_settings());
|
||||
Plugin_028_write8(BMx280_REGISTER_CONTROL, Plugin_028_get_control_settings());
|
||||
|
||||
// Start measurement
|
||||
delay(1000); // Wait one second to make sure the filtered values stabilize.
|
||||
|
||||
last_temp_val[idx] = Plugin_028_readTemperature(i2cAddress);
|
||||
last_press_val[idx] = ((float)Plugin_028_readPressure(i2cAddress)) / 100;
|
||||
last_hum_val[idx] = ((float)Plugin_028_readHumidity(i2cAddress));
|
||||
|
||||
// Set to sleep mode again to prevent the sensor from heating up.
|
||||
Plugin_028_write8(BMx280_REGISTER_CONTROL, 0x00);
|
||||
|
||||
String log;
|
||||
log.reserve(120); // Prevent re-allocation
|
||||
log = Plugin_028_getDeviceName();
|
||||
log += F(":");
|
||||
boolean logAdded = false;
|
||||
if (Plugin_028_hasHumidity()) {
|
||||
// Apply half of the temp offset, to correct the dew point offset.
|
||||
// The sensor is warmer than the surrounding air, which has effect on the perceived humidity.
|
||||
last_dew_temp_val[idx] = compute_dew_point_temp(last_temp_val[idx] + (tempOffset / 2.0), last_hum_val[idx]);
|
||||
} else {
|
||||
// No humidity measurement, thus set dew point equal to air temperature.
|
||||
last_dew_temp_val[idx] = last_temp_val[idx];
|
||||
}
|
||||
if (tempOffset > 0.1 || tempOffset < -0.1) {
|
||||
// There is some offset to apply.
|
||||
log += F(" Apply temp offset ");
|
||||
log += tempOffset;
|
||||
log += F("C");
|
||||
if (Plugin_028_hasHumidity()) {
|
||||
log += F(" humidity ");
|
||||
log += last_hum_val[idx];
|
||||
last_hum_val[idx] = compute_humidity_from_dewpoint(last_temp_val[idx] + tempOffset, last_dew_temp_val[idx]);
|
||||
log += F("% => ");
|
||||
log += last_hum_val[idx];
|
||||
log += F("%");
|
||||
}
|
||||
log += F(" temperature ");
|
||||
log += last_temp_val[idx];
|
||||
last_temp_val[idx] = last_temp_val[idx] + tempOffset;
|
||||
log += F("C => ");
|
||||
log += last_temp_val[idx];
|
||||
log += F("C");
|
||||
logAdded = true;
|
||||
}
|
||||
if (Plugin_028_hasHumidity()) {
|
||||
log += F(" dew point ");
|
||||
log += last_dew_temp_val[idx];
|
||||
log += F("C");
|
||||
logAdded = true;
|
||||
}
|
||||
if (logAdded)
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************/
|
||||
// Check BME280 presence
|
||||
//**************************************************************************/
|
||||
bool Plugin_028_check(uint8_t a) {
|
||||
_i2caddr = a?a:0x76;
|
||||
const uint8_t idx = Plugin_028_device_index(_i2caddr);
|
||||
bool wire_status = false;
|
||||
if (Plugin_028_read8(BME280_REGISTER_CHIPID, &wire_status) != 0x60) {
|
||||
return false;
|
||||
} else {
|
||||
return wire_status;
|
||||
const uint8_t chip_id = Plugin_028_read8(BMx280_REGISTER_CHIPID, &wire_status);
|
||||
switch (chip_id) {
|
||||
case BMP280_DEVICE_SAMPLE1:
|
||||
case BMP280_DEVICE_SAMPLE2:
|
||||
case BMP280_DEVICE:
|
||||
case BME280_DEVICE: {
|
||||
if (wire_status) {
|
||||
// Store detected chip ID when chip found.
|
||||
if (_sensorID[idx] != chip_id) {
|
||||
_sensorID[idx] = static_cast<BMx_ChipId>(chip_id);
|
||||
String log = F("BMx280 : Detected ");
|
||||
log += Plugin_028_getFullDeviceName();
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
} else {
|
||||
_sensorID[idx] = Unknown_DEVICE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
_sensorID[idx] = Unknown_DEVICE;
|
||||
break;
|
||||
}
|
||||
if (_sensorID[idx] == Unknown_DEVICE) {
|
||||
String log = F("BMx280 : Unable to detect chip ID");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
return false;
|
||||
}
|
||||
return wire_status;
|
||||
}
|
||||
|
||||
//**************************************************************************/
|
||||
@@ -212,16 +419,11 @@ bool Plugin_028_check(uint8_t a) {
|
||||
bool Plugin_028_begin(uint8_t a) {
|
||||
if (! Plugin_028_check(a))
|
||||
return false;
|
||||
|
||||
Plugin_028_readCoefficients(_i2caddr & 0x01);
|
||||
|
||||
// Set the Sensor in sleep to be make sure that the following configs will be stored
|
||||
Plugin_028_write8(BME280_REGISTER_CONTROL, 0x00);
|
||||
|
||||
Plugin_028_write8(BME280_REGISTER_CONFIG, BME280_CONFIG_SETTING);
|
||||
Plugin_028_write8(BME280_REGISTER_CONTROLHUMID, BME280_CONTROL_SETTING_HUMIDITY);
|
||||
Plugin_028_write8(BME280_REGISTER_CONTROL, BME280_CONTROL_SETTING);
|
||||
|
||||
// Perform soft reset
|
||||
Plugin_028_write8(BMx280_REGISTER_SOFTRESET, 0xB6);
|
||||
delay(2); // Startup time is 2 ms (datasheet)
|
||||
Plugin_028_readCoefficients(a);
|
||||
delay(65); //May be needed here as well to fix first wrong measurement?
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -314,45 +516,48 @@ int16_t Plugin_028_readS16_LE(byte reg)
|
||||
//**************************************************************************/
|
||||
// Reads the factory-set coefficients
|
||||
//**************************************************************************/
|
||||
void Plugin_028_readCoefficients(uint8_t idx)
|
||||
void Plugin_028_readCoefficients(uint8_t i2cAddress)
|
||||
{
|
||||
_bme280_calib[idx].dig_T1 = Plugin_028_read16_LE(BME280_REGISTER_DIG_T1);
|
||||
_bme280_calib[idx].dig_T2 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_T2);
|
||||
_bme280_calib[idx].dig_T3 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_T3);
|
||||
const uint8_t idx = Plugin_028_device_index(i2cAddress);
|
||||
|
||||
_bme280_calib[idx].dig_P1 = Plugin_028_read16_LE(BME280_REGISTER_DIG_P1);
|
||||
_bme280_calib[idx].dig_P2 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P2);
|
||||
_bme280_calib[idx].dig_P3 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P3);
|
||||
_bme280_calib[idx].dig_P4 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P4);
|
||||
_bme280_calib[idx].dig_P5 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P5);
|
||||
_bme280_calib[idx].dig_P6 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P6);
|
||||
_bme280_calib[idx].dig_P7 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P7);
|
||||
_bme280_calib[idx].dig_P8 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P8);
|
||||
_bme280_calib[idx].dig_P9 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_P9);
|
||||
_bme280_calib[idx].dig_T1 = Plugin_028_read16_LE(BMx280_REGISTER_DIG_T1);
|
||||
_bme280_calib[idx].dig_T2 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_T2);
|
||||
_bme280_calib[idx].dig_T3 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_T3);
|
||||
|
||||
_bme280_calib[idx].dig_H1 = Plugin_028_read8(BME280_REGISTER_DIG_H1);
|
||||
_bme280_calib[idx].dig_H2 = Plugin_028_readS16_LE(BME280_REGISTER_DIG_H2);
|
||||
_bme280_calib[idx].dig_H3 = Plugin_028_read8(BME280_REGISTER_DIG_H3);
|
||||
_bme280_calib[idx].dig_H4 = (Plugin_028_read8(BME280_REGISTER_DIG_H4) << 4) | (Plugin_028_read8(BME280_REGISTER_DIG_H4 + 1) & 0xF);
|
||||
_bme280_calib[idx].dig_H5 = (Plugin_028_read8(BME280_REGISTER_DIG_H5 + 1) << 4) | (Plugin_028_read8(BME280_REGISTER_DIG_H5) >> 4);
|
||||
_bme280_calib[idx].dig_H6 = (int8_t)Plugin_028_read8(BME280_REGISTER_DIG_H6);
|
||||
_bme280_calib[idx].dig_P1 = Plugin_028_read16_LE(BMx280_REGISTER_DIG_P1);
|
||||
_bme280_calib[idx].dig_P2 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P2);
|
||||
_bme280_calib[idx].dig_P3 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P3);
|
||||
_bme280_calib[idx].dig_P4 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P4);
|
||||
_bme280_calib[idx].dig_P5 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P5);
|
||||
_bme280_calib[idx].dig_P6 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P6);
|
||||
_bme280_calib[idx].dig_P7 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P7);
|
||||
_bme280_calib[idx].dig_P8 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P8);
|
||||
_bme280_calib[idx].dig_P9 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_P9);
|
||||
|
||||
if (Plugin_028_hasHumidity()) {
|
||||
_bme280_calib[idx].dig_H1 = Plugin_028_read8(BMx280_REGISTER_DIG_H1);
|
||||
_bme280_calib[idx].dig_H2 = Plugin_028_readS16_LE(BMx280_REGISTER_DIG_H2);
|
||||
_bme280_calib[idx].dig_H3 = Plugin_028_read8(BMx280_REGISTER_DIG_H3);
|
||||
_bme280_calib[idx].dig_H4 = (Plugin_028_read8(BMx280_REGISTER_DIG_H4) << 4) | (Plugin_028_read8(BMx280_REGISTER_DIG_H4 + 1) & 0xF);
|
||||
_bme280_calib[idx].dig_H5 = (Plugin_028_read8(BMx280_REGISTER_DIG_H5 + 1) << 4) | (Plugin_028_read8(BMx280_REGISTER_DIG_H5) >> 4);
|
||||
_bme280_calib[idx].dig_H6 = (int8_t)Plugin_028_read8(BMx280_REGISTER_DIG_H6);
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************/
|
||||
// Read temperature
|
||||
//**************************************************************************/
|
||||
float Plugin_028_readTemperature(uint8_t idx)
|
||||
float Plugin_028_readTemperature(uint8_t i2cAddress)
|
||||
{
|
||||
const uint8_t idx = Plugin_028_device_index(i2cAddress);
|
||||
int32_t var1, var2;
|
||||
|
||||
// set to forced mode, i.e. "take next measurement"
|
||||
Plugin_028_write8(BME280_REGISTER_CONTROL, BME280_CONTROL_SETTING);
|
||||
// wait until measurement has been completed, otherwise we would read
|
||||
// the values from the last measurement
|
||||
while (Plugin_028_read8(BME280_REGISTER_STATUS) & 0x08)
|
||||
while (Plugin_028_read8(BMx280_REGISTER_STATUS) & 0x08)
|
||||
delay(1);
|
||||
|
||||
int32_t adc_T = Plugin_028_read24(BME280_REGISTER_TEMPDATA);
|
||||
int32_t adc_T = Plugin_028_read24(BMx280_REGISTER_TEMPDATA);
|
||||
adc_T >>= 4;
|
||||
|
||||
var1 = ((((adc_T >> 3) - ((int32_t)_bme280_calib[idx].dig_T1 << 1))) *
|
||||
@@ -371,10 +576,12 @@ float Plugin_028_readTemperature(uint8_t idx)
|
||||
//**************************************************************************/
|
||||
// Read pressure
|
||||
//**************************************************************************/
|
||||
float Plugin_028_readPressure(uint8_t idx) {
|
||||
float Plugin_028_readPressure(uint8_t i2cAddress)
|
||||
{
|
||||
const uint8_t idx = Plugin_028_device_index(i2cAddress);
|
||||
int64_t var1, var2, p;
|
||||
|
||||
int32_t adc_P = Plugin_028_read24(BME280_REGISTER_PRESSUREDATA);
|
||||
int32_t adc_P = Plugin_028_read24(BMx280_REGISTER_PRESSUREDATA);
|
||||
adc_P >>= 4;
|
||||
|
||||
var1 = ((int64_t)t_fine) - 128000;
|
||||
@@ -400,9 +607,21 @@ float Plugin_028_readPressure(uint8_t idx) {
|
||||
//**************************************************************************/
|
||||
// Read humidity
|
||||
//**************************************************************************/
|
||||
float Plugin_028_readHumidity(uint8_t idx) {
|
||||
|
||||
int32_t adc_H = Plugin_028_read16(BME280_REGISTER_HUMIDDATA);
|
||||
float Plugin_028_readHumidity(uint8_t i2cAddress)
|
||||
{
|
||||
if (!Plugin_028_hasHumidity()) {
|
||||
// No support for humidity
|
||||
return 0.0;
|
||||
}
|
||||
// It takes at least 1.587 sec for valit measurements to complete.
|
||||
// The datasheet names this the "T63" moment.
|
||||
// 1 second = 63% of the time needed to perform a measurement.
|
||||
const uint8_t idx = Plugin_028_device_index(i2cAddress);
|
||||
unsigned long difTime = millis() - last_measurement[idx];
|
||||
if (difTime < 1587) {
|
||||
delay(1587 - difTime);
|
||||
}
|
||||
int32_t adc_H = Plugin_028_read16(BMx280_REGISTER_HUMIDDATA);
|
||||
|
||||
int32_t v_x1_u32r;
|
||||
|
||||
@@ -438,7 +657,7 @@ float Plugin_028_readAltitude(float seaLevel)
|
||||
// at high altitude. See this thread for more information:
|
||||
// http://forums.adafruit.com/viewtopic.php?f=22&t=58064
|
||||
|
||||
float atmospheric = Plugin_028_readPressure(_i2caddr & 0x01) / 100.0F;
|
||||
float atmospheric = Plugin_028_readPressure(_i2caddr) / 100.0F;
|
||||
return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903));
|
||||
}
|
||||
|
||||
|
||||
+10
-4
@@ -137,14 +137,14 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
|
||||
for (uint t = 0; t < c0; t++)
|
||||
printWebString += F("0");
|
||||
}
|
||||
//So, as we recieve a "1", and processed the counted 0s
|
||||
//So, as we receive a "1", and processed the counted 0s
|
||||
//sending them as a ms timing into the buffer, we clear
|
||||
//the 0s counter
|
||||
c0 = 0;
|
||||
} else {
|
||||
//So, bit is 0
|
||||
|
||||
//On first call, ignore 0s (supress left-most 0s)
|
||||
//On first call, ignore 0s (suppress left-most 0s)
|
||||
if (c0+c1 != 0) {
|
||||
//add 1 to counter c0
|
||||
c0++;
|
||||
@@ -154,11 +154,11 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
|
||||
//add the total ms into the buffer (number of 1s
|
||||
//multiplied by defined pulse length ms)
|
||||
buf[idx++] = c1 * IrPLen;
|
||||
//print the number of 1s just for debuging/info purpouses
|
||||
//print the number of 1s just for debugging/info purposes
|
||||
for (uint t = 0; t < c1; t++)
|
||||
printWebString += F("1");
|
||||
}
|
||||
//So, as we recieve a "0", and processed the counted 1s
|
||||
//So, as we receive a "0", and processed the counted 1s
|
||||
//sending them as a ms timing into the buffer, we clear
|
||||
//the 1s counter
|
||||
c1 = 0;
|
||||
@@ -195,9 +195,14 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
|
||||
//sprintf_P(log, PSTR("IR Params2: RAW Code:%s"), IrRaw.c_str());
|
||||
//addLog(LOG_LEVEL_INFO, log);
|
||||
} else {
|
||||
unsigned int IrRepeat=0;
|
||||
unsigned long IrSecondCode=0UL;
|
||||
|
||||
if (GetArgv(command, TmpStr1, 2)) IrType = TmpStr1;
|
||||
if (GetArgv(command, TmpStr1, 3)) IrCode = strtoul(TmpStr1, NULL, 16); //(long) TmpStr1
|
||||
if (GetArgv(command, TmpStr1, 4)) IrBits = str2int(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 5)) IrRepeat = str2int(TmpStr1);
|
||||
if (GetArgv(command, TmpStr1, 6)) IrSecondCode = strtoul(TmpStr1, NULL, 16);
|
||||
|
||||
if (IrType.equalsIgnoreCase("NEC")) Plugin_035_irSender->sendNEC(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("JVC")) Plugin_035_irSender->sendJVC(IrCode, IrBits, 2);
|
||||
@@ -206,6 +211,7 @@ boolean Plugin_035(byte function, struct EventStruct *event, String& string)
|
||||
if (IrType.equalsIgnoreCase("SAMSUNG")) Plugin_035_irSender->sendSAMSUNG(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("SONY")) Plugin_035_irSender->sendSony(IrCode, IrBits);
|
||||
if (IrType.equalsIgnoreCase("PANASONIC")) Plugin_035_irSender->sendPanasonic(IrBits, IrCode);
|
||||
if (IrType.equalsIgnoreCase("PIONEER")) Plugin_035_irSender->sendPioneer(IrCode, IrBits, IrRepeat, IrSecondCode);
|
||||
}
|
||||
|
||||
addLog(LOG_LEVEL_INFO, F("IRTX :IR Code Sent"));
|
||||
|
||||
+21
-3
@@ -15,6 +15,11 @@
|
||||
// If you use 'NeoPixelAll' this will off all LED (like NeoPixelAll,0,0,0)
|
||||
// (3): Set color LED between <start led nr> and <stop led nr> to specified color (eg. NeoPixelLine,1,6,255,255,255)
|
||||
|
||||
//RGBW note:
|
||||
// for RGBW strips append the additional <brightness> to the commands
|
||||
// eg: NeoPixel,<led nr>,<red 0-255>,<green 0-255>,<blue 0-255>,<brightness 0-255>
|
||||
// The NeoPixelLine command does not work for RGBW, cause espeasy currently only allows max. 5 parameters
|
||||
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
Adafruit_NeoPixel *Plugin_038_pixels;
|
||||
|
||||
@@ -55,8 +60,13 @@ boolean Plugin_038(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
const String options[] = { F("GRB"), F("GRBW") };
|
||||
int indices[] = { 1, 2 };
|
||||
|
||||
addFormNumericBox(string, F("Led Count"), F("plugin_038_leds"), Settings.TaskDevicePluginConfig[event->TaskIndex][0],1,999);
|
||||
addFormPinSelect(string, F("GPIO"), F("taskdevicepin1"), Settings.TaskDevicePin1[event->TaskIndex]);
|
||||
addFormSelector(string, F("Strip Type"), F("plugin_038_strip"), 2, options, indices, Settings.TaskDevicePluginConfig[event->TaskIndex][1] );
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -65,6 +75,7 @@ boolean Plugin_038(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_038_leds"));
|
||||
MaxPixels = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_038_strip"));
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -73,7 +84,14 @@ boolean Plugin_038(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
if (!Plugin_038_pixels)
|
||||
{
|
||||
Plugin_038_pixels = new Adafruit_NeoPixel(Settings.TaskDevicePluginConfig[event->TaskIndex][0], Settings.TaskDevicePin1[event->TaskIndex], NEO_GRB + NEO_KHZ800);
|
||||
byte striptype = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
if (striptype == 1)
|
||||
Plugin_038_pixels = new Adafruit_NeoPixel(Settings.TaskDevicePluginConfig[event->TaskIndex][0], Settings.TaskDevicePin1[event->TaskIndex], NEO_GRB + NEO_KHZ800);
|
||||
else if (striptype == 2)
|
||||
Plugin_038_pixels = new Adafruit_NeoPixel(Settings.TaskDevicePluginConfig[event->TaskIndex][0], Settings.TaskDevicePin1[event->TaskIndex], NEO_GRBW + NEO_KHZ800);
|
||||
else
|
||||
Plugin_038_pixels = new Adafruit_NeoPixel(Settings.TaskDevicePluginConfig[event->TaskIndex][0], Settings.TaskDevicePin1[event->TaskIndex], NEO_GRB + NEO_KHZ800);
|
||||
|
||||
Plugin_038_pixels->begin(); // This initializes the NeoPixel library.
|
||||
}
|
||||
MaxPixels = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
@@ -98,7 +116,7 @@ boolean Plugin_038(byte function, struct EventStruct *event, String& string)
|
||||
// string.toCharArray(Line, 80);
|
||||
// int Par4 = 0;
|
||||
// if (GetArgv(Line, TmpStr1, 5)) Par4 = str2int(TmpStr1);
|
||||
Plugin_038_pixels->setPixelColor(event->Par1 - 1, Plugin_038_pixels->Color(event->Par2, event->Par3, event->Par4));
|
||||
Plugin_038_pixels->setPixelColor(event->Par1 - 1, Plugin_038_pixels->Color(event->Par2, event->Par3, event->Par4, event->Par5));
|
||||
Plugin_038_pixels->show(); // This sends the updated pixel color to the hardware.
|
||||
success = true;
|
||||
}
|
||||
@@ -111,7 +129,7 @@ boolean Plugin_038(byte function, struct EventStruct *event, String& string)
|
||||
// string.toCharArray(Line, 80);
|
||||
for (int i = 0; i < MaxPixels; i++)
|
||||
{
|
||||
Plugin_038_pixels->setPixelColor(i, Plugin_038_pixels->Color(event->Par1, event->Par2, event->Par3));
|
||||
Plugin_038_pixels->setPixelColor(i, Plugin_038_pixels->Color(event->Par1, event->Par2, event->Par3, event->Par4));
|
||||
}
|
||||
Plugin_038_pixels->show();
|
||||
success = true;
|
||||
|
||||
+40
-13
@@ -9,15 +9,15 @@
|
||||
// MAX6675 or MAX31855 in order to read the values. Take a look at ebay to find such boards :-)
|
||||
// You can only use ESP8266 boards which expose the SPI Interface. This Plugin uses only the Hardware
|
||||
// SPI Interface - no software SPI at the moment.
|
||||
// But neverless you need at least 3 Pins to use SPI. So using an very simple ESP-01 is no option - Sorry.
|
||||
// The Wiring ist straight forward ...
|
||||
// But nevertheless you need at least 3 Pins to use SPI. So using an very simple ESP-01 is no option - Sorry.
|
||||
// The Wiring is straight forward ...
|
||||
//
|
||||
// If you like to send suggestions feel free to send me an email : dominik@logview.info
|
||||
// Have fun ... Dominik
|
||||
|
||||
// Wiring
|
||||
// https://de.wikipedia.org/wiki/Serial_Peripheral_Interface
|
||||
// You need an ESP8266 device with accessable SPI Pins. These are:
|
||||
// You need an ESP8266 device with accessible SPI Pins. These are:
|
||||
// Name Description GPIO NodeMCU Notes
|
||||
// MOSI Master Output GPIO13 D7 Not used (No Data sending to MAX)
|
||||
// MISO Master Input GPIO12 D6 Hardware SPI
|
||||
@@ -42,6 +42,7 @@
|
||||
|
||||
uint8_t Plugin_039_SPI_CS_Pin = 15; // D8
|
||||
bool Plugin_039_SensorAttached = true;
|
||||
uint32_t Plugin_039_Sensor_fault = 0;
|
||||
double Plugin_039_Celsius = 0.0;
|
||||
|
||||
boolean Plugin_039(byte function, struct EventStruct *event, String& string)
|
||||
@@ -231,9 +232,28 @@ double readMax31855()
|
||||
log += String(rawvalue);
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
if (Plugin_039_Sensor_fault != (rawvalue & 0x7)) {
|
||||
// Fault code changed, log them
|
||||
Plugin_039_Sensor_fault = (rawvalue & 0x7);
|
||||
log = F("P039 : MAX31855");
|
||||
if (Plugin_039_Sensor_fault == 0) {
|
||||
log += F("Fault resolved");
|
||||
} else {
|
||||
log += F("Fault code:");
|
||||
if (rawvalue & 0x01) {
|
||||
log += F(" Open (no connection)");
|
||||
}
|
||||
if (rawvalue & 0x02) {
|
||||
log += F(" Short-circuit to GND");
|
||||
}
|
||||
if (rawvalue & 0x04) {
|
||||
log += F(" Short-circuit to Vcc");
|
||||
}
|
||||
}
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
}
|
||||
// D16 - This bit reads at 1 when any of the SCV, SCG, or OC faults are active. Default value is 0.
|
||||
Plugin_039_SensorAttached = !(rawvalue & 0x00010000);
|
||||
|
||||
if (Plugin_039_SensorAttached)
|
||||
{
|
||||
// Data is D[31:18]
|
||||
@@ -246,19 +266,26 @@ double readMax31855()
|
||||
// -0.25 1111 1111 1111 11
|
||||
// -1.00 1111 1111 1111 00
|
||||
// -250.00 1111 0000 0110 00
|
||||
if (rawvalue & 0x2000) // Bit 31=1 -> neg Values
|
||||
{
|
||||
// Negate all Bits
|
||||
rawvalue = ~rawvalue;
|
||||
// Add 1 and make negative
|
||||
rawvalue = (rawvalue + 1) * -1;
|
||||
}
|
||||
|
||||
// We're left with (32 - 18 =) 14 bits
|
||||
int temperature = Plugin_039_convert_two_complement(rawvalue, 14);
|
||||
// Calculate Celsius
|
||||
return rawvalue * 0.25;
|
||||
return temperature * 0.25;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fault state, thus output no value.
|
||||
return NAN;
|
||||
}
|
||||
}
|
||||
|
||||
int Plugin_039_convert_two_complement(uint32_t value, int nr_bits) {
|
||||
const bool negative = (value & (1 << (nr_bits - 1))) != 0;
|
||||
int nativeInt;
|
||||
if (negative) {
|
||||
// Add zeroes to the left to create the proper negative native-sized integer.
|
||||
nativeInt = value | ~((1 << nr_bits) - 1);
|
||||
} else {
|
||||
nativeInt = value;
|
||||
}
|
||||
return nativeInt;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
// * Extract jscolor.min.js
|
||||
// * Now open the Web UI of your ESPEasy with this URL:
|
||||
// http://<IP-ESPEasy>/upload
|
||||
// * Select Browse ... and choose the extracted jscolor.min.js File (ensure the ...min... verion !!)
|
||||
// * Select Browse ... and choose the extracted jscolor.min.js File (ensure the ...min... version !!)
|
||||
// * Press Upload und you are done.
|
||||
|
||||
// Add the Adafruit Neopixel Library to your library path. You will find it here:
|
||||
@@ -21,14 +21,14 @@
|
||||
// NOTES
|
||||
// Please keep in mind that you can add tasks which produce a very large delay while reading the sensor.
|
||||
// For example the DS18B20 is very slow in reading the values. This can slow down the simulation and you
|
||||
// will notice that the candle did not run smooth. So keep an eye on your tasks and donßt add to much other tasks.
|
||||
// will notice that the candle did not run smooth. So keep an eye on your tasks and don't add to much other tasks.
|
||||
|
||||
// HARDWARE
|
||||
// The Wifi Candle uses 20 WS2812 RGB pixels. They are all connected in one row.
|
||||
// I build a wooden wick with 5 pixels on each side. (A picture is here : http://www.esp8266.nu/forum/viewtopic.php?f=2&t=2147)
|
||||
// The pixels are connected to 5V and the data pin I use is GPIO13 (but you can choose another one).
|
||||
// Please ensure that you use a strong power supply because the pixels consume a lot of power when they
|
||||
// shine in white with high brigthness!
|
||||
// shine in white with high brightness!
|
||||
// I also placed a 100µF capacitor at the end of the WS2812 chain on +5/GND just to ensure a good power stability.
|
||||
// btw ... My Testboard was a NodeMCU V3.
|
||||
|
||||
@@ -80,7 +80,7 @@ byte Candle_bright = 128;
|
||||
SimType Candle_type = TypeSimpleCandle;
|
||||
ColorType Candle_color = ColorDefault;
|
||||
|
||||
// gloable Variables
|
||||
// global variables
|
||||
unsigned long Candle_Update = 0;
|
||||
word Candle_Temp[4] = { 0, 0, 0 }; // Temp variables
|
||||
int Candle_Temp4 = 0;
|
||||
|
||||
@@ -114,6 +114,7 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
if (ExtraTaskSettings.TaskDevicePluginConfigLong[4] == 2)
|
||||
serialconfig += 0x20;
|
||||
Serial.begin(ExtraTaskSettings.TaskDevicePluginConfigLong[1], (SerialConfig)serialconfig);
|
||||
if (P1GatewayServer) P1GatewayServer->close();
|
||||
P1GatewayServer = new WiFiServer(ExtraTaskSettings.TaskDevicePluginConfigLong[0]);
|
||||
P1GatewayServer->begin();
|
||||
|
||||
@@ -138,7 +139,7 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
addLog(LOG_LEVEL_DEBUG, F("P1 : DSMR version 4 meter, CRC on"));
|
||||
CRCcheck = true;
|
||||
} else {
|
||||
addLog(LOG_LEVEL_DEBUG, F("P1 : DSMR version 4 meter, CRC on"));
|
||||
addLog(LOG_LEVEL_DEBUG, F("P1 : DSMR version 4 meter, CRC off"));
|
||||
CRCcheck = false;
|
||||
}
|
||||
|
||||
@@ -148,6 +149,17 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_EXIT:
|
||||
{
|
||||
if (P1GatewayServer) {
|
||||
P1GatewayServer->close();
|
||||
//FIXME: shouldnt P1P1GatewayServer be deleted?
|
||||
P1GatewayServer = NULL;
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_TEN_PER_SECOND:
|
||||
{
|
||||
if (Plugin_044_init)
|
||||
@@ -223,8 +235,8 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
case WAITING:
|
||||
if (ch == '/') {
|
||||
Plugin_044_serial_buf[bytes_read] = ch;
|
||||
bytes_read++;
|
||||
Plugin_044_serial_buf[0] = ch;
|
||||
bytes_read=1;
|
||||
state = READING;
|
||||
} // else ignore data
|
||||
break;
|
||||
@@ -239,6 +251,10 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
if (validP1char(ch)) {
|
||||
Plugin_044_serial_buf[bytes_read] = ch;
|
||||
bytes_read++;
|
||||
} else if (ch=='/') {
|
||||
addLog(LOG_LEVEL_DEBUG, F("P1 : Error: Start detected, discarded input."));
|
||||
Plugin_044_serial_buf[0] = ch;
|
||||
bytes_read = 1;
|
||||
} else { // input is non-ascii
|
||||
addLog(LOG_LEVEL_DEBUG, F("P1 : Error: DATA corrupt, discarded input."));
|
||||
Serial.flush();
|
||||
@@ -248,13 +264,12 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
case CHECKSUM:
|
||||
checkI ++;
|
||||
if (checkI == 5) {
|
||||
if (checkI == 4) {
|
||||
checkI = 0;
|
||||
state = DONE;
|
||||
} else {
|
||||
Plugin_044_serial_buf[bytes_read] = ch;
|
||||
bytes_read++;
|
||||
}
|
||||
Plugin_044_serial_buf[bytes_read] = ch;
|
||||
bytes_read++;
|
||||
break;
|
||||
case DONE:
|
||||
// Plugin_044_serial_buf[bytes_read]= '\n';
|
||||
@@ -278,7 +293,6 @@ boolean Plugin_044(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
if (state == DONE) {
|
||||
if (checkDatagram(bytes_read)) {
|
||||
bytes_read++;
|
||||
Plugin_044_serial_buf[bytes_read] = '\r';
|
||||
bytes_read++;
|
||||
Plugin_044_serial_buf[bytes_read] = '\n';
|
||||
|
||||
@@ -17,23 +17,23 @@
|
||||
// included in all copies or substantial portions of the Software.
|
||||
|
||||
|
||||
// This plugin enables the use of a MPU6050 sensor as e.g. used in the breakoutboard GY-521.
|
||||
// This plugin enables the use of a MPU6050 sensor as e.g. used in the breakout-board GY-521.
|
||||
// Using the webform you can set thresholds for the x-y-z axis and timeout values. If the thresholds are
|
||||
// exceeded the sensor is on, if the thresholds are not met during the timeout period the sensor is off.
|
||||
|
||||
// Using this plugin you can get a notification from your home automationsystem when the monitored machine or
|
||||
// device is no longer vibrating and thus this can be used as a signaling device for the end of a (dish)washer
|
||||
// Using this plugin you can get a notification from your home automation system when the monitored machine or
|
||||
// device is no longer vibrating and thus this can be used as a signalling device for the end of a (dish)washer
|
||||
// or dryer cycle.
|
||||
|
||||
// You can also use the plugin to read raw sensorvalues. You can use more then one instance of the plugin and
|
||||
// You can also use the plugin to read raw sensor values. You can use more then one instance of the plugin and
|
||||
// you can set multiple movement alarms by giving each instance other threshold values if needed.
|
||||
|
||||
// Best practise: Create three custom sensors in your homecontroller (like domoticz) and let it plot the x, y and
|
||||
// z range. Plot the sensorvalues while you use the washingmachine and/or dryer. Also keep monitoring when they
|
||||
// Best practise: Create three custom sensors in your home controller (like domoticz) and let it plot the x, y and
|
||||
// z range. Plot the sensor values while you use the washing machine and/or dryer. Also keep monitoring when they
|
||||
// are not in use so you can determine the needed thresholds. When you have these you can select the movement
|
||||
// detection function to setup the plugin for further use.
|
||||
|
||||
// The plugin can simultanious be used with two MPU6050 devices by adding multiple instances.
|
||||
// The plugin can be used simultaneously with two MPU6050 devices by adding multiple instances.
|
||||
// Originally released in the PlayGround as Plugin 118.
|
||||
|
||||
// Plugin var usage:
|
||||
|
||||
+34
-34
@@ -5,26 +5,26 @@
|
||||
// Purpose: Sniff the data received by the Ventus W266 display unit and send it to Domoticz
|
||||
// Status : "Initial release"
|
||||
|
||||
// This plugin can be used on a esp8266 connected to the recievermodule inside a Ventus W266 or
|
||||
// Renkforce W205GU display unit. The plugin then reads the data send from the remote sensorunit and
|
||||
// This plugin can be used on a esp8266 connected to the receiver module inside a Ventus W266 or
|
||||
// Renkforce W205GU display unit. The plugin then reads the data send from the remote sensor unit and
|
||||
// can send the data to Domoticz or an other controller. The plugin does not read the data of the
|
||||
// sensors in the display unit such as indoor temperature and airpressure.
|
||||
// sensors in the display unit such as indoor temperature and air pressure.
|
||||
|
||||
// The displaynit has a RFM31 reciever but the pinout of this receiver is identical to the pinout
|
||||
// of a RFM01 reciever. We need to connect 4 wires to read the SPI exchange between the host and the
|
||||
// reciever. Because we need to read both MOSI and MISO signals the hardware SPI is unusable and we
|
||||
// use bitbanging to achive the same result.
|
||||
// The display unit has a RFM31 receiver but the pinout of this receiver is identical to the pinout
|
||||
// of a RFM01 receiver. We need to connect 4 wires to read the SPI exchange between the host and the
|
||||
// receiver. Because we need to read both MOSI and MISO signals the hardware SPI is unusable and we
|
||||
// use bit-banging to achieve the same result.
|
||||
|
||||
// Connect pins 5-8 from the "RFM31BJ-S1" to the pins you defined in de webgui.
|
||||
// Connect pins 5-8 from the "RFM31BJ-S1" to the pins you defined in the webgui.
|
||||
// Pinout of the RFM31: 5-MOSI, 6-SCLK, 7-nSEL (active low CS), 8-MISO, 14-GND.
|
||||
// In my original setup these were connected to 4, 12, 14 and 5.
|
||||
// Try to avoid GPIO 15 as nSEL line because if the line is high during a reboot, and it is mostly high,
|
||||
// the boot will fail!
|
||||
|
||||
// The Ventus W266 remote has the following sensor outputs:
|
||||
// Humidity, Temperature, Wind direction, Wind avarage, Wind gust, Rainfall, UV and Lightning. That is
|
||||
// Humidity, Temperature, Wind direction, Wind average, Wind gust, Rainfall, UV and Lightning. That is
|
||||
// more than te maximum of 4 values per device for espeasy. The plugins functionality is therefore
|
||||
// devided per sensorgroup. To read all the sensor data you need to run 6 instances of the plugin.
|
||||
// divided per sensor group. To read all the sensor data you need to run 6 instances of the plugin.
|
||||
|
||||
// The plugin can (and should) be used more then one time, however only one plugin instance can be
|
||||
// the main plugin. The plugin function can be selected by a dropdown and only the main plugin has
|
||||
@@ -32,25 +32,25 @@
|
||||
|
||||
// The plugin uses two buffers, ine for the ISR routines and one for the other plugin instances.
|
||||
|
||||
// This plugin was originally released into th eplayground as Plugin 186, it is assimilated into the core as 046.
|
||||
// This plugin was originally released into the playground as Plugin 186, it is assimilated into the core as 046.
|
||||
// Why plugin nr 186? Well 266 is not possible, 206 (id on the back of the unit) is nit within the
|
||||
// playground range and the W186 is an additinal external thermometer for the Ventus W266.
|
||||
// playground range and the W186 is an additional external thermometer for the Ventus W266.
|
||||
// The Ventus W266 is also known as the Renkforce W205GU.
|
||||
|
||||
// TaskDevicePluginConfig[x][0] = Instance function
|
||||
// TaskDevicePluginConfig[x][1] = MOSI (eg. GPOI pin 4)
|
||||
// TaskDevicePluginConfig[x][2] = SCLK (eg. GPIO pin 12)
|
||||
// TaskDevicePluginConfig[x][3] = nSEL (eg. GPIO pin 14)
|
||||
// TaskDevicePluginConfig[x][4] = MISO (eg. GPIO pin 5)
|
||||
// TaskDevicePluginConfig[x][1] = MOSI (e.g. GPOI pin 4)
|
||||
// TaskDevicePluginConfig[x][2] = SCLK (e.g. GPIO pin 12)
|
||||
// TaskDevicePluginConfig[x][3] = nSEL (e.g. GPIO pin 14)
|
||||
// TaskDevicePluginConfig[x][4] = MISO (e.g. GPIO pin 5)
|
||||
// If you use GPIO 4&5, please disable the I2C/SPI option in the hardware tab.
|
||||
|
||||
// The buffers contain the following data:
|
||||
// hhIDhh 1A tlth ?b tlth wb alahglgh rlrh?? uv ld?? lllhcrc
|
||||
// 7F9827 1A B100 00 B100 06 00000000 1E0000 00 3F8A 2A0017
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2
|
||||
// hh=header > This is actualy not part of the real payload but a wanted artifact of the sniffing method.
|
||||
// hh=header > This is actually not part of the real payload but a wanted artifact of the sniffing method.
|
||||
// hh=humidity (bcd) > Humidity is bcd encoded
|
||||
// tlth=temperature-low/temphigh (*10) > Temperature is stored as a 16bit integer holding the temperature in Celcius * 10 but low byte first.
|
||||
// tlth=temperature-low/temphigh (*10) > Temperature is stored as a 16bit integer holding the temperature in Celsius * 10 but low byte first.
|
||||
// b=battery (1=low) > This byte is 00 but 01 when the battery of the transmitter runs low
|
||||
// wb=bearing (cw0-15) > The windbearing in 16 clockwise steps (0 = north, 4 = east, 8 = south and C = west)
|
||||
// alah=windaverage-low/high (m/s/2) > A 16 bit int holding the wind avarage in m/s * 2, low byte first
|
||||
@@ -79,7 +79,7 @@
|
||||
#ifdef PLUGIN_BUILD_DISABLED
|
||||
// #ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define PLUGIN_046_DEBUG true // Shows recieved frames and crc in log@INFO
|
||||
#define PLUGIN_046_DEBUG true // Shows received frames and crc in log@INFO
|
||||
|
||||
#define PLUGIN_046 // Mandatory framework constants
|
||||
#define PLUGIN_ID_046 46
|
||||
@@ -100,12 +100,12 @@ int8_t Plugin_046_MISOpin = -1;
|
||||
byte Plugin_046_ISR_Buffer[Plugin_046_RAW_BUFFER_SIZE]; // Buffer used in ISR routine
|
||||
//Test data: volatile byte Plugin_046_databuffer[] = {0x7F, 0x98, 0x33, 0x1A, 0xB0, 0x00, 0x00, 0xB0, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x3F, 0x8A, 0x25, 0x00, 0x49, 0x00}; // Buffer used by other instances
|
||||
byte Plugin_046_databuffer[Plugin_046_RAW_BUFFER_SIZE]; // Buffer used by other instances
|
||||
boolean Plugin_046_RecieveActive = false; // Active session in progress
|
||||
boolean Plugin_046_ReceiveActive = false; // Active session in progress
|
||||
boolean Plugin_046_MasterSlave = false; // Which pin o read? false=MOSI, true=MISO
|
||||
boolean Plugin_046_newData = false; // "Valid" data ready, please process
|
||||
byte Plugin_046_bitpointer; // Pointer for recieved bit
|
||||
byte Plugin_046_bytepointer; // Pointe for ISR recieve buffer
|
||||
byte Plugin_046_recievedData; // Byte to store recieved bits
|
||||
byte Plugin_046_bitpointer; // Pointer for received bit
|
||||
byte Plugin_046_bytepointer; // Pointer for ISR receive buffer
|
||||
byte Plugin_046_receivedData; // Byte to store received bits
|
||||
|
||||
// Vars used for interpreting the data:
|
||||
volatile unsigned long Plugin_046_lastrainctr; // Keep track of wdcounter (1/2 min tick)
|
||||
@@ -294,7 +294,7 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
if (Plugin_046_newData) {
|
||||
uint8_t crc = 0xff; // init = 0xff
|
||||
char data; // CRC = MAXIM with modified init: poly 0x31, init 0xff, refin 1; refout 1, xorout 0x00
|
||||
// Copy recieved data to buffer and check CRC
|
||||
// Copy received data to buffer and check CRC
|
||||
Plugin_046_databuffer[0] = Plugin_046_ISR_Buffer[0];
|
||||
for (int i = 1; i < Plugin_046_bytepointer; i++) {
|
||||
data = Plugin_046_ISR_Buffer[i];
|
||||
@@ -458,39 +458,39 @@ boolean Plugin_046(byte function, struct EventStruct *event, String& string)
|
||||
void Plugin_046_ISR_nSEL() // Interrupt on nSEL change
|
||||
{
|
||||
if (digitalRead(Plugin_046_nSELpin)) {
|
||||
Plugin_046_RecieveActive = false; // nSEL high? Recieve done.
|
||||
if (Plugin_046_MasterSlave) { // If MISO not active, no data recieved
|
||||
Plugin_046_ReceiveActive = false; // nSEL high? Receive done.
|
||||
if (Plugin_046_MasterSlave) { // If MISO not active, no data received
|
||||
if (Plugin_046_bytepointer == Plugin_046_Payload) { // If not 23 then bad datapacket
|
||||
Plugin_046_newData = true; // We have new data!
|
||||
}
|
||||
}
|
||||
} else { // nSEL low? Start recieve
|
||||
} else { // nSEL low? Start receive
|
||||
if (!Plugin_046_newData) { // Only accept new data if the old is processed
|
||||
Plugin_046_bitpointer = 7; // reset pointer (MSB first)
|
||||
Plugin_046_bytepointer = 0; // reset pointers & flags
|
||||
Plugin_046_MasterSlave = false;
|
||||
Plugin_046_RecieveActive = true; // We are now recieving data
|
||||
Plugin_046_ReceiveActive = true; // We are now receiving data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Plugin_046_ISR_SCLK() // Interrupt on SCLK rising
|
||||
{
|
||||
if (Plugin_046_RecieveActive) { // Are we recieving or glitch?
|
||||
if (Plugin_046_ReceiveActive) { // Are we receiving or glitch?
|
||||
if (Plugin_046_MasterSlave) { // Read MISO or MOSI?
|
||||
bitWrite(Plugin_046_recievedData, Plugin_046_bitpointer, digitalRead(Plugin_046_MISOpin));
|
||||
bitWrite(Plugin_046_receivedData, Plugin_046_bitpointer, digitalRead(Plugin_046_MISOpin));
|
||||
} else {
|
||||
bitWrite(Plugin_046_recievedData, Plugin_046_bitpointer, digitalRead(Plugin_046_MOSIpin));
|
||||
bitWrite(Plugin_046_receivedData, Plugin_046_bitpointer, digitalRead(Plugin_046_MOSIpin));
|
||||
}
|
||||
if (Plugin_046_bitpointer == 0) { // 8 bits done?
|
||||
Plugin_046_bitpointer = 7;
|
||||
if (Plugin_046_recievedData==Plugin_046_MagicByte) { // Switch data pins?
|
||||
if (Plugin_046_receivedData==Plugin_046_MagicByte) { // Switch data pins?
|
||||
Plugin_046_MasterSlave = true;
|
||||
}
|
||||
Plugin_046_ISR_Buffer[Plugin_046_bytepointer] = Plugin_046_recievedData;
|
||||
Plugin_046_ISR_Buffer[Plugin_046_bytepointer] = Plugin_046_receivedData;
|
||||
Plugin_046_bytepointer++; // TReady for the next byte ...
|
||||
if (Plugin_046_bytepointer > Plugin_046_RAW_BUFFER_SIZE) {
|
||||
Plugin_046_RecieveActive = false; // We don't want a bufferoverflow, so abort
|
||||
Plugin_046_ReceiveActive = false; // We don't want a bufferoverflow, so abort
|
||||
Plugin_046_MasterSlave = false;
|
||||
}
|
||||
} else {
|
||||
|
||||
+92
-25
@@ -17,13 +17,19 @@
|
||||
#define PLUGIN_VALUENAME3_049 "U" // Undocumented, minimum measurement per time period?
|
||||
#define PLUGIN_READ_TIMEOUT 3000
|
||||
|
||||
#define PLUGIN_049_FILTER_OFF 1
|
||||
#define PLUGIN_049_FILTER_OFF_ALLSAMPLES 2
|
||||
#define PLUGIN_049_FILTER_FAST 3
|
||||
#define PLUGIN_049_FILTER_MEDIUM 4
|
||||
#define PLUGIN_049_FILTER_SLOW 5
|
||||
|
||||
boolean Plugin_049_init = false;
|
||||
// Default of the sensor is to run ABC
|
||||
boolean Plugin_049_ABC_Disable = false;
|
||||
boolean Plugin_049_ABC_MustApply = false;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial *Plugin_049_SoftSerial;
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
ESPeasySoftwareSerial *Plugin_049_SoftSerial;
|
||||
|
||||
// 9-bytes CMD PPM read command
|
||||
byte mhzCmdReadPPM[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
|
||||
@@ -43,6 +49,56 @@ enum
|
||||
ABC_disabled = 0x02
|
||||
};
|
||||
|
||||
boolean Plugin_049_Check_and_ApplyFilter(unsigned int prevVal, unsigned int &newVal, uint32_t s, const int filterValue, String& log) {
|
||||
if (s == 1) {
|
||||
// S==1 => "A" version sensor bootup, do not use values.
|
||||
return false;
|
||||
}
|
||||
if (prevVal < 400 || prevVal > 5000) {
|
||||
// Prevent unrealistic values during start-up with filtering enabled.
|
||||
// Just assume the entered value is correct.
|
||||
return true;
|
||||
}
|
||||
boolean filterApplied = filterValue > PLUGIN_049_FILTER_OFF_ALLSAMPLES;
|
||||
int32_t difference = newVal - prevVal;
|
||||
if (s > 0 && s < 64 && filterValue != PLUGIN_049_FILTER_OFF) {
|
||||
// Not the "B" version of the sensor, S value is used.
|
||||
// S==0 => "B" version, else "A" version
|
||||
// The S value is an indication of the stability of the reading.
|
||||
// S == 64 represents a stable reading and any lower value indicates (unusual) fast change.
|
||||
// Now we increase the delay filter for low values of S and increase response time when the
|
||||
// value is more stable.
|
||||
// This will make the reading useful in more turbulent environments,
|
||||
// where the sensor would report more rapid change of measured values.
|
||||
difference = difference * s;
|
||||
difference /= 64;
|
||||
log += F("Compensate Unstable ");
|
||||
filterApplied = true;
|
||||
}
|
||||
switch (filterValue) {
|
||||
case PLUGIN_049_FILTER_OFF: {
|
||||
if (s != 0 && s != 64) {
|
||||
log += F("Skip Unstable ");
|
||||
return false;
|
||||
}
|
||||
filterApplied = false;
|
||||
break;
|
||||
}
|
||||
// #Samples to reach >= 75% of step response
|
||||
case PLUGIN_049_FILTER_OFF_ALLSAMPLES: filterApplied = false; break; // No Delay
|
||||
case PLUGIN_049_FILTER_FAST: difference /= 2; break; // Delay: 2 samples
|
||||
case PLUGIN_049_FILTER_MEDIUM: difference /= 4; break; // Delay: 5 samples
|
||||
case PLUGIN_049_FILTER_SLOW: difference /= 8; break; // Delay: 11 samples
|
||||
}
|
||||
if (filterApplied) {
|
||||
log += F("Raw PPM: ");
|
||||
log += newVal;
|
||||
log += F(" Filtered ");
|
||||
}
|
||||
newVal = static_cast<unsigned int>(prevVal + difference);
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
bool success = false;
|
||||
@@ -86,6 +142,16 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
String options[2] = { F("Normal"), F("ABC disabled") };
|
||||
int optionValues[2] = { ABC_enabled, ABC_disabled };
|
||||
addFormSelector(string, F("Auto Base Calibration"), F("plugin_049_abcdisable"), 2, options, optionValues, choice);
|
||||
byte choiceFilter = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
String filteroptions[5] = { F("Skip Unstable"), F("Use Unstable"), F("Fast Response"), F("Medium Response"), F("Slow Response") };
|
||||
int filteroptionValues[5] = {
|
||||
PLUGIN_049_FILTER_OFF,
|
||||
PLUGIN_049_FILTER_OFF_ALLSAMPLES,
|
||||
PLUGIN_049_FILTER_FAST,
|
||||
PLUGIN_049_FILTER_MEDIUM,
|
||||
PLUGIN_049_FILTER_SLOW };
|
||||
addFormSelector(string, F("Filter"), F("plugin_049_filter"), 5, filteroptions, filteroptionValues, choiceFilter);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -100,6 +166,8 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
Plugin_049_ABC_Disable = new_ABC_disable;
|
||||
}
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = formValue;
|
||||
const int filterValue = getFormItemInt(F("plugin_049_filter"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = filterValue;
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
@@ -111,7 +179,7 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
// No guarantee the correct state is active on the sensor after reboot.
|
||||
Plugin_049_ABC_MustApply = true;
|
||||
}
|
||||
Plugin_049_SoftSerial = new SoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
|
||||
Plugin_049_SoftSerial = new ESPeasySoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], false, 18);
|
||||
Plugin_049_SoftSerial->begin(9600);
|
||||
addLog(LOG_LEVEL_INFO, F("MHZ19: Init OK "));
|
||||
|
||||
@@ -288,32 +356,31 @@ boolean Plugin_049(byte function, struct EventStruct *event, String& string)
|
||||
log += F("Will disable ABC when bootup complete. ");
|
||||
}
|
||||
success = false;
|
||||
|
||||
// If s = 0x40 the reading is stable; anything else should be ignored
|
||||
} else if (s > 0 && s < 64) {
|
||||
|
||||
log += F("Unstable reading, ignoring! ");
|
||||
success = false;
|
||||
|
||||
// Finally, stable readings are used for variables
|
||||
} else {
|
||||
|
||||
UserVar[event->BaseVarIndex] = (float)ppm;
|
||||
UserVar[event->BaseVarIndex + 1] = (float)temp;
|
||||
UserVar[event->BaseVarIndex + 2] = (float)u;
|
||||
if (Plugin_049_ABC_MustApply) {
|
||||
// Send ABC enable/disable command based on the desired state.
|
||||
if (Plugin_049_ABC_Disable) {
|
||||
Plugin_049_SoftSerial->write(mhzCmdABCDisable, 9);
|
||||
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Disable!"));
|
||||
} else {
|
||||
Plugin_049_SoftSerial->write(mhzCmdABCEnable, 9);
|
||||
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Enable!"));
|
||||
const int filterValue = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
if (Plugin_049_Check_and_ApplyFilter(UserVar[event->BaseVarIndex], ppm, s, filterValue, log)) {
|
||||
UserVar[event->BaseVarIndex] = (float)ppm;
|
||||
UserVar[event->BaseVarIndex + 1] = (float)temp;
|
||||
UserVar[event->BaseVarIndex + 2] = (float)u;
|
||||
if (s==0 || s==64) {
|
||||
// Reading is stable.
|
||||
if (Plugin_049_ABC_MustApply) {
|
||||
// Send ABC enable/disable command based on the desired state.
|
||||
if (Plugin_049_ABC_Disable) {
|
||||
Plugin_049_SoftSerial->write(mhzCmdABCDisable, 9);
|
||||
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Disable!"));
|
||||
} else {
|
||||
Plugin_049_SoftSerial->write(mhzCmdABCEnable, 9);
|
||||
addLog(LOG_LEVEL_INFO, F("MHZ19: Sent sensor ABC Enable!"));
|
||||
}
|
||||
Plugin_049_ABC_MustApply = false;
|
||||
}
|
||||
}
|
||||
Plugin_049_ABC_MustApply = false;
|
||||
success = true;
|
||||
} else {
|
||||
success = false;
|
||||
}
|
||||
success = true;
|
||||
|
||||
}
|
||||
|
||||
// Log values in all cases
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Plugin originally written by: Daniel Tedenljung info__AT__tedenljungconsulting.com
|
||||
Rewritten by: Mikael Trieb mikael__AT__triebconsulting.se
|
||||
|
||||
This plugin reads availble values of Senseair Co2 Sensors.
|
||||
This plugin reads available values of Senseair Co2 Sensors.
|
||||
Datasheet can be found here:
|
||||
S8: http://www.senseair.com/products/oem-modules/senseair-s8/
|
||||
K30: http://www.senseair.com/products/oem-modules/k30/
|
||||
@@ -24,8 +24,8 @@
|
||||
|
||||
boolean Plugin_052_init = false;
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial *Plugin_052_SoftSerial;
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
ESPeasySoftwareSerial *Plugin_052_SoftSerial;
|
||||
|
||||
boolean Plugin_052(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
@@ -130,7 +130,7 @@ boolean Plugin_052(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
Plugin_052_init = true;
|
||||
Plugin_052_SoftSerial = new SoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex],
|
||||
Plugin_052_SoftSerial = new ESPeasySoftwareSerial(Settings.TaskDevicePin1[event->TaskIndex],
|
||||
Settings.TaskDevicePin2[event->TaskIndex]);
|
||||
|
||||
/*
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
//
|
||||
// http://www.aqmd.gov/docs/default-source/aq-spec/resources-page/plantower-pms5003-manual_v2-3.pdf?sfvrsn=2
|
||||
//
|
||||
// The PMSx003 are particle sensors. Particles are measured by blowing air though the enclosue and,
|
||||
// togther with a laser, count the amount of particles. These sensors have an integrated microcontroller
|
||||
// The PMSx003 are particle sensors. Particles are measured by blowing air through the enclosure and,
|
||||
// together with a laser, count the amount of particles. These sensors have an integrated microcontroller
|
||||
// that counts particles and transmits measurement data over the serial connection.
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
#define PLUGIN_053
|
||||
#define PLUGIN_ID_053 53
|
||||
@@ -22,7 +22,7 @@
|
||||
#define PMSx003_SIG2 0X4d
|
||||
#define PMSx003_SIZE 32
|
||||
|
||||
SoftwareSerial *swSerial = NULL;
|
||||
ESPeasySoftwareSerial *swSerial = NULL;
|
||||
boolean Plugin_053_init = false;
|
||||
boolean values_received = false;
|
||||
|
||||
@@ -171,7 +171,7 @@ boolean Plugin_053(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
log = F("PMSx003: using software serial");
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
swSerial = new SoftwareSerial(rxPin, txPin);
|
||||
swSerial = new ESPeasySoftwareSerial(rxPin, txPin);
|
||||
swSerial->begin(9600);
|
||||
swSerial->flush();
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
// DMX,5=123,8=44" Set channel 5 to value 123, channel 8 to 44
|
||||
// DMX,OFF" Pitch Black
|
||||
|
||||
// Transeiver:
|
||||
// Transceiver:
|
||||
// SN75176 or MAX485 or LT1785 or ...
|
||||
// Pin 5: GND
|
||||
// Pin 2, 3, 5: +5V
|
||||
@@ -134,8 +134,9 @@ boolean Plugin_054(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
string.toLowerCase();
|
||||
String command = parseString(string, 1);
|
||||
String lowerString=string;
|
||||
lowerString.toLowerCase();
|
||||
String command = parseString(lowerString, 1);
|
||||
|
||||
if (command == F("dmx"))
|
||||
{
|
||||
@@ -146,11 +147,11 @@ boolean Plugin_054(byte function, struct EventStruct *event, String& string)
|
||||
int16_t channel = 1;
|
||||
int16_t value = 0;
|
||||
|
||||
string.replace(" ", " ");
|
||||
string.replace(" =", "=");
|
||||
string.replace("= ", "=");
|
||||
lowerString.replace(" ", " ");
|
||||
lowerString.replace(" =", "=");
|
||||
lowerString.replace("= ", "=");
|
||||
|
||||
param = parseString(string, paramIdx++);
|
||||
param = parseString(lowerString, paramIdx++);
|
||||
if (param.length())
|
||||
{
|
||||
while (param.length())
|
||||
@@ -211,7 +212,7 @@ boolean Plugin_054(byte function, struct EventStruct *event, String& string)
|
||||
channel++;
|
||||
}
|
||||
|
||||
param = parseString(string, paramIdx++);
|
||||
param = parseString(lowerString, paramIdx++);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//#################################### Plugin 055: Chiming Mechanism ####################################
|
||||
//#######################################################################################################
|
||||
|
||||
// ESPEasy plugin to strike up to 4 pysical bells and gongs with chiming sequences.
|
||||
// ESPEasy plugin to strike up to 4 physical bells and gongs with chiming sequences.
|
||||
// You also can use an antique door bell as a single strikes (not ringing) notification.
|
||||
// Optional you can use it as hourly chiming clock
|
||||
// written by Jochen Krapf (jk@nerd2nerd.org)
|
||||
@@ -37,8 +37,8 @@
|
||||
// save tokens with name "<HH><MM>" and enable NTP (advanced settings)
|
||||
//
|
||||
// examples:
|
||||
// CHIMESAVE,0815,1111! Dayly Alarm at 8:15am
|
||||
// CHIMESAVE,2015,11121 Dayly Alarm at 8:15pm
|
||||
// CHIMESAVE,0815,1111! Daily Alarm at 8:15am
|
||||
// CHIMESAVE,2015,11121 Daily Alarm at 8:15pm
|
||||
// CHIMESAVE,2015 Delete Alarm at 8:15pm
|
||||
|
||||
// Electronics:
|
||||
|
||||
+83
-15
@@ -33,7 +33,7 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_056;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_SINGLE;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_DUAL;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_DUAL;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
@@ -42,7 +42,7 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
|
||||
Device[deviceCount].ValueCount = 2;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].TimerOptional = true;
|
||||
Device[deviceCount].TimerOptional = false;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
@@ -59,11 +59,34 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_056));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
if (Plugin_056_hasTxPin(event)) {
|
||||
addFormNumericBox(string, F("Sleep time"), F("plugin_056_sleeptime"),
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0],
|
||||
0, 30);
|
||||
addUnit(string, F("Minutes"));
|
||||
addFormNote(string, F("0 = continous, 1..30 = Work 30 seconds and sleep n*60-30 seconds"));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
if (Plugin_056_hasTxPin(event)) {
|
||||
// Communications to device should work.
|
||||
const int newsleeptime = getFormItemInt(F("plugin_056_sleeptime"));
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][0] != newsleeptime) {
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_056_sleeptime"));
|
||||
Plugin_056_setWorkingPeriod(newsleeptime);
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
case PLUGIN_GET_DEVICEGPIONAMES:
|
||||
{
|
||||
event->String1 = F("GPIO ← TX");
|
||||
//event->String2 = F("GPIO ⇢ RX (optional)");
|
||||
event->String2 = F("GPIO ⇢ RX (optional)");
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -71,8 +94,14 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
if (Plugin_056_SDS)
|
||||
delete Plugin_056_SDS;
|
||||
Plugin_056_SDS = new CjkSDS011(Settings.TaskDevicePin1[event->TaskIndex], -1);
|
||||
addLog(LOG_LEVEL_INFO, F("SDS : Init OK "));
|
||||
const int16_t serial_rx = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
const int16_t serial_tx = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
Plugin_056_SDS = new CjkSDS011(serial_rx, serial_tx);
|
||||
String log = F("SDS : Init OK ESP GPIO-pin RX:");
|
||||
log += serial_rx;
|
||||
log += F(" TX:");
|
||||
log += serial_tx;
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
|
||||
success = true;
|
||||
break;
|
||||
@@ -98,16 +127,18 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
if (Plugin_056_SDS->available())
|
||||
{
|
||||
const float pm2_5 = Plugin_056_SDS->GetPM2_5();
|
||||
const float pm10 = Plugin_056_SDS->GetPM10_();
|
||||
String log = F("SDS : act ");
|
||||
log += Plugin_056_SDS->GetPM2_5();
|
||||
log += pm2_5;
|
||||
log += F(" ");
|
||||
log += Plugin_056_SDS->GetPM10_();
|
||||
log += pm10;
|
||||
addLog(LOG_LEVEL_DEBUG, log);
|
||||
|
||||
if (Settings.TaskDeviceTimer[event->TaskIndex] == 0)
|
||||
{
|
||||
UserVar[event->BaseVarIndex + 0] = Plugin_056_SDS->GetPM2_5();
|
||||
UserVar[event->BaseVarIndex + 1] = Plugin_056_SDS->GetPM10_();
|
||||
UserVar[event->BaseVarIndex + 0] = pm2_5;
|
||||
UserVar[event->BaseVarIndex + 1] = pm10;
|
||||
event->sensorType = SENSOR_TYPE_DUAL;
|
||||
sendData(event);
|
||||
}
|
||||
@@ -123,11 +154,11 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
|
||||
break;
|
||||
|
||||
float pm25, pm10;
|
||||
Plugin_056_SDS->ReadAverage(pm25, pm10);
|
||||
|
||||
UserVar[event->BaseVarIndex + 0] = pm25;
|
||||
UserVar[event->BaseVarIndex + 1] = pm10;
|
||||
success = true;
|
||||
if (Plugin_056_SDS->ReadAverage(pm25, pm10)) {
|
||||
UserVar[event->BaseVarIndex + 0] = pm25;
|
||||
UserVar[event->BaseVarIndex + 1] = pm10;
|
||||
success = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -135,4 +166,41 @@ boolean Plugin_056(byte function, struct EventStruct *event, String& string)
|
||||
return success;
|
||||
}
|
||||
|
||||
boolean Plugin_056_hasTxPin(struct EventStruct *event) {
|
||||
const int16_t serial_tx = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
return serial_tx >= 0;
|
||||
}
|
||||
|
||||
String Plugin_056_ErrorToString(int error) {
|
||||
String log;
|
||||
if (error < 0) {
|
||||
log = F("comm error: ");
|
||||
log += error;
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
String Plugin_056_WorkingPeriodToString(int workingPeriod) {
|
||||
if (workingPeriod < 0) {
|
||||
return Plugin_056_ErrorToString(workingPeriod);
|
||||
}
|
||||
String log;
|
||||
if (workingPeriod > 0) {
|
||||
log += workingPeriod;
|
||||
log += F(" minutes");
|
||||
} else {
|
||||
log += F(" continuous");
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
void Plugin_056_setWorkingPeriod(int minutes) {
|
||||
if (!Plugin_056_SDS)
|
||||
return;
|
||||
Plugin_056_SDS->SetWorkingPeriod(minutes);
|
||||
String log = F("SDS : Working Period set to: ");
|
||||
log += Plugin_056_WorkingPeriodToString(minutes);
|
||||
addLog(LOG_LEVEL_INFO, log);
|
||||
}
|
||||
|
||||
#endif //PLUGIN_BUILD_TESTING
|
||||
|
||||
+12
-11
@@ -150,13 +150,14 @@ boolean Plugin_057(byte function, struct EventStruct *event, String& string)
|
||||
if (!Plugin_057_M)
|
||||
return false;
|
||||
|
||||
string.toLowerCase();
|
||||
String command = parseString(string, 1);
|
||||
String lowerString=string;
|
||||
lowerString.toLowerCase();
|
||||
String command = parseString(lowerString, 1);
|
||||
|
||||
if (command == F("mprint"))
|
||||
{
|
||||
int paramPos = getParamStartPos(string, 2);
|
||||
String text = string.substring(paramPos);
|
||||
int paramPos = getParamStartPos(lowerString, 2);
|
||||
String text = lowerString.substring(paramPos);
|
||||
byte seg = 0;
|
||||
|
||||
Plugin_057_M->ClearRowBuffer();
|
||||
@@ -171,8 +172,8 @@ boolean Plugin_057(byte function, struct EventStruct *event, String& string)
|
||||
success = true;
|
||||
}
|
||||
else if (command == F("mbr")) {
|
||||
int paramPos = getParamStartPos(string, 2);
|
||||
uint8_t brightness = string.substring(paramPos).toInt();
|
||||
int paramPos = getParamStartPos(lowerString, 2);
|
||||
uint8_t brightness = lowerString.substring(paramPos).toInt();
|
||||
Plugin_057_M->SetBrightness(brightness);
|
||||
success = true;
|
||||
}
|
||||
@@ -185,11 +186,11 @@ boolean Plugin_057(byte function, struct EventStruct *event, String& string)
|
||||
uint8_t seg = 0;
|
||||
uint16_t value = 0;
|
||||
|
||||
string.replace(" ", " ");
|
||||
string.replace(" =", "=");
|
||||
string.replace("= ", "=");
|
||||
lowerString.replace(" ", " ");
|
||||
lowerString.replace(" =", "=");
|
||||
lowerString.replace("= ", "=");
|
||||
|
||||
param = parseString(string, paramIdx++);
|
||||
param = parseString(lowerString, paramIdx++);
|
||||
if (param.length())
|
||||
{
|
||||
while (param.length())
|
||||
@@ -259,7 +260,7 @@ boolean Plugin_057(byte function, struct EventStruct *event, String& string)
|
||||
seg++;
|
||||
}
|
||||
|
||||
param = parseString(string, paramIdx++);
|
||||
param = parseString(lowerString, paramIdx++);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -7,17 +7,16 @@
|
||||
|
||||
// Connection:
|
||||
// Use 1st and 2nd GPIO for encoders A and B signal.
|
||||
// Optional use 3rd GPIO for encoders I signel to reset counter to 0 at first trigger.
|
||||
// Optional use 3rd GPIO for encoders I signal to reset counter to 0 at first trigger.
|
||||
// If counter runs in wrong direction, change A and B GPIOs in settings page
|
||||
|
||||
// Note: Up to 4 encoders can be used simultaniously
|
||||
// Note: Up to 4 encoders can be used simultaneously
|
||||
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define PLUGIN_059
|
||||
#define PLUGIN_ID_059 59
|
||||
#define PLUGIN_NAME_059 "Switch Input - Rotary Encoder [TESTING]"
|
||||
#define PLUGIN_NAME_059 "Switch Input - Rotary Encoder"
|
||||
#define PLUGIN_VALUENAME1_059 "Counter"
|
||||
|
||||
#include <QEIx4.h>
|
||||
@@ -170,5 +169,3 @@ boolean Plugin_059(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
// ESPEasy Plugin to scan a 16 key touch pad chip TTP229
|
||||
// written by Jochen Krapf (jk@nerd2nerd.org)
|
||||
|
||||
// Important: There are several types of TTP299 chips with different features available. They are namead all TTP229 but differ in the letter(s) followed.
|
||||
// On the china boards (found on eBay and AliExpress) the TTP229-B is used which has NO! I2C-interface. It uses a properitary serial protocol with clock (SCL) and bidirectional data (SDO)
|
||||
// Important: There are several types of TTP299 chips with different features available. They are named all TTP229 but differ in the letter(s) followed.
|
||||
// On the china boards (found on eBay and AliExpress) the TTP229-B is used which has NO! I2C-interface. It uses a proprietary serial protocol with clock (SCL) and bidirectional data (SDO)
|
||||
|
||||
// ScanCode;
|
||||
// Value 1...16 for the key number
|
||||
@@ -19,15 +19,12 @@
|
||||
// Electronics:
|
||||
// Connect SCL to 1st GPIO and SDO to 2nd GPIO. Use 3.3 volt for VCC.
|
||||
// Set the jumper for 16 key mode (TP2=jumper3). Additional set jumper for multi-key (TP3=jumper4, TP4=jumper5).
|
||||
// Scematics: https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/TTP229B-Schematic-Diagram.pdf
|
||||
// Schematics: https://www.openimpulse.com/blog/wp-content/uploads/wpsc/downloadables/TTP229B-Schematic-Diagram.pdf
|
||||
// Datasheet: http://www.datasheet4u.com/download_new.php?id=996751
|
||||
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define PLUGIN_063
|
||||
#define PLUGIN_ID_063 63
|
||||
#define PLUGIN_NAME_063 "Keypad - TTP229 Touch [TESTING]"
|
||||
#define PLUGIN_NAME_063 "Keypad - TTP229 Touch"
|
||||
#define PLUGIN_VALUENAME1_063 "ScanCode"
|
||||
|
||||
// #include <*.h> no lib required
|
||||
@@ -207,5 +204,3 @@ boolean Plugin_063(byte function, struct EventStruct *event, String& string)
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+11
-10
@@ -5,20 +5,20 @@
|
||||
// ESPEasy Plugin to controls a MP3-player-module DFPlayer-Mini SKU:DFR0299
|
||||
// written by Jochen Krapf (jk@nerd2nerd.org)
|
||||
|
||||
// Important! The module WTV020-SD look similar to the module DFPlayer-Mini but is NOT pin and command compatible!
|
||||
// Important! The module WTV020-SD look similar to the module DFPlayer-Mini but is NOT pin nor command compatible!
|
||||
|
||||
// Commands:
|
||||
// play,<track> Plays the n-th track 1...3000 on SD-card in root folder. The track number is the physical ordenr - not the order displayed in file explorer!
|
||||
// play,<track> Plays the n-th track 1...3000 on SD-card in root folder. The track number is the physical order - not the order displayed in file explorer!
|
||||
// stop Stops actual playing sound
|
||||
// vol,<volume> Set volume level 1...30
|
||||
// eq,<type> Set the equalizer type 0=Normal, 1=Pop, 2=Rock, 3=Jazz, 4=classic, 5=Base
|
||||
|
||||
// Circuit wiring
|
||||
// 1st-GPIO -> ESP TX to module RX [Pin2]
|
||||
// 5V to module VCC [Pin1] (can be more than 100mA) Note: Use a capacitor to denoise VCC
|
||||
// 5 V to module VCC [Pin1] (can be more than 100 mA) Note: Use a blocking capacitor to stabilise VCC
|
||||
// GND to module GND [Pin7+Pin10]
|
||||
// Speaker to module SPK_1 and SPK_2 [Pin6,Pin8] (not to GND!) Note: If speaker has to low impedance, use a resistor (like 33 Ohm) in line to speaker
|
||||
// (optional) module BUSY [Pin16] to LED driver (3.3V on idle, 0V on playing)
|
||||
// (optional) module BUSY [Pin16] to LED driver (3.3 V on idle, 0 V on playing)
|
||||
// All other pins unconnected
|
||||
|
||||
// Note: Notification sounds with Creative Commons Attribution license: https://notificationsounds.com/
|
||||
@@ -33,7 +33,7 @@
|
||||
#define PLUGIN_NAME_065 "Notify - DFPlayer-Mini MP3 [TESTING]"
|
||||
#define PLUGIN_VALUENAME1_065 ""
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
|
||||
#ifndef CONFIG
|
||||
#define CONFIG(n) (Settings.TaskDevicePluginConfig[event->TaskIndex][n])
|
||||
@@ -42,7 +42,7 @@
|
||||
#define PIN(n) (Settings.TaskDevicePin[n][event->TaskIndex])
|
||||
#endif
|
||||
|
||||
SoftwareSerial* Plugin_065_SoftSerial = NULL;
|
||||
ESPeasySoftwareSerial* Plugin_065_SoftSerial = NULL;
|
||||
|
||||
|
||||
boolean Plugin_065(byte function, struct EventStruct *event, String& string)
|
||||
@@ -106,7 +106,7 @@ boolean Plugin_065(byte function, struct EventStruct *event, String& string)
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
|
||||
Plugin_065_SoftSerial = new SoftwareSerial(-1, PIN(0)); // no RX, only TX
|
||||
Plugin_065_SoftSerial = new ESPeasySoftwareSerial(-1, PIN(0)); // no RX, only TX
|
||||
|
||||
Plugin_065_SoftSerial->begin(9600);
|
||||
|
||||
@@ -121,9 +121,10 @@ boolean Plugin_065(byte function, struct EventStruct *event, String& string)
|
||||
if (!Plugin_065_SoftSerial)
|
||||
break;
|
||||
|
||||
string.toLowerCase();
|
||||
String command = parseString(string, 1);
|
||||
String param = parseString(string, 2);
|
||||
String lowerString=string;
|
||||
lowerString.toLowerCase();
|
||||
String command = parseString(lowerString, 1);
|
||||
String param = parseString(lowerString, 2);
|
||||
|
||||
if (command == F("play"))
|
||||
{
|
||||
|
||||
@@ -266,8 +266,9 @@ boolean Plugin_067(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
string.toLowerCase();
|
||||
String command = parseString(string, 1);
|
||||
String lowerString=string;
|
||||
lowerString.toLowerCase();
|
||||
String command = parseString(lowerString, 1);
|
||||
|
||||
if (command == F("tare"))
|
||||
{
|
||||
|
||||
@@ -144,11 +144,12 @@ boolean Plugin_070(byte function, struct EventStruct *event, String& string)
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
string.toLowerCase();
|
||||
String command = parseString(string, 1);
|
||||
String param1 = parseString(string, 2);
|
||||
String param2 = parseString(string, 3);
|
||||
String param3 = parseString(string, 4);
|
||||
String lowerString=string;
|
||||
lowerString.toLowerCase();
|
||||
String command = parseString(lowerString, 1);
|
||||
String param1 = parseString(lowerString, 2);
|
||||
String param2 = parseString(lowerString, 3);
|
||||
String param3 = parseString(lowerString, 4);
|
||||
|
||||
if (command == F("clock")) {
|
||||
if (param1 != "") {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#include <SoftwareSerial.h>
|
||||
#include <ESPeasySoftwareSerial.h>
|
||||
#define PLUGIN_071
|
||||
#define PLUGIN_ID_071 71
|
||||
#define PLUGIN_NAME_071 "Communication - Kamstrup Multical 401 [TESTING]"
|
||||
@@ -76,7 +76,7 @@ boolean Plugin_071(byte function, struct EventStruct *event, String& string)
|
||||
PIN_KAMSER_RX = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
PIN_KAMSER_TX = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
|
||||
SoftwareSerial kamSer(PIN_KAMSER_RX, PIN_KAMSER_TX, false); // Initialize serial
|
||||
ESPeasySoftwareSerial kamSer(PIN_KAMSER_RX, PIN_KAMSER_TX, false); // Initialize serial
|
||||
|
||||
pinMode(PIN_KAMSER_RX,INPUT);
|
||||
pinMode(PIN_KAMSER_TX,OUTPUT);
|
||||
|
||||
@@ -0,0 +1,628 @@
|
||||
//#######################################################################################################
|
||||
//################### Plugin 073 - 7-segment display plugin TM1637/MAX7219 ######################
|
||||
//#######################################################################################################
|
||||
//
|
||||
// Chip supported:
|
||||
// - TM1637 -- 2 pins - 4 digits and colon in the middle (XX:XX)
|
||||
// - MAX7219/21 -- 3 pins - 8 digits and dot on each digit
|
||||
//
|
||||
// Plugin can be setup as:
|
||||
// - Manual -- display is manually updated sending commands
|
||||
// "7dn,<number>" (number can be negative or positive)
|
||||
// "7dt,<temperature>" (temperature can be negative or positive and containing decimals)
|
||||
// - Clock-Blink -- display is automatically updated with current time and blinking dot/lines
|
||||
// - Clock-NoBlink -- display is automatically updated with current time and steady dot/lines
|
||||
//
|
||||
// Generic commands:
|
||||
// - "7don" -- turn ON the display
|
||||
// - "7doff" -- turn OFF the display
|
||||
// - "7db,<0-15> -- set brightness to specifi value between 0 and 15
|
||||
//
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define PLUGIN_073
|
||||
#define PLUGIN_ID_073 73
|
||||
#define PLUGIN_NAME_073 "Display - 7-segment display [TESTING]"
|
||||
#define PLUGIN_073_DEBUG true //activate extra log info in the debug
|
||||
|
||||
//---------------------------------------------------
|
||||
// Class used by plugin
|
||||
//---------------------------------------------------
|
||||
class p073_7dgt
|
||||
{
|
||||
public:
|
||||
uint8_t pin1, pin2, pin3;
|
||||
byte type;
|
||||
byte output;
|
||||
byte brightness;
|
||||
boolean timesep;
|
||||
};
|
||||
p073_7dgt *Plugin_073_7dgt;
|
||||
//---------------------------------------------------
|
||||
|
||||
uint8_t p073_showbuffer[8];
|
||||
byte p073_spidata[2];
|
||||
byte p073_dotpos;
|
||||
|
||||
#define TM1637_POWER_ON 0b10001000
|
||||
#define TM1637_POWER_OFF 0b10000000
|
||||
|
||||
// each char table is specific for each display and maps all numbers/symbols needed:
|
||||
// - pos 0-9 - Numbers from 0 to 9
|
||||
// - pos 10 - Space " "
|
||||
// - pos 11 - minus symbol "-"
|
||||
// - pos 12 - degree symbol "°"
|
||||
const byte CharTableTM1637 [13] = {B00111111,B00000110,B01011011,B01001111,B01100110,B01101101,B01111101,B00000111,B01111111,B01101111,B00000000,B01000000,B01100011};
|
||||
const byte CharTableMAX7219 [13] = {B01111110,B00110000,B01101101,B01111001,B00110011,B01011011,B01011111,B01110000,B01111111,B01111011,B00000000,B00000001,B01100011};
|
||||
|
||||
boolean Plugin_073(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_073;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_TRIPLE;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_SWITCH;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = false;
|
||||
Device[deviceCount].ValueCount = 0;
|
||||
Device[deviceCount].SendDataOption = false;
|
||||
Device[deviceCount].TimerOption = false;
|
||||
Device[deviceCount].TimerOptional = false;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_073);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
addFormNote(string, F("TM1637: 1st=CLK-Pin, 2nd=DIO-Pin"));
|
||||
addFormNote(string, F("MAX7219: 1st=DIN-Pin, 2nd=CLK-Pin, 3rd=CS-Pin"));
|
||||
String displtype[3] = { F("TM1637 - 4 digit"), F("MAX7219 - 8 digit")};
|
||||
addFormSelector(string, F("Display Type"), F("plugin_073_displtype"), 2, displtype, NULL, Settings.TaskDevicePluginConfig[event->TaskIndex][0]);
|
||||
String displout[4] = { F("Manual"), F("Clock - Blink"), F("Clock - No Blink"), F("Date") };
|
||||
addFormSelector(string, F("Display Output"), F("plugin_073_displout"), 4, displout, NULL, Settings.TaskDevicePluginConfig[event->TaskIndex][1]);
|
||||
addFormNumericBox(string, F("Brightness"), F("plugin_073_brightness"), Settings.TaskDevicePluginConfig[event->TaskIndex][2], 0, 15);
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][0] = getFormItemInt(F("plugin_073_displtype"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][1] = getFormItemInt(F("plugin_073_displout"));
|
||||
Settings.TaskDevicePluginConfig[event->TaskIndex][2] = getFormItemInt(F("plugin_073_brightness"));
|
||||
if (Plugin_073_7dgt) {
|
||||
Plugin_073_7dgt->pin1 = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
Plugin_073_7dgt->pin2 = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
Plugin_073_7dgt->pin3 = Settings.TaskDevicePin3[event->TaskIndex];
|
||||
Plugin_073_7dgt->type = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
Plugin_073_7dgt->output = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
Plugin_073_7dgt->brightness = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
Plugin_073_7dgt->timesep = true;
|
||||
switch (Settings.TaskDevicePluginConfig[event->TaskIndex][0])
|
||||
{
|
||||
case 0: // set brightness of TM1637
|
||||
{
|
||||
int tm1637_bright = Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2;
|
||||
tm1637_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], tm1637_bright, true);
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 0)
|
||||
tm1637_ClearDisplay(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
|
||||
break;
|
||||
}
|
||||
case 1: // set brightness of MAX7219
|
||||
{
|
||||
max7219_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], Settings.TaskDevicePin3[event->TaskIndex], Settings.TaskDevicePluginConfig[event->TaskIndex][2], true);
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 0)
|
||||
max7219_ClearDisplay(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], Settings.TaskDevicePin3[event->TaskIndex]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
if (!Plugin_073_7dgt) {
|
||||
Plugin_073_7dgt = new p073_7dgt;
|
||||
Plugin_073_7dgt->pin1 = Settings.TaskDevicePin1[event->TaskIndex];
|
||||
Plugin_073_7dgt->pin2 = Settings.TaskDevicePin2[event->TaskIndex];
|
||||
Plugin_073_7dgt->pin3 = Settings.TaskDevicePin3[event->TaskIndex];
|
||||
Plugin_073_7dgt->type = Settings.TaskDevicePluginConfig[event->TaskIndex][0];
|
||||
Plugin_073_7dgt->output = Settings.TaskDevicePluginConfig[event->TaskIndex][1];
|
||||
Plugin_073_7dgt->brightness = Settings.TaskDevicePluginConfig[event->TaskIndex][2];
|
||||
switch (Settings.TaskDevicePluginConfig[event->TaskIndex][0])
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
tm1637_InitDisplay(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex]);
|
||||
int tm1637_bright = Settings.TaskDevicePluginConfig[event->TaskIndex][2] / 2;
|
||||
tm1637_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], tm1637_bright, true);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
max7219_InitDisplay(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], Settings.TaskDevicePin3[event->TaskIndex]);
|
||||
max7219_SetPowerBrightness(Settings.TaskDevicePin1[event->TaskIndex], Settings.TaskDevicePin2[event->TaskIndex], Settings.TaskDevicePin3[event->TaskIndex], Settings.TaskDevicePluginConfig[event->TaskIndex][2], true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WRITE:
|
||||
{
|
||||
if (!Plugin_073_7dgt)
|
||||
break;
|
||||
|
||||
String tmpString = string;
|
||||
int argIndex = tmpString.indexOf(',');
|
||||
if (argIndex)
|
||||
tmpString = tmpString.substring(0, argIndex);
|
||||
|
||||
String tmpStr = string;
|
||||
int comma1 = tmpStr.indexOf(',');
|
||||
|
||||
if (tmpString.equalsIgnoreCase(F("7dn"))) {
|
||||
if (Plugin_073_7dgt->output != 0)
|
||||
break;
|
||||
switch (Plugin_073_7dgt->type)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (event->Par1 > -1000 && event->Par1 < 10000)
|
||||
p073_FillBufferWithNumber(String(int(event->Par1)));
|
||||
else
|
||||
p073_FillBufferWithDash();
|
||||
tm1637_ShowBuffer(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (comma1 > 0) {
|
||||
if (event->Par1 > -10000000 && event->Par1 < 100000000) {
|
||||
p073_FillBufferWithNumber(tmpStr.substring(comma1+1).c_str());
|
||||
}
|
||||
else
|
||||
p073_FillBufferWithDash();
|
||||
max7219_ShowBuffer(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->pin3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (tmpString.equalsIgnoreCase(F("7dt"))) {
|
||||
if (Plugin_073_7dgt->output != 0)
|
||||
break;
|
||||
double p073_temptemp = 0;
|
||||
bool p073_tempflagdot = false;
|
||||
if (comma1 > 0)
|
||||
p073_temptemp = atof(tmpStr.substring(comma1+1).c_str());
|
||||
switch (Plugin_073_7dgt->type)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
if (p073_temptemp > 999 || p073_temptemp < -99.9)
|
||||
p073_FillBufferWithDash();
|
||||
else {
|
||||
if (p073_temptemp < 100 && p073_temptemp > -10) {
|
||||
p073_temptemp = int(p073_temptemp*10);
|
||||
p073_tempflagdot = true;
|
||||
}
|
||||
p073_FillBufferWithTemp(p073_temptemp);
|
||||
if (p073_temptemp == 0 && p073_tempflagdot)
|
||||
p073_showbuffer[5] = 0;
|
||||
}
|
||||
tm1637_ShowTimeTemp(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, p073_tempflagdot, 4);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
p073_temptemp = int(p073_temptemp*10);
|
||||
p073_FillBufferWithTemp(p073_temptemp);
|
||||
if (p073_temptemp == 0)
|
||||
p073_showbuffer[5] = 0;
|
||||
max7219_ShowTemp(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->pin3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
bool p073_validcmd = false;
|
||||
bool p073_displayon;
|
||||
if (tmpString.equalsIgnoreCase(F("7don"))) {
|
||||
p073_displayon = true;
|
||||
p073_validcmd = true;
|
||||
}
|
||||
else if (tmpString.equalsIgnoreCase(F("7doff"))) {
|
||||
p073_displayon = false;
|
||||
p073_validcmd = true;
|
||||
}
|
||||
else if (tmpString.equalsIgnoreCase(F("7db"))) {
|
||||
if (event->Par1 >= 0 && event->Par1 < 16) {
|
||||
Plugin_073_7dgt->brightness = event->Par1;
|
||||
p073_displayon = true;
|
||||
p073_validcmd = true;
|
||||
}
|
||||
}
|
||||
if (p073_validcmd) {
|
||||
switch (Plugin_073_7dgt->type)
|
||||
{
|
||||
case 0:
|
||||
{ int tm1637_bright = Plugin_073_7dgt->brightness / 2;
|
||||
tm1637_SetPowerBrightness(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, tm1637_bright, p073_displayon);
|
||||
break; }
|
||||
case 1:
|
||||
{ max7219_SetPowerBrightness(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->pin3, Plugin_073_7dgt->brightness, p073_displayon);
|
||||
break; }
|
||||
}
|
||||
}
|
||||
}
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_ONCE_A_SECOND:
|
||||
{
|
||||
if (Plugin_073_7dgt->output == 0)
|
||||
break;
|
||||
|
||||
if (Plugin_073_7dgt->output == 1)
|
||||
{ Plugin_073_7dgt->timesep = !Plugin_073_7dgt->timesep; }
|
||||
else
|
||||
{ Plugin_073_7dgt->timesep = true; }
|
||||
|
||||
if (Plugin_073_7dgt->output == 3)
|
||||
p073_FillBufferWithDate();
|
||||
else
|
||||
p073_FillBufferWithTime();
|
||||
|
||||
switch (Plugin_073_7dgt->type)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
tm1637_ShowTimeTemp(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->timesep, 0);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
if (Settings.TaskDevicePluginConfig[event->TaskIndex][1] == 3)
|
||||
max7219_ShowDate(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->pin3);
|
||||
else
|
||||
max7219_ShowTime(Plugin_073_7dgt->pin1, Plugin_073_7dgt->pin2, Plugin_073_7dgt->pin3, Plugin_073_7dgt->timesep);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void p073_FillBufferWithTime()
|
||||
{
|
||||
memset(p073_showbuffer,0,sizeof(p073_showbuffer));
|
||||
byte sevendgt_hours = hour();
|
||||
byte sevendgt_minutes = minute();
|
||||
byte sevendgt_seconds = second();
|
||||
uint8_t p073_digit1, p073_digit2;
|
||||
p073_digit1 = (uint8_t)(sevendgt_hours / 10);
|
||||
p073_digit2 = sevendgt_hours - p073_digit1*10;
|
||||
p073_showbuffer[0] = p073_digit1; p073_showbuffer[1] = p073_digit2;
|
||||
p073_digit1 = (uint8_t)(sevendgt_minutes / 10);
|
||||
p073_digit2 = sevendgt_minutes - p073_digit1*10;
|
||||
p073_showbuffer[2] = p073_digit1; p073_showbuffer[3] = p073_digit2;
|
||||
p073_digit1 = (uint8_t)(sevendgt_seconds / 10);
|
||||
p073_digit2 = sevendgt_seconds - p073_digit1*10;
|
||||
p073_showbuffer[4] = p073_digit1; p073_showbuffer[5] = p073_digit2;
|
||||
}
|
||||
|
||||
void p073_FillBufferWithDate()
|
||||
{
|
||||
memset(p073_showbuffer,0,sizeof(p073_showbuffer));
|
||||
byte sevendgt_day = day();
|
||||
byte sevendgt_month = month();
|
||||
byte sevendgt_year1 = uint8_t(year()/100);
|
||||
byte sevendgt_year2 = uint8_t(year()-(sevendgt_year1*100));
|
||||
uint8_t p073_digit1, p073_digit2;
|
||||
p073_digit1 = (uint8_t)(sevendgt_day / 10);
|
||||
p073_digit2 = sevendgt_day - p073_digit1*10;
|
||||
p073_showbuffer[0] = p073_digit1; p073_showbuffer[1] = p073_digit2;
|
||||
p073_digit1 = (uint8_t)(sevendgt_month / 10);
|
||||
p073_digit2 = sevendgt_month - p073_digit1*10;
|
||||
p073_showbuffer[2] = p073_digit1; p073_showbuffer[3] = p073_digit2;
|
||||
p073_digit1 = (uint8_t)(sevendgt_year1 / 10);
|
||||
p073_digit2 = sevendgt_year1 - p073_digit1*10;
|
||||
p073_showbuffer[4] = p073_digit1; p073_showbuffer[5] = p073_digit2;
|
||||
p073_digit1 = (uint8_t)(sevendgt_year2 / 10);
|
||||
p073_digit2 = sevendgt_year2 - p073_digit1*10;
|
||||
p073_showbuffer[6] = p073_digit1; p073_showbuffer[7] = p073_digit2;
|
||||
}
|
||||
|
||||
void p073_FillBufferWithNumber(String number)
|
||||
{
|
||||
memset(p073_showbuffer,10,sizeof(p073_showbuffer));
|
||||
byte p073_numlenght = number.length();
|
||||
byte p073_dispdigit;
|
||||
byte p073_index = 7;
|
||||
p073_dotpos = -1; // -1 means no dot to display
|
||||
for (int i=p073_numlenght;i>0;i--) {
|
||||
char p073_tmpchar = number.charAt(i-1);
|
||||
p073_dispdigit = 10; // default is space
|
||||
if (p073_tmpchar > 47 && p073_tmpchar < 58)
|
||||
p073_dispdigit = p073_tmpchar-48;
|
||||
else if (p073_tmpchar == 32) // space
|
||||
p073_dispdigit = 10;
|
||||
else if (p073_tmpchar == 45) // minus
|
||||
p073_dispdigit = 11;
|
||||
if (p073_tmpchar == 46) // dot
|
||||
p073_dotpos = p073_index;
|
||||
else {
|
||||
p073_showbuffer[p073_index] = p073_dispdigit;
|
||||
p073_index--; }
|
||||
}
|
||||
}
|
||||
|
||||
void p073_FillBufferWithTemp(long temperature)
|
||||
{
|
||||
memset(p073_showbuffer,10,sizeof(p073_showbuffer));
|
||||
char p073_digit[8];
|
||||
sprintf(p073_digit, "%7d", static_cast<int>(temperature));
|
||||
int p073_numlenght = strlen(p073_digit);
|
||||
byte p073_dispdigit;
|
||||
for (int i=0;i<p073_numlenght;i++) {
|
||||
if (p073_digit[i] > 47 && p073_digit[i] < 58)
|
||||
p073_dispdigit = p073_digit[i]-48;
|
||||
else if (p073_digit[i] == 32) // space
|
||||
p073_dispdigit = 10;
|
||||
else if (p073_digit[i] == 45) // minus
|
||||
p073_dispdigit = 11;
|
||||
p073_showbuffer[i] = p073_dispdigit;
|
||||
}
|
||||
p073_showbuffer[7] = 12; // degree "°"
|
||||
}
|
||||
|
||||
void p073_FillBufferWithDash() // in case of error show all dashes
|
||||
{
|
||||
memset(p073_showbuffer,11,sizeof(p073_showbuffer));
|
||||
}
|
||||
|
||||
//===================================
|
||||
//---- TM1637 specific functions ----
|
||||
//===================================
|
||||
|
||||
#define CLK_HIGH() digitalWrite(clk_pin, HIGH)
|
||||
#define CLK_LOW() digitalWrite(clk_pin, LOW)
|
||||
#define DIO_HIGH() pinMode(dio_pin, INPUT)
|
||||
#define DIO_LOW() pinMode(dio_pin, OUTPUT)
|
||||
|
||||
void tm1637_i2cStart (uint8_t clk_pin, uint8_t dio_pin)
|
||||
{
|
||||
CLK_HIGH();
|
||||
DIO_HIGH();
|
||||
delayMicroseconds(2);
|
||||
DIO_LOW();
|
||||
}
|
||||
|
||||
void tm1637_i2cStop (uint8_t clk_pin, uint8_t dio_pin)
|
||||
{
|
||||
CLK_LOW();
|
||||
delayMicroseconds(2);
|
||||
DIO_LOW();
|
||||
delayMicroseconds(2);
|
||||
CLK_HIGH();
|
||||
delayMicroseconds(2);
|
||||
DIO_HIGH();
|
||||
}
|
||||
|
||||
void tm1637_i2cAck (uint8_t clk_pin, uint8_t dio_pin)
|
||||
{
|
||||
CLK_LOW();
|
||||
DIO_HIGH();
|
||||
delayMicroseconds(5);
|
||||
while(digitalRead(dio_pin));
|
||||
CLK_HIGH();
|
||||
delayMicroseconds(2);
|
||||
CLK_LOW();
|
||||
}
|
||||
|
||||
void tm1637_i2cWrite (uint8_t clk_pin, uint8_t dio_pin, uint8_t bytetoprint)
|
||||
{
|
||||
uint8_t i;
|
||||
for(i=0; i<8; i++)
|
||||
{
|
||||
CLK_LOW();
|
||||
(bytetoprint & B00000001)? DIO_HIGH() : DIO_LOW();
|
||||
delayMicroseconds(3);
|
||||
bytetoprint = bytetoprint >> 1;
|
||||
CLK_HIGH();
|
||||
delayMicroseconds(3);
|
||||
}
|
||||
}
|
||||
|
||||
void tm1637_ClearDisplay (uint8_t clk_pin, uint8_t dio_pin)
|
||||
{
|
||||
tm1637_i2cStart(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, 0xC0);
|
||||
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
|
||||
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
|
||||
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
|
||||
tm1637_i2cAck(clk_pin, dio_pin); tm1637_i2cWrite(clk_pin, dio_pin, 0);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cStop(clk_pin, dio_pin);
|
||||
}
|
||||
|
||||
void tm1637_SetPowerBrightness (uint8_t clk_pin, uint8_t dio_pin, uint8_t brightlvl, bool poweron)
|
||||
{
|
||||
uint8_t brightvalue = (brightlvl & 0b111);
|
||||
if (poweron)
|
||||
brightvalue = TM1637_POWER_ON | brightvalue;
|
||||
else
|
||||
brightvalue = TM1637_POWER_OFF | brightvalue;
|
||||
tm1637_i2cStart(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, brightvalue);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cStop(clk_pin, dio_pin);
|
||||
}
|
||||
|
||||
void tm1637_InitDisplay(uint8_t clk_pin, uint8_t dio_pin)
|
||||
{
|
||||
pinMode(dio_pin, OUTPUT);
|
||||
digitalWrite(dio_pin, LOW);
|
||||
pinMode(dio_pin, INPUT_PULLUP);
|
||||
pinMode(clk_pin, OUTPUT);
|
||||
tm1637_i2cStart(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, 0x40);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cStop(clk_pin, dio_pin);
|
||||
tm1637_ClearDisplay(clk_pin, dio_pin);
|
||||
}
|
||||
|
||||
void tm1637_ShowTimeTemp(uint8_t clk_pin, uint8_t dio_pin, bool sep, byte bufoffset)
|
||||
{
|
||||
tm1637_i2cStart(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, 0xc0);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[0+bufoffset]]);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
// add bit for colon on second digit if required
|
||||
byte p073_datashowpos1 = CharTableTM1637[p073_showbuffer[1+bufoffset]];
|
||||
if (sep) p073_datashowpos1 |= 0b10000000;
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, p073_datashowpos1);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[2+bufoffset]]);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[3+bufoffset]]);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cStop(clk_pin, dio_pin);
|
||||
}
|
||||
|
||||
void tm1637_ShowBuffer(uint8_t clk_pin, uint8_t dio_pin)
|
||||
{
|
||||
tm1637_i2cStart(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, 0xc0);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[4]]);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[5]]);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[6]]);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cWrite(clk_pin, dio_pin, CharTableTM1637[p073_showbuffer[7]]);
|
||||
tm1637_i2cAck(clk_pin, dio_pin);
|
||||
tm1637_i2cStop(clk_pin, dio_pin);
|
||||
}
|
||||
|
||||
//====================================
|
||||
//---- MAX7219 specific functions ----
|
||||
//====================================
|
||||
|
||||
#define OP_DECODEMODE 9
|
||||
#define OP_INTENSITY 10
|
||||
#define OP_SCANLIMIT 11
|
||||
#define OP_SHUTDOWN 12
|
||||
#define OP_DISPLAYTEST 15
|
||||
|
||||
void max7219_spiTransfer (uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin, volatile byte opcode, volatile byte data)
|
||||
{
|
||||
p073_spidata[0]=(byte)0; p073_spidata[1]=(byte)0;
|
||||
p073_spidata[1]=opcode; p073_spidata[0]=data;
|
||||
digitalWrite(cs_pin,LOW);
|
||||
shiftOut(din_pin,clk_pin,MSBFIRST,p073_spidata[1]);
|
||||
shiftOut(din_pin,clk_pin,MSBFIRST,p073_spidata[0]);
|
||||
digitalWrite(cs_pin,HIGH);
|
||||
}
|
||||
|
||||
void max7219_ClearDisplay (uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin)
|
||||
{
|
||||
for(int i=0;i<8;i++) {
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, i+1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void max7219_SetPowerBrightness (uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin, uint8_t brightlvl, bool poweron)
|
||||
{
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, OP_INTENSITY, brightlvl);
|
||||
if (poweron)
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, OP_SHUTDOWN, 1);
|
||||
else
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, OP_SHUTDOWN, 0);
|
||||
}
|
||||
|
||||
void max7219_SetDigit(uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin, int dgtpos, byte dgtvalue, boolean showdot)
|
||||
{
|
||||
byte p073_tempvalue;
|
||||
p073_tempvalue = CharTableMAX7219[dgtvalue];
|
||||
if(showdot)
|
||||
p073_tempvalue |= 0b10000000;
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, dgtpos+1, p073_tempvalue);
|
||||
}
|
||||
|
||||
void max7219_InitDisplay(uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin)
|
||||
{
|
||||
pinMode(din_pin, OUTPUT);
|
||||
pinMode(clk_pin, OUTPUT);
|
||||
pinMode(cs_pin, OUTPUT);
|
||||
digitalWrite(cs_pin, HIGH);
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, OP_DISPLAYTEST, 0);
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, OP_SCANLIMIT, 7); // scanlimit setup to max at Init
|
||||
max7219_spiTransfer(din_pin, clk_pin, cs_pin, OP_DECODEMODE, 0);
|
||||
max7219_ClearDisplay(din_pin, clk_pin, cs_pin);
|
||||
max7219_SetPowerBrightness(din_pin, clk_pin, cs_pin,0,false);
|
||||
}
|
||||
|
||||
void max7219_ShowTime(uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin, bool sep)
|
||||
{
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 0, p073_showbuffer[5], false);
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 1, p073_showbuffer[4], false);
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 3, p073_showbuffer[3], false);
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 4, p073_showbuffer[2], false);
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 6, p073_showbuffer[1], false);
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 7, p073_showbuffer[0], false);
|
||||
if (sep) {
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 2, 11, false);
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 5, 11, false);
|
||||
}
|
||||
else {
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 2, 10, false);
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 5, 10, false);
|
||||
}
|
||||
}
|
||||
|
||||
void max7219_ShowTemp(uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin)
|
||||
{
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, 0, 10, false);
|
||||
byte dotflags[8] = {false,false,false,false,false,true,false,false};
|
||||
for(int i=1;i<8;i++)
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, i, p073_showbuffer[8-i], dotflags[8-i]);
|
||||
}
|
||||
|
||||
void max7219_ShowDate(uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin)
|
||||
{
|
||||
byte dotflags[8] = {false,true,false,true,false,false,false,false};
|
||||
for(int i=0;i<8;i++)
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, i, p073_showbuffer[7-i], dotflags[7-i]);
|
||||
}
|
||||
|
||||
void max7219_ShowBuffer(uint8_t din_pin, uint8_t clk_pin, uint8_t cs_pin)
|
||||
{
|
||||
byte dotflags[8] = {false,false,false,false,false,false,false,false};
|
||||
if (p073_dotpos >= 0) dotflags[p073_dotpos] = true;
|
||||
for(int i=0;i<8;i++)
|
||||
max7219_SetDigit(din_pin, clk_pin, cs_pin, i, p073_showbuffer[7-i], dotflags[7-i]);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,265 @@
|
||||
//#######################################################################################################
|
||||
//######################## Plugin 074 TSL2591 I2C Lux/IR Sensor #########################################
|
||||
//#######################################################################################################
|
||||
//
|
||||
// by: https://github.com/krikk
|
||||
// this plugin is based on the adafruit library
|
||||
// written based on version 1.0.2 from https://github.com/adafruit/Adafruit_TSL2591_Library
|
||||
// does need Adafruit Sensors Library
|
||||
// added lux calculation improvement https://github.com/adafruit/Adafruit_TSL2591_Library/issues/14
|
||||
// added fix for issue https://github.com/adafruit/Adafruit_TSL2591_Library/issues/17
|
||||
|
||||
#ifdef PLUGIN_BUILD_TESTING
|
||||
|
||||
#define PLUGIN_074
|
||||
#define PLUGIN_ID_074 74
|
||||
#define PLUGIN_NAME_074 "Light/Lux - TSL2591 [TESTING]"
|
||||
#define PLUGIN_VALUENAME1_074 "Lux"
|
||||
#define PLUGIN_VALUENAME2_074 "Full"
|
||||
#define PLUGIN_VALUENAME3_074 "Visible"
|
||||
#define PLUGIN_VALUENAME4_074 "IR"
|
||||
|
||||
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include "Adafruit_TSL2591.h"
|
||||
|
||||
#ifndef CONFIG
|
||||
#define CONFIG(n) (Settings.TaskDevicePluginConfig[event->TaskIndex][n])
|
||||
#endif
|
||||
|
||||
Adafruit_TSL2591 tsl;
|
||||
boolean TSL2591_initialized = false;
|
||||
|
||||
boolean Plugin_074(byte function, struct EventStruct *event, String& string)
|
||||
{
|
||||
boolean success = false;
|
||||
|
||||
switch (function)
|
||||
{
|
||||
case PLUGIN_DEVICE_ADD:
|
||||
{
|
||||
Device[++deviceCount].Number = PLUGIN_ID_074;
|
||||
Device[deviceCount].Type = DEVICE_TYPE_I2C;
|
||||
Device[deviceCount].Ports = 0;
|
||||
Device[deviceCount].VType = SENSOR_TYPE_QUAD;
|
||||
Device[deviceCount].PullUpOption = false;
|
||||
Device[deviceCount].InverseLogicOption = false;
|
||||
Device[deviceCount].FormulaOption = true;
|
||||
Device[deviceCount].ValueCount = 4;
|
||||
Device[deviceCount].SendDataOption = true;
|
||||
Device[deviceCount].TimerOption = true;
|
||||
Device[deviceCount].TimerOptional = false;
|
||||
Device[deviceCount].GlobalSyncOption = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICENAME:
|
||||
{
|
||||
string = F(PLUGIN_NAME_074);
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_GET_DEVICEVALUENAMES:
|
||||
{
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_074));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_074));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[2], PSTR(PLUGIN_VALUENAME3_074));
|
||||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[3], PSTR(PLUGIN_VALUENAME4_074));
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_LOAD:
|
||||
{
|
||||
int optionValues[1] = { TSL2591_ADDR };
|
||||
addFormSelectorI2C(string, F("plugin_074_i2c_addr"), 1, optionValues, TSL2591_ADDR); //Only for display I2C address
|
||||
|
||||
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS); // shortest integration time (bright light)
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
|
||||
// tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS); // longest integration time (dim light)
|
||||
|
||||
String optionsMode[6] = { F("100ms"), F("200ms"), F("300ms"), F("400ms"), F("500ms"), F("600ms") };
|
||||
addFormSelector(string, F("Integration Time"), F("plugin_074_itime"), 6, optionsMode, NULL, CONFIG(1));
|
||||
|
||||
|
||||
// TSL2591_GAIN_LOW = 0x00, // low gain (1x)
|
||||
// TSL2591_GAIN_MED = 0x10, // medium gain (25x)
|
||||
// TSL2591_GAIN_HIGH = 0x20, // medium gain (428x)
|
||||
// TSL2591_GAIN_MAX = 0x30, // max gain (9876x)
|
||||
|
||||
String optionsGain[4] = {
|
||||
F("low gain (1x)"),
|
||||
F("medium gain (25x)"),
|
||||
F("medium gain (428x)"),
|
||||
F("max gain (9876x)") };
|
||||
addFormSelector(string, F("Value Mapping"), F("plugin_074_gain"), 4, optionsGain, NULL, CONFIG(2));
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_WEBFORM_SAVE:
|
||||
{
|
||||
//CONFIG(0) = getFormItemInt(F("plugin_074_i2c_addr"));
|
||||
CONFIG(1) = getFormItemInt(F("plugin_074_itime"));
|
||||
CONFIG(2) = getFormItemInt(F("plugin_074_gain"));
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_INIT:
|
||||
{
|
||||
tsl = Adafruit_TSL2591(2591); // pass in a number for the sensor identifier (for your use later)
|
||||
|
||||
if (tsl.begin())
|
||||
{
|
||||
String log = F("TSL2591: Address: 0x");
|
||||
log += String(TSL2591_ADDR,HEX);
|
||||
|
||||
|
||||
// Changing the integration time gives you a longer time over which to sense light
|
||||
// longer timelines are slower, but are good in very low light situtations!
|
||||
switch (CONFIG(1))
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
{
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_100MS);
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_200MS);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_300MS);
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_400MS);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_500MS);
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
tsl.setTiming(TSL2591_INTEGRATIONTIME_600MS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
log += F(": Integration Time: ");
|
||||
log += String((tsl.getTiming() + 1) * 100, DEC);
|
||||
log += F(" ms");
|
||||
|
||||
|
||||
// You can change the gain on the fly, to adapt to brighter/dimmer light situations
|
||||
switch (CONFIG(2))
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
{
|
||||
tsl.setGain(TSL2591_GAIN_LOW); // 1x gain (bright light)
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
tsl.setGain(TSL2591_GAIN_MED); // 25x gain
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
tsl.setGain(TSL2591_GAIN_HIGH); // 428x gain
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
tsl.setGain(TSL2591_GAIN_MAX); // 9876x gain
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Display the gain and integration time for reference sake */
|
||||
log += (F(" Gain: "));
|
||||
tsl2591Gain_t gain = tsl.getGain();
|
||||
switch(gain)
|
||||
{
|
||||
case TSL2591_GAIN_LOW:
|
||||
log += F("1x (Low)");
|
||||
break;
|
||||
case TSL2591_GAIN_MED:
|
||||
log += F("25x (Medium)");
|
||||
break;
|
||||
case TSL2591_GAIN_HIGH:
|
||||
log += F("428x (High)");
|
||||
break;
|
||||
case TSL2591_GAIN_MAX:
|
||||
log += F("9876x (Max)");
|
||||
break;
|
||||
}
|
||||
|
||||
TSL2591_initialized = true;
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
TSL2591_initialized = false;
|
||||
addLog(LOG_LEVEL_ERROR,F("TSL2591: No sensor found ... check your wiring?"));
|
||||
}
|
||||
|
||||
|
||||
success = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case PLUGIN_READ:
|
||||
{
|
||||
if (TSL2591_initialized)
|
||||
{
|
||||
// Simple data read example. Just read the infrared, fullspecrtrum diode
|
||||
// or 'visible' (difference between the two) channels.
|
||||
// This can take 100-600 milliseconds! Uncomment whichever of the following you want to read
|
||||
float lux, full, visible, ir;
|
||||
visible = tsl.getLuminosity(TSL2591_VISIBLE);
|
||||
ir = tsl.getLuminosity(TSL2591_INFRARED);
|
||||
full = tsl.getLuminosity(TSL2591_FULLSPECTRUM);
|
||||
lux = tsl.calculateLuxf(full, ir); // get LUX
|
||||
|
||||
UserVar[event->BaseVarIndex + 0] = lux;
|
||||
UserVar[event->BaseVarIndex + 1] = full;
|
||||
UserVar[event->BaseVarIndex + 2] = visible;
|
||||
UserVar[event->BaseVarIndex + 3] = ir;
|
||||
|
||||
String log = F("TSL2591: Lux: ");
|
||||
log += String(lux);
|
||||
log += F(" Full: ");
|
||||
log += String(full);
|
||||
log += F(" Visible: ");
|
||||
log += String(visible);
|
||||
log += F(" IR: ");
|
||||
log += String(ir);
|
||||
addLog(LOG_LEVEL_INFO,log);
|
||||
}
|
||||
else {
|
||||
addLog(LOG_LEVEL_ERROR,F("TSL2591: Sensor not initialized!?"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user