Merge pull request #153 from biveraxe/ver4dev

Последние изменения перед возвращением
This commit is contained in:
2022-08-09 17:35:56 +03:00
committed by GitHub
142 changed files with 5431 additions and 1619 deletions

3
.gitignore vendored
View File

@@ -3,5 +3,4 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
lib/libraies-master
data_svelte/settings.json

179
PrepareProject.py Normal file
View File

@@ -0,0 +1,179 @@
# PrepareProject.py - инструмент для подготовки проекта к компиляции.
# Необходимо вызвать при изменении персональных настроек или состава модулей.
#
# При отсутствии файла с персональными настройками, myProfile.json будет создан автоматически
# python PrepareProject.py
#
# Если myProfile.json уже существует, можно запустить PrepareProject.py с параметром -u или --update для обновления списка модулей.
# Данная функция будет полезна для разработчиков при добавлении модуля в папку src/modules
# python PrepareProject.py --update
# python PrepareProject.py -u
#
# Возможно использовать несколько вариантов персональных настроек и уточнять имя файла при запуске с использованием параметра -p или -profile
# python PrepareProject.py --profile <ИмяФайла>
# python PrepareProject.py -p <ИмяФайла>
#
#
import configparser
import os, json, sys, getopt
from pathlib import Path
config = configparser.ConfigParser() # создаём объекта парсера INI
def printHelp():
print('''Usage:
PrepareProject.py
-p --profile <file.json_in_root_folder>
-u --update
-h --help''')
def updateModulesInProfile(profJson):
profJson["modules"] = {}
for root,d_names,f_names in os.walk("src\\modules"):
for fname in f_names:
if fname == "modinfo.json":
with open(root + "\\" + fname, "r", encoding='utf-8') as read_file:
modinfoJson = json.load(read_file)
# проверяем есть ли уже узловой элемент и если нет, то создаем
if not modinfoJson['menuSection'] in profJson["modules"]:
profJson["modules"][modinfoJson['menuSection']] = []
# добавляем информацию о модуле в узловой элемент
profJson["modules"][modinfoJson['menuSection']].append({
'path': root,
'active': modinfoJson['defActive']
})
update = False # признак необходимости обновить список модулей
profile = 'myProfile.json' # имя профиля. Будет заменено из консоли, если указано при старте
argv = sys.argv[1:]
try:
opts, args = getopt.getopt(argv, 'hp:u', ['help', 'profile=', 'update'])
except getopt.GetoptError:
print('Ошибка обработки параметров!')
printHelp()
sys.exit(2)
for opt, arg in opts:
if opt in ("-h", "--help"):
printHelp()
sys.exit()
elif opt in ("-p", "--profile"):
profile = arg
elif opt in ("-u", "--update"):
update = True
if Path(profile).is_file():
# подтягиваем уже существующий профиль
with open(profile, "r", encoding='utf-8') as read_file:
profJson = json.load(read_file)
# если хотим обновить список модулей в существующем профиле
if update:
updateModulesInProfile(profJson)
with open(profile, "w", encoding='utf-8') as write_file:
json.dump(profJson, write_file, ensure_ascii=False, indent=4, sort_keys=False)
else:
# если файла нет - создаем по образу настроек из проекта
profJson = json.loads('{}')
# копируем параметры IOTM из settings.json в новый профиль
with open("data_svelte/settings.json", "r", encoding='utf-8') as read_file:
profJson['iotmSettings'] = json.load(read_file)
# устанавливаем параметры сборки
profJson['projectProp'] = {
'platformio': {
'default_envs': 'esp8266_4mb',
'data_dir': 'data_svelte'
}
}
# загружаем список модулей для сборки
updateModulesInProfile(profJson)
# сохраняем новый профиль
with open(profile, "w", encoding='utf-8') as write_file:
json.dump(profJson, write_file, ensure_ascii=False, indent=4, sort_keys=False)
# генерируем файлы проекта на основе подготовленного профиля
# заполняем конфигурационный файл прошивки параметрами из профиля
with open("data_svelte/settings.json", "r", encoding='utf-8') as read_file:
iotmJson = json.load(read_file)
for key, value in profJson['iotmSettings'].items():
iotmJson[key] = value
with open("data_svelte/settings.json", "w", encoding='utf-8') as write_file:
json.dump(iotmJson, write_file, ensure_ascii=False, indent=4, sort_keys=False)
# определяем какое устройство используется в профиле
deviceName = profJson['projectProp']['platformio']['default_envs']
# собираем меню прошивки из модулей
# параллельно формируем список имен активных модулей
# параллельно собираем необходимые активным модулям библиотеки для включения в компиляцию для текущего типа устройства (esp8266_4m, esp32_4mb)
activeModulesName = [] # список имен активных модулей
allLibs = "" # подборка всех библиотек необходимых модулям для дальнейшей записи в конфигурацию platformio
itemsCount = 1;
includeDirs = "" # подборка путей ко всем модулям для дальнейшей записи в конфигурацию platformio
itemsJson = json.loads('[{"name": "Выберите элемент", "num": 0}]')
for section, modules in profJson['modules'].items():
itemsJson.append({"header": section})
for module in modules:
if module['active']:
with open(module['path'] + "\\modinfo.json", "r", encoding='utf-8') as read_file:
moduleJson = json.load(read_file)
if deviceName in moduleJson['devices']: # проверяем поддерживает ли модуль текущее устройство
activeModulesName.append(moduleJson['about']['moduleName']) # запоминаем имена для использования на след шагах
includeDirs = includeDirs + "\n+<" + module['path'].replace("src\\", "") + ">" # запоминаем пути к модулям для компиляции
for libPath in moduleJson['devices'][deviceName]: # запоминаем библиотеки необходимые модулю для текущей платы
allLibs = allLibs + "\n" + libPath
for configItemsJson in moduleJson['configItem']:
configItemsJson['num'] = itemsCount
configItemsJson['name'] = str(itemsCount) + ". " + configItemsJson['name']
itemsCount = itemsCount + 1
itemsJson.append(configItemsJson)
with open("data_svelte/items.json", "w", encoding='utf-8') as write_file:
json.dump(itemsJson, write_file, ensure_ascii=False, indent=4, sort_keys=False)
# учитываем вызовы модулей в API.cpp
allAPI_head = ""
allAPI_exec = ""
for activModuleName in activeModulesName:
allAPI_head = allAPI_head + "\nvoid* getAPI_" + activModuleName + "(String subtype, String params);"
allAPI_exec = allAPI_exec + "\nif ((tmpAPI = getAPI_" + activModuleName + "(subtype, params)) != nullptr) return tmpAPI;"
apicpp = '#include "ESPConfiguration.h"\n'
apicpp = apicpp + allAPI_head
apicpp = apicpp + '\n\nvoid* getAPI(String subtype, String params) {\nvoid* tmpAPI;'
apicpp = apicpp + allAPI_exec
apicpp = apicpp + '\nreturn nullptr;\n}'
with open('src/modules/API.cpp', 'w') as f:
f.write(apicpp)
# корректируем параметры platformio
# собираем пути всех отключенных модулей для исключения их из процесса компиляции
# excludeDirs = ""
# for root,d_names,f_names in os.walk("src\\modules"):
# for fname in f_names:
# if fname == "modinfo.json":
# with open(root + "\\" + fname, "r", encoding='utf-8') as read_file:
# modinfoJson = json.load(read_file)
# if not modinfoJson['about']['moduleName'] in activeModulesName:
# excludeDirs = excludeDirs + "\n-<" + root.replace("src\\", "") + ">"
# фиксируем изменения в platformio.ini
config.clear()
config.read("platformio.ini")
config["env:" + deviceName + "_fromitems"]["lib_deps"] = allLibs
config["env:" + deviceName + "_fromitems"]["build_src_filter"] = includeDirs
config["platformio"]["default_envs"] = deviceName
config["platformio"]["data_dir"] = profJson['projectProp']['platformio']['data_dir']
with open("platformio.ini", 'w') as configFile:
config.write(configFile)

View File

@@ -1,100 +0,0 @@
import configparser
import os
import json, pprint
config = configparser.ConfigParser() # создаём объекта парсера INI
allLibs_esp8266_4mb = ""
allLibs_esp32_4mb = ""
allMenuItems = json.loads('[]')
allMenuItemsCount = 1
allAPI_head = ""
allAPI_exec = ""
def getDirs(path):
for file in os.listdir(path):
if os.path.isdir(os.path.join(path, file)):
yield file
def getPIOLibs(patch):
global allLibs_esp8266_4mb, allLibs_esp32_4mb
for dir in getDirs(patch):
if (config.read(patch + dir + "/platformio.ini")):
print(patch + dir + "/platformio.ini")
allLibs_esp8266_4mb = allLibs_esp8266_4mb + config["env:esp8266_4mb"]["lib_deps"]
allLibs_esp32_4mb = allLibs_esp32_4mb + config["env:esp32_4mb"]["lib_deps"]
def getMenuItems(patch):
global allMenuItems, allMenuItemsCount
with open(patch + "items.json", "r") as read_file:
allMenuItems = allMenuItems + json.load(read_file)
for dir in getDirs(patch):
with open(patch + dir + "/items.json", "r") as read_file:
print(patch + dir + "/items.json")
data = json.load(read_file)
for item in data:
item["name"] = str(allMenuItemsCount) + ". " + item["name"]
item["num"] = allMenuItemsCount
allMenuItemsCount = allMenuItemsCount + 1
allMenuItems = allMenuItems + data
def getAPI(patch):
global allAPI_head, allAPI_exec
for dir in getDirs(patch):
print(patch + dir)
allAPI_head = allAPI_head + "\nvoid* getAPI_" + dir + "(String subtype, String params);"
allAPI_exec = allAPI_exec + "\nif ((tmpAPI = getAPI_" + dir + "(subtype, params)) != nullptr) return tmpAPI;"
# читаем и запоминаем все либы мз каждого модуля
getPIOLibs("src/modules/system/")
getPIOLibs("src/modules/exec/")
getPIOLibs("src/modules/sensors/")
getPIOLibs("src/modules/lcd/")
# сохраняем собранные либы в настройках PIO
config.read("platformio.ini")
config["env:esp8266_4mb_fromitems"]["lib_deps"] = allLibs_esp8266_4mb
config["env:esp32_4mb_fromitems"]["lib_deps"] = allLibs_esp32_4mb
with open("platformio.ini", 'w') as configfile:
config.write(configfile)
# готовим первый элемент меню
with open("src/modules/items.json", "r") as read_file:
allMenuItems = allMenuItems + json.load(read_file)
# читаем и запоминаем пункты меню модуелей
getMenuItems("src/modules/system/")
getMenuItems("src/modules/exec/")
getMenuItems("src/modules/sensors/")
getMenuItems("src/modules/lcd/")
# сохраняем пункты меню в общий файл
with open('data_svelte/items.json', 'w') as f:
json.dump(allMenuItems, f, ensure_ascii=False, indent=4, sort_keys=False)
# собираем списки API для интеграции вызовов модулей
getAPI("src/modules/system/")
getAPI("src/modules/exec/")
getAPI("src/modules/sensors/")
getAPI("src/modules/lcd/")
# сохраняем все API в API.cpp
apicpp = '#include "ESPConfiguration.h"\n'
apicpp = apicpp + allAPI_head
apicpp = apicpp + '\n\nvoid* getAPI(String subtype, String params) {\nvoid* tmpAPI;'
apicpp = apicpp + allAPI_exec
apicpp = apicpp + 'return nullptr;\n}'
with open('src/modules/API.cpp', 'w') as f:
f.write(apicpp)

0
data_svelte/dev_conf.txt Normal file
View File

BIN
data_svelte/edit.htm.gz Normal file

Binary file not shown.

View File

@@ -4,50 +4,43 @@
"num": 0
},
{
"header": "Расширения"
"header": "Экраны"
},
{
"name": "1. Расширитель портов Mcp23017",
"num": 1,
"name": "1. LCD экран 2004",
"type": "Reading",
"subtype": "Mcp23017",
"id": "Mcp",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "",
"int": "0",
"addr": "0x20",
"index": 1
"descr": "T",
"int": 15,
"addr": "0x27",
"size": "20,4",
"coord": "0,0",
"id2show": "id датчика",
"num": 1
},
{
"name": "2. Доп. функции системы",
"num": 2,
"name": "2. LCD экран 1602",
"type": "Reading",
"subtype": "SysExt",
"id": "SysExt",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "",
"int": 15
},
{
"name": "3. Переменная",
"num": 3,
"type": "Reading",
"subtype": "Variable",
"id": "var",
"widget": "",
"page": "",
"descr": "",
"int": "0",
"val": "0"
"descr": "T",
"int": 15,
"addr": "0x27",
"size": "16,2",
"coord": "0,0",
"id2show": "id датчика",
"num": 2
},
{
"header": "Модули управления"
},
{
"name": "4. Кнопка (подключенная физически)",
"num": 4,
"name": "3. Кнопка (подключенная физически)",
"type": "Writing",
"subtype": "ButtonIn",
"id": "btn",
@@ -59,11 +52,11 @@
"execLevel": "1",
"pinMode": "INPUT",
"debounceDelay": 50,
"fixState": 1
"fixState": 1,
"num": 3
},
{
"name": "5. Кнопка управляющая пином (Реле с кнопкой)",
"num": 5,
"name": "4. Кнопка управляющая пином (Реле с кнопкой)",
"type": "Writing",
"subtype": "ButtonOut",
"id": "btn",
@@ -72,31 +65,56 @@
"descr": "",
"int": 0,
"inv": 0,
"pin": 2
"pin": 2,
"num": 4
},
{
"name": "5. Сервопривод",
"type": "Writing",
"subtype": "IoTServo",
"id": "servo",
"widget": "range",
"page": "servo",
"descr": "угол",
"int": 1,
"pin": 12,
"apin": -1,
"amap": "0, 4096, 0, 180",
"num": 5
},
{
"name": "6. MP3 плеер",
"type": "Reading",
"subtype": "Mp3",
"id": "mp3",
"widget": "",
"page": "",
"descr": "",
"int": 1,
"pins": "14,12",
"volume": 20,
"num": 6
},
{
"name": "7. Таймер",
"type": "Writing",
"subtype": "Timer",
"id": "timer",
"widget": "",
"page": "",
"descr": "",
"int": 1,
"countDown": 15,
"ticker": 0,
"repeat": 0,
"needSave": 0,
"num": 7
},
{
"header": "Сенсоры"
},
{
"name": "6. Датчик напряжения ADS1115",
"num": 6,
"type": "Reading",
"subtype": "Ads1115",
"id": "Ads3",
"widget": "anydataVlt",
"page": "Сенсоры",
"descr": "ADS_3",
"pin": "0",
"mode": "volt",
"gain": "3/4x",
"plus": 0,
"multiply": 1,
"round": 100,
"int": 10
},
{
"name": "7. Cенсор температуры AHT20",
"num": 7,
"name": "8. Cенсор температуры AHT20",
"type": "Reading",
"subtype": "Aht20t",
"id": "Temp20",
@@ -105,11 +123,11 @@
"descr": "AHT20 Температура",
"int": 15,
"addr": "0x38",
"round": 1
"round": 1,
"num": 8
},
{
"name": "8. Cенсор влажности AHT20",
"num": 8,
"name": "9. Cенсор влажности AHT20",
"type": "Reading",
"subtype": "Aht20h",
"id": "Hum20",
@@ -118,11 +136,11 @@
"descr": "AHT20 Влажность",
"int": 15,
"addr": "0x38",
"round": 1
"round": 1,
"num": 9
},
{
"name": "9. Аналоговый сенсор",
"num": 9,
"name": "10. Аналоговый сенсор",
"type": "Reading",
"subtype": "AnalogAdc",
"id": "t",
@@ -134,11 +152,12 @@
"multiply": 1,
"round": 1,
"pin": 0,
"int": 15
"int": 15,
"avgSteps": 1,
"num": 10
},
{
"name": "10. Cенсор температуры Bme280",
"num": 10,
"name": "11. Cенсор температуры Bme280",
"type": "Reading",
"subtype": "Bme280t",
"id": "tmp3",
@@ -147,11 +166,11 @@
"descr": "Температура",
"int": 15,
"addr": "0x77",
"round": 1
"round": 1,
"num": 11
},
{
"name": "11. Cенсор давления Bme280",
"num": 11,
"name": "12. Cенсор давления Bme280",
"type": "Reading",
"subtype": "Bme280p",
"id": "Press3",
@@ -160,11 +179,11 @@
"descr": "Давление",
"int": 15,
"addr": "0x77",
"round": 1
"round": 1,
"num": 12
},
{
"name": "12. Cенсор влажности Bme280",
"num": 12,
"name": "13. Cенсор влажности Bme280",
"type": "Reading",
"subtype": "Bme280h",
"id": "Hum3",
@@ -173,11 +192,11 @@
"descr": "Влажность",
"int": 15,
"addr": "0x77",
"round": 1
"round": 1,
"num": 13
},
{
"name": "13. Cенсор температуры Bmp280",
"num": 13,
"name": "14. Cенсор температуры Bmp280",
"type": "Reading",
"subtype": "Bmp280t",
"id": "tmp3",
@@ -186,11 +205,11 @@
"descr": "280 Температура",
"int": 15,
"addr": "0x77",
"round": 1
"round": 1,
"num": 14
},
{
"name": "14. Cенсор давления Bmp280",
"num": 14,
"name": "15. Cенсор давления Bmp280",
"type": "Reading",
"subtype": "Bmp280p",
"id": "Press3",
@@ -199,11 +218,11 @@
"descr": "280 Давление",
"int": 15,
"addr": "0x77",
"round": 1
"round": 1,
"num": 15
},
{
"name": "15. Cенсор температуры dht11",
"num": 15,
"name": "16. Cенсор температуры dht11",
"type": "Reading",
"subtype": "Dht1122t",
"id": "tmp3",
@@ -212,11 +231,11 @@
"descr": "Температура",
"int": 15,
"pin": 0,
"senstype": "dht11"
"senstype": "dht11",
"num": 16
},
{
"name": "16. Cенсор влажности dht11",
"num": 16,
"name": "17. Cенсор влажности dht11",
"type": "Reading",
"subtype": "Dht1122h",
"id": "Hum3",
@@ -225,11 +244,11 @@
"descr": "Влажность",
"int": 15,
"pin": 0,
"senstype": "dht11"
"senstype": "dht11",
"num": 17
},
{
"name": "17. Cенсор температуры ds18b20",
"num": 17,
"name": "18. Cенсор температуры ds18b20",
"type": "Reading",
"subtype": "Ds18b20",
"id": "dstmp",
@@ -240,11 +259,11 @@
"pin": 2,
"index": 0,
"addr": "",
"round": 1
"round": 1,
"num": 18
},
{
"name": "18. Cенсор температуры GY21",
"num": 18,
"name": "19. Cенсор температуры GY21",
"type": "Reading",
"subtype": "GY21t",
"id": "tmp4",
@@ -252,11 +271,11 @@
"page": "Сенсоры",
"descr": "Температура",
"round": 1,
"int": 15
"int": 15,
"num": 19
},
{
"name": "19. Cенсор влажности GY21",
"num": 19,
"name": "20. Cенсор влажности GY21",
"type": "Reading",
"subtype": "GY21h",
"id": "Hum4",
@@ -264,11 +283,11 @@
"page": "Сенсоры",
"descr": "Влажность",
"round": 1,
"int": 15
"int": 15,
"num": 20
},
{
"name": "20. Cенсор температуры HDC1080",
"num": 20,
"name": "21. Cенсор температуры HDC1080",
"type": "Reading",
"subtype": "Hdc1080t",
"id": "Temp1080",
@@ -277,11 +296,11 @@
"descr": "1080 Температура",
"int": 15,
"addr": "0x40",
"round": 1
"round": 1,
"num": 21
},
{
"name": "21. Cенсор влажности HDC1080",
"num": 21,
"name": "22. Cенсор влажности HDC1080",
"type": "Reading",
"subtype": "Hdc1080h",
"id": "Hum1080",
@@ -290,11 +309,11 @@
"descr": "1080 Влажность",
"int": 15,
"addr": "0x40",
"round": 1
"round": 1,
"num": 22
},
{
"name": "22. Cенсор температуры MAX6675",
"num": 22,
"name": "23. Cенсор температуры MAX6675",
"type": "Reading",
"subtype": "Max6675t",
"id": "maxtmp",
@@ -304,131 +323,21 @@
"int": 15,
"DO": 12,
"CS": 13,
"CLK": 14
"CLK": 14,
"num": 23
},
{
"name": "23. Датчик CO2 MHZ-19 UART",
"num": 23,
"type": "Reading",
"subtype": "Mhz19uart",
"id": "co2uart",
"widget": "anydataPpm",
"page": "Сенсоры",
"descr": "CO2uart",
"plus": 0,
"multiply": 1,
"round": 1,
"pin": 0,
"rxPin": 14,
"txPin": 16,
"int": 15,
"range": 5000,
"ABC": 1
},
{
"name": "24. Датчик CO2 MHZ-19 PWM",
"name": "24. Сканер кнопок 433 MHz",
"num": 24,
"type": "Reading",
"subtype": "Mhz19pwm",
"id": "co2pwm",
"widget": "anydataPpm",
"page": "Сенсоры",
"descr": "CO2pwm",
"plus": 0,
"multiply": 1,
"round": 1,
"pin": 16,
"int": 300
"subtype": "RCswitch",
"id": "rsw",
"int": 500,
"pinRx": 12,
"pinTx": 12
},
{
"name": "25. Cенсор температуры от MHZ-19 UART",
"num": 25,
"type": "Reading",
"subtype": "Mhz19temp",
"id": "Mhz19temp",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Температура",
"plus": 0,
"multiply": 1,
"round": 1,
"rxPin": 14,
"txPin": 16,
"ABC": 1,
"int": 30
},
{
"name": "26. Рабочий диапазон от MHZ-19 UART",
"num": 26,
"type": "Reading",
"subtype": "Mhz19range",
"id": "Mhz19range",
"widget": "anydataPpm",
"page": "Сенсоры",
"descr": "Диапазон",
"plus": 0,
"multiply": 1,
"round": 1,
"rxPin": 14,
"txPin": 16,
"range": 5000,
"ABC": 1,
"int": 30
},
{
"name": "27. Автокалибровка от MHZ-19 UART",
"num": 27,
"type": "Reading",
"subtype": "Mhz19ABC",
"id": "Mhz19ABC",
"widget": "anydataDef",
"page": "Сенсоры",
"descr": "ABC",
"rxPin": 14,
"txPin": 16,
"range": 5000,
"ABC": 1,
"int": 30
},
{
"name": "28. Датчик пыли SDS011 PM25",
"num": 28,
"type": "Reading",
"subtype": "Sds011_25",
"id": "pmuart25",
"widget": "anydataPpm",
"page": "Сенсоры",
"descr": "PM-2.5",
"plus": 0,
"multiply": 1,
"round": 10,
"rxPin": 13,
"txPin": 12,
"int": 15,
"warmUp": 30,
"period": 300
},
{
"name": "29. Датчик пыли SDS011 PM10",
"num": 29,
"type": "Reading",
"subtype": "Sds011_10",
"id": "pmuart10",
"widget": "anydataPpm",
"page": "Сенсоры",
"descr": "PM-10",
"plus": 0,
"multiply": 1,
"round": 10,
"rxPin": 13,
"txPin": 12,
"int": 15,
"warmUp": 30,
"period": 300
},
{
"name": "30. Cенсор температуры Sht20",
"num": 30,
"name": "25. Cенсор температуры Sht20",
"type": "Reading",
"subtype": "Sht20t",
"id": "tmp2",
@@ -436,11 +345,11 @@
"page": "Сенсоры",
"descr": "Температура",
"int": 15,
"round": 1
"round": 1,
"num": 25
},
{
"name": "31. Cенсор влажности Sht20",
"num": 31,
"name": "26. Cенсор влажности Sht20",
"type": "Reading",
"subtype": "Sht20h",
"id": "Hum2",
@@ -448,39 +357,76 @@
"page": "Сенсоры",
"descr": "Влажность",
"int": 15,
"round": 1
"round": 1,
"num": 26
},
{
"header": "Экраны"
},
{
"name": "32. LCD экран 2004",
"num": 32,
"name": "27. Сонар HC-SR04",
"num": 27,
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"subtype": "Sonar",
"id": "sonar",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Расстояние (см)",
"pinTrig": 5,
"pinEcho": 4,
"int": 5
},
{
"header": "Расширения"
},
{
"name": "28. Поддержка DS1302(1), DS1307(2), DS3231(3), RX8025(4)",
"type": "Reading",
"subtype": "IarduinoRTC",
"id": "RTC",
"widget": "",
"page": "",
"descr": "T",
"int": 15,
"addr": "0x27",
"size": "20,4",
"coord": "0,0",
"id2show": "id датчика"
"descr": "",
"int": "1",
"chipNum": 1,
"rst": 16,
"clk": 5,
"dat": 4,
"defFormat": "d-m-Y",
"ticker": 0,
"num": 28
},
{
"name": "33. LCD экран 1602",
"num": 33,
"name": "29. Расширитель портов Mcp23017",
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"subtype": "Mcp23017",
"id": "Mcp",
"widget": "",
"page": "",
"descr": "T",
"descr": "",
"int": "0",
"addr": "0x20",
"index": 1,
"num": 29
},
{
"name": "30. Доп. функции системы",
"type": "Reading",
"subtype": "SysExt",
"id": "SysExt",
"widget": "",
"page": "",
"descr": "",
"int": 15,
"addr": "0x27",
"size": "16,2",
"coord": "0,0",
"id2show": "id датчика"
"num": 30
},
{
"name": "31. Переменная",
"type": "Reading",
"subtype": "Variable",
"id": "var",
"widget": "",
"page": "",
"descr": "",
"int": "0",
"val": "0",
"num": 31
}
]

View File

@@ -41,7 +41,7 @@ enum TimerTask_t { WIFI_SCAN,
TIME,
TIME_SYNC,
UPTIME,
UDP,
UDP, //UDPP
TIMES,
PTASK };

View File

@@ -5,10 +5,10 @@
extern void standWebServerInit();
extern bool handleFileRead(String path);
extern String getContentType(String filename);
#ifdef REST_FILE_OPERATIONS
//#ifdef REST_FILE_OPERATIONS
extern void handleFileUpload();
extern void handleFileDelete();
extern void handleFileCreate();
extern void handleFileList();
#endif
//#endif
#endif

View File

@@ -1,10 +1,14 @@
#pragma once
#include "classes/IoTGpio.h"
#include <iarduino_RTC.h>
struct IoTValue {
float valD = 0;
String valS = "";
bool isDecimal = true;
uint8_t *extBinInfo = NULL; // дополнительные бинарные данные из модуля
size_t extBinInfoSize = 0; // размер дополнительных данных в байтах
};
class IoTItem {
@@ -22,17 +26,24 @@ class IoTItem {
String getID();
String getValue();
void setInterval(unsigned long interval);
unsigned long currentMillis;
unsigned long prevMillis;
unsigned long difference;
IoTValue value; // хранение основного значения, котрое обновляется из сценария, execute(), loop() или doByInterval()
IoTValue value; // хранение основного значения, которое обновляется из сценария, execute(), loop() или doByInterval()
bool iAmDead = false; // признак необходимости удалить объект из базы
bool iAmLocal = true; // признак локальной переменной
bool needSave = false;
bool enableDoByInt = true;
virtual IoTGpio* getGpioDriver();
virtual iarduino_RTC_BASE* getRtcDriver();
virtual void setValue(IoTValue Value);
virtual void setValue(String valStr);
protected:
String _subtype;

22
include/classes/IoTRTC.h Normal file
View File

@@ -0,0 +1,22 @@
#pragma once
#include <Arduino.h>
#include <iarduino_RTC.h>
class iarduino_RTC_NTP: public iarduino_RTC_BASE {
public:
iarduino_RTC_NTP();
~iarduino_RTC_NTP();
void begin(void);
uint8_t funcReadTimeIndex(uint8_t i);
void funcWriteTimeIndex(uint8_t i, uint8_t j);
uint8_t funcConvertNumToCode (uint8_t i) {return ((i/10) << 4) + (i%10);}
};
class IoTRTC : public iarduino_RTC {
public:
IoTRTC(uint8_t i, uint8_t j=SS, uint8_t k=SCK, uint8_t n=MOSI) : iarduino_RTC(i, j, k, n) {
if (i == 0) objClass = new iarduino_RTC_NTP();
};
~IoTRTC();
};

View File

@@ -1,255 +0,0 @@
#pragma once
#include "Global.h"
#include "MqttClient.h"
#include "Buffers.h"
class Scenario {
public:
void loop2() {
if (!jsonReadBool(settingsFlashJson, "scen")) {
return;
}
String allBlocks = scenario;
allBlocks += "\n";
String incommingEvent = selectToMarker(eventBuf, ",");
String incommingEventKey = selectToMarker(incommingEvent, " ");
String incommingEventValue = selectToMarkerLast(incommingEvent, " ");
while (allBlocks.length()) {
String oneBlock = selectToMarker(allBlocks, "end\n");
String condition = selectToMarker(oneBlock, "\n");
//логическое и
if (condition.indexOf("&&") != -1) {
condition = condition += " && ";
//посчитаем количество условий
int conditionCnt = itemsCount2(condition, "&&") - 1;
//создадим и заполним динамический массив
bool *arr = new bool[conditionCnt];
for (int i = 0; i < conditionCnt; i++) {
arr[i] = false;
}
//есть ли входящее событие хотя бы в одном из условий и удавлетварено ли оно?
int evenInConditionNum = -1;
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " && ", i);
if (isScenarioNeedToDo(buf, incommingEventKey, incommingEventValue, 1)) {
arr[i] = true;
evenInConditionNum = i;
}
}
//если да то проверяем остальные условия по json
if (evenInConditionNum >= 0) {
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " && ", i);
if (i != evenInConditionNum) {
if (isScenarioNeedToDoJson(buf)) {
arr[i] = true;
}
}
}
}
//все элементы массива должны быть true
bool result = true;
for (int i = 0; i < conditionCnt; i++) {
if (!arr[i]) {
result = false;
}
}
delete[] arr;
if (result) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("i", "Event done", incommingEvent);
SerialPrint("i", F("Scenario"), F("All conditions are matched"));
spaceCmdExecute(oneBlock);
}
//логическое или
} else if (condition.indexOf("||") != -1) {
condition = condition += " || ";
//посчитаем количество условий
int conditionCnt = itemsCount2(condition, "||") - 1;
//создадим и заполним динамический массив
bool *arr = new bool[conditionCnt];
for (int i = 0; i < conditionCnt; i++) {
arr[i] = false;
}
//есть ли входящее событие хотя бы в одном из условий и удавлетварено ли оно?
int evenInConditionNum = -1;
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " || ", i);
if (isScenarioNeedToDo(buf, incommingEventKey, incommingEventValue, 1)) {
arr[i] = true;
evenInConditionNum = i;
}
}
//если да то проверяем остальные условия по json
if (evenInConditionNum >= 0) {
for (int i = 0; i < conditionCnt; i++) {
String buf = selectFromMarkerToMarker(condition, " || ", i);
if (i != evenInConditionNum) {
if (isScenarioNeedToDoJson(buf)) {
arr[i] = true;
}
}
}
}
//хотя бы один элемент массива должн быть true
bool result = false;
for (int i = 0; i < conditionCnt; i++) {
if (arr[i]) {
result = true;
}
}
delete[] arr;
if (result) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("i", "Event done", incommingEvent);
SerialPrint("i", F("Scenario"), F("One of all condition are matched"));
spaceCmdExecute(oneBlock);
}
//если гистерезис
} else if (condition.indexOf("+-") != -1) {
if (isScenarioNeedToDo(condition, incommingEventKey, incommingEventValue, 2)) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("i", "Event done", incommingEvent);
SerialPrint("i", F("Scenario"), "Condition are matched: " + condition);
spaceCmdExecute(oneBlock);
}
//остальные случаи
} else {
if (isScenarioNeedToDo(condition, incommingEventKey, incommingEventValue, 1)) {
oneBlock = deleteBeforeDelimiter(oneBlock, "\n");
oneBlock.replace("end", "");
// SerialPrint("i", "Event done", incommingEvent);
SerialPrint("i", F("Scenario"), "Condition are matched: " + condition);
spaceCmdExecute(oneBlock);
}
}
allBlocks = deleteBeforeDelimiter(allBlocks, "end\n");
}
eventBuf = deleteBeforeDelimiter(eventBuf, ",");
}
private:
bool isScenarioNeedToDo(String &condition, String &incommingEventKey, String &incommingEventValue, int type) {
bool res = false;
String setEventKey = selectFromMarkerToMarker(condition, " ", 0);
if (isEventExist(incommingEventKey, setEventKey)) {
String setEventSign;
String setEventValue;
if (type == 1) preCalculation(condition, setEventSign, setEventValue);
if (type == 2) preCalculationGisteresis(condition, setEventSign, setEventValue);
if (isConditionMatch(setEventSign, incommingEventValue, setEventValue)) {
res = true;
}
}
return res;
}
bool isScenarioNeedToDoJson(String &condition) {
bool res = false;
String setEventKey = selectFromMarkerToMarker(condition, " ", 0);
String setEventSign;
String setEventValue;
preCalculation(condition, setEventSign, setEventValue);
String jsonValue = getValueJson(setEventKey);
if (isConditionMatch(setEventSign, jsonValue, setEventValue)) {
res = true;
}
return res;
}
// bool isScenarioNeedToDoJson2(String &condition, String &incommingEventKey, String &incommingEventValue) {
// bool res = false;
// String setEventKey = selectFromMarkerToMarker(condition, " ", 0);
// if (isEventExist(incommingEventKey, setEventKey)) {
// String setEventSign;
// String setEventValue;
// preCalculation(condition, setEventSign, setEventValue);
// if (isConditionMatch(setEventSign, incommingEventValue, setEventValue)) {
// res = true;
// }
// }
// return res;
// }
void preCalculation(String &condition, String &setEventSign, String &setEventValue) {
setEventSign = selectFromMarkerToMarker(condition, " ", 1);
setEventValue = selectFromMarkerToMarker(condition, " ", 2);
if (!isDigitDotCommaStr(setEventValue)) {
setEventValue = getValueJson(setEventValue);
}
}
void preCalculationGisteresis(String &condition, String &setEventSign, String &setEventValue) {
setEventSign = selectFromMarkerToMarker(condition, " ", 1);
setEventValue = selectFromMarkerToMarker(condition, " ", 2);
if (!isDigitDotCommaStr(setEventValue)) {
String setEventValueName = selectToMarker(setEventValue, "+-");
String gisteresisValue = selectToMarkerLast(setEventValue, "+-");
gisteresisValue.replace("+-", "");
String value = getValueJson(setEventValueName);
String upValue = String(value.toFloat() + gisteresisValue.toFloat());
String lowValue = String(value.toFloat() - gisteresisValue.toFloat());
if (setEventSign == ">") {
setEventValue = upValue;
} else if (setEventSign == "<") {
setEventValue = lowValue;
}
}
}
bool isEventExist(String &incommingEventKey, String &setEventKey) {
bool res = false;
if (incommingEventKey == setEventKey) {
res = true;
}
return res;
}
bool isConditionMatch(String &setEventSign, String &incommingEventValue, String &setEventValue) {
boolean flag = false;
if (setEventSign == "=") {
flag = incommingEventValue == setEventValue;
} else if (setEventSign == "!=") {
flag = incommingEventValue != setEventValue;
} else if (setEventSign == "<") {
flag = incommingEventValue.toFloat() < setEventValue.toFloat();
} else if (setEventSign == ">") {
flag = incommingEventValue.toFloat() > setEventValue.toFloat();
} else if (setEventSign == ">=") {
flag = incommingEventValue.toFloat() >= setEventValue.toFloat();
} else if (setEventSign == "<=") {
flag = incommingEventValue.toFloat() <= setEventValue.toFloat();
}
return flag;
}
};
extern Scenario *myScenario;

13
lib/iarduino_RTC/LICENSE Normal file
View File

@@ -0,0 +1,13 @@
Copyright © 2019 iarduino.ru
Данная лицензия разрешает лицам, получившим копию данного программного обеспечения и сопутствующей документации (в дальнейшем именуемыми «Программное Обеспечение»), безвозмездно использовать Программное Обеспечение без ограничений, включая неограниченное право на использование, копирование, изменение, слияние, публикацию, распространение, сублицензирование и/или продажу копий Программного Обеспечения, а также лицам, которым предоставляется данное Программное Обеспечение, при соблюдении следующих условий:
Указанное выше уведомление об авторском праве и данные условия должны быть включены во все копии или значимые части данного Программного Обеспечения.
ДАННОЕ ПРОГРАММНОЕ ОБЕСПЕЧЕНИЕ ПРЕДОСТАВЛЯЕТСЯ «КАК ЕСТЬ», БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ, ЯВНО ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, ВКЛЮЧАЯ ГАРАНТИИ ТОВАРНОЙ ПРИГОДНОСТИ, СООТВЕТСТВИЯ ПО ЕГО КОНКРЕТНОМУ НАЗНАЧЕНИЮ И ОТСУТСТВИЯ НАРУШЕНИЙ, НО НЕ ОГРАНИЧИВАЯСЬ ИМИ. НИ В КАКОМ СЛУЧАЕ АВТОРЫ ИЛИ ПРАВООБЛАДАТЕЛИ НЕ НЕСУТ ОТВЕТСТВЕННОСТИ ПО КАКИМ-ЛИБО ИСКАМ, ЗА УЩЕРБ ИЛИ ПО ИНЫМ ТРЕБОВАНИЯМ, В ТОМ ЧИСЛЕ, ПРИ ДЕЙСТВИИ КОНТРАКТА, ДЕЛИКТЕ ИЛИ ИНОЙ СИТУАЦИИ, ВОЗНИКШИМ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ ИЛИ ИНЫХ ДЕЙСТВИЙ С ПРОГРАММНЫМ ОБЕСПЕЧЕНИЕМ.
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

104
lib/iarduino_RTC/README.md Normal file
View File

@@ -0,0 +1,104 @@
[![](https://iarduino.ru/img/logo.svg)](https://iarduino.ru)[![](https://wiki.iarduino.ru/img/git-shop.svg?3)](https://iarduino.ru) [![](https://wiki.iarduino.ru/img/git-wiki.svg?2)](https://wiki.iarduino.ru) [![](https://wiki.iarduino.ru/img/git-lesson.svg?2)](https://lesson.iarduino.ru)[![](https://wiki.iarduino.ru/img/git-forum.svg?2)](http://forum.trema.ru)
# iarduino_RTC [СКАЧАТЬ](https://github.com/tremaru/iarduino_RTC/archive/1.2.1.zip)
Библиотека позволяет читать и записывать время RTC модулей на базе чипов: DS1302, [DS1307](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html), [DS3231](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html), ...
Преимуществом данной библиотеки является удобная реализация получения времени.
> Подробнее про установку библиотеки читайте в нашей [инструкции](https://wiki.iarduino.ru/page/Installing_libraries/).
Пример подключения к [Arduino](https://iarduino.ru/shop/boards/arduino-uno-r3.html)/[Piranha UNO](https://iarduino.ru/shop/boards/piranha-uno-r3.html) с помощью [Trema Shield](https://iarduino.ru/shop/Expansion-payments/trema-shield.html)
Подробнее о [подключении модуля](https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/)
![enter image description here](https://iarduino.ru/img/upload/6a83fe7f3deb2f48d1408daac49284ba.png)
| Модель | Ссылка на магазин|
|--|--|
| DS1307 ![enter image description here](https://wiki.iarduino.ru/img/resources/643/643.svg) | https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html|
| DS3231 ![enter image description here](https://wiki.iarduino.ru/img/resources/877/877.svg) | https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html |
## Описание библиотеки:
Библиотека позволяет читать и записывать время RTC модулей на базе чипов: DS1302, [DS1307](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html), [DS3231](http://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html), …
Преимуществом данной библиотеки является удобная реализация получения времени.
**[ Подробное описание, подключение и примеры работы ](https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/)**
## Назначение функций и переменных:
Подробное описание работы с библиотекой, находится в разделе https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
**Подключаем библиотеку.**
#include <iarduino_RTC.h> // Подключаем библиотеку.
**Создаём объект.**
iarduino_RTC ОБЪЕКТ ( НАЗВАНИЕ [, ВЫВОД_RST [, ВЫВОД_CLK [, ВЫВОД_DAT ]]] ); // Создаём объект.
**Инициализация работы RTC модуля.**
Функция begin(); // Инициализация работы RTC модуля.
**Установка времени.**
Функция settime( СЕК [, МИН [, ЧАС [, ДЕНЬ [, МЕС [, ГОД [, ДН ]]]]]] ); // Установка времени.
**Чтение времени.**
Функция gettime( [ СТРОКА ] ); // Чтение времени.
**Заставляет функцию gettime «мигать» указанным параметром времени.**
функция blinktime( ПАРАМЕТР [ ЧАСТОТА ] ); // Заставляет функцию gettime «мигать» указанным параметром времени.
**Указывает минимальный период обращения к модулю в минутах.**
функция period( МИНУТЫ ); // Указывает минимальный период обращения к модулю в минутах.
**Возвращает секунды от 0 до 59.**
Переменная seconds // Возвращает секунды от 0 до 59.
**Возвращает минуты от 0 до 59.**
Переменная minutes // Возвращает минуты от 0 до 59.
**Возвращает часы от 1 до 12.**
Переменная hours // Возвращает часы от 1 до 12.
**Возвращает часы от 0 до 23.**
Переменная Hours // Возвращает часы от 0 до 23.
**Возвращает полдень 0 или 1 (0-am, 1-pm).**
Переменная midday // Возвращает полдень 0 или 1 (0-am, 1-pm).
**Возвращает день месяца от 1 до 31.**
Переменная day // Возвращает день месяца от 1 до 31.
**Возвращает день недели от 0 до 6 (0-воскресенье, 6-суббота).**
Переменная weekday // Возвращает день недели от 0 до 6 (0-воскресенье, 6-суббота).
**Возвращает месяц от 1 до 12.**
Переменная month // Возвращает месяц от 1 до 12.
**Возвращает год от 0 до 99.**
Переменная year // Возвращает год от 0 до 99.

View File

@@ -0,0 +1,128 @@
// Пример считывания текущего времени: //
//
// Раскомментируйте для программной реализации шины I2C: //
// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C.
// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C.
// Раскомментируйте для совместимости с большинством плат: //
// #include <Wire.h> // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.
// Ссылки для ознакомления: //
// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/
// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
//
#include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT.
// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C.
iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C.
// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C.
//
void setup(){ //
delay(300); // Ждем готовности модуля отвечать на запросы.
Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
watch.begin(); // Инициируем работу с модулем.
} //
void loop(){ //
if(millis()%1000==0){ // Если прошла 1 секунда.
Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время.
delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс.
} //
} //
//
// ====================================================== //
// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ:
//
// • Подключение библиотеки:
// #include <iarduino_RTC.h>
// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]);
// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231);
// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22);
// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT.
//
// • Для работы с модулями, в библиотеке реализованы 7 функции:
// - Инициировать модуль begin();
// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]);
// - Получить время gettime(["строка с параметрами"]);
// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень);
// - Разгрузить шину period(минуты);
// - Получить Unix время gettimeUnix();
// - Указать Unix время settimeUnix(секунды);
//
// • Функция begin():
// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д.
//
// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]):
// - Функция записывает время в модуль.
// - Год указывается без учёта века, в формате 0-99.
// - Часы указываются в 24-часовом формате, от 0 до 23.
// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота.
// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение.
// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён.
// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений.
// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений.
// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений.
//
// • Функция gettime(["строка с параметрами"]):
// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время:
// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu".
// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05".
// - Указанные символы идентичны символам для функции date() в PHP:
// s - Вернуть секунды от 00 до 59 (два знака).
// i - Вернуть минуты от 00 до 59 (два знака).
// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака).
// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака).
// d - Вернуть день месяца от 01 до 31 (два знака).
// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота).
// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun).
// m - Вернуть месяц от 01 до 12 (два знака).
// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).
// Y - Вернуть год от 2000 до 2099 (четыре знака).
// y - Вернуть год от 00 до 99 (два знака).
// a - Вернуть полдень am или pm (два знака, в нижнем регистре).
// A - Вернуть полдень AM или PM (два знака, в верхнем регистре).
//
// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных:
// - Пример: watch.gettime();
// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы.
// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты.
// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды.
// seconds - Переменная содержит секунды 0-59.
// minutes - Переменная содержит минуты 0-59.
// hours - Переменная содержит часы 1-12.
// Hours - Переменная содержит часы 0-23.
// midday - Переменная содержит полдень 0-1 (0-am, 1-pm).
// day - Переменная содержит день месяца 1-31.
// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота).
// month - Переменная содержит месяц 1-12.
// year - Переменная содержит год 0-99.
// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix.
//
// • Функция blinktime(параметр [, частота ]):
// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами).
// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени.
// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете.
// - Первым аргументом функции указывается параметр в виде числа от 0 до 8:
// 0 - не мигать.
// 1 - мигают сек.
// 2 - мигают мин.
// 3 - мигают час.
// 4 - мигают дни.
// 5 - мигают мес.
// 6 - мигает год.
// 7 - мигают дни недели.
// 8 - мигает полдень.
// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц.
// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц.
// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц.
//
// • Функция period(минуты):
// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255).
// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю).
// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут.
// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения.
//
// • Функция gettimeUnix():
// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года).
//
// • Функция settimeUnix(секунды):
// - Функция записывает время в модуль.
// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix.
// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00.

View File

@@ -0,0 +1,128 @@
// Пример считывания секунд прошедших с начала эпохи Unix: //
//
// Раскомментируйте для программной реализации шины I2C: //
// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C.
// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C.
// Раскомментируйте для совместимости с большинством плат: //
// #include <Wire.h> // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.
// Ссылки для ознакомления: //
// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/
// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
//
#include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT.
// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C.
iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C.
// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C.
//
void setup(){ //
delay(300); // Ждем готовности модуля отвечать на запросы.
Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
watch.begin(); // Инициируем работу с модулем.
} //
void loop(){ //
if (millis()%1000==0){ // Если прошла 1 секунда.
Serial.println( watch.gettimeUnix() ); // Выводим количество секунд прошедших с начала эпохи Unix (01.01.1970 00:00:00 GMT).
delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс.
} //
} //
//
// ====================================================== //
// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ:
//
// • Подключение библиотеки:
// #include <iarduino_RTC.h>
// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]);
// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231);
// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22);
// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT.
//
// • Для работы с модулями, в библиотеке реализованы 7 функции:
// - Инициировать модуль begin();
// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]);
// - Получить время gettime(["строка с параметрами"]);
// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень);
// - Разгрузить шину period(минуты);
// - Получить Unix время gettimeUnix();
// - Указать Unix время settimeUnix(секунды);
//
// • Функция begin():
// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д.
//
// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]):
// - Функция записывает время в модуль.
// - Год указывается без учёта века, в формате 0-99.
// - Часы указываются в 24-часовом формате, от 0 до 23.
// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота.
// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение.
// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён.
// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений.
// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений.
// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений.
//
// • Функция gettime(["строка с параметрами"]):
// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время:
// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu".
// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05".
// - Указанные символы идентичны символам для функции date() в PHP:
// s - Вернуть секунды от 00 до 59 (два знака).
// i - Вернуть минуты от 00 до 59 (два знака).
// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака).
// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака).
// d - Вернуть день месяца от 01 до 31 (два знака).
// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота).
// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun).
// m - Вернуть месяц от 01 до 12 (два знака).
// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).
// Y - Вернуть год от 2000 до 2099 (четыре знака).
// y - Вернуть год от 00 до 99 (два знака).
// a - Вернуть полдень am или pm (два знака, в нижнем регистре).
// A - Вернуть полдень AM или PM (два знака, в верхнем регистре).
//
// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных:
// - Пример: watch.gettime();
// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы.
// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты.
// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды.
// seconds - Переменная содержит секунды 0-59.
// minutes - Переменная содержит минуты 0-59.
// hours - Переменная содержит часы 1-12.
// Hours - Переменная содержит часы 0-23.
// midday - Переменная содержит полдень 0-1 (0-am, 1-pm).
// day - Переменная содержит день месяца 1-31.
// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота).
// month - Переменная содержит месяц 1-12.
// year - Переменная содержит год 0-99.
// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix.
//
// • Функция blinktime(параметр [, частота ]):
// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами).
// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени.
// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете.
// - Первым аргументом функции указывается параметр в виде числа от 0 до 8:
// 0 - не мигать.
// 1 - мигают сек.
// 2 - мигают мин.
// 3 - мигают час.
// 4 - мигают дни.
// 5 - мигают мес.
// 6 - мигает год.
// 7 - мигают дни недели.
// 8 - мигает полдень.
// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц.
// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц.
// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц.
//
// • Функция period(минуты):
// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255).
// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю).
// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут.
// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения.
//
// • Функция gettimeUnix():
// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года).
//
// • Функция settimeUnix(секунды):
// - Функция записывает время в модуль.
// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix.
// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00.

View File

@@ -0,0 +1,138 @@
// Пример считывания текущего времени в переменные: //
//
// Раскомментируйте для программной реализации шины I2C: //
// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C.
// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C.
// Раскомментируйте для совместимости с большинством плат: //
// #include <Wire.h> // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.
// Ссылки для ознакомления: //
// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/
// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
//
#include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT.
// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C.
iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C.
// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C.
//
uint8_t D, M, Y, h, m, s, W; // Объявляем переменные для получения следующих значений: D-день, M-месяц, Y-год, h-часы, m-минуты, s-секунды, W-день недели.
//
void setup(){ //
delay(300); // Ждем готовности модуля отвечать на запросы.
Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
watch.begin(); // Инициируем работу с модулем.
} //
void loop(){ //
if(millis()%1000==0){ // Если прошла 1 секунда.
watch.gettime(); // Считываем текущее время из модуля в буфер библиотеки.
D = watch.day; // Получаем из буфера библиотеки текущий день месяца 1-31.
M = watch.month; // Получаем из буфера библиотеки текущий месяц 1-12.
Y = watch.year; // Получаем из буфера библиотеки текущий год 0-99.
h = watch.Hours; // Получаем из буфера библиотеки текущие часы 0-23.
m = watch.minutes; // Получаем из буфера библиотеки текущие минуты 0-59.
s = watch.seconds; // Получаем из буфера библиотеки текущие секунды 0-59.
W = watch.weekday; // Получаем из буфера библиотеки текущий день недели 0-6.
Serial.println((String) D+"-"+M+"-"+Y+", "+h+":"+m+":"+s+", "+W); // Выводим время в монитор, одной строкой.
delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс.
} //
} //
//
// ================================================================== //
// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ:
//
// • Подключение библиотеки:
// #include <iarduino_RTC.h>
// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]);
// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231);
// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22);
// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT.
//
// • Для работы с модулями, в библиотеке реализованы 7 функции:
// - Инициировать модуль begin();
// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]);
// - Получить время gettime(["строка с параметрами"]);
// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень);
// - Разгрузить шину period(минуты);
// - Получить Unix время gettimeUnix();
// - Указать Unix время settimeUnix(секунды);
//
// • Функция begin():
// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д.
//
// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]):
// - Функция записывает время в модуль.
// - Год указывается без учёта века, в формате 0-99.
// - Часы указываются в 24-часовом формате, от 0 до 23.
// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота.
// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение.
// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён.
// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений.
// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений.
// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений.
//
// • Функция gettime(["строка с параметрами"]):
// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время:
// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu".
// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05".
// - Указанные символы идентичны символам для функции date() в PHP:
// s - Вернуть секунды от 00 до 59 (два знака).
// i - Вернуть минуты от 00 до 59 (два знака).
// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака).
// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака).
// d - Вернуть день месяца от 01 до 31 (два знака).
// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота).
// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun).
// m - Вернуть месяц от 01 до 12 (два знака).
// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).
// Y - Вернуть год от 2000 до 2099 (четыре знака).
// y - Вернуть год от 00 до 99 (два знака).
// a - Вернуть полдень am или pm (два знака, в нижнем регистре).
// A - Вернуть полдень AM или PM (два знака, в верхнем регистре).
//
// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных:
// - Пример: watch.gettime();
// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы.
// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты.
// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды.
// seconds - Переменная содержит секунды 0-59.
// minutes - Переменная содержит минуты 0-59.
// hours - Переменная содержит часы 1-12.
// Hours - Переменная содержит часы 0-23.
// midday - Переменная содержит полдень 0-1 (0-am, 1-pm).
// day - Переменная содержит день месяца 1-31.
// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота).
// month - Переменная содержит месяц 1-12.
// year - Переменная содержит год 0-99.
// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix.
//
// • Функция blinktime(параметр [, частота ]):
// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами).
// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени.
// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете.
// - Первым аргументом функции указывается параметр в виде числа от 0 до 8:
// 0 - не мигать.
// 1 - мигают сек.
// 2 - мигают мин.
// 3 - мигают час.
// 4 - мигают дни.
// 5 - мигают мес.
// 6 - мигает год.
// 7 - мигают дни недели.
// 8 - мигает полдень.
// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц.
// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц.
// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц.
//
// • Функция period(минуты):
// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255).
// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю).
// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут.
// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения.
//
// • Функция gettimeUnix():
// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года).
//
// • Функция settimeUnix(секунды):
// - Функция записывает время в модуль.
// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix.
// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00.

View File

@@ -0,0 +1,137 @@
// Пример установки системного времени (вашего компьютера) //
//
// Раскомментируйте для программной реализации шины I2C: //
// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C.
// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C.
// Раскомментируйте для совместимости с большинством плат: //
// #include <Wire.h> // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.
// Ссылки для ознакомления: //
// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/
// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
//
#include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT.
// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C.
iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C.
// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C.
//
// Определяем системное время: // Время загрузки скетча.
const char* strM="JanFebMarAprMayJunJulAugSepOctNovDec"; // Определяем массив всех вариантов текстового представления текущего месяца находящегося в предопределенном макросе __DATE__.
const char* sysT=__TIME__; // Получаем время компиляции скетча в формате "SS:MM:HH".
const char* sysD=__DATE__; // Получаем дату компиляции скетча в формате "MMM:DD:YYYY", где МММ - текстовое представление текущего месяца, например: Jul.
// Парсим полученные значения в массив: // Определяем массив «i» из 6 элементов типа int, содержащий следующие значения: секунды, минуты, часы, день, месяц и год компиляции скетча.
const int i[6] {(sysT[6]-'0')*10+(sysT[7]-'0'), (sysT[3]-'0')*10+(sysT[4]-'0'), (sysT[0]-'0')*10+(sysT[1]-'0'), (sysD[4]-'0')*10+(sysD[5]-'0'), ((int)memmem(strM,36,sysD,3)+3-(int)&strM[0])/3, (sysD[9]-'0')*10+(sysD[10]-'0')};
//
void setup(){ //
delay(300); // Ждем готовности модуля отвечать на запросы.
Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
watch.begin(); // Инициируем работу с модулем.
watch.settime(i[0],i[1],i[2],i[3],i[4],i[5]); // Устанавливаем время в модуль: i[0] сек, i[1] мин, i[2] час, i[3] день, i[4] месяц, i[5] год, без указания дня недели.
// watch.settime(i[0],i[1],i[2],i[3],i[4],i[5], 2); // Можно установить время с указанием дня недели, где последний параметр, это день недели (указывается вручную) в формате: 0-воскресенье, 1-понедельник, ... , 6-суббота.
} //
void loop(){ //
if(millis()%1000==0){ // Если прошла 1 секунда.
Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время.
delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс.
} //
} //
//
// ====================================================== //
// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ:
//
// • Подключение библиотеки:
// #include <iarduino_RTC.h>
// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]);
// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231);
// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22);
// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT.
//
// • Для работы с модулями, в библиотеке реализованы 7 функции:
// - Инициировать модуль begin();
// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]);
// - Получить время gettime(["строка с параметрами"]);
// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень);
// - Разгрузить шину period(минуты);
// - Получить Unix время gettimeUnix();
// - Указать Unix время settimeUnix(секунды);
//
// • Функция begin():
// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д.
//
// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]):
// - Функция записывает время в модуль.
// - Год указывается без учёта века, в формате 0-99.
// - Часы указываются в 24-часовом формате, от 0 до 23.
// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота.
// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение.
// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён.
// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений.
// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений.
// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений.
//
// • Функция gettime(["строка с параметрами"]):
// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время:
// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu".
// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05".
// - Указанные символы идентичны символам для функции date() в PHP:
// s - Вернуть секунды от 00 до 59 (два знака).
// i - Вернуть минуты от 00 до 59 (два знака).
// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака).
// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака).
// d - Вернуть день месяца от 01 до 31 (два знака).
// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота).
// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun).
// m - Вернуть месяц от 01 до 12 (два знака).
// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).
// Y - Вернуть год от 2000 до 2099 (четыре знака).
// y - Вернуть год от 00 до 99 (два знака).
// a - Вернуть полдень am или pm (два знака, в нижнем регистре).
// A - Вернуть полдень AM или PM (два знака, в верхнем регистре).
//
// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных:
// - Пример: watch.gettime();
// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы.
// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты.
// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды.
// seconds - Переменная содержит секунды 0-59.
// minutes - Переменная содержит минуты 0-59.
// hours - Переменная содержит часы 1-12.
// Hours - Переменная содержит часы 0-23.
// midday - Переменная содержит полдень 0-1 (0-am, 1-pm).
// day - Переменная содержит день месяца 1-31.
// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота).
// month - Переменная содержит месяц 1-12.
// year - Переменная содержит год 0-99.
// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix.
//
// • Функция blinktime(параметр [, частота ]):
// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами).
// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени.
// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете.
// - Первым аргументом функции указывается параметр в виде числа от 0 до 8:
// 0 - не мигать.
// 1 - мигают сек.
// 2 - мигают мин.
// 3 - мигают час.
// 4 - мигают дни.
// 5 - мигают мес.
// 6 - мигает год.
// 7 - мигают дни недели.
// 8 - мигает полдень.
// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц.
// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц.
// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц.
//
// • Функция period(минуты):
// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255).
// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю).
// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут.
// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения.
//
// • Функция gettimeUnix():
// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года).
//
// • Функция settimeUnix(секунды):
// - Функция записывает время в модуль.
// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix.
// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00.

View File

@@ -0,0 +1,129 @@
// Пример установки времени модуля: //
//
// Раскомментируйте для программной реализации шины I2C: //
// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C.
// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C.
// Раскомментируйте для совместимости с большинством плат: //
// #include <Wire.h> // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.
// Ссылки для ознакомления: //
// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/
// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
//
#include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT.
// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C.
iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C.
// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C.
//
void setup(){ //
delay(300); // Ждем готовности модуля отвечать на запросы.
Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
watch.begin(); // Инициируем работу с модулем.
watch.settime(0,51,21,27,10,15,2); // Записываем время в модуль: 0 сек, 51 мин, 21 час, 27, октября, 2015 года, вторник.
} //
void loop(){ //
if(millis()%1000==0){ // Если прошла 1 секунда.
Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время.
delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс.
} //
} //
//
// ====================================================== //
// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ:
//
// • Подключение библиотеки:
// #include <iarduino_RTC.h>
// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]);
// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231);
// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22);
// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT.
//
// • Для работы с модулями, в библиотеке реализованы 7 функции:
// - Инициировать модуль begin();
// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]);
// - Получить время gettime(["строка с параметрами"]);
// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень);
// - Разгрузить шину period(минуты);
// - Получить Unix время gettimeUnix();
// - Указать Unix время settimeUnix(секунды);
//
// • Функция begin():
// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д.
//
// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]):
// - Функция записывает время в модуль.
// - Год указывается без учёта века, в формате 0-99.
// - Часы указываются в 24-часовом формате, от 0 до 23.
// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота.
// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение.
// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён.
// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений.
// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений.
// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений.
//
// • Функция gettime(["строка с параметрами"]):
// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время:
// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu".
// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05".
// - Указанные символы идентичны символам для функции date() в PHP:
// s - Вернуть секунды от 00 до 59 (два знака).
// i - Вернуть минуты от 00 до 59 (два знака).
// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака).
// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака).
// d - Вернуть день месяца от 01 до 31 (два знака).
// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота).
// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun).
// m - Вернуть месяц от 01 до 12 (два знака).
// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).
// Y - Вернуть год от 2000 до 2099 (четыре знака).
// y - Вернуть год от 00 до 99 (два знака).
// a - Вернуть полдень am или pm (два знака, в нижнем регистре).
// A - Вернуть полдень AM или PM (два знака, в верхнем регистре).
//
// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных:
// - Пример: watch.gettime();
// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы.
// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты.
// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды.
// seconds - Переменная содержит секунды 0-59.
// minutes - Переменная содержит минуты 0-59.
// hours - Переменная содержит часы 1-12.
// Hours - Переменная содержит часы 0-23.
// midday - Переменная содержит полдень 0-1 (0-am, 1-pm).
// day - Переменная содержит день месяца 1-31.
// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота).
// month - Переменная содержит месяц 1-12.
// year - Переменная содержит год 0-99.
// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix.
//
// • Функция blinktime(параметр [, частота ]):
// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами).
// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени.
// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете.
// - Первым аргументом функции указывается параметр в виде числа от 0 до 8:
// 0 - не мигать.
// 1 - мигают сек.
// 2 - мигают мин.
// 3 - мигают час.
// 4 - мигают дни.
// 5 - мигают мес.
// 6 - мигает год.
// 7 - мигают дни недели.
// 8 - мигает полдень.
// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц.
// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц.
// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц.
//
// • Функция period(минуты):
// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255).
// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю).
// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут.
// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения.
//
// • Функция gettimeUnix():
// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года).
//
// • Функция settimeUnix(секунды):
// - Функция записывает время в модуль.
// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix.
// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00.

View File

@@ -0,0 +1,129 @@
// Пример установки времени модуля значением Unix time: //
//
// Раскомментируйте для программной реализации шины I2C: //
// #define pin_SW_SDA 3 // Назначение любого вывода Arduino для работы в качестве линии SDA программной шины I2C.
// #define pin_SW_SCL 9 // Назначение любого вывода Arduino для работы в качестве линии SCL программной шины I2C.
// Раскомментируйте для совместимости с большинством плат: //
// #include <Wire.h> // Библиотека iarduino_RTC будет использовать методы и функции библиотеки Wire.
// Ссылки для ознакомления: //
// Подробная информация о подключении модуля к шине I2C: // http://wiki.iarduino.ru/page/i2c_connection/
// Подробная информация о функциях и методах библиотеки: // http://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
//
#include <iarduino_RTC.h> // Подключаем библиотеку iarduino_RTC для работы с модулями реального времени.
// iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1302, указывая выводы Arduino подключённые к выводам модуля RST, CLK, DAT.
// iarduino_RTC watch(RTC_DS1307); // Объявляем объект watch для работы с RTC модулем на базе чипа DS1307, используется шина I2C.
iarduino_RTC watch(RTC_DS3231); // Объявляем объект watch для работы с RTC модулем на базе чипа DS3231, используется шина I2C.
// iarduino_RTC watch(RTC_RX8025); // Объявляем объект watch для работы с RTC модулем на базе чипа RX8025, используется шина I2C.
//
void setup(){ //
delay(300); // Ждем готовности модуля отвечать на запросы.
Serial.begin(9600); // Инициируем передачу данных в монитор последовательного порта на скорости 9600 бод.
watch.begin(); // Инициируем работу с модулем.
watch.settimeUnix(1577836800); // Записываем время в модуль: 01.01.1970 00:00:00 (дата начала эпохи Unix) + 1577836800 сек = 01.01.2020 00:00:00.
} //
void loop(){ //
if(millis()%1000==0){ // Если прошла 1 секунда.
Serial.println(watch.gettime("d-m-Y, H:i:s, D")); // Выводим время.
delay(1); // Приостанавливаем скетч на 1 мс, чтоб не выводить время несколько раз за 1мс.
} //
} //
//
// ====================================================== //
// ОПИСАНИЯ ПАРАМЕТРОВ ФУНКЦИЙ:
//
// • Подключение библиотеки:
// #include <iarduino_RTC.h>
// iarduino_RTC watch(название модуля [, вывод SS/RST [, вывод CLK [, вывод DAT]]]);
// - Если модуль работает на шине I2C или SPI, то достаточно указать 1 параметр, например: iarduino_RTC watch(RTC_DS3231);
// - Если модуль работает на шине SPI, а аппаратный вывод SS занят, то номер назначенного вывода SS для модуля указывается вторым параметром, например: iarduino_RTC watch(RTC_DS1305,22);
// - Если модуль работает на трехпроводной шине, то указываются номера всех выводов, например: iarduino_RTC watch(RTC_DS1302, 2, 3, 4); // RST, CLK, DAT.
//
// • Для работы с модулями, в библиотеке реализованы 7 функции:
// - Инициировать модуль begin();
// - Указать время settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]);
// - Получить время gettime(["строка с параметрами"]);
// - Мигать времем blinktime(0-не_мигать / 1-мигают_сек / 2-мигают_мин / 3-мигают_час / 4-мигают_дни / 5-мигают_мес / 6-мигает_год / 7-мигают_дни_недели / 8-мигает_полдень);
// - Разгрузить шину period(минуты);
// - Получить Unix время gettimeUnix();
// - Указать Unix время settimeUnix(секунды);
//
// • Функция begin():
// - Функция инициирует модуль: проверяет регистры модуля, запускает генератор модуля и т.д.
//
// • Функция settime(секунды [, минуты [, часы [, день [, месяц [, год [, день недели]]]]]]):
// - Функция записывает время в модуль.
// - Год указывается без учёта века, в формате 0-99.
// - Часы указываются в 24-часовом формате, от 0 до 23.
// - День недели указывается в виде числа: 0-воскресенье, 1-понедельник, 2-вторник ..., 6-суббота.
// - Если предыдущий параметр надо оставить без изменений, то можно указать отрицательное или заведомо большее значение.
// - Все параметры, кроме секунд, являются необязательными. Если параметр не указан, значит он не будет изменён.
// - Пример: watch.settime(-1, 10); // Установить 10 минут, а секунды, часы и дату, оставить без изменений.
// - Пример: watch.settime(0, 5, 13); // Установить 13 часов, 5 минут, 0 секунд, а дату оставить без изменений.
// - Пример: watch.settime(-1, -1, -1, 9, 2, 17); // Установить дату 09.02.2017, а время и день недели оставить без изменений.
//
// • Функция gettime(["строка с параметрами"]):
// - Функция получает и возвращает строку заменяя описанные ниже символы на текущее время:
// - Пример: watch.gettime("d-m-Y, H:i:s, D"); // Вернуть строку с датой и временем, например: "01-10-2015, 14:00:05, Thu".
// - Пример: watch.gettime("s"); // Вернуть строку с секундами, например: "05".
// - Указанные символы идентичны символам для функции date() в PHP:
// s - Вернуть секунды от 00 до 59 (два знака).
// i - Вернуть минуты от 00 до 59 (два знака).
// h - Вернуть часы в 12-часовом формате от 01 до 12 (два знака).
// H - Вернуть часы в 24-часовом формате от 00 до 23 (два знака).
// d - Вернуть день месяца от 01 до 31 (два знака).
// w - Вернуть день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота).
// D - Вернуть день недели наименование от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun).
// m - Вернуть месяц от 01 до 12 (два знака).
// M - Вернуть месяц наименование от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec).
// Y - Вернуть год от 2000 до 2099 (четыре знака).
// y - Вернуть год от 00 до 99 (два знака).
// a - Вернуть полдень am или pm (два знака, в нижнем регистре).
// A - Вернуть полдень AM или PM (два знака, в верхнем регистре).
//
// Если требуется получить время в виде цифр, то можно вызвать функцию gettime() без параметра, после чего получить время из переменных:
// - Пример: watch.gettime();
// Serial.print(watch.Hours); Serial.print(":"); // Вывести часы.
// Serial.print(watch.minutes); Serial.print(":"); // Вывести минуты.
// Serial.print(watch.seconds); Serial.println(""); // Вывести секунды.
// seconds - Переменная содержит секунды 0-59.
// minutes - Переменная содержит минуты 0-59.
// hours - Переменная содержит часы 1-12.
// Hours - Переменная содержит часы 0-23.
// midday - Переменная содержит полдень 0-1 (0-am, 1-pm).
// day - Переменная содержит день месяца 1-31.
// weekday - Переменная содержит день недели 0-6 (0-воскресенье, 6-суббота).
// month - Переменная содержит месяц 1-12.
// year - Переменная содержит год 0-99.
// Unix - Переменная содержит секунды прошедшие с начала эпохи Unix.
//
// • Функция blinktime(параметр [, частота ]):
// - Данная функция указывает функции gettime("строка с параметрами"); мигать одним из параметров времени (заменять параметр пробелами).
// - Эта функция может быть полезна, для отображения на дисплее, устанавливаемого параметра времени.
// Например, при установке минут, они начинают мигать, и Вам понятно, что именно Вы устанавливаете.
// - Первым аргументом функции указывается параметр в виде числа от 0 до 8:
// 0 - не мигать.
// 1 - мигают сек.
// 2 - мигают мин.
// 3 - мигают час.
// 4 - мигают дни.
// 5 - мигают мес.
// 6 - мигает год.
// 7 - мигают дни недели.
// 8 - мигает полдень.
// - Второй аргумент функции является необязательным, он указвает частоту миганий в Гц, по умолчанию 1Гц.
// - Пример: watch.blinktime(6); // При выводе на дисплей будет мигать год с частотой по умолчанию 1Гц.
// - Пример: watch.blinktime(6, 2); // При выводе на дисплей будет мигать год с частотой 2Гц.
//
// • Функция period(минуты):
// - Устанавливает минимальный период обращения к модулю в минутах (от 0 до 255).
// - Данная функция указывает функции gettime() откуда брать текущее время: из модуля (не чаще заданного периода), или рассчитать в библиотеке (без обращения к модулю).
// - Пример: watch.period(10); // Теперь функция gettime() будет получать время от модуля только 1 раз в 10 минут.
// Ответом на все остальные запросы к функции gettime(), будет рассчитанное время: сумма времени полученного от модуля и времени прошедшего с момента его получения.
//
// • Функция gettimeUnix():
// - Функция возвращает число равное количеству секунд прошедших с начала эпохи Unix (с полуночи 1 января 1970 года).
//
// • Функция settimeUnix(секунды):
// - Функция записывает время в модуль.
// - В качестве единственного параметра функции указывается количество секунд прошедших с начала эпохи Unix.
// - Пример: watch.settimeUnix(1577836800); // Установить время на 1577836800 сек больше даты 01.01.1970г 00:00:00, что соответствует дате 01.01.2020г 00:00:00.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,196 @@
Модуль часов реального времени RX-8025 SA/NB:
НАЗНАЧЕНИЕ ВЫВОДОВ:
+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+
| Вывод | I/O | Назначение: |
+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+
| SCL | I | Линия тактирования шины I2C. |
| SDA | I/O | Линия данных шины I2C. |
+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+
| FOUT | O | Выход тактового сигнала (32,768 кГц), работает при наличии 1 на выводе FOE. Если на FOE уровень 0 или OPEN, то FOUT=0. |
| FOE | I | Вход управления выводом FOUT. Если FOE=1 то FOUT=32.768кГц. Если FOE=0 то FOUT=0. Вывод FOE толерантен к 5.5В, он внутрисхемно прижат к GND. |
+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+
| /INTA | O | N-канальный выходом с открытым стоком, предназначен для вывода прерываний будильника Alarm_D и периодических прерываний. |
| /INTB | O | N-канальный выходом с открытым стоком, предназначен для вывода прерываний будильника Alarm_W. |
+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+
| TEST | | Вывод используется производителем для тестирования. Обязательно подключите к Vcc. |
| VDD | | Vcc от +1.7В до +5.5В, номинально 3.0В. |
| GND | | GND. |
| N.C. | | На чипе RX-8025NB контакты N.C. соеденены друг с другом. Оставьте их неподключёнными или подключите все к Vcc или все к GND. |
+-------+-----+----------------------------------------------------------------------------------------------------------------------------------------------+
ЛОГИЧЕСКИЕ УРОВНИ:
Vin 0 = 0В...0,2Vcc
Vin 1 = 0,8Vcc...5,5В
ФУНКЦИИ МОДУЛЯ:
1) ТЕКУЩЕЕ ВРЕМЯ:
Модуль позволяет устанавливать, синхронизировать и отображать данные, включая год (последние две цифры), месяц, дату, день, час, минуту и ​​секунду.
Любой (двузначный) год, кратный 4, считается високосным и рассчитывается автоматически до 2099 года.
2) ФУНКЦИЯ РЕГУЛИРОВКИ ТОЧНОСТИ ЧАСОВ:
Точность часов можно отрегулировать вперед или назад изменив частоту с кварца 32,768 кГц с шагом ±3,05 × 10^6.
Для регулировки требуется записать в регистр Digital Offset знаковое значение в 7-битном двоичном коде (от 62 до +63).
На предделитель часов поступит частота = 32768 Гц - DigitalOffset * 3,05 × 10^6.
Примечание: Можно настроить только точность часов. Настройки не влияют на выходной сигнал 32,768 кГц с вывода FOUT.
3) ФУНКЦИЯ ПЕРИОДИЧЕСКОГО ПРЕРЫВАНИЯ:
В дополнение к функции будильника Alarm_D через вывод /INTA могут выводиться периодические прерывания.
Периодическое прерывание настраивается битами CT2-CT0 регистра Control-1.
При срабатывании прерывания устанавливается флаг CTFG регистра Control-2, а на выводе /INTA устанавливается уровень логического 0.
Сброс флага CTFG освобождает вывод /INTA до следующего прерывания.
Биты CT2-CT0 позволяют выбрать частоту прерываний: 2 Гц (пол секунды), 1 Гц (ежесекундно), 1/60 Гц (ежеминутно), ежечасно или ежемесячно.
4) ФУНКЦИИ БУДИЛЬНИКА:
Модуль оснащен двумя будильниками (Alarm_D и Alarm_W), которые выводят сигнал прерывания (на выводы /INTA, /INTB) при совпадении времени.
• Будильник Alarm_W на основе дня недели, часа и минут, выводит сигнал прерывания через вывод /INTB. Будильник позволяет выбрать несколько деней недели.
Будильник срабатывает если он включён битом WALE регистра Control-1, при совпадении времени будильника с текущим временем.
При срабатывании будильника устанавливается флаг WAFG регистра Control-2, а на выводе /INTB устанавливается уровень логического 0.
Сброс флага WAFG освобождает вывод /INTB до следующего прерывания.
Если для будильника установить текущее время, то он сработает не немедленно, а при следующем совпадении времени.
Для установки нового времени будильника рекомендуется его отключить WALE=0, установить время будильника Alarm_W Minute/Hour/Day, сбросить прерывание будильника WAFG=0, включить будильник WALE=1.
• Будильник Alarm_D использует только часы и минуты, выводит сигнал прерывания через вывод /INTA.
Будильник срабатывает если он включён битом DALE регистра Control-1, при совпадении времени будильника с текущим временем.
При срабатывании будильника устанавливается флаг DAFG регистра Control-2, в на выводе /INTA устанавливается уровень логического 0.
Сброс флага DAFG освобождает вывод /INTA до следующего прерывания.
Если для будильника установить текущее время, то он сработает не немедленно, а при следующем совпадении времени.
Для установки нового времени будильника рекомендуется его отключить DALE=0, установить время будильника Alarm_D Minute/Hour, сбросить прерывание будильника DAFG=0, включить будильник DALE=1.
5) ФУНКЦИЯ ОБНАРУЖЕНИЯ ОСТАНОВКИ КОЛЕБАНИЙ:
При обнаружении остановки колебаний устанавливается флаг /XST регистра Control-2 (активный уровень 0) и остаётся в таком состоянии до его сброва в 1 по шине I2C.
Это позволяет определить, что данные часов стали некорректными.
6) ФУНКЦИЯ ОБНАРУЖЕНИЯ ПАДЕНИЯ МОЩНОСТИ (КОНТРОЛЬ НАПРЯЖЕНИЯ):
При снижении Vcc ниже порогового уровня, устанавливается флаг VDET регистра Control-2 и остаётся в таком состоянии до его перезаписи в 0 по шине I2C.
Выборка напряжения выполняется один раз в секунду.
Пороговый уровень выбирается битом VDSL регистра Control-2, доступны значения 1.3В и 2.1 В.
7) ФУНКЦИЯ ОБНАРУЖЕНИЯ СБРОСА ПРИ ВКЛЮЧЕНИИ ПИТАНИЯ:
При подаче питания происходит сброс регистров в значение по умолчанию и установка флага PON регистра Control-2 в значение 1, это значение остается до его перезаписи в 0 по шине I2C.
Пока флаг PON установлен в 1, все биты регистров Digital-Offset, Control-1 и Control-2 (кроме PON и /XST) сбрасываются в «0». Это также приводит к остановке прерываний на выводах /INTA и /INTB.
Для начала работы необходимо сбросить флаг PON в 0, что перезапустит функцию обнаружения сброса при включении питания.
8) ТАКТОВЫЙ ВЫХОД 32,768 кГц
Тактовая частота 32,768 кГц (с точностью, равной точности встроенного кварцевого генератора) может выводиться через вывод с открытым стоком FOUT.
Вывод FOUT включается подачей 1 на вход FOE. Если на вход FOE подать 0, то и на выходе FOUT будет 0.
9) ИНТЕРФЕЙС
Данные считываются и записываются через интерфейс шины I2C. Максимальная тактовая частота 400 кГц (при Vcc ≥ 1,7 В).
КАРТА РЕГИСТРОВ:
+-------+-------------------+---------------------------------------------------------------------------------------------------+
|Address| Function | 7 6 5 4 3 2 1 0 |
+-------+-------------------+---------------------------------------------------------------------------------------------------+
| 0 | Seconds | (0) S40 S20 S10 S8 S4 S2 S1 |
| 1 | Minutes | (0) M40 M20 M10 M8 M4 M2 M1 |
| 2 | Hours | (0) (0) H20 P,/A H10 H8 H4 H2 H1 |
| 3 | Days | (0) (0) (0) (0) (0) W4 W2 W1 | Так написано в datasheet
| | | (0) Сб Пт Чт Ср Вт Пн Вс | А так на самом деле. И модуль не определяет день недели, а тупо его увеличивает после 23:59:59
| 4 | Days | (0) (0) D20 D10 D8 D4 D2 D1 |
| 5 | Months | «0» (0) (0) MO10 MO8 MO4 MO2 MO1 |
| 6 | Years | Y80 Y40 Y20 Y10 Y8 Y4 Y2 Y1 |
+-------+-------------------+---------------------------------------------------------------------------------------------------+
| 7 | Digital Offset | «0» F6 F5 F4 F3 F2 F1 F0 | Значения по умолчанию (с момента установки бита PON) 00000000
+-------+-------------------+---------------------------------------------------------------------------------------------------+
| 8 | Alarm_W Minute | (0) WM40 WM20 WM10 WM8 WM4 WM2 WM1 |
| 9 | Alarm_W Hour | (0) (0) WH20 WP,/A WH10 WH8 WH4 WH2 WH1 |
| A | Alarm_W Day | (0) WW6 WW5 WW4 WW3 WW2 WW1 WW0 |
| B | Alarm_D Minute | (0) DM40 DM20 DM10 DM8 DM4 DM2 DM1 |
| C | Alarm_D Hour | (0) (0) DH20 DP,/A DH10 DH8 DH4 DH2 DH1 |
+-------+-------------------+---------------------------------------------------------------------------------------------------+
| D | Reserved | - - - - - - - - |
+-------+-------------------+---------------------------------------------------------------------------------------------------+
| E | Control-1 | WALE DALE /12,24 • TEST CT2 CT1 CT0 | Значения по умолчанию (с момента установки бита PON) 00000000
| F | Control-2 | VDSL VDET /XST PON • CTFG WAFG DAFG | Значения по умолчанию (с момента установки бита PON) 00?10000
+-------+-------------------+---------------------------------------------------------------------------------------------------+
Осторожно:
Бит PON Является битом флага сброса при включении питания. Устанавливается в 1, когда происходит сброс, например, при первоначальном включении питания или при восстановлении после падения напряжения питания.
При этом все биты в регистрах Control-1 и Control-2, кроме битов PON и /XST, сбрасываются в 0.
Примечание: Пока бит PON не установится в 1 все остальные значения регистров не определены, поэтому обязательно выполните сброс перед использованием модуля.
Кроме того, избегайте ввода неверных данных о дате и времени, так как работа часов не гарантируется, если данные о времени неверны.
Бит TEST Используется производителем для тестирования. Убедитесь, что для этого бита установлено значение «0».
Reserved Регистр с адресом D используется для заводских настроек. Не читайте и не записывайте в этот регистр.
Биты «0» Должны быть установлены в 0 при записи. Их значение при чтении будет 0.
Биты (0) Доступны только для чтения. Их значение при чтении всегда равно 0.
Биты • Являются битами ОЗУ, которые могут содержать любое значение и доступны для чтения/записи. Однако эти биты сбрасываются в 0, когда значение бита PON равно 1.
0) Seconds Регистр счётчика секунд в двоично-десятичном формате (0b X101 1001 = 59сек).
1) Minutes Регистр счётчика минут в двоично-десятичном формате (0b X101 1001 = 59мин).
2) Hours Регистр счётчика часов в двоично-десятичном формате (0b XX01 1001 = 19час).
H20 P,/A В 24-часовом формате бит функционирует как H20
В 12-часовом формате бит функционирует как P,/A (0-AM, 1-PM).
Формат часов задаёт бит /12,24 регистра Control-1.
3) Days Регистр счётчика дней недели (1-Пн, 6-Сб, 0-Вс). Значение 7-недопустимо. Так написано в datasheet, типа у регистра активны только 3 младших бита формирующих число от 0 до 6.
А на самом деле регистр хранит 7 значащих бит. Установленный бит указывает на день недели: 0-бит Вс, 1-бит Пн, 2-бит Вт, ... 6-бит Сб, 7-бит всегда 0.
4) Days Регистр счётчика дней в двоично-десятичном формате (0b XX11 0001 = 31день).
5) Months Регистр счётчика месяцев в двоично-десятичном формате (0b XXX1 0010 = 12мес = декабрь).
6) Years Регистр счётчика лет в двоично-десятичном формате (0b 1001 1001 = 99год).
7) Digital Offset Регистр регулировки точности часов. Хранит знаковое значение в 7-битном двоичном коде (от 62 = 0bX1000010, до +63 = 0bX0111111)
Частота поступающая на предделитель = 32768 Гц - DigitalOffset * 3,05 × 10^6. (32768Гц62*3,05×10^6 = 32768Гц+189.1×10^6)
Функция цифрового смещения корректирует количество тактовых импульсов каждые 20 сек. (в 00сек, 20сек и 40сек каждой минуты)
Частота на выходе FOUT не изменяется.
8) Alarm_W Minute Регистр минут будильника Alarm_W. Формат хранения данных аналогичен регистру Minutes.
9) Alarm_W Hour Регистр часов будильника Alarm_W. Формат хранения данных аналогичен регистру Hours.
WH20 WP,/A В 24-часовом формате бит функционирует как WH20
В 12-часовом формате бит функционирует как WP,/A (0-AM, 1-PM).
Формат часов задаёт бит /12,24 регистра Control-1.
A) Alarm_W Day Регистр дней недели будильника Alarm_W. Позволяет выбрать 1 до 7 дней недели.
WW6-WW0 WW1-Пн, WW2-Вт, WW3-ср, WW4-Чт, WW5-Пт, WW6-Сб, WW0-Вс.
Если все биты установлены в 0, то будильник Alarm_W выключен.
B) Alarm_D Minute Регистр минут будильника Alarm_D. Формат хранения данных аналогичен регистру Minutes.
C) Alarm_D Hour Регистр часов будильника Alarm_D. Формат хранения данных аналогичен регистру Hours.
DH20 DP,/A В 24-часовом формате бит функционирует как DH20
В 12-часовом формате бит функционирует как DP,/A (0-AM, 1-PM).
Формат часов задаёт бит /12,24 регистра Control-1.
E) Control-1 Регистр управления 1
WALE Бит разрешения работы будильника Alarm_W.
0 - будильник Alarm_W отключён.
1 - будильник Alarm_W включён, при совпадении времени на выводе /INTB появляется прерывание.
DALE Бит разрешения работы будильника Alarm_D.
0 - будильник Alarm_D отключён.
1 - будильник Alarm_D включён, при совпадении времени на выводе /INTA появляется прерывание.
/12,24 Бит выбора формата часов текущего времени и будильников.
0 - Часы текущего времени и будильников хранятся в 12-часовом формате.
1 - Часы текущего времени и будильников хранятся в 24-часовом формате.
TEST
CT2-CT0 Биты настройки периодического прерывания на выводе /INTA.
000 Периодическое прерывание отключено, вывод /INTA отключён.
001 Периодическое прерывание отключено, на выволе /INTA уровень 0.
010 - Периодическое прерывание работает на частоте 2 Гц с коэффициентом заполнения 50%.
011 - Периодическое прерывание работает на частоте 1 Гц с коэффициентом заполнения 50%.
100 - Периодическое прерывание срабатывает в начале каждой секунды.
101 - Периодическое прерывание срабатывает в начале 00 секунды каждой минуты.
110 - Периодическое прерывание срабатывает в начале 00 секунды, 00 минуты каждого часа.
111 - Периодическое прерывание срабатывает в начале 00 секунды, 00 минуты 00 часа каждого первого числа месяца.
F) Control-2 Регистр управления 2
VDSL Выбор порогового значения напряжения для функции обнаружения падения мощности.
0 - 2,1 В в качестве порога функции обнаружения падения мощности.
1 - 1,3 В в качестве порога функции обнаружения падения мощности.
VDET Флаг функции обнаружения падения мощности. Устанавливается в 1 после падения Vcc ниже порога.
Чтение: 0 - Падение мощности не обнаружено.
1 - Обнаружено падение Vcc ниже порогового. Флаг остаётся 1 до его перезаписи в 0 по шине I2C.
Запись: 0 - Сброс флага в 0 и перезапуск функции обнаружения падения мощности.
1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА.
/XST Флаг функции обнаружения остановки колебаний.
Чтение: 0 - Обнаружена остановка колебаний. Флаг остаётся 0 до его перезаписи в 1 по шине I2C.
1 - Остановка колебаний не обнаружено.
Запись: 0 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 0 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА.
1 - Сброс флага в 1 и перезапуск функции обнаружения остановки колебаний.
PON Флаг функции обнаружения сброса при включении питания.
Чтение: 0 - Сброс при включении питания не обнаружен.
1 - Обнаружен сброс при включении питания. Флаг остаётся 1 до его перезаписи в 0 по шине I2C.
Пока флаг установлен в 1, все биты регистров Digital-Offset, Control-1 и Control-2 (кроме PON и /XST) сбрасываются в «0». Это также приводит к остановке прерываний на выводах /INTA и /INTB.
Запись: 0 - Сброс флага в 0 и перезапуск функции обнаружения сброса при включении питания.
1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА.
• Бит является битом ОЗУ, он может содержать любое значение и доступен для чтения/записи. Бит сбрасывается в 0 если обнаружен сброс при включении питания (PON=1).
CTFG Флаг наличия периодического прерывания на выводе /INTA.
Чтение: 0 - На выходе /INTA нет сигнала периодического прерывания.
1 - На выходе /INTA установлен сигнал периодического прерывания.
Запись: 0 - Сброс флага в 0 и освобождение /INTA до следующего прерывания. Сброс возможен если не поступает очередное прерывание и не срабатывает будильник Alarm_D.
1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА.
WAFG Флаг будильника Alarm_W. Значение флага актуально если бит WALE регистра Control-1 равен 1.
Чтение: 0 - Будильник Alarm_W не сработал или бит WALE регистра Control-1 равен 0.
1 - Сработал будильник Alarm_W. Флаг остаётся 1 до его перезаписи в 0 по шине I2C.
Запись: 0 - Сброс флага в 0 и отключение прерывания на выводе /INTB.
1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА.
DAFG Флаг будильника Alarm_D. Значение флага актуально если бит DALE регистра Control-1 равен 1.
Чтение: 0 - Будильник Alarm_D не сработал или бит DALE регистра Control-1 равен 0.
1 - Сработал будильник Alarm_D. Флаг остаётся 1 до его перезаписи в 0 по шине I2C.
Запись: 0 - Сброс флага в 0 и отключение прерывания на выводе /INTA.
1 - ЗАПРЕЩЕНО! НЕ ЗАПИСЫВАЙТЕ 1 ДАЖЕ ЕСЛИ ЭТО НЕ ИМЕЕТ ЭФФЕКТА.

View File

@@ -0,0 +1,30 @@
# ####################################################
# СИНТАКСИЧЕСКАЯ РАСКРАСКА ДЛЯ БИБИЛИОТЕКИ:
# iarduino_RTC
# ####################################################
# ТИПЫ ДАННЫХ: (KEYWORD1)
iarduino_RTC KEYWORD1
# ####################################################
# МЕТОДЫ И ФУНКЦИИ: (KEYWORD2)
begin KEYWORD2
settime KEYWORD2
gettime KEYWORD2
settimeUnix KEYWORD2
gettimeUnix KEYWORD2
blinktime KEYWORD2
period KEYWORD2
seconds KEYWORD2
minutes KEYWORD2
hours KEYWORD2
Hours KEYWORD2
midday KEYWORD2
day KEYWORD2
weekday KEYWORD2
month KEYWORD2
year KEYWORD2
Unix KEYWORD2
# ####################################################
# КОНСТАНТЫ: (LITERAL1)
RTC_DS1302 LITERAL1
RTC_DS1307 LITERAL1
RTC_DS3231 LITERAL1

View File

@@ -0,0 +1,10 @@
name = iarduino RTC (часы реального времени)
version = 2.0.0
author = iarduino <shop@iarduino.ru>
maintainer = Панькин Павел <shop@iarduino.ru>
sentence = Библиотека для работы с часами реального времени.
paragraph = Поддерживает часы на чипах: DS1302, DS1307, DS3231, RX8025, есть возможность добавлять часы на других чипах. Библиотека позволяет устанавливать и считывать дату/время. Преимуществом данной библиотеки является удобная реализация получения времени. Считывание даты/времени можно осуществить как через переменные (year, month, day, hours, minutes, seconds и т.д.), так и одной строкой в которую попадут значения в соответствии с указанным Вами шаблоном.
category = Timing
url = http://iarduino.ru/file/235.html
architectures = avr,esp8266,esp32
includes = iarduino_RTC.h

View File

@@ -0,0 +1,134 @@
#include "iarduino_RTC.h"
// Вывод даты и времени
char* iarduino_RTC::gettime(String i){char j[i.length()+1]; i.toCharArray(j, i.length()); j[i.length()]=0; return gettime(j);}
char* iarduino_RTC::gettime(const char* i){
uint8_t j, k, n; bool f; // Объявляем локальные переменные
if(valRequest > millis()){valRequest=0;} // Избавляемся от переполнения millis()
// Получаем текущее время:
if(valPeriod == 0) {funcReadTime();}else // Если минимальный период опроса модуля == 0 минут, то получаем время из регистров модуля, иначе ...
if(valRequest == 0 || (valPeriod+valRequest <= millis())) {funcReadTime();}else // Если время последнего опроса модуля превысило минимальный период опроса модуля, то получаем время из регистров модуля, иначе ...
{funcCalculationTime();} // Получаем время без обращения к модулю (время рассчитывая исходя из millis и valRequest)
funcSetMoreTime(); // Преобразуем переменные не читаемые из модуля
// Вычисляем размер блока памяти под строку с ответом:
n=strlen(i)+1; // Определяем размер равный введённой строке (i) + 1 символ конца строки
for(j=0; j<strlen(i); j++) { // Проходим по символам полученной строки
for(k=0; k<strlen(charInput); k++) { // Проходим по служебным символам строки charInput
if (i[j]==charInput[k]) { // Если символы обеих строк совпали, то ...
if(k>0){n++;} if(k>9){n++;} if(k>11){n++;} // Увеличиваем размер (n) в соостветствии со значениём найденного служебного символа
}}}
// Выделяем блок памяти под строку с ответом:
free(charReturn); // Освобождаем ранее созданный блок памяти
charReturn = (char*) malloc(n); // Выделяем новый блок памяти размером n байт
// Заполняем выделенный блок памяти:
n=0; // Определяем позицию в блоке памяти для следующего подставляемого значения
for(j=0; j<strlen(i); j++) { // Проходим по символам полученной строки
if(i[j]==charInput[0] /* w */ ) {funcFillChar( weekday ,0,n,7); n+=1;}else // Подставляем день недели от 0 до 6 (один знак: 0-воскресенье, 6-суббота)
if(i[j]==charInput[1] /* a */ ) {funcFillChar( midday*2 ,2,n,8); n+=2;}else // Подставляем полдень am или pm (два знака, в нижнем регистре)
if(i[j]==charInput[2] /* A */ ) {funcFillChar((midday+2)*2 ,2,n,8); n+=2;}else // Подставляем полдень AM или PM (два знака, в верхнем регистре)
if(i[j]==charInput[3] /* d */ ) {funcFillChar( day ,1,n,4); n+=2;}else // Подставляем день месяца от 01 до 31 (два знака)
if(i[j]==charInput[4] /* h */ ) {funcFillChar( hours ,1,n,3); n+=2;}else // Подставляем часы от 01 до 12 (два знака)
if(i[j]==charInput[5] /* H */ ) {funcFillChar( Hours ,1,n,3); n+=2;}else // Подставляем часы от 00 до 23 (два знака)
if(i[j]==charInput[6] /* i */ ) {funcFillChar( minutes ,1,n,2); n+=2;}else // Подставляем минуты от 00 до 59 (два знака)
if(i[j]==charInput[7] /* m */ ) {funcFillChar( month ,1,n,5); n+=2;}else // Подставляем месяц от 01 до 12 (два знака)
if(i[j]==charInput[8] /* s */ ) {funcFillChar( seconds ,1,n,1); n+=2;}else // Подставляем секунды от 00 до 59 (два знака)
if(i[j]==charInput[9] /* y */ ) {funcFillChar( year ,1,n,6); n+=2;}else // Подставляем год от 00 до 99 (два знака)
if(i[j]==charInput[10] /* M */ ) {funcFillChar((month+6)*3 ,3,n,5); n+=3;}else // Подставляем имя месяца от Jan до Dec (три знака: Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)
if(i[j]==charInput[11] /* D */ ) {funcFillChar( weekday*3 ,3,n,7); n+=3;}else // Подставляем имя деня недели от Mon до Sun (три знака: Mon Tue Wed Thu Fri Sat Sun)
if(i[j]==charInput[12] /* Y */ ) {funcFillChar( year ,4,n,6); n+=4;}else // Подставляем год от 2000 до 2099 (четыре знака)
{charReturn[n]=i[j]; n+=1;} // Если символ полученной строки не совпал со служебными, то подставляем его в блок памяти как есть, без изменений
} charReturn[n]='\0'; return charReturn; // Устанавливаем символ конца строки и возвращаем указатель на блок памяти с результатом
}
// Заполняем значением определённую позицию блока памяти:
void iarduino_RTC::funcFillChar(uint8_t i, uint8_t j, uint8_t n, uint8_t k){ // (данные, тип данных, позиция для вставки, мигание)
bool f=valBlink==k; if((millis()%valFrequency)<(valFrequency/2)){f=false;} // Устанавливаем флаг мигания, если значение valBlink равно значению параметра k
switch (j){
/* 1 знак */ case 0: if(i>6 ){i=6; } charReturn[n]=f?32:i+48; break;
/* 2 знака */ case 1: if(i>99){i=99;} charReturn[n]=f?32:i/10+48; charReturn[n+1]=f?32:i%10+48; break;
/* AM / PM */ case 2: if(i>6 ){i=6; } charReturn[n]=f?32:charMidday[i]; charReturn[n+1]=f?32:charMidday[i+1]; break;
/* дн / мес */ case 3: if(i>54){i=54;} charReturn[n]=f?32:charDayMon[i]; charReturn[n+1]=f?32:charDayMon[i+1]; charReturn[n+2]=f?32:charDayMon[i+2]; break;
/* 4 знака */ case 4: if(i>99){i=99;} charReturn[n]=f?32:(valCentury-1)/10+48; charReturn[n+1]=f?32:(valCentury-1)%10+48; charReturn[n+2]=f?32:i/10+48; charReturn[n+3]=f?32:i%10+48; break;
}
}
// Установка даты и времени
void iarduino_RTC::settime(int i1, int i2, int i3, int i4, int i5, int i6, int i7){ // (сек, мин, час, день, мес, год, день_недели)
funcWriteTime(i1, i2, i3, i4, i5, i6, i7); // Записываем дату и время в регистры модуля
funcReadTime(); // Читаем дату и время из регистров модуля
funcSetMoreTime(); // Корректируем переменные не читаемые из модуля (hours, midday)
}
// Установка даты и времени от начала эпохи Unix
void iarduino_RTC::settimeUnix(uint32_t i){ // (сек)
uint32_t j; uint8_t k; bool f=true; // Объявляем временные переменные.
seconds = i % 60; // Получаем текущее значение секунд. (остаток от деления секунд прошедших с начала эпохи Unix на количество секунд в минуте)
i = (i-seconds) / 60; // Получаем количество минут прошедших с начала эпохи Unix.
minutes = i % 60; // Получаем текущее значение минут. (остаток от деления минут прошедших с начала эпохи Unix на количество минут в часе)
i = (i-minutes) / 60; // Получаем количество часов прошедших с начала эпохи Unix.
Hours = i % 24; // Получаем текущее значение часов. (остаток от деления часов прошедших с начала эпохи Unix на количество часов в дне)
i = (i-Hours) / 24; // Получаем количество дней прошедших с начала эпохи Unix.
j = 0; while((((j+1)*365)+((j+2)/4))<=i){j++;} // Получаем количество лет прошедших с начала эпохи Unix.
weekday = (i+4) % 7; // Получаем текущий день недели. (0-воскресенье, 1-понедельник, ... , 6-суббота)
i = i - (j*365) - ((j+1)/4); // Получаем количество дней прошедших в текущем году.
valCentury = ((1970+j)/100)+1; // Получаем текущий век.
year = (1970+j)%100; // Получаем две последние цифры текущего года.
k = ((1970+j)%4)==0?29:28; // Получаем количество дней в феврале текущего года.
month = 0; while(f){month++; j=month; j=(((j+1)%2)^(j<8))?31:(j==2?k:30); if(i>=j){i-=j;}else{f=false;}}
day = i+1; // Получаем текущий день.
// Устанавливаем время:
settime(seconds, minutes, Hours, day, month, year, weekday);
}
// Чтение даты и времени в переменные из регистров модуля:
void iarduino_RTC::funcReadTime(void){ // (без параметров)
seconds = arrCalculationTime[0] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(0)); // Получаем секунды
minutes = arrCalculationTime[1] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(1)); // Получаем минуты
Hours = arrCalculationTime[2] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(2)); // Получаем часы
day = arrCalculationTime[3] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(3)); // Получаем день
month = arrCalculationTime[4] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(4)); // Получаем месяц
year = arrCalculationTime[5] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(5)); // Получаем год
weekday = arrCalculationTime[6] = funcConvertCodeToNum(objClass -> funcReadTimeIndex(6))-1; // Получаем день недели (в регистре значение от 1 до 7, а в переменной от 0 до 6)
Unix = funcCalculationUnix(); // Получаем количество секунд (прошедших с начала эпохи Unix)
valRequest = millis(); // Сохраняем время данного запроса
}
// Запись даты и времени в регистры модуля:
void iarduino_RTC::funcWriteTime(int i1, int i2, int i3, int i4, int i5, int i6, int i7){ //
if(i1<=60 && i1>=0){objClass -> funcWriteTimeIndex(0, funcConvertNumToCode(i1 ));} // Сохраняем секунды
if(i2<=60 && i2>=0){objClass -> funcWriteTimeIndex(1, funcConvertNumToCode(i2 ));} // Сохраняем минуты
if(i3<=23 && i3>=0){objClass -> funcWriteTimeIndex(2, funcConvertNumToCode(i3 ));} // Сохраняем часы
if(i4<=31 && i4>=1){objClass -> funcWriteTimeIndex(3, funcConvertNumToCode(i4 ));} // Сохраняем день
if(i5<=12 && i5>=1){objClass -> funcWriteTimeIndex(4, funcConvertNumToCode(i5 ));} // Сохраняем месяц
if(i6<=99 && i6>=0){objClass -> funcWriteTimeIndex(5, funcConvertNumToCode(i6 ));} // Сохраняем год
if(i7<= 6 && i7>=0){objClass -> funcWriteTimeIndex(6, funcConvertNumToCode(i7+1));} // Сохраняем день недели (в регистре значение от 1 до 7, а в переменной от 0 до 6)
}
// Расчёт времени без обращения к модулю:
void iarduino_RTC::funcCalculationTime(void){ // (без параметров)
uint32_t i=(millis()-valRequest)/1000; // Определяем количество секунд (прошедших после последнего обращения к модулю)
uint8_t j=30 + ( (arrCalculationTime[4] + (arrCalculationTime[4]>7?1:0)) % 2 ); // Определяем количество дней в месяце (31, 30, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
if(arrCalculationTime[4]==2){j=28+((((uint16_t)valCentury-1)*100+arrCalculationTime[5])%4?0:1);}// Если текущий месяц - февраль, то меняем на ... (31, 28/29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
i+=arrCalculationTime[0]; seconds = i%60; i/=60; // Добавляем к прошедним секундам (i) посление прочитанные секунды (arrCalculationTime[0]), результатом будет остаток, а значение i превращаем в минуты
i+=arrCalculationTime[1]; minutes = i%60; i/=60; // Добавляем к прошедним минутам (i) посление прочитанные минуты (arrCalculationTime[1]), результатом будет остаток, а значение i превращаем в часы
i+=arrCalculationTime[2]; Hours = i%24; i/=24; // Добавляем к прошедним часам (i) посление прочитанные часы (arrCalculationTime[2]), результатом будет остаток, а значение i превращаем в дни
weekday = arrCalculationTime[6]+i; if(weekday>6){weekday=0;} // День недели увеличится на (i) от прочитанного дня недели (arrCalculationTime[6])
i+=arrCalculationTime[3]; day = i%(j+1); i/=(j+1); day+=i; // Добавляем к прошедним дням (i) посление прочитанные дни (arrCalculationTime[3]), результатом будет остаток, а значение i превращаем в месяцы
i+=arrCalculationTime[4]; month = i%13; i/=13; month+=i; // Добавляем к прошедним месяцам (i) посление прочитанные месяцы (arrCalculationTime[4]), результатом будет остаток, а значение i превращаем в годы
i+=arrCalculationTime[5]; year = i%100; // Добавляем к прошедним годам (i) посление прочитанные годы (arrCalculationTime[5]), результатом будет остаток, а значение i превращаем в дни
Unix = funcCalculationUnix(); // Получаем количество секунд прошедших с начала эпохи Unix
}
// Расчёт количества cекунд прошедших с начала эпохи Unix:
uint32_t iarduino_RTC::funcCalculationUnix(void){ // (без параметров)
uint32_t i; // Объявляем переменную для хранения результата. (рассчёты производятся из значений переменных: seconds, minutes, Hours, day, month, year и valCentury).
uint32_t j = (uint32_t)(valCentury-1) * 100 + year; // Определяем текущий год с учётом века. (valCentury - век, year - последние два знака текущего года).
i = j - 1970; // Определяем количество прошедших лет (с 01.01.1970 г.)
i = i * 365 + ((i+1)/4); // Определяем количество дней в прошедших годах ((i+1)/4) - количество прошедших високосных лет (без учёта текущего года).
i += (month-1)*30 + ( (month + (month<9?0:1) )/2 ); // Добавляем количество дней в прошедших месяцах ((month+(month<9?0:1))/2) - количество прошедших месяцев текущего года, содержащих 31 день.
i -= month>2? (j%4==0?1:2) : 0; // Вычитаем 1 или 2 дня из февраля текущего года ((month>2) - если февраль уже прошел, j%4==0 - если текущий год високосный)
i += day-1; // Добавляем количество прошедших дней этого месяца
i *= 86400; // Получаем количество секунд прошедших дней
i += (uint32_t)Hours * 3600 + (uint32_t)minutes * 60 + seconds; // Добавляем количество секунд текущего дня
return i; // Возвращаем результат
}

View File

@@ -0,0 +1,107 @@
// Библиотека для работы с часами реального времени: (на чипе DS1302) https://iarduino.ru/shop/Expansion-payments/rtc-modul-ds1302.html
// (на чипе DS1307) https://iarduino.ru/shop/Expansion-payments/kroshechnye-rtc-modul-realnogo-vremeni.html
// https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul.html
// (на чипе DS3231) https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-ds3231.html
// https://iarduino.ru/shop/Expansion-payments/chasy-realnogo-vremeni-rtc-trema-modul-v2-0.html
// (на чипе RX8025)
// Версия: 2.0.0
// Последнюю версию библиотеки Вы можете скачать по ссылке: https://iarduino.ru/file/235.html
// Подробное описание функции бибилиотеки доступно по ссылке: https://wiki.iarduino.ru/page/chasy-realnogo-vremeni-rtc-trema-modul/
// Библиотека является собственностью интернет магазина iarduino.ru и может свободно использоваться и распространяться!
// При публикации устройств или скетчей с использованием данной библиотеки, как целиком, так и её частей,
// в том числе и в некоммерческих целях, просим Вас опубликовать ссылку: https://iarduino.ru
// Автор библиотеки: Панькин Павел
// Если у Вас возникли технические вопросы, напишите нам: shop@iarduino.ru
#ifndef iarduino_RTC_h //
#define iarduino_RTC_h //
//
#define RTC_UNDEFINED 0 // Модуль часов реального времени не определён
//
#if defined(ARDUINO) && (ARDUINO >= 100) //
#include <Arduino.h> //
#else //
#include <WProgram.h> //
#endif //
//
#include "memorysaver.h" // Подключаем файл «хранитель памяти» (внутри файла есть комментарий поясняющий как сэкономить мапять)
//
class iarduino_RTC_BASE{ // Объявляем полиморфный класс
public: //
virtual void begin (void); // Объявляем функцию инициализации модуля (без параметров)
virtual uint8_t funcReadTimeIndex (uint8_t); // Объявляем функцию чтения 1 значения из регистров даты и времени (0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
virtual void funcWriteTimeIndex (uint8_t, uint8_t); // Объявляем функцию записи 1 значения в регистры даты и времени (0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, значение)
}; //
//
#include "iarduino_RTC_DS1302.h" // Подключаем файл iarduino_RTC_DS1302.h
#include "iarduino_RTC_DS1307.h" // Подключаем файл iarduino_RTC_DS1307.h
#include "iarduino_RTC_DS3231.h" // Подключаем файл iarduino_RTC_DS3231.h
#include "iarduino_RTC_RX8025.h" // Подключаем файл iarduino_RTC_RX8025.h
//
class iarduino_RTC{ //
public: //
/** Конструктор класса **/ //
iarduino_RTC(uint8_t i, uint8_t j=SS, uint8_t k=SCK, uint8_t n=MOSI){ // Конструктор основного класса (название [, вывод SS/RST [, вывод SCK/CLK [, вывод MOSI/DAT]]])
switch(i){ // Тип выбранного модуля
#ifdef RTC_ENABLE_DS1302 //
case RTC_DS1302: objClass = new iarduino_RTC_DS1302(j,k,n); break; // Если используется модуль на базе чипа DS1302, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS1302 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
#endif //
#ifdef RTC_ENABLE_DS1307 //
case RTC_DS1307: objClass = new iarduino_RTC_DS1307; break; // Если используется модуль на базе чипа DS1307, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS1307 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
#endif //
#ifdef RTC_ENABLE_DS3231 //
case RTC_DS3231: objClass = new iarduino_RTC_DS3231; break; // Если используется модуль на базе чипа DS3231, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_DS3231 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
#endif //
#ifdef RTC_ENABLE_RX8025 //
case RTC_RX8025: objClass = new iarduino_RTC_RX8025; break; // Если используется модуль на базе чипа RX8025, то присваеиваем указателю objClass ссылку на новый объект производного класса iarduino_RTC_RX8025 переопределяя на него все виртуальные функции полиморфного класса iarduino_RTC_BASE
#endif //
} //
} //
/** Пользовательские функции **/ //
void begin (void) {objClass -> begin(); gettime();} // Определяем функцию инициализации модуля (без параметров)
void period (uint8_t i) {valPeriod=i; valPeriod*=60000;} // Определяем функцию задания минимального периода обращения к модулю (i = период в минутах)
void blinktime (uint8_t i, float j=1) {valBlink=i; valFrequency=uint32_t(1000/j);} // Определяем функцию позволяющую мигать одним из параметров времени (i = 0-нет / 1-сек / 2-мин / 3-час / 4-день / 5-мес / 6-год / 7-день_недели / 8-полдень , j = частота мигания в Гц)
void gettime (void) {gettime("");} // Определяем функцию получения даты и времени из переменных (без параметров)
char* gettime (String); // Объявляем функцию «дублёр» получения даты и времени из переменных (строка с параметрами)
char* gettime (const char*); // Объявляем функцию получения даты и времени ввиде строки (строка с параметрами)
void settime (int, int=-1, int=-1, int=-1, int=-1, int=-1, int=-1); // Объявляем функцию установки даты и времени (сек, мин, час, день, мес, год, день_недели)
uint32_t gettimeUnix (void) {gettime(""); return Unix;} // Определяем функцию получения cекунд прошедших с начала эпохи Unix (без параметров)
void settimeUnix (uint32_t); // Объявляем функцию установки cекунд прошедших с начала эпохи Unix (сек)
//
/** Переменные доступные для пользователя **/ //
uint8_t seconds = 0; // Секунды 0-59
uint8_t minutes = 0; // Минуты 0-59
uint8_t hours = 1; // Часы 1-12
uint8_t Hours = 0; // Часы 0-23
uint8_t midday = 0; // Полдень 0-1 (0-am, 1-pm)
uint8_t day = 1; // День месяца 1-31
uint8_t weekday = 0; // День недели 0-6 (0-воскресенье, 1-понедельник, ... , 6-суббота)
uint8_t month = 1; // Месяц 1-12
uint8_t year = 0; // Год 0-99 (без учёта века)
uint32_t Unix = 0; // Секунды прошедшие с начала эпохи Unix (01.01.1970 00:00:00 GMT)
//
/** Внутренние переменные **/ //
iarduino_RTC_BASE* objClass; // Объявляем указатель на объект полиморфного класса (функции данного класса будут переопределены, т.к. указателю будет присвоена ссылка на производный класс)
char* charReturn = (char*) malloc(1); // Определяем указатель на символьную область памяти в 1 байт (указатель будет ссылаться на строку вывода времени)
const char* charInput = "waAdhHimsyMDY"; // Определяем константу-строку с символами требующими замены (данные символы заменяются функцией gettime на значение времени)
const char* charMidday = "ampmAMPM"; // Определяем константу-строку для вывода полудня (am / pm / AM / PM)
const char* charDayMon = "SunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec"; // Определяем константу-строку для вывода дня недели или месяца (Mon ... Sun / Jan ... Dec)
uint8_t arrCalculationTime[7]; // Объявляем массив для рассчёта времени без обращения к модулю (для хранения последних, прочитанных из модуля, значений даты и времени)
uint8_t valBlink = 0; // Определяем параметр времени, который должен мигать (1-сек / 2-мин / 3-час / 4-день / 5-мес / 6-год / 7-день_недели / 8-полдень)
uint32_t valFrequency = 1000; // Определяем частоту мигания параметра времени для функции blinktime (по умолчанию 1 Гц)
uint8_t valCentury = 21; // Определяем переменную для хранения текущего века (по умолчанию 21 век)
uint16_t valPeriod = 0; // Определяем минимальный период опроса модуля (в минутах, от 00 до 255)
uint32_t valRequest = 0; // Определяем время последнего чтения регистров времени
private: //
/** Внутренние функции **/ //
void funcReadTime (void); // Объявляем функцию чтения даты и времени из регистров модуля (без параметров)
void funcWriteTime (int, int, int, int, int, int, int); // Объявляем функцию записи даты и времени в регистры модуля (без параметров)
uint8_t funcConvertCodeToNum (uint8_t i) {return (i >> 4)*10 + (i & 0x0F);} // Определяем функцию преобразования двоично-десятичного кода в число (код)
uint8_t funcConvertNumToCode (uint8_t i) {return ((i/10) << 4) + (i%10);} // Определяем функцию преобразования числа в двоично-десятичный код (число)
void funcSetMoreTime (void){hours=(Hours%12)?(Hours%12):12; midday=(Hours<12)?0:1;} // Корректировка переменных не читаемых из модуля (без параметров)
void funcCalculationTime (void); // Объявляем функцию расчёта времени без обращения к модулю (без параметров)
uint32_t funcCalculationUnix (void); // Объявляем функцию расчёта cекунд прошедших с начала эпохи Unix (без параметров)
void funcFillChar (uint8_t, uint8_t, uint8_t, uint8_t); // Объявляем функцию заполнения строки вывода времени (данные, тип данных, позиция для вставки, мигание)
}; //
//
#endif //

View File

@@ -0,0 +1,67 @@
#ifndef iarduino_RTC_DS1302_h //
#define iarduino_RTC_DS1302_h //
#define RTC_DS1302 1 // Модуль часов реального времени с протоколом передачи данных SI3, памятью 040x8 (31 байт которой доступны для хранения данных пользователя)
//
class iarduino_RTC_DS1302: public iarduino_RTC_BASE{ //
public: //
/** Конструктор класса **/ //
iarduino_RTC_DS1302(uint8_t i=SS, uint8_t j=SCK, uint8_t k=MOSI){pinRES=i; pinCLK=j; pinDAT=k;} // (вывод RST, вывод CLK, вывод DAT)
/** функции доступные пользователю **/ //
// Инициализация модуля: //
void begin(void){ // (без параметров)
// Инициализация работы с трехпроводной шиной: //
funcBegin(); // (без параметров)
// Установка флагов управления и состояния модуля: //
varI=funcReadReg(0x81); if( varI & 0b10000000){funcWriteReg(0x81, (varI&~0b10000000));} // (если установлен 7 бит в 129 регистре, то сбрасываем его - запускаем генератор)
varI=funcReadReg(0x85); if( varI & 0b10000000){funcWriteReg(0x85, (varI&~0b10000000));} // (если установлен 7 бит в 133 регистре, то сбрасываем его - переводим модуль в 24 часовой режим)
varI=funcReadReg(0x8F); if( varI & 0b10000000){funcWriteReg(0x8F, (varI&~0b10000000));} // (если установлен 7 бит в 143 регистре, то сбрасываем его - разрешаем запись в регистры модуля)
} //
//
// Чтение одного значения из регистров даты и времени модуля: //
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
delay(1); return funcReadReg(arrTimeRegAddr[i]) & arrTimeRegMack[i]; //
} //
//
// Запись одного значения в регистры даты и времени модуля: //
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
varI=funcReadTimeIndex(i); // Читаем данные из регистра i
j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
funcWriteReg(arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i]
} //
//
private: //
/** Внутренние переменные **/ //
uint8_t pinRES = 0; // Определяем переменную для хранения номера вывода RST трехпроводной шины
uint8_t pinCLK = 0; // Определяем переменную для хранения номера вывода CLK трехпроводной шины
uint8_t pinDAT = 0; // Определяем переменную для хранения номера вывода DAT трехпроводной шины
uint8_t arrTimeRegAddr[7] = {0x81,0x83,0x85,0x87,0x89,0x8D,0x8B}; // Определяем массив с адресами регистров чтения даты и времени (сек, мин, час, день, месяц, год, день недели)
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
uint8_t busRate = 10; // Скорость передачи данных трехпроводной шине в кГц (до 255 кГц)
uint8_t varI; //
//
/** Внутренние функции **/ //
// Функция чтения данных из регистра модуля: //
uint8_t funcReadReg(uint8_t i){ // Определяем функцию читения данных из регистра модуля (аргумент: адрес_регистра)
varI=1; // Предустанавливаем переменную varI в значение 1, чтоб не вывести: 45 апреля 255 часов 127 минут и 200 секунд
digitalWrite (pinRES, 1); // Устанавливаем линию RES в активное состояние
funcWriteByte (i); // Отправляем адрес регистра
varI=funcReadByte (true); // Читаем байт из регистра с учётом предустановленного бита
digitalWrite (pinRES, 0); // Устанавливаем линию RES в неактивное состояние
return varI; // Возвращаем значение переменной varI
} //
// Функция записи данных в регистр модуля: //
void funcWriteReg(uint8_t i, uint8_t j){ // Определяем функцию записи данных в регистр модуля (аргументы: адрес_регистра, байт_данных)
digitalWrite (pinRES, 1); // Устанавливаем линию RES в активное состояние
funcWriteByte (i-1); // Отправляем адрес регистра (при чтении указывается адрес-1)
funcWriteByte (j); // Отправляем байт данных
digitalWrite (pinRES, 0); // Устанавливаем линию RES в неактивное состояние
} //
//
/** функции для работы с трехпроводной шиной **/ //
void funcWriteByte (uint8_t j) /* Передача одного байта (байт для передачи) */ {uint8_t i=0, n=500/busRate+1; pinMode(pinDAT, OUTPUT); while(i>=0 && i<8){digitalWrite(pinDAT, (j & _BV(i))); delayMicroseconds(n); digitalWrite(pinCLK, 1); delayMicroseconds(n); digitalWrite(pinCLK, 0); i++;} pinMode(pinDAT, INPUT);}
uint8_t funcReadByte (bool j) /* Получение одного байта (флаг чтения предустановленного бита с линии DAT) */ {uint8_t i=0, k=0, n=500/busRate+1; pinMode(pinDAT, INPUT); if(j){if(digitalRead(pinDAT)){k |= _BV(i);} i++;} while(i>=0 && i<8){digitalWrite(pinCLK, 1); delayMicroseconds(n); digitalWrite(pinCLK, 0); delayMicroseconds(n); if(digitalRead(pinDAT)){k |= _BV(i);} i++;} return k;}
void funcBegin (void) /* Подготовка выводов шины (без параметров) */ {pinMode(pinRES, OUTPUT); pinMode(pinCLK, OUTPUT); pinMode(pinDAT, INPUT); digitalWrite(pinCLK, 0); digitalWrite(pinRES, 0);}
}; //
//
#endif //

View File

@@ -0,0 +1,42 @@
#ifndef iarduino_RTC_DS1307_h //
#define iarduino_RTC_DS1307_h //
#define RTC_DS1307 2 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 064x8 (56 байт которой доступны для хранения данных пользователя)
#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C
//
class iarduino_RTC_DS1307: public iarduino_RTC_BASE{ //
public: //
/** функции доступные пользователю **/ //
// Инициализация модуля: //
void begin(void){ // (без параметров)
// Инициализация работы с шиной I2C: //
objI2C.begin(100); // (скорость шины в кГц)
// Установка флагов управления и состояния модуля: //
varI=objI2C.readByte(valAddress, 0x00); if( varI & 0b10000000 ){objI2C.writeByte(valAddress, 0x00, (varI&~0b10000000) );} // (если установлен 7 бит в 0 регистре, то сбрасываем его - запускаем генератор)
varI=objI2C.readByte(valAddress, 0x02); if( varI & 0b01000000 ){objI2C.writeByte(valAddress, 0x02, (varI&~0b01000000) );} // (если установлен 6 бит в 2 регистре, то сбрасываем его - переводим модуль в 24 часовой режим)
varI=objI2C.readByte(valAddress, 0x07); if((varI & 0b00000011) || !(varI & 0b00010000)){objI2C.writeByte(valAddress, 0x07, (varI&~0b00000011)|0b00010000 );} // (если установлены 1 и 0 биты или сброшен 4 бит в 7 регистре, то сбрасываем 1 с 0 битами, а 4 устанавливаем - выводим меандр с частотой 1 Гц на выводе SQW/OUT модуля)
} //
//
// Чтение одного значения из регистров даты и времени модуля: //
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
delay(1); //
return objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; //
} //
//
// Запись одного значения в регистры даты и времени модуля: //
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
varI=funcReadTimeIndex(i); // Читаем данные из регистра i
j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
objI2C.writeByte(valAddress, arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i]
} //
//
private: //
/** Внутренние переменные **/ //
iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C
uint8_t valAddress = 0x68; // Адрес модуля на шине I2C
uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели)
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
uint8_t varI; //
}; //
//
#endif //

View File

@@ -0,0 +1,42 @@
#ifndef iarduino_RTC_DS3231_h //
#define iarduino_RTC_DS3231_h //
#define RTC_DS3231 3 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 019x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором
#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C
//
class iarduino_RTC_DS3231: public iarduino_RTC_BASE{ //
public: //
/** функции доступные пользователю **/ //
// Инициализация модуля: //
void begin(void){ // (без параметров)
// Инициализация работы с шиной I2C: //
objI2C.begin(100); // (скорость шины в кГц)
// Установка флагов управления и состояния модуля: //
varI=objI2C.readByte(valAddress, 0x02); if( varI & 0b01000000 ){objI2C.writeByte(valAddress, 0x02, (varI&~0b01000000) );} // (если установлен 6 бит в 2 регистре, то сбрасываем его - переводим модуль в 24 часовой режим)
varI=objI2C.readByte(valAddress, 0x0E); if( varI & 0b11011111 ){objI2C.writeByte(valAddress, 0x0E, (varI&~0b11011111) );} // (если установлены 7,6,4,3,2,1 и 0 биты в 14 регистре, то сбрасываем их - разрешаем генератору работать от батарейки, запрещаем выводу SQW работать от батарейки, выводим меандр с частотой 1Гц на вывод SQW, переводим вывод INT/SQW в режим SQW, запрещаем прерывания будильников)
varI=objI2C.readByte(valAddress, 0x0F); if((varI & 0b10000011) || !(varI & 0b00001000)){objI2C.writeByte(valAddress, 0x0F, (varI&~0b10000011)|0b00001000 );} // (если установлены 7,1 и 0 биты или сброшен 3 бит в 15 регистре, то сбрасываем 7,1 и 0 биты, а 3 устанавливаем - сбрасываем флаг остановки генератора, разрешаем меандр с частотой 32768Гц на выводе 32kHz, сбрасываем флаги будильников)
} //
//
// Чтение одного значения из регистров даты и времени модуля: //
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
delay(1); //
return objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; //
} //
//
// Запись одного значения в регистры даты и времени модуля: //
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
varI=funcReadTimeIndex(i); // Читаем данные из регистра i
j |= ~arrTimeRegMack[i] & varI; // Устанавливаем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
j &= arrTimeRegMack[i] | varI; // Сбрасываем биты значения j по маске arrTimeRegMack[i] в прочитанные из регистра i
objI2C.writeByte(valAddress, arrTimeRegAddr[i], j); // Сохраняем значение j в регистр arrTimeRegAddr[i]
} //
//
private: //
/** Внутренние переменные **/ //
iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C
uint8_t valAddress = 0x68; // Адрес модуля на шине I2C
uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели)
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x07}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
uint8_t varI; //
}; //
//
#endif //

View File

@@ -0,0 +1,461 @@
#ifndef iarduino_I2C_h // Разрешаем включить данный код в скетч, только если он не был включён ранее
#define iarduino_I2C_h // Запрещаем повторное включение данного кода в скетч
//
// Определяем тип реализации шины I2C: //
#define iarduino_I2C_SW // Объявляем константу iarduino_I2C_SW - Возможна программная реализация шины I2C.
#if (!defined(pin_SW_SDA) || !defined(pin_SW_SCL)) // Если выводы не определены пользователем, то ...
#undef iarduino_I2C_SW // Отменяем объявление константы iarduino_I2C_SW - Программная реализация шины I2C не возможна (так как выводы не указаны).
#if defined(ESP8266) || defined(ESP32) // Если используются указанные платы, то ...
#include <Wire.h> // Подключаем библиотеку Wire.
#define pin_SW_SDA 255 // № вывода SDA не определён
#define pin_SW_SCL 255 // № вывода SCL не определён
#define iarduino_I2C_TW // Объявляем константу iarduino_I2C_TW - Будет использована аппаратная реализация шины I2C под управлением библиотеки Wire.
#elif defined(TwoWire_h) // Проверяем не подключена ли библиотека Wire.
#define pin_SW_SDA 255 // № вывода SDA не определён
#define pin_SW_SCL 255 // № вывода SCL не определён
#define iarduino_I2C_TW // Объявляем константу iarduino_I2C_TW - Будет использована аппаратная реализация шины I2C под управлением библиотеки Wire.
#elif (defined(SDA) && defined(SCL)) // Определяем выводы для шины I2C
#define pin_SW_SDA SDA // № вывода SDA = SDA
#define pin_SW_SCL SCL // № вывода SCL = SCL
#define iarduino_I2C_HW // Объявляем константу iarduino_I2C_HW - Будет использована аппаратная реализация шины I2C.
#elif (defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)) // Определяем выводы для шины I2C
#define pin_SW_SDA PIN_WIRE_SDA // № вывода SDA = PIN_WIRE_SDA
#define pin_SW_SCL PIN_WIRE_SCL // № вывода SCL = PIN_WIRE_SCL
#define iarduino_I2C_HW // Объявляем константу iarduino_I2C_HW - Будет использована аппаратная реализация шины I2C.
#elif (defined(SDA1) && defined(SCL1)) // Определяем выводы для шины I2C-1
#define pin_SW_SDA SDA1 // № вывода SDA = SDA1
#define pin_SW_SCL SCL1 // № вывода SCL = SCL1
#define iarduino_I2C_HW_1 // Объявляем константу iarduino_I2C_HW_1 - Будет использована аппаратная реализация шины I2C-1.
#else // Если выводы определить не удалось, то ...
#define pin_SW_SDA 255 // № вывода SDA не определён - Аппаратная реализация шины I2C не возможна.
#define pin_SW_SCL 255 // № вывода SCL не определён - Аппаратная реализация шины I2C не возможна.
#endif //
#endif //
//
class iarduino_I2C_BASE{ // Определяем полиморфный класс
public: // Доступные методы и функции:
// ОСНОВНЫЕ ФУНКЦИИ: (поддерживаются библиотекой Wire) //
virtual void begin (uint32_t); // Объявляем функцию указания скорости шины I2C. Аргументы: скорость в кГц.
virtual uint8_t readByte (uint8_t, uint8_t ); // Объявляем функцию чтения байта данных из регистра модуля. Аргументы: адресодуля, адрес_регистра. (адрес регистра указывает модулю, данные какого регистра требуется отправить мастеру)
virtual bool writeByte (uint8_t, uint8_t, uint8_t); // Объявляем функцию записи байта данных в регистр модуля. Аргументы: адресодуля, адрес_регистра, байт_данных. (адрес регистра указывает модулю, в какой регистр требуется сохранить данные)
virtual uint8_t readByte (uint8_t ); // Объявляем функцию чтения байта данных из модуля. Аргументы: адресодуля (функция отличается тем, что она не отправляет модулю адрес регистра)
virtual bool writeByte (uint8_t, uint8_t); // Объявляем функцию записи байта данных в модуль. Аргументы: адресодуля, байт_данных. (функция отличается тем, что она не отправляет модулю адрес регистра)
virtual bool readBytes (uint8_t, uint8_t, uint8_t*, uint8_t); // Объявляем функцию чтения байтов данных из регистров модуля. Аргументы: адресодуля, адрес_первого_регистра, указатель_наассив, количество_байт. (адрес первого регистра указывает модулю, с какого регистра требуется начать передачу данных мастеру)
virtual bool writeBytes (uint8_t, uint8_t, uint8_t*, uint8_t); // Объявляем функцию записи байтов данных в регистры модуля. Аргументы: адресодуля, адрес_первого_регистра, указатель_наассив, количество_байт. (адрес первого регистра указывает модулю, начиная с какого регистра требуется сохранять данные)
virtual bool readBytes (uint8_t, uint8_t*, uint8_t); // Объявляем функцию чтения байтов данных из модуля. Аргументы: адресодуля, указатель_наассив, количество_байт. (функция отличается тем, что она не отправляет модулю адрес первого регистра, а начинает цикл чтения сразу после отправки адреса модуля.)
virtual bool writeBytes (uint8_t, uint8_t*, uint8_t); // Объявляем функцию записи байтов данных в модуль. Аргументы: адресодуля, указатель_наассив, количество_байт. (функция отличается тем, что после отправки адреса модуля она сразу начинает цикл отправки данных, без передачи адреса первого регистра.)
// ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ: (поддерживаются библиотекой Wire) //
virtual uint8_t getType (void); // Объявляем функцию получения типа реализации шины I2C. Аргументы: отсутствуют.
virtual bool checkAddress(uint8_t); // Объявляем функцию поиска модуля на шине I2C. Аргументы: адресодуля.
// ФУНКЦИИ НИЖНЕГО УРОВНЯ: (не поддерживаются библиотекой Wire) //
virtual bool start (void); // Объявляем функцию установки состояния START. Аргументы: отсутствуют.
virtual bool reStart (void); // Объявляем функцию установки состояния RESTART. Аргументы: отсутствуют.
virtual void stop (void); // Объявляем функцию установки состояния STOP. Аргументы: отсутствуют.
virtual bool sendID (uint8_t, bool); // Объявляем функцию передачи адреса модуля. Аргументы: ID-адрес модуля, бит RW (0-запись, 1-чтение).
virtual bool setByte (uint8_t); // Объявляем функцию передачи байта данных. Аргументы: байт для передачи.
virtual uint8_t getByte (bool); // Объявляем функцию получения байта данных. Аргументы: бит подтверждения ACK/NACK
private: //
virtual bool setSCL (bool); // Объявляем функцию установки уровня на линии SCL. Аргументы: логический уровень.
virtual void setSDA (bool); // Объявляем функцию установки уровня на линии SDA. Аргументы: логический уровень.
virtual bool getSDA (void); // Объявляем функцию чтения уровня с линии SDA. Аргументы: отсутствуют.
}; //
//
class iarduino_I2C: public iarduino_I2C_BASE{ // Определяем производный класс
public: // Доступные методы и функции:
//
/** ОСНОВНЫЕ ФУНКЦИИ: **/ //
//
// Функция подготовки шины I2C: // Определяем функцию подготовки шины I2C.
void begin(uint32_t speed){ // Аргумент: скорость шины в кГц.
// _ _ _ _______ _ _ _ //
// SCL: _?_?_/ OUTPUT //
// _ _ _ _ _____ _ _ _ //
// SDA: _?_?_ _/ OUTPUT //
// //
#if defined(iarduino_I2C_TW) //
// Если используется шина I2C под управлением библиотеки Wire: //
Wire.setClock(speed*1000L); // Устанавливаем скорость передачи данных по шине I2C.
Wire.begin(); // Инициируем работу на шине I2C в качестве мастера.
#elif defined(iarduino_I2C_HW) //
// Если используется аппаратная шина I2C: //
pinMode(pin_SDA, INPUT ); digitalWrite(pin_SDA, HIGH); // Определяем вывод pin_SDA как вход и подтягиваем его к Vcc.
pinMode(pin_SCL, INPUT ); digitalWrite(pin_SCL, HIGH); // Определяем вывод pin_SCL как вход и подтягиваем его к Vcc.
TWBR=((F_CPU/(speed*1000L))-16)/2; // Определяем значение регистра скорости связи TWBR: speed = F_CPU / (16 + 2 * TWBR * 4^TWPS). Значит TWBR = (F_CPU/speed - 16) / (2 * 4^TWPS), но так как биты предделителя TWPS мы далее сбросим в 0, то формула упростится до: TWBR = (F_CPU/speed - 16) / 2. Так как speed указана в кГц, а F_CPU в Гц, то умножаем speed на 1000.
if(TWBR<10){TWBR=10;} // Если значение регистра скорости TWBR стало меньше 10 (параметр speed > 400 кГ) то оставляем значение этого регистра равным 10 иначе шина будет работать нестабильно.
TWSR&=(~(_BV(TWPS1)|_BV(TWPS0))); // Определяем значение регистра статуса TWSR: оставляем все его биты не тронутыми, кроме двух битов предделитея TWPS сбрасывая их в 0.
#elif defined(iarduino_I2C_SW) //
// Если используется программная шина I2C: //
port_SDA = digitalPinToPort (pin_SDA); // Определяем номер порта для вывода pin_SDA.
port_SCL = digitalPinToPort (pin_SCL); // Определяем номер порта для вывода pin_SCL.
mask_SDA = digitalPinToBitMask (pin_SDA); // Определяем маску для вывода pin_SDA. в переменной mask_SDA будет установлен только тот бит который соответствует позиции бита управления выводом pin_SDA.
mask_SCL = digitalPinToBitMask (pin_SCL); // Определяем маску для вывода pin_SCL. в переменной mask_SCL будет установлен только тот бит который соответствует позиции бита управления выводом pin_SCL.
mod_SDA = portModeRegister (port_SDA); // Определяем указатель на адрес регистра конфигурации направления работы выводов порта port_SDA.
mod_SCL = portModeRegister (port_SCL); // Определяем указатель на адрес регистра конфигурации направления работы выводов порта port_SCL.
inp_SDA = portInputRegister (port_SDA); // Определяем указатель на адрес регистра входных значений для управления портом port_SDA.
inp_SCL = portInputRegister (port_SCL); // Определяем указатель на адрес регистра входных значений для управления портом port_SCL.
out_SDA = portOutputRegister (port_SDA); // Определяем указатель на адрес регистра выходных значений для управления портом port_SDA.
out_SCL = portOutputRegister (port_SCL); // Определяем указатель на адрес регистра выходных значений для управления портом port_SCL.
setSCL(1); // Переводим вывод SCL в режим входа с подтяжкой к Vcc
setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
#endif //
} //
//
// Функция чтения одного байта из регистра модуля: //
uint8_t readByte(uint8_t adr, uint8_t reg){ // Определяем функцию чтения одного байта данных из регистра модуля (аргументы: адресодуля, адрес_регистра)
uint8_t i=0; readBytes(adr, reg, &i, 1); return i; // Объявляем переменную i и указываем её ссылку для получения 1 байта из регистра reg модуля с адресом adr
} //
//
// Функция чтения одного байта из модуля: //
uint8_t readByte(uint8_t adr){ // Определяем функцию чтения одного байта данных из регистра модуля (аргументы: адресодуля)
uint8_t i=0; readBytes(adr, &i, 1); return i; // Объявляем переменную i и указываем её ссылку для получения 1 байта из модуля с адресом adr
} //
//
// Функция записи одного байта в регистр модуля: //
bool writeByte(uint8_t adr, uint8_t reg, uint8_t data){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адресодуля, адрес_регистра, байт_данных)
return writeBytes(adr, reg, &data, 1); // Запысываем 1 байт по ссылке на переменную data в регистр reg модуля с адресом adr
} //
//
// Функция записи одного байта в модуль: //
bool writeByte(uint8_t adr, uint8_t data){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адресодуля, байт_данных)
return writeBytes(adr, &data, 1); // Запысываем 1 байт по ссылке на переменную data в модуль с адресом adr
} //
//
// Функция пакетного чтения нескольких байт данных из регистров модуля: //
bool readBytes(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sum){ // Определяем функцию пакетного чтения нескольких байт данных из регистров модуля (аргументы: адресодуля, адрес_первого_регистра, указатель_наассив, количество_байт)
#if defined(iarduino_I2C_TW) //
// Если используется шина I2C под управлением библиотеки Wire: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это ответ по умолчанию.
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
Wire.write(reg); // Определяем значение первого байта (reg - адреса регистра) который будет отправлен после байта адреса. Функция write() поместит указанный байт в буфер для передачи.
i=Wire.endTransmission(false); if(i){return 0;} // Выполняем инициированную ранее передачу данных (без установки состояния STOP). Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка.
if(!Wire.requestFrom( adr, sum )) {return i;} // Читаем (запрашиваем) sum байт данных от устройства с адресом adr и битом RW=1 => чтение. Функция requestFrom() возвращает количество реально принятых байтов. Так как предыдущая функция не установила состояние STOP, то состояние START данной функции будет расценено как RESTART.
while(Wire.available() && i<sum){data[i]=Wire.read(); i++;} // Читаем sum принятых байт из буфера для полученных данных в массив по указателю data.
while(Wire.available()){Wire.read();}return i==sum; // Если в буфере для полученных данных есть еще принятые байты, то чистим буфер. Возвращаем true если удалось прочитать sum байт.
#else //
// Если шина управляется функциями нижнего уровня данного класса: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи.
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
if ( setByte (reg) ) { i=3; // Если модуль ответил ACK на получение адреса регистра i, то ...
if ( reStart () ) { i=4; // Если на шине I2C установилось состояние RESTART, то ...
if ( sendID (adr,1) ) { i=5; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=1 (чтение), то ...
while(sum>0){ *data=getByte(sum>1); // Получаем по одному байту из очередного регистра за каждый проход цикла while. Прочитанный байт записываются по указателю data. Аргумент функции getByte имеет значение true на всех проходах цикла кроме последнего
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму прочитанных байт sum.
#if defined(iarduino_I2C_HW) // Проверить корректность чтения каждого байта можно только на аппаратном уровне
if (sum) { if(TWSR&0xF8!=0x50) { i=0;}} // Если после чтения очередного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x50 значит произошла ошибка при чтении
else { if(TWSR&0xF8!=0x58) { i=0;}} // Если после чтения последного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x58 значит произошла ошибка при чтении
#endif //
}}}}}} stop (); return i==5; // Отправляем команду STOP и возвращаем результат успешности чтения
#endif //
} //
//
// Функция пакетного чтения нескольких байт данных из модуля: //
bool readBytes(uint8_t adr, uint8_t *data, uint8_t sum){ // Определяем функцию пакетного чтения нескольких байт данных из модуля (аргументы: адресодуля, указатель_наассив, количество_байт)
#if defined(iarduino_I2C_TW) //
// Если используется шина I2C под управлением библиотеки Wire: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это ответ по умолчанию.
if(!Wire.requestFrom( adr, sum )) {return i;} // Читаем (запрашиваем) sum байт данных от устройства с адресом adr и битом RW=1 => чтение. Функция requestFrom() возвращает количество реально принятых байтов.
while(Wire.available() && i<sum){data[i]=Wire.read(); i++;} // Читаем sum принятых байт из буфера для полученных данных в массив по указателю data.
while(Wire.available()){Wire.read();}return i==sum; // Если в буфере для полученных данных есть еще принятые байты, то чистим буфер. Возвращаем true если удалось прочитать sum байт.
#else //
// Если шина управляется функциями нижнего уровня данного класса: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи.
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
if ( sendID (adr,1) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=1 (чтение), то ...
while(sum>0){ *data=getByte(sum>1); // Получаем по одному байту из очередного регистра за каждый проход цикла while. Прочитанный байт записываются по указателю data. Аргумент функции getByte имеет значение true на всех проходах цикла кроме последнего
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму прочитанных байт sum.
#if defined(iarduino_I2C_HW) // Проверить корректность чтения каждого байта можно только на аппаратном уровне
if (sum) { if(TWSR&0xF8!=0x50) { i=0;}} // Если после чтения очередного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x50 значит произошла ошибка при чтении
else { if(TWSR&0xF8!=0x58) { i=0;}} // Если после чтения последного байта пакета значение регистра состояния шины I2C Arduino TWSR с маской 0xF8 не равно 0x58 значит произошла ошибка при чтении
#endif //
}}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат успешности чтения
#endif //
} //
//
// Функция пакетной записи нескольких байт данных в регистр модуля: //
bool writeBytes(uint8_t adr, uint8_t reg, uint8_t *data, uint8_t sum){ // Определяем функцию пакетной записи нескольких байт данных в регистры модуля (аргументы: адресодуля, адрес_первого_регистра, указатель_наассив, количество_байт)
#if defined(iarduino_I2C_TW) //
// Если используется шина I2C под управлением библиотеки Wire: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
Wire.write(reg); // Определяем значение первого байта (reg - адреса регистра) который будет отправлен после байта адреса. Функция write() поместит указанный байт в буфер для передачи.
Wire.write(data, sum); // Определяем значения следующих байт (data - массив данных) который будет отправлен после байта регистра. Функция write() поместит sum элементов массива data в буфер для передачи.
i = Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу данных. Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true.
#else //
// Если шина управляется функциями нижнего уровня данного класса: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
if ( setByte (reg) ) { i=3; // Если модуль ответил ACK на получение адреса регистра reg, то ...
while(sum>0){if(!setByte(*data )) { i=0;} // Передаём один байт из массива по указателю data в очередной регистр за каждый проход цикла while. Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
}}}} stop (); return i==3; // Отправляем команду STOP и возвращаем результат записи.
#endif //
} //
//
// Функция пакетной записи нескольких байт данных в модуль: //
bool writeBytes(uint8_t adr, uint8_t *data, uint8_t sum){ // Определяем функцию пакетной записи нескольких байт данных в модуль (аргументы: адресодуля, указатель_наассив, количество_байт)
#if defined(iarduino_I2C_TW) //
// Если используется шина I2C под управлением библиотеки Wire: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
Wire.write(data, sum); // Указываем массив данных который будет отправлен после байта адреса. Функция write() поместит sum элементов массива data в буфер для передачи.
i = Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу данных. Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true.
#else //
// Если шина управляется функциями нижнего уровня данного класса: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
while(sum>0){if(!setByte(*data )) { i=0;} // Передаём один байт из массива по указателю data в очередной регистр за каждый проход цикла while. Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
data++; sum--; // Увеличиваем адрес указателя data, и уменьшаем сумму переданных байт sum.
}}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат записи.
#endif //
} //
//
/** ДОПОЛНИТЕЛЬНЫЕ ФУНКЦИИ: **/ //
//
// Функция получения типа реализации шины I2C: // Определяем функцию получения типа шины Ш2С.
uint8_t getType(void){ // Аргументы: отсутсвуют.
#if defined(iarduino_I2C_TW) //
return 4; // Используется аппаратная реализация шины I2C под управлением библиотеки Wire.
#elif defined(iarduino_I2C_HW) //
return 3; // Используется аппаратная реализация шины I2C.
#elif defined(iarduino_I2C_HW_1) //
return 2; // Используется аппаратная реализация шины I2C-1.
#elif defined(iarduino_I2C_SW) //
return 1; // Используется программная реализация шины I2C.
#else //
return 0; // Тип реализации шины I2C не определён.
#endif //
} //
//
// Функция проверки наличия ведомого по его адресу: //
bool checkAddress(uint8_t adr){ // Определяем функцию записи одного байта данных в регистр модуля (аргументы: адрес_регистра, байт_данных)
#if defined(iarduino_I2C_TW) //
// Если используется шина I2C под управлением библиотеки Wire: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат проверки.
Wire.beginTransmission(adr); // Инициируем передачу данных по шине I2C к устройству с адресом adr и битом RW=0 => запись. При этом сама передача не начнётся.
i=Wire.endTransmission(); return i==0; // Выполняем инициированную ранее передачу но без данных (отправится только START, байт адреса, STOP). Функция endTransmission() возвращает: 0-передача успешна / 1 - переполнен буфер для передачи / 2 - получен NACK при передаче адреса / 3 - получен NACK при передаче данных / 4 - другая ошибка. В качестве параметра функция endTransmission() может принимать флаг установки стсояния STOP - по умолчанию true.
#else //
// Если шина управляется функциями нижнего уровня данного класса: //
uint8_t i=0; // Предустанавливаем переменную i в значение 0 - это результат записи.
if ( start () ) { i=1; // Если на шине I2C установилось состояние START, то ...
if ( sendID (adr,0) ) { i=2; // Если модуль ответил ACK на получение адреса устройства adr с битом RW=0 (запись), то ...
}} stop (); return i==2; // Отправляем команду STOP и возвращаем результат записи.
#endif //
} //
//
/** ФУНКЦИИ НИЖНЕГО УРОВНЯ: **/ //
//
// Функция нижнего уровня - установка состояния START: // Определяем функцию установки состояния START.
bool start(void){ // Аргументы: отсутствуют.
// _ _ _ _____:___ _ _ _ //
// SCL: : \___ _ _ _ _ _/ //
// _ _ _ _____: _ _ _ _ _ _ // Спад логического уровня на линии SDA с «1» в «0», при наличии уровня логической «1» на линии SCL
// SDA: :\______ _ _/_ _ _ _ _ _ //
// //
#if defined(iarduino_I2C_HW) //
// Если используется аппаратная шина I2C: //
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния start.
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTA (бит условия START).
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов.
if((TWSR & 0xF8)==0x08){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x08, значит состояние START установилось на шине I2C.
return false; // Если предыдущая строка не вернула true, значит состояние START не установилось на шине I2C, возвращаем false.
#elif defined(iarduino_I2C_SW) //
// Если используется программная шина I2C: //
bool i= setSCL(1); // Устанавливаем «1» на линии SCL. Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
setSDA(0); // Устанавливаем «0» на линии SDA
setSCL(0); // Устанавливаем «0» на линии SCL
return i; // Если счетчик i не дошел до 0 при ожидании «1» на линии SCL, то вернётся true.
#else //
// Если тип шины I2C не поддерживается или не определён: //
return false; // Возвращаем false.
#endif //
} //
//
// Функция нижнего уровня - установка состояния RESTART: // Определяем функцию установки состояния RESTART.
bool reStart(void){ // Аргументы: отсутствуют.
// _ _ _ ___:___ _ _ _ //
// SCL: \_ _ _ _ / : \___ _ _ _ _ _/ //
// _ _ _ _ _ ________: _ _ _ _ _ _ // Спад логического уровня на линии SDA с «1» в «0», при наличии уровня логической «1» на линии SCL
// SDA: _ _ _ _ _/ :\______ _ _/_ _ _ _ _ _ // Сигнал рестрат аналогичен сигналу старт и отличается лишь тем, что ему не предшествует сигнал STOP
// //
#if defined(iarduino_I2C_HW) //
// Если используется аппаратная шина I2C: //
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния RESTART.
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTA); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTA (бит условия START).
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов.
if((TWSR & 0xF8)==0x10){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x10, значит состояние RESTART установилось на шине I2C.
return false; // Если предыдущая строка не вернула true, значит состояние RESTART не установилось на шине I2C, возвращаем false.
#elif defined(iarduino_I2C_SW) //
// Если используется программная шина I2C: //
return start(); // Программная реализация состояния RESTART идентична программной реализации состояния START.
#else //
// Если тип шины I2C не поддерживается или не определён: //
return false; // Возвращаем false.
#endif //
} //
//
// Функция нижнего уровня - установка состояния STOP: // Определяем функцию установки состояния STOP.
void stop(void){ // Аргументы: отсутствуют.
// _ _ _ ___:____ _ _ _ //
// SCL: \_ _ _ _/ : //
// _ _ _ _ _ :____ _ _ _ // Подъём логического уровня на линии SDA с «0» в «1», при наличии уровня логической «1» на линии SCL
// SDA: _ _ _ _ _\______/: //
// //
#if defined(iarduino_I2C_HW) //
// Если используется аппаратная шина I2C: //
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания установки состояния STOP
TWCR = _BV(TWINT) | _BV(TWEN) | _BV(TWSTO); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания), TWEN (бит разрешения работы шины), TWSTO (бит условия STOP).
while((!(TWCR & _BV(TWSTO))) && i){i--;} // Ждём сброса бита условия стоп TWSTO в регистре управления TWCR, но не дольше чем i циклов
// if((TWSR & 0xF8)==0xA0){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0xA0, значит состояние STOP установилось на шине I2C.
delayMicroseconds(20); // Данная функция не возвращает результат, но в любом случае делаем задержку меджу завершением текущего пакета и возможным началом следующего
#elif defined(iarduino_I2C_SW) //
// Если используется программная шина I2C: //
setSDA(0); // Устанавливаем «0» на линии SDA
setSCL(1); // Устанавливаем «1» на линии SCL. Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
setSDA(1); // Устанавливаем «1» на линии SDA
#endif //
} //
//
// Функция нижнего уровня - передача первого байта АДРЕС+RW: // Определяем функцию передачи первого байта после cигнала START. Это байт адреса модуля с битом RW
bool sendID(uint8_t adr, bool rw){ // Аргументы: ID-адрес модуля, бит RW (0-запись, 1-чтение)
// 1 2 3 4 5 6 7 8 9 //
// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ //
// ________________________ // Передача 7-битного адреса и 1 бита RW. На 9 тактирубщем импульсе модуль отвечает ACK («0» - «я сдесь»), или NACK («1» - «нет»)
// SDA: _ _ _ ___/________ADDRESS_______RW>----____ _ _ _ //
// вход //
#if defined(iarduino_I2C_HW) //
// Если используется аппаратная шина I2C: //
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания получения подтверждения от ведомого ввиде бита ACK.
TWDR = (adr<<1)+rw; // Определяем значение регистра данных TWDR: записываем в него адрес adr сдвигая его на 1 бит влево, при этом младший бит (освободившийся) займёт бит RW (0-запись / 1-чтение)
TWCR = _BV(TWINT) | _BV(TWEN); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины).
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов
if((TWSR & 0xF8)==0x40 && rw){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x40, значит ведомый опознал свой адрес с битом RW=1 и отправил бит подтверждения ACK (в противном случае значение регистра TWSR будет равно 0x48).
if((TWSR & 0xF8)==0x18 && !rw){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x18, значит ведомый опознал свой адрес с битом RW=0 и отправил бит подтверждения ACK (в противном случае значение регистра TWSR будет равно 0x20).
return false; // Если предыдущая строка не вернула true, значит на шине нет ведомых у сказанным адресом, возвращаем false.
#elif defined(iarduino_I2C_SW) //
// Если используется программная шина I2C: //
bool i=true; // Определяем флаг возвращаемый данной функцией.
uint8_t j=7; // Определяем счётчик количества переданных бит адреса.
while(j){ j--; // Передаём 7 бит адреса adr в цикле
setSDA(adr & bit(j)); // Устанавливаем очередной бит адреса на линии SDA
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
} setSDA(rw); // Устанавливаем бит RW на линии SDA
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
if( getSDA( ) ) {i=false;} // Если на линии SDA установлена «1» значит ведомый ответил NACK
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
return i; // Если линия SCL была занята или модуль ответил NACK, то вернётся false.
#else //
// Если тип шины I2C не поддерживается или не определён: //
return false; // Возвращаем false
#endif //
} //
//
// Функция нижнего уровня - передача одного байта данных: // Определяем функцию передачи одного байта (в любом месте между байтом адреса с битом RW=0 и сигналом STOP).
bool setByte(uint8_t data){ // Аргумент: байт для передачи.
// 1 2 3 4 5 6 7 8 9 //
// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ //
// ________________________ // Передача 1 байта, каждый бит читается модулем по фронту тактирубщих импульсов. На 9 тактирубщем импульсе модуль отвечает ACK («0» - «принял»), или NACK («1» - «нет»)
// SDA: _ _ _ ___/__________DATA__________>----____ _ _ _ //
// вход //
#if defined(iarduino_I2C_HW) //
// Если используется аппаратная шина I2C: //
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания получения подтверждения от ведомого ввиде бита ACK.
TWDR = data; // Определяем значение регистра данных TWDR: записываем в него байт для передачи по шине I2C.
TWCR = _BV(TWINT) | _BV(TWEN); // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины).
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов
if((TWSR & 0xF8)==0x28){return true;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x28, значит ведомый отправил бит подтверждения приёма данных ACK (в противном случае значение регистра TWSR будет равно 0x30).
return false; // Если предыдущая строка не вернула true, значит ведомый не принял отправленный ему байт, возвращаем false.
#elif defined(iarduino_I2C_SW) //
// Если используется программная шина I2C: //
bool i=true; // Определяем флаг возвращаемый данной функцией.
uint8_t j=8; // Определяем счётчик количества переданных байт.
while(j){ j--; // Передаём 8 бит байта data в цикле
setSDA(data & bit(j)); // Устанавливаем очередной бит байта на линии SDA
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
} setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
if( getSDA( ) ) {i=false;} // Если на линии SDA установлена «1» значит ведомый ответил NACK
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
return i; // Если счетчик i не дошел до 0 и не был сброшен в 0 при получении NACK, то вернётся true.
#else //
// Если тип шины I2C не поддерживается или не определён: //
return false; // Возвращаем false
#endif //
} //
//
// Функция нижнего уровня - получение одного байта данных: // Определяем функцию получения одного байта (в любом месте между байтом адреса с битом RW=1 и сигналом STOP).
uint8_t getByte(bool ack){ // Аргумент: бит подтверждения ACK/NACK
// 1 2 3 4 5 6 7 8 9 //
// SCL: _ _ _ _____/\_/\_/\_/\_/\_/\_/\_/\__/\_____ _ _ _ //
// __ // Получение 1 байта, каждый бит читается мастером по фронту тактирубщих импульсов. На 9 тактирубщем импульсе мастер отвечает ACK («0» - «давай еще»), или NACK («1» - «хватит»)
// SDA: _ _ _ ___/----------DATA-----------<__\____ _ _ _ //
// вход выход //
#if defined(iarduino_I2C_HW) //
// Если используется аппаратная шина I2C: //
uint16_t i=60000L; // Определяем счётчик указывая максимальное количество циклов для ожидания.
TWCR = _BV(TWINT) | _BV(TWEN) | ack<<TWEA; // Определяем значение регистра управления TWCR: устанавливаем биты TWINT (флаг прерывания) и TWEN (бит разрешения работы шины), а бит TWEA (бит разрешения подтверждения) устанавливаем только если мы собираемся отправить ведомому бит подтверждения получения данных ACK.
while((!(TWCR & _BV(TWINT))) && i){i--;} // Ждём сброса флага прерывания TWINT в регистре управления TWCR, но не дольше чем i циклов
if((TWSR & 0xF8)==0x50 && ack){return TWDR;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x50, значит данные приняты и сохранены в регистре TWDR, а ведомому отправлен бит ACK.
if((TWSR & 0xF8)==0x58 && !ack){return TWDR;} // Проверяем значение регистра статуса TWSR: если его значение с маской 0xF8 равно 0x58, значит данные приняты и сохранены в регистре TWDR, а ведомому отправлен бит NACK.
return 0; // Если предыдущая строка не вернула принятый байт из регистра данных TWDR, значит мы не приняли байт, возвращаем 0.
#elif defined(iarduino_I2C_SW) //
// Если используется программная шина I2C: //
bool i=true; // Определяем флаг возвращаемый данной функцией.
uint8_t j=8; // Определяем счётчик количества полученных битов байта.
uint8_t k=0; // Объявляем переменную для хранения прочитанного байта данных.
setSDA(1); // Переводим вывод SDA в режим входа с подтяжкой к Vcc
while(j){ j--; // Получаем 8 бит байта в цикле
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
if( getSDA( ) ) { k |= (1<<j); } // Заполняем биты байта k в соотсетствии с уровнем на линии SDA
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
} setSDA(!ack); // Устанавливаем бит «ACK/NACK» на линии SDA (ACK-прижимаем, NACK-отпускаем)
if(!setSCL(1) ) {i=false;} // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса). Если ведомый удерживает линию SCL прижатой, то функция ждёт освобождения линии и, если не дождётся, то возвращает false.
setSCL(0); // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса)
return i?k:0; // Если во время ожидания поднятия логического уровня на линии SCL, cчётчик i не дошел до 0, то функция вернёт байт из переменной k.
#else //
// Если тип шины I2C не поддерживается или не определён: //
return 0; // Возвращаем false
#endif //
} //
//
private: //
uint8_t pin_SDA = pin_SW_SDA; // Определяем вывод pin_SDA.
uint8_t pin_SCL = pin_SW_SCL; // Определяем вывод pin_SCL.
uint8_t port_SDA; // Объявляем переменную для хранения номера порта вывода pin_SDA.
uint8_t port_SCL; // Объявляем переменную для хранения номера порта вывода pin_SCL.
uint8_t mask_SDA; // Объявляем переменную для хранения позиции бита управления выводом pin_SDA.
uint8_t mask_SCL; // Объявляем переменную для хранения позиции бита управления выводом pin_SCL.
volatile uint8_t *mod_SDA; // Объявляем указатель на регистр направления работы выводов порта port_SDA.
volatile uint8_t *mod_SCL; // Объявляем указатель на регистр направления работы выводов порта port_SCL.
volatile uint8_t *inp_SDA; // Объявляем указатель на регистр входных значений порта port_SDA.
volatile uint8_t *inp_SCL; // Объявляем указатель на регистр входных значений порта port_SCL.
volatile uint8_t *out_SDA; // Объявляем указатель на регистр выходных значений порта port_SDA.
volatile uint8_t *out_SCL; // Объявляем указатель на регистр выходных значений порта port_SCL.
//
// функция установки уровня на линии SCL: // Определяем функцию установки уровня на линии SCL.
bool setSCL(bool f){ // Аргумент: логический уровень.
uint16_t i=60000L; // Определяем счётчик ожидания освобождения линии SCL.
if(!f) {*mod_SCL |= mask_SCL; *out_SCL &= ~mask_SCL;} // Устанавливаем «0» на линии SCL (Спад тактирубщего импульса) pinMode(pin_SCL, OUTPUT); digitalWrite(pin_SCL, LOW );
else {*mod_SCL &= ~mask_SCL; *out_SCL |= mask_SCL; // Устанавливаем «1» на линии SCL (Фронт тактирующего импульса) pinMode(pin_SCL, INPUT ); digitalWrite(pin_SCL, HIGH);
while((*inp_SCL & mask_SCL)==0 && i){i--;} } // Ждём поднятия логического уровня на линии SCL while(digitalRead(pin_SCL)==0 && i){ цикл выполняется пока на линии 0 или пока i не сброситя d 0}
return i; //
} //
//
// Функция установки уровня на линии SDA: // Определяем функцию установки уровня на линии SDA.
void setSDA(bool f){ // Аргумент: логический уровень.
if(!f) {*mod_SDA |= mask_SDA; *out_SDA &= ~mask_SDA;} // Устанавливаем «0» на линии SDA (если бит RW=«0») pinMode(pin_SDA, OUTPUT); digitalWrite(pin_SDA, LOW );
else {*mod_SDA &= ~mask_SDA; *out_SDA |= mask_SDA;} // Устанавливаем «1» на линии SDA (если бит RW=«1») pinMode(pin_SDA, INPUT ); digitalWrite(pin_SDA, HIGH );
} //
//
// Функция чтения уровня с линии SDA: // Определяем функцию чтения уровня с линии SDA. Перед чтением необходимо вызвать функцию setSDA(1) которая переведёт вывод SDA в режим входа
bool getSDA(void){ return (*inp_SDA & mask_SDA); } // Аргументы: отсутсвуют. digitalRead(pin_SDA);
}; //
//
#endif //

View File

@@ -0,0 +1,43 @@
#ifndef iarduino_RTC_RX8025_h //
#define iarduino_RTC_RX8025_h //
#define RTC_RX8025 4 // Модуль часов реального времени с протоколом передачи данных I2C, памятью 016x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором
#include "iarduino_RTC_I2C.h" // Подключаем файл iarduino_RTC_I2C.h - для работы с шиной I2C
//
class iarduino_RTC_RX8025: public iarduino_RTC_BASE{ //
public: //
/** функции доступные пользователю **/ //
// Инициализация модуля: //
void begin(void){ // (без параметров)
// Инициализация работы с шиной I2C: //
objI2C.begin(100); // (скорость шины в кГц)
// Установка флагов управления и состояния модуля: //
delay(10); objI2C.writeByte(valAddress, 0x0F, 0xA0); // Записываем байт 0xA0 (10100000) в регистр 0x0F (Control-2): VDSL=1 пороговое напряжение 1.3В, VDET=0 перезапуск определения падения мощности, /XST=1 перезапуск определения остановки колебаний, PON=0 перезапуск сброса при вкл питания, 0, CTFG=0 сброс периодического прерывания, WAFG=0 и DAFG=0 сброс прерываний будильников Alarm_D и Alarm_W
delay(10); objI2C.writeByte(valAddress, 0x0E, 0x20); // Записываем байт 0x20 (00100000) в регистр 0x0E (Control-1): WALE=0 и DALE=0 отключение будильников Alarm_W и Alarm_D, /12,24=1 переключение в 24-часовой формат, 00, CT2-0=000 отключение периодического прерывания.
} //
//
// Чтение одного значения из регистров даты и времени модуля: //
uint8_t funcReadTimeIndex(uint8_t i){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели)
delay(1); //
varI = objI2C.readByte(valAddress, arrTimeRegAddr[i]) & arrTimeRegMack[i]; // Читаем байт из регистра arrTimeRegAddr[i] с маской arrTimeRegMack[i] в переменную varI.
if(i==6){for(uint8_t j=1;j<8;j++){if(varI&bit(j-1)){return j;}} return 1;} // Если запрошен день недели, то возвращаем позицию (1...7) установленного бита в байте varI.
// if( i==6 ){ varI++; } // Если чип считает день недели как написано в datasheet, то раскомментируйте данную строку и закомментируйте предыдущую.
return varI; //
} //
//
// Запись одного значения в регистры даты и времени модуля: //
void funcWriteTimeIndex(uint8_t i, uint8_t j){ // (i = 0-секунды / 1-минуты / 2-часы / 3-день / 4-месяц / 5-год / 6-день недели, j = значение)
if( i==6 ){ if( (j==0)||(j>7) ){ j=1; } j=bit(j-1); } // Устанавливаем один бит в переменной j;
// if( i==6 ){j--;} // Если чип считает день недели как написано в datasheet, то раскомментируйте данную строку и закомментируйте предыдущую.
objI2C.writeByte(valAddress, arrTimeRegAddr[i], j&arrTimeRegMack[i]); // Сохраняем значение j в регистр arrTimeRegAddr[i] с маской arrTimeRegMack[i].
} //
//
private: //
/** Внутренние переменные **/ //
iarduino_I2C objI2C; // Создаём объект для работы с шиной I2C
uint8_t valAddress = 0x32; // Адрес модуля на шине I2C
uint8_t arrTimeRegAddr[7] = {0x00,0x01,0x02,0x04,0x05,0x06,0x03}; // Определяем массив с адресами регистров даты и времени (сек, мин, час, день, месяц, год, день недели)
uint8_t arrTimeRegMack[7] = {0x7F,0x7F,0x3F,0x3F,0x1F,0xFF,0x7F}; // Определяем маскировочный массив для регистров даты и времени (при чтении/записи, нужно совершить побитовое «и»)
uint8_t varI; //
}; //
//
#endif //

View File

@@ -0,0 +1,9 @@
// Файл: «ХРАНИТЕЛЬ ПАМЯТИ»
// Если закомментировать строки с названиями тех модулей которые не используются в Вашем устройстве, можно освободить около 50 байт флеш-памяти.
// Если закомментировать строку с названием используемого модуля, компилятор выдаст ошибку.
#define RTC_ENABLE_DS1302 1 // Модуль часов реального времени (RTC) на базе чипа DS1302, с протоколом передачи данных SI3, памятью 040x8 (31 байт которой доступны для хранения данных пользователя).
#define RTC_ENABLE_DS1307 1 // Модуль часов реального времени (RTC) на базе чипа DS1307, с протоколом передачи данных I2C, памятью 064x8 (56 байт которой доступны для хранения данных пользователя).
#define RTC_ENABLE_DS3231 1 // Модуль часов реального времени (RTC) на базе чипа DS3231, с протоколом передачи данных I2C, памятью 019x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором.
#define RTC_ENABLE_RX8025 1 // Модуль часов реального времени (RTC) на базе чипа RX8025, с протоколом передачи данных I2C, памятью 016x8, температурной компенсацией, двумя будильниками и встроенным кварцевым резонатором.

View File

@@ -9,9 +9,15 @@ board = nodemcuv2
board_build.ldscript = eagle.flash.4m1m.ld
platform = espressif8266 @2.6.3
monitor_filters = esp8266_exception_decoder
upload_speed = 921600
upload_speed = 115200
monitor_speed = 115200
board_build.filesystem = littlefs
build_src_filter =
+<*.cpp>
+<classes/*.cpp>
+<utils/*.cpp>
+<modules/*.cpp>
${env:esp8266_4mb_fromitems.build_src_filter}
[env:esp32_4mb]
lib_deps =
@@ -23,11 +29,17 @@ framework = arduino
board = esp32dev
platform = espressif32 @3.3.0
monitor_filters = esp32_exception_decoder
upload_speed = 921600
upload_speed = 115200
monitor_speed = 115200
build_src_filter =
+<*.cpp>
+<classes/*.cpp>
+<utils/*.cpp>
+<modules/*.cpp>
${env:esp32_4mb_fromitems.build_src_filter}
[platformio]
default_envs = esp8266_4mb
default_envs = esp32_4mb
data_dir = data_svelte
[common_env_data]
@@ -38,8 +50,8 @@ lib_deps_external =
[env:esp8266_4mb_fromitems]
lib_deps =
adafruit/Adafruit MCP23017 Arduino Library@^2.0.2
adafruit/Adafruit ADS1X15 @ ^2.3.0
marcoschwartz/LiquidCrystal_I2C@^1.1.4
dfrobot/DFRobotDFPlayerMini @ ^1.0.5
Adafruit AHTX0
adafruit/Adafruit BME280 Library
adafruit/Adafruit BMP280 Library
@@ -48,14 +60,39 @@ lib_deps =
https://github.com/JonasGMorsch/GY-21.git
ClosedCube HDC1080
adafruit/MAX6675 library
Nova Fitness Sds dust sensors library@1.5.1
rc-switch @ ^2.6.4
robtillaart/SHT2x@^0.1.1
marcoschwartz/LiquidCrystal_I2C@^1.1.4
adafruit/Adafruit MCP23017 Arduino Library@^2.0.2
adafruit/Adafruit BusIO @ ^1.13.0
build_src_filter =
+<modules\display\Lcd2004>
+<modules\exec\ButtonIn>
+<modules\exec\ButtonOut>
+<modules\exec\IoTServo>
+<modules\exec\Mp3>
+<modules\exec\Timer>
+<modules\sensors\Aht20>
+<modules\sensors\AnalogAdc>
+<modules\sensors\Bme280>
+<modules\sensors\Bmp280>
+<modules\sensors\Dht1122>
+<modules\sensors\Ds18b20>
+<modules\sensors\GY21>
+<modules\sensors\Hdc1080>
+<modules\sensors\Max6675>
+<modules\sensors\RCswitch>
+<modules\sensors\Sht20>
+<modules\sensors\Sonar>
+<modules\system\IarduinoRTC>
+<modules\system\Mcp23017>
+<modules\system\SysExt>
+<modules\system\Variable>
[env:esp32_4mb_fromitems]
lib_deps =
adafruit/Adafruit MCP23017 Arduino Library@^2.0.2
adafruit/Adafruit ADS1X15 @ ^2.3.0
marcoschwartz/LiquidCrystal_I2C@^1.1.4
https://github.com/RoboticsBrno/ServoESP32
dfrobot/DFRobotDFPlayerMini @ ^1.0.5
Adafruit AHTX0
adafruit/Adafruit BME280 Library
adafruit/Adafruit BMP280 Library
@@ -64,7 +101,31 @@ lib_deps =
https://github.com/JonasGMorsch/GY-21.git
ClosedCube HDC1080
adafruit/MAX6675 library
Nova Fitness Sds dust sensors library@1.5.1
rc-switch @ ^2.6.4
robtillaart/SHT2x@^0.1.1
marcoschwartz/LiquidCrystal_I2C@^1.1.4
adafruit/Adafruit MCP23017 Arduino Library@^2.0.2
adafruit/Adafruit BusIO @ ^1.13.0
build_src_filter =
+<modules\display\Lcd2004>
+<modules\exec\ButtonIn>
+<modules\exec\ButtonOut>
+<modules\exec\IoTServo>
+<modules\exec\Mp3>
+<modules\exec\Timer>
+<modules\sensors\Aht20>
+<modules\sensors\AnalogAdc>
+<modules\sensors\Bme280>
+<modules\sensors\Bmp280>
+<modules\sensors\Dht1122>
+<modules\sensors\Ds18b20>
+<modules\sensors\GY21>
+<modules\sensors\Hdc1080>
+<modules\sensors\Max6675>
+<modules\sensors\RCswitch>
+<modules\sensors\Sht20>
+<modules\sensors\Sonar>
+<modules\system\IarduinoRTC>
+<modules\system\Mcp23017>
+<modules\system\SysExt>
+<modules\system\Variable>

View File

@@ -54,7 +54,7 @@ void asyncUdpInit() {
//будем отправлять каждые 30 секунд презентацию данного устройства
ts.add(
UDP, 60000, [&](void*) {
UDP, 60000, [&](void*) { //UDPP
if (isNetworkActive()) {
SerialPrint("i", F("UDP"), F("Broadcast device presentation"));
asyncUdp.broadcastTo(getThisDevice().c_str(), 4210);

View File

@@ -1,7 +1,9 @@
#include "ESPConfiguration.h"
#include "classes/IoTGpio.h"
#include "classes/IoTRTC.h"
extern IoTGpio IoTgpio;
extern IoTRTC *watch;
std::list<IoTItem*> IoTItems;
void* getAPI(String subtype, String params);
@@ -25,8 +27,22 @@ void configure(String path) {
} else {
myIoTItem = (IoTItem*)getAPI(subtype, jsonArrayElement);
if (myIoTItem) {
IoTGpio* tmp = myIoTItem->getGpioDriver();
if (tmp) IoTgpio.regDriver(tmp);
// пробуем спросить драйвер GPIO
IoTGpio* gpiotmp = myIoTItem->getGpioDriver();
if (gpiotmp) IoTgpio.regDriver(gpiotmp);
// пробуем спросить драйвер RTC
iarduino_RTC_BASE* rtctmp = myIoTItem->getRtcDriver();
if (rtctmp) {
Serial.println("Start delete watch objClass");
delete watch->objClass;
watch->objClass = rtctmp;
int valPeriod_save = watch->valPeriod;
watch->valPeriod = 0;
watch->gettime();
watch->valPeriod = valPeriod_save;
}
IoTItems.push_back(myIoTItem);
}
}
@@ -39,6 +55,7 @@ void configure(String path) {
void clearConfigure() {
Serial.printf("Start clearing config\n");
for (std::list<IoTItem*>::iterator it=IoTItems.begin(); it != IoTItems.end(); ++it) {
Serial.printf("Start delete iotitem %s \n", (*it)->getID().c_str());
if (*it) delete *it;
}
IoTItems.clear();

View File

@@ -29,12 +29,7 @@ void handleOrder() {
IoTItem* item = findIoTItem(selectToMarker(order, " "));
if (item) {
String valStr = selectToMarkerLast(order, " ");
IoTValue value;
if (value.isDecimal = isDigitDotCommaStr(valStr))
value.valD = valStr.toFloat();
else
value.valS = valStr;
item->setValue(value);
item->setValue(valStr);
}
orderBuf = deleteBeforeDelimiter(orderBuf, ",");

View File

@@ -1,7 +1,16 @@
#include "Main.h"
#include "classes/IoTRTC.h"
#include <time.h>
IoTScenario iotScen; // объект управления сценарием
IoTRTC *watch; // объект хранения времени, при старте часы 00:00
time_t iotTimeNow;
String volStrForSave = "";
unsigned long currentMillis;
unsigned long prevMillis;
void setup() {
Serial.begin(115200);
Serial.flush();
@@ -23,6 +32,29 @@ void setup() {
//подключаемся к роутеру
routerConnect();
// настраиваем получение времени из сети Интернет
String ntpServer = jsonReadStr(settingsFlashJson, F("ntp"));
int timezone = jsonReadInt(settingsFlashJson, F("timezone"));
configTime(3600*timezone, 0, ntpServer.c_str(), "ru.pool.ntp.org", "pool.ntp.org");
Serial.println("Start syncing NTP time");
time(&iotTimeNow);
// int i = 0;
// while (isNetworkActive() && iotTimeNow < 1510592825 && i < 200)
// {
// time(&iotTimeNow);
// delay(300);
// Serial.print(".");
// i++;
// }
// Serial.println();
// настраиваем локальный RTC
watch = new IoTRTC(0); // создаем объект главного хранилища времени, но с заглушкой (0) для получения системного времени
watch->period(60); // время в минутах для синхронизации с часами реального времени или системным
watch->begin();
//Serial.print(F("Time from Local: "));
//Serial.println(watch->gettime("d-m-Y, H:i:s, M"));
//инициализация асинхронного веб сервера и веб сокетов
#ifdef ASYNC_WEB_SERVER
asyncWebServerInit();
@@ -56,7 +88,9 @@ void setup() {
//загрузка сценария
iotScen.loadScenario("/scenario.txt");
// iotScen.ExecScenario("");
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}"));
generateEvent("onStart", "");
// test
Serial.println("-------test start--------");
@@ -83,6 +117,13 @@ void setup() {
}
void loop() {
// if(millis()%2000==0){
// //watch->settimeUnix(time(&iotTimeNow));
// Serial.println(watch->gettime("d-m-Y, H:i:s, M"));
// delay(1);
// }
//обновление задач таскера
ts.update();
@@ -118,5 +159,24 @@ void loop() {
handleEvent();
// iotScen.ExecScenario();
// сохраняем значения IoTItems в файл каждую секунду, если были изменения (установлены маркеры на сохранение)
currentMillis = millis();
if (currentMillis - prevMillis >= 1000) {
prevMillis = millis();
volStrForSave = "";
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
if ((*it)->needSave) {
(*it)->needSave = false;
volStrForSave = volStrForSave + (*it)->getID() + "=" + (*it)->getValue() + ";";
}
}
if (volStrForSave != "") {
Serial.print("volStrForSave: ");
Serial.println(volStrForSave.c_str());
}
}
}

View File

@@ -125,7 +125,9 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
payloadStr += (char)payload[i];
}
// SerialPrint("i", "=>MQTT", payloadStr);
//SerialPrint("i", "=>MQTT", payloadStr);
//SerialPrint("i", F("=>MQTT"), "Msg from iotmanager: " + topicStr);
if (payloadStr.startsWith("HELLO")) {
SerialPrint("i", F("MQTT"), F("Full update"));
@@ -153,8 +155,19 @@ void mqttCallback(char* topic, uint8_t* payload, size_t length) {
if (topicStr.indexOf(chipId) == -1) {
String devId = selectFromMarkerToMarker(topicStr, "/", 2);
String id = selectFromMarkerToMarker(topicStr, "/", 3);
//добавим событие в базу
IoTItems.push_back((IoTItem*)new externalVariable(payloadStr));
IoTItem* itemExist = findIoTItem(id);
if (itemExist) {
String valAsStr;
if (jsonRead(payloadStr, F("val"), valAsStr, false)) {
itemExist->setValue(valAsStr);
unsigned long interval;
jsonRead(payloadStr, F("int"), interval);
itemExist->setInterval(interval);
}
} else {
//добавим событие в базу
IoTItems.push_back((IoTItem*)new externalVariable(payloadStr));
}
//запустим проверку его в сценариях
generateEvent(id, payloadStr);
SerialPrint("i", F("=>MQTT"), "Received event from other device: '" + devId + "' " + id + " " + payloadStr);

View File

@@ -48,36 +48,53 @@ void standWebServerInit() {
// Запускаем HTTP сервер
HTTP.begin();
#ifdef REST_FILE_OPERATIONS
SPIFFS.begin();
{
Dir dir = SPIFFS.openDir("/");
while (dir.next()) {
String fileName = dir.fileName();
size_t fileSize = dir.fileSize();
}
}
//#ifdef REST_FILE_OPERATIONS
// SPIFFS.begin();
// {
// Dir dir = SPIFFS.openDir("/");
// while (dir.next()) {
// String fileName = dir.fileName();
// size_t fileSize = dir.fileSize();
// }
// }
// HTTP страницы для работы с FFS
// list directory
HTTP.on("/list", HTTP_GET, handleFileList);
//загрузка редактора editor
HTTP.on("/edit", HTTP_GET, []() {
if (!handleFileRead("/edit.htm")) HTTP.send(404, "text/plain", "FileNotFound");
if (!HTTP.args()) {
if (!handleFileRead("/edit.htm")) HTTP.send(404, "text/plain", "FileNotFound");
}
if (HTTP.hasArg("list")) {
handleFileList();
}
if (HTTP.hasArg("edit")) {
if (!handleFileRead(HTTP.arg("edit"))) HTTP.send(404, "text/plain", "FileNotFound");
}
if (HTTP.hasArg("download")) {
if (!handleFileRead(HTTP.arg("download"))) HTTP.send(404, "text/plain", "FileNotFound");
}
});
//Создание файла
HTTP.on("/edit", HTTP_PUT, handleFileCreate);
//Удаление файла
HTTP.on("/edit", HTTP_DELETE, handleFileDelete);
// first callback is called after the request has ended with all parsed arguments
// second callback handles file uploads at that location
HTTP.on(
"/edit", HTTP_POST, []() {
//Изменение файла
HTTP.on("/edit", HTTP_POST, []() {
HTTP.send(200, "text/plain", "");
},
handleFileUpload);
#endif
//#endif
// called when the url is not defined here
// use it to load content from SPIFFS
HTTP.onNotFound([]() {
if (!handleFileRead(HTTP.uri()))
HTTP.send(404, "text/plain", "FileNotFound");
@@ -92,6 +109,8 @@ bool handleFileRead(String path) {
if (FileFS.exists(pathWithGz))
path += ".gz";
File file = FileFS.open(path, "r");
if (contentType == "application/octet-stream")
HTTP.sendHeader("Content-Disposition", "attachment;filename=" + (String)file.name());
HTTP.streamFile(file, contentType);
file.close();
return true;
@@ -131,7 +150,7 @@ String getContentType(String filename) {
return "text/plain";
}
#ifdef REST_FILE_OPERATIONS
//#ifdef REST_FILE_OPERATIONS
// Здесь функции для работы с файловой системой
void handleFileUpload() {
if (HTTP.uri() != "/edit") return;
@@ -181,27 +200,25 @@ void handleFileCreate() {
}
void handleFileList() {
if (!HTTP.hasArg("dir")) {
if (!HTTP.hasArg("list")) {
HTTP.send(500, "text/plain", "BAD ARGS");
return;
}
String path = HTTP.arg("dir");
Dir dir = FileFS.openDir(path);
path = String();
File dir = FileFS.open(HTTP.arg("list"), "r");
String output = "[";
while (dir.next()) {
File entry = dir.openFile("r");
File entry;
while (entry = dir.openNextFile()) {
if (output != "[") output += ',';
bool isDir = false;
bool isDir = entry.isDirectory();
output += "{\"type\":\"";
output += (isDir) ? "dir" : "file";
output += "\",\"name\":\"";
output += String(entry.name()).substring(1);
output += String(entry.name());
output += "\"}";
entry.close();
}
output += "]";
HTTP.send(200, "text/json", output);
}
#endif
//#endif
#endif

View File

@@ -1,4 +1,7 @@
#include "WsServer.h"
#include "classes/IoTScenario.h"
extern IoTScenario iotScen;
#ifdef STANDARD_WEB_SOCKETS
void standWebSocketsInit() {
standWebSocket.begin();
@@ -66,8 +69,11 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
//**сохранение**//
if (headerStr == "/gifnoc|") {
writeFileUint8tByFrames("config.json", payload, length, headerLenth, 256);
// clearConfigure();
// configure("/config.json");
Serial.println("Start clear");
clearConfigure();
Serial.println("Start config");
configure("/config.json");
iotScen.loadScenario("/scenario.txt");
}
//**сохранение**//
if (headerStr == "/tuoyal|") {
@@ -76,6 +82,11 @@ void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload, size_t length)
//**сохранение**//
if (headerStr == "/oiranecs|") {
writeFileUint8tByFrames("scenario.txt", payload, length, headerLenth, 256);
iotScen.loadScenario("/scenario.txt");
// создаем событие завершения конфигурирования для возможности выполнения блока кода при загрузке
IoTItems.push_back((IoTItem*)new externalVariable("{\"id\":\"onStart\",\"val\":1,\"int\":60}"));
generateEvent("onStart", "");
}
// page connection===================================================================
//**отправка**//

View File

@@ -1,6 +1,5 @@
#include "utils/JsonUtils.h"
#include "utils/SerialPrint.h"
#include "classes/ScenarioClass3.h"
#include "classes/IoTItem.h"
#include "WsServer.h"
#include "ESPConfiguration.h"
@@ -8,6 +7,7 @@
IoTItem::IoTItem(String parameters) {
jsonRead(parameters, F("int"), _interval);
if (_interval == 0) enableDoByInt = false;
_interval = _interval * 1000;
jsonRead(parameters, F("subtype"), _subtype);
jsonRead(parameters, F("id"), _id);
@@ -42,10 +42,14 @@ String IoTItem::getID() {
return _id;
};
void IoTItem::setInterval(unsigned long interval) {
_interval = interval;
}
String IoTItem::getValue() {
if (value.isDecimal)
if (_round >= 0) {
char buf[8];
if (_round >= 0 && _round <= 6) {
char buf[15];
sprintf(buf, ("%1." + (String)_round + "f").c_str(), value.valD);
return (String)buf;
} else return (String)value.valD;
@@ -54,11 +58,13 @@ String IoTItem::getValue() {
}
void IoTItem::loop() {
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= _interval) {
prevMillis = millis();
this->doByInterval();
if (enableDoByInt) {
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= _interval) {
prevMillis = millis();
this->doByInterval();
}
}
}
@@ -81,7 +87,7 @@ void IoTItem::regEvent(String value, String consoleInfo = "") {
void IoTItem::regEvent(float regvalue, String consoleInfo = "") {
if (_multiply) regvalue = regvalue * _multiply;
if (_plus) regvalue = regvalue + _multiply;
if (_plus) regvalue = regvalue + _plus;
if (_round >= 0 && _round <= 6) {
int sot = _round ? pow(10, (int)_round) : 1;
regvalue = round(regvalue * sot) / sot;
@@ -101,6 +107,10 @@ IoTGpio* IoTItem::getGpioDriver() {
return nullptr;
}
iarduino_RTC_BASE* IoTItem::getRtcDriver() {
return nullptr;
}
void IoTItem::setValue(IoTValue Value) {
value = Value;
if (value.isDecimal)
@@ -109,6 +119,15 @@ void IoTItem::setValue(IoTValue Value) {
regEvent(value.valS, "");
}
void IoTItem::setValue(String valStr) {
if (value.isDecimal = isDigitDotCommaStr(valStr)) {
value.valD = valStr.toFloat();
} else {
value.valS = valStr;
}
setValue(value);
}
externalVariable::externalVariable(String parameters) : IoTItem(parameters) {
prevMillis = millis(); // запоминаем текущее значение таймера для выполения doByInterval после int сек
iAmLocal = false; // указываем, что это сущность прилетела из сети

46
src/classes/IoTRTC.cpp Normal file
View File

@@ -0,0 +1,46 @@
#include "classes/IoTRTC.h"
IoTRTC::~IoTRTC() {
}
iarduino_RTC_NTP::iarduino_RTC_NTP() {
}
void iarduino_RTC_NTP::begin(void) {
}
uint8_t iarduino_RTC_NTP::funcReadTimeIndex(uint8_t i) {
static tm localTimeVar;
if (i == 0) {
Serial.println(F("Read time from system."));
time_t timeNowVar;
time(&timeNowVar);
localTimeVar = *localtime(&timeNowVar);
}
switch (i)
{
case 0: return funcConvertNumToCode(localTimeVar.tm_sec);
case 1: return funcConvertNumToCode(localTimeVar.tm_min);
case 2: return funcConvertNumToCode(localTimeVar.tm_hour);
case 3: return funcConvertNumToCode(localTimeVar.tm_mday);
case 4: return funcConvertNumToCode(localTimeVar.tm_mon+1);
case 5: return funcConvertNumToCode(localTimeVar.tm_year-100);
case 6: return funcConvertNumToCode(localTimeVar.tm_wday);
}
return 0;
}
void iarduino_RTC_NTP::funcWriteTimeIndex(uint8_t i, uint8_t j) {
}
iarduino_RTC_NTP::~iarduino_RTC_NTP() {
}

View File

@@ -44,7 +44,7 @@ public:
IoTValue* exec() {
if (isIotScenException) return nullptr;
Serial.printf("Call from NumberExprAST: %f\n", Val.valD);
//Serial.printf("Call from NumberExprAST: %f\n", Val.valD);
return &Val;
}
};
@@ -57,7 +57,7 @@ public:
IoTValue* exec() {
if (isIotScenException) return nullptr;
Serial.printf("Call from StringExprAST: %s\n", Val.valS.c_str());
//Serial.printf("Call from StringExprAST: %s\n", Val.valS.c_str());
return &Val;
}
};
@@ -85,9 +85,9 @@ public:
if (isIotScenException) return nullptr;
if (!ItemIsLocal) Item = findIoTItem(Name);
if (Item) {
if (Item->value.isDecimal)
Serial.printf("Call from VariableExprAST: %s = %f\n", Name.c_str(), Item->value.valD);
else Serial.printf("Call from VariableExprAST: %s = %s\n", Name.c_str(), Item->value.valS.c_str());
//if (Item->value.isDecimal)
// Serial.printf("Call from VariableExprAST: %s = %f\n", Name.c_str(), Item->value.valD);
//else Serial.printf("Call from VariableExprAST: %s = %s\n", Name.c_str(), Item->value.valS.c_str());
return &(Item->value);
}
@@ -100,6 +100,7 @@ class BinaryExprAST : public ExprAST {
signed char Op;
ExprAST *LHS, *RHS;
IoTValue val;
String lhsStr, rhsStr;
public:
BinaryExprAST(signed char op, ExprAST *lhs, ExprAST *rhs)
@@ -108,7 +109,7 @@ public:
~BinaryExprAST() {
if (LHS) delete LHS;
if (RHS) delete RHS;
Serial.printf("Call from BinaryExprAST delete\n");
//Serial.printf("Call from BinaryExprAST delete\n");
}
IoTValue* exec(){
@@ -121,7 +122,7 @@ public:
else if (Op == tok_greateq) printStr = ">=";
else printStr = printStr + (char)Op;
Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str());
//Serial.printf("Call from BinaryExprAST: %s\n", printStr.c_str());
if (RHS == nullptr || LHS == nullptr) return nullptr;
@@ -182,10 +183,18 @@ public:
return &val;
}
if (!lhs->isDecimal && !rhs->isDecimal) {
if (!lhs->isDecimal || !rhs->isDecimal) {
if (lhs->isDecimal) lhsStr = lhs->valD; else lhsStr = lhs->valS;
if (rhs->isDecimal) rhsStr = rhs->valD; else rhsStr = rhs->valS;
switch (Op) {
case tok_equal:
val.valD = lhs->valS == rhs->valS;
val.valD = compStr(lhsStr, rhsStr);
break;
case '+':
val.valS = lhsStr + rhsStr;
val.valD = 1;
val.isDecimal = false;
break;
default:
@@ -194,8 +203,19 @@ public:
return &val;
}
}
return nullptr;
return &val;
}
bool compStr(String str1, String str2){
if (str1.length() != str2.length()) return false;
for (int i = 0; i < str1.length(); i++) {
if (str1[i] == '*' || str2[i] == '*') continue; //считаем, что если есть подстановочная звезда, то символы равны
if (str1[i] != str2[i]) return false;
}
return true;//str1 == str2;
}
};
/// CallExprAST - Класс узла выражения для вызова команды.
@@ -240,8 +260,8 @@ public:
ret = Item->execute(Cmd, ArgsAsIoTValue); // вызываем команду из модуля напрямую с передачей всех аргументов
if (ret.isDecimal) Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %f\n", Callee.c_str(), Cmd.c_str(), ret.valD);
else Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %s\n", Callee.c_str(), Cmd.c_str(), ret.valS.c_str());
//if (ret.isDecimal) Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %f\n", Callee.c_str(), Cmd.c_str(), ret.valD);
//else Serial.printf("Call from CallExprAST ID = %s, Command = %s, exec result = %s\n", Callee.c_str(), Cmd.c_str(), ret.valS.c_str());
return &ret;
}
@@ -250,7 +270,7 @@ public:
if (Args[i]) delete Args[i];
}
Args.clear();
Serial.printf("Call from CallExprAST delete\n");
//Serial.printf("Call from CallExprAST delete\n");
}
};
@@ -268,8 +288,8 @@ public:
}
bool hasEventIdName(String eventIdName) {
Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str());
return _IDNames.indexOf(eventIdName) >= 0; // определяем встречался ли ИД, для которого исполняем сценарий в выражении IF
//Serial.printf("Call from BinaryExprAST _IDNames:%s\n", _IDNames.c_str());
return _IDNames.indexOf(" " + eventIdName + " ") >= 0; // определяем встречался ли ИД, для которого исполняем сценарий в выражении IF
}
IoTValue* exec() {
@@ -280,7 +300,7 @@ public:
if (Cond) cond_ret = Cond->exec();
if (!cond_ret) {
Serial.printf("Call from IfExprAST: Skip If\n");
//Serial.printf("Call from IfExprAST: Skip If\n");
return nullptr; //&zeroIotVal;
}
@@ -292,9 +312,9 @@ public:
res_ret = Else->exec();
}
if (!res_ret) Serial.printf("Call from IfExprAST: Cond result = %f, no body result\n", cond_ret->valD);
else if (res_ret->isDecimal) Serial.printf("Call from IfExprAST: Cond result = %f, result = %f\n", cond_ret->valD, res_ret->valD);
else Serial.printf("Call from IfExprAST: Cond result = %f, result = %s\n", cond_ret->valD, res_ret->valS.c_str());
//if (!res_ret) Serial.printf("Call from IfExprAST: Cond result = %f, no body result\n", cond_ret->valD);
//else if (res_ret->isDecimal) Serial.printf("Call from IfExprAST: Cond result = %f, result = %f\n", cond_ret->valD, res_ret->valD);
//else Serial.printf("Call from IfExprAST: Cond result = %f, result = %s\n", cond_ret->valD, res_ret->valS.c_str());
Serial.printf("\n");
return cond_ret;
}
@@ -303,7 +323,7 @@ public:
if (Cond) delete Cond;
if (Then) delete Then;
if (Else) delete Else;
Serial.printf("Call from IfExprAST delete\n");
//Serial.printf("Call from IfExprAST delete\n");
}
};
@@ -317,7 +337,7 @@ public:
IoTValue* exec() {
if (isIotScenException) return nullptr;
Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size());
//Serial.printf("Call from BracketsExprAST OperCount = %d \n", BracketsList.size());
IoTValue* lastExecValue = nullptr;
for (unsigned int i = 0; i < BracketsList.size(); i++) {
@@ -334,7 +354,7 @@ public:
}
BracketsList.clear();
Serial.printf("Call from BracketsExprAST delete\n");
//Serial.printf("Call from BracketsExprAST delete\n");
}
};
@@ -356,9 +376,9 @@ public:
while (isspace(LastChar))
LastChar = getLastChar();
if (isalpha(LastChar)) { // идентификатор: [a-zA-Z][a-zA-Z0-9]*
if (isalpha(LastChar) || LastChar == '_') { // идентификатор: [a-zA-Z][a-zA-Z0-9]*
IdentifierStr = LastChar;
while (isalnum((LastChar = getLastChar()))){
while (isalnum((LastChar = getLastChar())) || LastChar == '_'){
IdentifierStr += LastChar;
}
@@ -609,7 +629,7 @@ public:
case tok_identifier: {
if (IDNames) {
String tmpstr = *IDNames;
*IDNames = tmpstr + " " + IdentifierStr;
*IDNames = tmpstr + " " + IdentifierStr + " ";
}
return ParseIdentifierExpr(IDNames);
}
@@ -707,7 +727,7 @@ public:
Serial.printf("Count root elements in scenario: %d\n", ScenarioElements.size());
for (unsigned int i = 0; i < ScenarioElements.size(); i++) {
if (ScenarioElements[i] && ScenarioElements[i]->hasEventIdName(eventIdName)) ScenarioElements[i]->exec();
else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str());
//else Serial.printf("Call from ExecScenario: Skip ifexec because %s not found\n", eventIdName.c_str());
if (isIotScenException) return;
}
}

View File

@@ -1,3 +0,0 @@
#include "classes/ScenarioClass3.h"
Scenario* myScenario;

View File

@@ -1,11 +1,11 @@
#include "ESPConfiguration.h"
void* getAPI_Mcp23017(String subtype, String params);
void* getAPI_SysExt(String subtype, String params);
void* getAPI_Variable(String subtype, String params);
void* getAPI_Lcd2004(String subtype, String params);
void* getAPI_ButtonIn(String subtype, String params);
void* getAPI_ButtonOut(String subtype, String params);
void* getAPI_Ads1115(String subtype, String params);
void* getAPI_IoTServo(String subtype, String params);
void* getAPI_Mp3(String subtype, String params);
void* getAPI_Timer(String subtype, String params);
void* getAPI_Aht20(String subtype, String params);
void* getAPI_AnalogAdc(String subtype, String params);
void* getAPI_Bme280(String subtype, String params);
@@ -15,19 +15,22 @@ void* getAPI_Ds18b20(String subtype, String params);
void* getAPI_GY21(String subtype, String params);
void* getAPI_Hdc1080(String subtype, String params);
void* getAPI_Max6675(String subtype, String params);
void* getAPI_Mhz19(String subtype, String params);
void* getAPI_Sds011(String subtype, String params);
void* getAPI_RCswitch(String subtype, String params);
void* getAPI_Sht20(String subtype, String params);
void* getAPI_Lcd2004(String subtype, String params);
void* getAPI_Sonar(String subtype, String params);
void* getAPI_IarduinoRTC(String subtype, String params);
void* getAPI_Mcp23017(String subtype, String params);
void* getAPI_SysExt(String subtype, String params);
void* getAPI_Variable(String subtype, String params);
void* getAPI(String subtype, String params) {
void* tmpAPI;
if ((tmpAPI = getAPI_Mcp23017(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_SysExt(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Variable(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Lcd2004(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_ButtonIn(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_ButtonOut(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Ads1115(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_IoTServo(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Mp3(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Timer(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Aht20(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_AnalogAdc(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Bme280(subtype, params)) != nullptr) return tmpAPI;
@@ -37,8 +40,12 @@ if ((tmpAPI = getAPI_Ds18b20(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_GY21(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Hdc1080(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Max6675(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Mhz19(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Sds011(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_RCswitch(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Sht20(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Lcd2004(subtype, params)) != nullptr) return tmpAPI;return nullptr;
if ((tmpAPI = getAPI_Sonar(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_IarduinoRTC(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Mcp23017(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_SysExt(subtype, params)) != nullptr) return tmpAPI;
if ((tmpAPI = getAPI_Variable(subtype, params)) != nullptr) return tmpAPI;
return nullptr;
}

View File

@@ -4,6 +4,8 @@
#include "LiquidCrystal_I2C.h"
#include <map>
void scanI2C();
LiquidCrystal_I2C *LCDI2C;
class Lcd2004 : public IoTItem {
@@ -14,12 +16,19 @@ class Lcd2004 : public IoTItem {
String _descr;
int _prevStrSize;
bool _isShow = true; // экран показывает
public:
Lcd2004(String parameters) : IoTItem(parameters) {
String addr, size, xy;
_prevStrSize = 0;
jsonRead(parameters, "addr", addr);
if (addr == "") {
scanI2C();
return;
}
jsonRead(parameters, "size", size);
int w = selectFromMarkerToMarker(size, ",", 0).toInt(); //количество столбцов
int h = selectFromMarkerToMarker(size, ",", 1).toInt(); //количество строк
@@ -48,8 +57,8 @@ class Lcd2004 : public IoTItem {
else tmpStr = getItemValue(_id2show);
LCDI2C->setCursor(_x, _y);
LCDI2C->print(tmpStr);
// LCDI2C->print("Helloy,Manager 404 !");
//LCDI2C->print("Helloy,Manager 404 !");
_prevStrSize = tmpStr.length();
}
@@ -60,18 +69,36 @@ class Lcd2004 : public IoTItem {
LCDI2C->noBacklight();
else if (command == "backlight")
LCDI2C->backlight();
else if (command == "noDisplay")
else if (command == "noDisplay") {
LCDI2C->noDisplay();
else if (command == "display")
_isShow = false;
} else if (command == "display") {
LCDI2C->display();
else if (command == "x") {
_x = param[0].valD;
_isShow = true;
} else if (command == "toggle") {
if (_isShow) {
LCDI2C->noDisplay();
_isShow = false;
} else {
LCDI2C->display();
_isShow = true;
}
} else if (command == "x") {
if (param.size()) {
_x = param[0].valD;
}
} else if (command == "y") {
_y = param[0].valD;
if (param.size()) {
_y = param[0].valD;
}
} else if (command == "descr") {
_descr = param[0].valS;
if (param.size()) {
_descr = param[0].valS;
}
} else if (command == "id2show") {
_id2show = param[0].valS;
if (param.size()) {
_id2show = param[0].valS;
}
}
doByInterval();

View File

@@ -0,0 +1,62 @@
{
"menuSection": "Экраны",
"configItem": [{
"name": "LCD экран 2004",
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"int": 15,
"addr": "0x27",
"size": "20,4",
"coord": "0,0",
"id2show": "id датчика"
},
{
"name": "LCD экран 1602",
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"int": 15,
"addr": "0x27",
"size": "16,2",
"coord": "0,0",
"id2show": "id датчика"
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "Sergey @Serghei63",
"moduleName": "Lcd2004",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет выводить на символьные экраны по указанным позициям значения других элементов конфигурации.",
"propInfo": {
"int": "Период времени в секундах обновления информации на экране по конкретному элементу.",
"addr": "Адрес устройства на шине, обычно 0x27.",
"size": "Размерность матрицы экрана.",
"coord": "Координата позиции для вывода данных элемента конфигурации.",
"id2show": "id элемента конфигурации."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"marcoschwartz/LiquidCrystal_I2C@^1.1.4"
],
"esp8266_4mb": [
"marcoschwartz/LiquidCrystal_I2C@^1.1.4"
]
}
}

View File

@@ -1,19 +0,0 @@
[
{
"name": "Кнопка (подключенная физически)",
"num": 31,
"type": "Writing",
"subtype": "ButtonIn",
"id": "btn",
"widget": "toggle",
"page": "Кнопки",
"descr": "",
"int": 0,
"pin": 16,
"execLevel": "1",
"pinMode": "INPUT",
"debounceDelay": 50,
"fixState": 1
}
]

View File

@@ -0,0 +1,44 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "Кнопка (подключенная физически)",
"type": "Writing",
"subtype": "ButtonIn",
"id": "btn",
"widget": "toggle",
"page": "Кнопки",
"descr": "",
"int": 0,
"pin": 16,
"execLevel": "1",
"pinMode": "INPUT",
"debounceDelay": 50,
"fixState": 1
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "ButtonIn",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет интерпретировать сигналы на цифровом пине как кнопку, т.е. создает в системе объект для чтения булевых значений с внешнего физического источника. Может вести себя как кнопка или как переключатель.",
"propInfo": {
"pin": "Укажите GPIO номер пина для чтения состояний подключенной кнопки",
"execLevel": "Высокий 1 или низкий 0 уровень переключения состояния",
"pinMode": "Может быть INPUT_PULLUP INPUT_PULLDOWN INPUT",
"debounceDelay": "Время обработки дребезга",
"fixState": "Поведение входа, срабатывание на переходе или на фиксации уровня (триггерный режим)"
}
},
"defActive": true,
"devices": {
"esp32_4mb": [],
"esp8266_4mb": []
}
}

View File

@@ -15,7 +15,7 @@ class ButtonOut : public IoTItem {
IoTgpio.pinMode(_pin, OUTPUT);
//TODO: прочитать состояние из памяти
IoTgpio.digitalWrite(_pin, LOW); // пока нет памяти, устанавливаем значение в ноль
IoTgpio.digitalWrite(_pin, _inv?HIGH:LOW); // пока нет памяти, устанавливаем значение в ноль
value.valD = 0;
}
@@ -30,7 +30,7 @@ class ButtonOut : public IoTItem {
// String command - имя команды после ID. (ID.Команда())
// param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22
if (command == "change") { // выполняем код при вызове спец команды из сценария: ID.reboot();
if (command == "change") {
value.valD = 1 - IoTgpio.digitalRead(_pin);
IoTgpio.digitalWrite(_pin, value.valD);
regEvent(value.valD, "ButtonOut");
@@ -41,7 +41,7 @@ class ButtonOut : public IoTItem {
void setValue(IoTValue Value) {
value = Value;
IoTgpio.digitalWrite(_pin, value.valD);
IoTgpio.digitalWrite(_pin, _inv?!value.valD:value.valD);
if (value.isDecimal) regEvent(value.valD, "ButtonOut");
else regEvent(value.valS, "ButtonOut");
}

View File

@@ -1,16 +0,0 @@
[
{
"name": "Кнопка управляющая пином (Реле с кнопкой)",
"num": 31,
"type": "Writing",
"subtype": "ButtonOut",
"id": "btn",
"widget": "toggle",
"page": "Кнопки",
"descr": "",
"int": 0,
"inv": 0,
"pin": 2
}
]

View File

@@ -0,0 +1,38 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "Кнопка управляющая пином (Реле с кнопкой)",
"type": "Writing",
"subtype": "ButtonOut",
"id": "btn",
"widget": "toggle",
"page": "Кнопки",
"descr": "",
"int": 0,
"inv": 0,
"pin": 2
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "ButtonOut",
"moduleVersion": "1.0",
"moduleDesc": "Управляем состоянием конкретного пина по модели реле.",
"propInfo": {
"pin": "Укажите GPIO номер пина для управления выходом",
"inv": "Инвертировать выходные сигналы"
}
},
"defActive": true,
"devices": {
"esp32_4mb": [],
"esp8266_4mb": []
}
}

View File

@@ -0,0 +1,157 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include "esp_camera.h"
#include "soc/soc.h" // Disable brownour problems
#include "soc/rtc_cntl_reg.h" // Disable brownour problems
// Pin definition for CAMERA_MODEL_AI_THINKER
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#define PICBUF_SIZE 50000
IoTItem* globalItem = nullptr;
bool webTicker = false;
void handleGetCam() {
//Serial.printf("try send pic by size=%d", lastPhotoBSize);
if (globalItem && globalItem->value.extBinInfoSize) {
//Serial.printf("try send pic by size=%d", globalItem->value.extBinInfoSize);
HTTP.send_P(200, "image/jpeg", (char*)globalItem->value.extBinInfo, globalItem->value.extBinInfoSize);
if (webTicker) globalItem->regEvent("webAsk", "EspCam");
} else HTTP.send(200, "text/json", "Item EspCam not prepared yet or camera hasn't taken a picture yet");
}
class EspCam : public IoTItem {
private:
camera_fb_t * fb = NULL;
bool _useLed, _ticker, _webTicker;
public:
EspCam(String parameters): IoTItem(parameters) {
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
jsonRead(parameters, "useLed", _useLed); // используем = 1 или нет = 0 подсветку (вспышку)
jsonRead(parameters, "ticker", _ticker); // тикать = 1 - сообщаем всем, что сделали снимок и он готов
jsonRead(parameters, "webTicker", _webTicker); // сообщать всем, что через веб попросили отдать картинку с камеры
webTicker = _webTicker;
globalItem = this; // выносим адрес переменной экземпляра для доступа к данным из обработчика событий веб
pinMode(4, OUTPUT);
digitalWrite(4, LOW);
camera_config_t config;
config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;
config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;
config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;
config.pin_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
value.extBinInfo = (uint8_t*)malloc(sizeof(uint8_t) * PICBUF_SIZE);
if(psramFound()){
config.frame_size = FRAMESIZE_SVGA; // FRAMESIZE_ + QVGA|CIF|VGA|SVGA|XGA|SXGA|UXGA
config.jpeg_quality = 20; //0-63 lower number means higher quality
config.fb_count = 1;
Serial.printf("Camera psramFound\n");
} else {
config.frame_size = FRAMESIZE_SVGA;
config.jpeg_quality = 20;
config.fb_count = 1;
}
// Init Camera
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x\n", err);
return;
}
HTTP.on("/getcam", HTTP_GET, handleGetCam);
}
void take_picture() {
if (_useLed) digitalWrite(4, HIGH); //Turn on the flash
// Take Picture with Camera
fb = esp_camera_fb_get();
if(!fb || fb->len >= PICBUF_SIZE) {
if (fb) {
Serial.printf("Camera capture failed size=%d\n", fb->len);
esp_camera_fb_return(fb);
} else Serial.printf("Camera capture failed\n");
return;
}
// if (value.extBinInfoSize < fb->len) {
// if (value.extBinInfo) free(value.extBinInfo);
// value.extBinInfo = (uint8_t*)malloc(sizeof(uint8_t) * fb->len);
// }
memcpy(value.extBinInfo, fb->buf, fb->len);
value.extBinInfoSize = fb->len;
Serial.printf("try send pic by size=%d", fb->len);
if (_useLed) digitalWrite(4, LOW);
if (_ticker) regEvent("shot", "EspCam");
esp_camera_fb_return(fb);
}
void doByInterval() {
take_picture();
}
IoTValue execute(String command, std::vector<IoTValue> &param) {
if (command == "shot") {
take_picture();
}
return {};
}
~EspCam() {
free(value.extBinInfo);
//globalItem = nullptr;
};
};
void* getAPI_EspCam(String subtype, String param) {
if (subtype == F("EspCam")) {
return new EspCam(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,42 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "Camera OV2640 (ESPcam)",
"type": "Reading",
"subtype": "EspCam",
"id": "EspCam",
"widget": "",
"page": "",
"descr": "",
"int": 60,
"useLed": 0,
"ticker": 0,
"webTicker": 0
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "EspCam",
"moduleVersion": "1.0",
"moduleDesc": "Предназначен для специальной платы esp32 со встроенной камерой. Добавляет в прошивку функцию создания фото и сохранения в оперативную память. Для сброса на флешкарту необходимо использовать парный модуль SDcard. Это экспериментальные модули и в будущем планируется пересобрать их.",
"propInfo": {
"int": "Пауза в секундах во время постоянной съемки.",
"useLed": "использовать диод подсветки при съемке.",
"ticker": "Генерировать(1) или нет(0) событие с интервалом int",
"webTicker": "Генерировать(1) или нет(0) событие при обращении через веб-страницу с текущим фото в памяти."
}
},
"defActive": false,
"devices": {
"esp32_4mb": [
"espressif/esp32-camera @ ^2.0.0"
]
}
}

View File

@@ -0,0 +1,73 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include "classes/IoTGpio.h"
extern IoTGpio IoTgpio;
#include <Servo.h>
class IoTServo : public IoTItem {
private:
Servo servObj;
int _apin, _oldValue;
int _locmap1, _locmap2, _locmap3, _locmap4;
public:
IoTServo(String parameters): IoTItem(parameters) {
int pin;
jsonRead(parameters, "pin", pin);
servObj.attach(pin);
jsonRead(parameters, "apin", _apin);
if (_apin >= 0) IoTgpio.pinMode(_apin, INPUT);
String map;
jsonRead(parameters, F("amap"), map, false);
if (map != "") {
_locmap1 = selectFromMarkerToMarker(map, ",", 0).toInt();
_locmap2 = selectFromMarkerToMarker(map, ",", 1).toInt();
_locmap3 = selectFromMarkerToMarker(map, ",", 2).toInt();
_locmap4 = selectFromMarkerToMarker(map, ",", 3).toInt();
}
}
void doByInterval() {
if (_apin >= 0) {
value.valD = map(IoTgpio.analogRead(_apin), _locmap1, _locmap2, _locmap3, _locmap4);
if (abs(_oldValue - value.valD) > 5) {
_oldValue = value.valD;
servObj.write(_oldValue);
}
}
}
IoTValue execute(String command, std::vector<IoTValue> &param) {
if (command == "rotate") {
if (param.size()) {
value.valD = param[0].valD;
servObj.write(value.valD);
regEvent(value.valD, "IoTServo");
}
}
return {};
}
void setValue(IoTValue Value) {
value = Value;
if (value.isDecimal & (_oldValue != value.valD)) {
_oldValue = value.valD;
servObj.write(_oldValue);
regEvent(value.valD, "IoTServo");
}
}
~IoTServo() {};
};
void* getAPI_IoTServo(String subtype, String param) {
if (subtype == F("IoTServo")) {
return new IoTServo(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,43 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "Сервопривод",
"type": "Writing",
"subtype": "IoTServo",
"id": "servo",
"widget": "range",
"page": "servo",
"descr": "угол",
"int": 1,
"pin": 12,
"apin": -1,
"amap": "0, 4096, 0, 180"
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "Oleg @Threedreality, Sergey @Serghei63",
"moduleName": "IoTServo",
"moduleVersion": "1.0",
"moduleDesc": "Предназначен для управления сервоприводом по уровню аналогово сигнала.",
"propInfo": {
"int": "Пауза в секундах между опросами аналогового входа. Если 0, то читаем постоянно",
"pin": "Пин, к которому подключен сервопривод",
"apin": "Номер GPIO аналогового пина. Если -1, то функция отключена.",
"amap": "Настройки преобразования значений аналога в нужный диапазон сервы, имеет смысл, если аналог включен."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"https://github.com/RoboticsBrno/ServoESP32"
],
"esp8266_4mb": []
}
}

View File

@@ -0,0 +1,135 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include "SoftwareSerial.h" // Подключаем библиотеку SoftwareSerial
#include "DFRobotDFPlayerMini.h" // Подключаем библиотеку DFPlayerMini_Fast
class Mp3 : public IoTItem {
private:
SoftwareSerial* mySerial;
DFRobotDFPlayerMini* myMP3;
public:
Mp3(String parameters): IoTItem(parameters) {
String tmpstr;
int volumetmp;
jsonRead(parameters, "pins", tmpstr);
int pinRx = selectFromMarkerToMarker(tmpstr, ",", 0).toInt();
int pinTx = selectFromMarkerToMarker(tmpstr, ",", 1).toInt();
mySerial = new SoftwareSerial(pinRx, pinTx);
pinMode(pinRx, INPUT);
pinMode(pinTx, OUTPUT);
jsonRead(parameters, "volume", volumetmp);
if (mySerial) {
mySerial->begin(9600);
myMP3 = new DFRobotDFPlayerMini();
}
if (myMP3) {
myMP3->begin(*mySerial);
myMP3->volume(volumetmp);
}
value.isDecimal = false; // значение объекта всегда будет строка
}
void doByInterval() {
if (myMP3 && myMP3->available()) {
switch (myMP3->readType()) {
case TimeOut:
value.valS = F("Time Out!");
break;
case WrongStack:
value.valS = F("Stack Wrong!");
break;
case DFPlayerCardInserted:
value.valS = F("Card Inserted!");
break;
case DFPlayerCardRemoved:
value.valS = F("Card Removed!");
break;
case DFPlayerCardOnline:
value.valS = F("Card Online!");
break;
case DFPlayerPlayFinished:
value.valS = F("Play Finished!");
break;
case DFPlayerError:
switch (myMP3->read()) {
case Busy:
value.valS = F("Card not found");
break;
case Sleeping:
value.valS = F("Sleeping");
break;
case SerialWrongStack:
value.valS = F("Get Wrong Stack");
break;
case CheckSumNotMatch:
value.valS = F("Check Sum Not Match");
break;
case FileIndexOut:
value.valS = F("File Index Out of Bound");
break;
case FileMismatch:
value.valS = F("Cannot Find File");
break;
case Advertise:
value.valS = F("In Advertise");
break;
default:
break;
}
break;
default:
break;
}
}
}
IoTValue execute(String command, std::vector<IoTValue> &param) {
// реакция на вызов команды модуля из сценария
// String command - имя команды после ID. (ID.Команда())
// param - вектор ("массив") значений параметров переданных вместе с командой: ID.Команда("пар1", 22, 33) -> param[0].ValS = "пар1", param[1].ValD = 22
if (myMP3) {
if (command == "enableLoop") {
myMP3->enableLoop();
} else if (command == "disableLoop") {
myMP3->disableLoop();
} else if (command == "randomAll") {
myMP3->randomAll();
} else if (command == "stop") {
myMP3->stop();
} else if (command == "volume") {
if (param.size()) {
myMP3->volume(param[0].valD);
}
} else if (command == "playFolder") {
if (param.size()) {
myMP3->playFolder(param[0].valD, param[1].valD); // (folderNum, fileNum)
}
} else if (command == "play") {
myMP3->play(1); //Play the first mp3
} else if (command == "next") {
myMP3->next(); //Play next mp3
} else if (command == "previous") {
myMP3->previous(); //Play previous mp3
}
}
return {}; // команда поддерживает возвращаемое значения. Т.е. по итогу выполнения команды или общения с внешней системой, можно вернуть значение в сценарий для дальнейшей обработки
}
~Mp3() {};
};
void* getAPI_Mp3(String subtype, String param) {
if (subtype == F("Mp3")) {
return new Mp3(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,43 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "MP3 плеер",
"type": "Reading",
"subtype": "Mp3",
"id": "mp3",
"widget": "",
"page": "",
"descr": "",
"int": 1,
"pins": "14,12",
"volume": 20
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "Mp3",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет управлять модулем проигрывания MP3 файлов с SD-карты по serial интерфейсу (DFplayer mini).",
"propInfo": {
"int": "Периодичность в секундах опроса состояния плеера.",
"pins": "Список GPIO через запятую, к которым подключен плеер.",
"volume": "Уровень громкости при инициализации."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"dfrobot/DFRobotDFPlayerMini @ ^1.0.5"
],
"esp8266_4mb": [
"dfrobot/DFRobotDFPlayerMini @ ^1.0.5"
]
}
}

View File

@@ -0,0 +1,70 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include "FS.h" // SD Card ESP32
#include "SD_MMC.h" // SD Card ESP32
class SDcard : public IoTItem {
private:
public:
SDcard(String parameters): IoTItem(parameters) {
// jsonRead(parameters, "useLed", _useLed); // используем = 1 или нет = 0 подсветку (вспышку)
// jsonRead(parameters, "ticker", _ticker); // тикать = 1 - сообщаем всем, что сделали снимок и он готов
// jsonRead(parameters, "webTicker", _webTicker); // сообщать всем, что через веб попросили отдать картинку с камеры
Serial.println("Starting SD Card");
if(!SD_MMC.begin()){
Serial.println("SD Card Mount Failed");
return;
}
uint8_t cardType = SD_MMC.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD Card attached");
return;
}
}
void savePicture(String path, IoTValue srcValue) {
if (srcValue.extBinInfoSize) {
fs::FS &fs = SD_MMC;
File file = fs.open(path.c_str(), FILE_WRITE);
if(!file){
Serial.println("Failed to open file in writing mode");
}
else {
file.write(srcValue.extBinInfo, srcValue.extBinInfoSize); // payload (image), payload length
Serial.printf("Picture file name: %s | bufsize: %d\n", path.c_str(), srcValue.extBinInfoSize);
}
file.close();
}
}
void doByInterval() {
}
IoTValue execute(String command, std::vector<IoTValue> &param) {
if (command == "saveBin") {
if (param.size() == 2) {
savePicture (param[0].valS, param[1]);
}
}
return {};
}
~SDcard() {
};
};
void* getAPI_SDcard(String subtype, String param) {
if (subtype == F("SDcard")) {
return new SDcard(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,36 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "SD карта",
"type": "Writing",
"subtype": "SDcard",
"id": "sd",
"widget": "",
"page": "",
"descr": "",
"int": 1
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "SDcard",
"moduleVersion": "1.0",
"moduleDesc": "Предназначен для специальной платы esp32 со встроенной камерой. Добавляет в прошивку функцию сохранения фото из оперативной памяти. Работает в паре с EspCam. Это экспериментальные модули и в будущем планируется пересобрать их.",
"propInfo": {
"int": "Не используется."
}
},
"defActive": false,
"devices": {
"esp32_4mb": [
"espressif/esp32-camera @ ^2.0.0"
]
}
}

View File

@@ -0,0 +1,141 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include "CTBot.h"
String uint64ToString(uint64_t input) {
String result = "";
uint8_t base = 10;
do {
char c = input % base;
input /= base;
if (c < 10)
c +='0';
else
c += 'A' - 10;
result = c + result;
} while (input);
return result;
}
class Telegram : public IoTItem {
private:
CTBot _myBot;
String _token;
bool _autos;
bool _receiveMsg;
int64_t _chatID;
String _prevMsg = "";
void telegramMsgParse(String msg) {
if (msg.indexOf("set") != -1) {
msg = deleteBeforeDelimiter(msg, "_");
generateOrder(selectToMarker(msg, "_"), selectToMarkerLast(msg, "_"));
_myBot.sendMessage(_chatID, "order done");
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + String(msg));
} else if (msg.indexOf("get") != -1) {
msg = deleteBeforeDelimiter(msg, "_");
IoTItem* item = findIoTItem(msg);
if (item) {
_myBot.sendMessage(_chatID, item->getValue());
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + String(msg));
}
} else if (msg.indexOf("all") != -1) {
String list = returnListOfParams();
_myBot.sendMessage(_chatID, list);
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + "\n" + list);
} else if (msg.indexOf("help") != -1) {
_myBot.sendMessage(_chatID, "ID: " + chipId);
_myBot.sendMessage(_chatID, "chatID: " + uint64ToString(_chatID));
_myBot.sendMessage(_chatID, F("Wrong order, use /all to get all values, /get_id to get value, or /set_id_value to set value"));
} else {
setValue(msg);
}
}
String returnListOfParams() {
String out;
for (std::list<IoTItem*>::iterator it = IoTItems.begin(); it != IoTItems.end(); ++it) {
if ((*it)->iAmLocal) out = out + (*it)->getID() + ": " + (*it)->getValue() + "\n";
}
return out;
}
public:
Telegram(String parameters): IoTItem(parameters) {
jsonRead(parameters, "token", _token);
jsonRead(parameters, "autos", _autos);
jsonRead(parameters, "receiveMsg", _receiveMsg);
String tmp;
jsonRead(parameters, "chatID", tmp);
_chatID = atoll(tmp.c_str());
#ifdef ESP32
_myBot.useDNS(true);
#endif
_myBot.setTelegramToken(_token);
_myBot.enableUTF8Encoding(true);
}
void doByInterval() {
if (_receiveMsg) {
TBMessage msg;
if (_myBot.getNewMessage(msg)) {
SerialPrint("->", F("Telegram"), "chat ID: " + uint64ToString(msg.sender.id) + ", msg: " + msg.text);
if (_autos) {
_chatID = msg.sender.id;
}
telegramMsgParse(String(msg.text));
}
}
}
IoTValue execute(String command, std::vector<IoTValue> &param) {
if (command == "sendMsg") {
if (param.size()) {
String strTmp;
if (param[0].isDecimal) strTmp = param[0].valD; else strTmp = param[0].valS;
sendTelegramMsg(false, strTmp);
}
} else if (command == "sendOftenMsg") {
if (param.size()) {
String strTmp;
if (param[0].isDecimal) strTmp = param[0].valD; else strTmp = param[0].valS;
sendTelegramMsg(true, strTmp);
}
}
return {};
}
void sendTelegramMsg(bool often, String msg) {
if (often) {
_myBot.sendMessage(_chatID, msg);
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + msg);
} else {
if (_prevMsg != msg) {
_prevMsg = msg;
_myBot.sendMessage(_chatID, msg);
SerialPrint("<-", F("Telegram"), "chat ID: " + uint64ToString(_chatID) + ", msg: " + msg);
}
}
}
~Telegram() {
};
};
void* getAPI_Telegram(String subtype, String param) {
if (subtype == F("Telegram")) {
return new Telegram(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,46 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "Телеграм-Бот",
"type": "Writing",
"subtype": "Telegram",
"id": "tg",
"widget": "",
"page": "",
"descr": "",
"int": 10,
"token": "",
"autos": 1,
"receiveMsg": 0,
"chatID": ""
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "Telegram",
"moduleVersion": "1.0",
"moduleDesc": "Добавляет возможность отправлять сообщения от имени бота контакту в Телеграм-чате и получать команды.",
"propInfo": {
"token": "Токен для авторизации бота в системе Telegram",
"autos": "Автоматически(1) или нет(0) запоминать ChatID по входящим сообщениям. Т.е. бот будет информировать тех, кто последний прислал сообщение.",
"receiveMsg": "Обрабатывать(1) или нет(0) входящие сообщения.",
"chatID": "ИД диалога с контактом. Необходим для отправки сообщений именно вам."
}
},
"defActive": false,
"devices": {
"esp32_4mb": [
"CTBot @2.1.9"
],
"esp8266_4mb": [
"CTBot @2.1.9"
]
}
}

View File

@@ -0,0 +1,69 @@
#include "Global.h"
#include "classes/IoTItem.h"
extern IoTGpio IoTgpio;
class Timer : public IoTItem {
private:
bool _unfin = false;
bool _ticker = false;
bool _repeat = false;
bool _needSave = false;
bool _pause = false;
int _initValue;
public:
Timer(String parameters): IoTItem(parameters) {
jsonRead(parameters, "countDown", _initValue);
_unfin = !_initValue;
value.valD = _initValue;
if (_initValue) value.valD = value.valD + 1; // +1 - компенсируем ранний вычет счетчика, ранний вычет, чтоб после события значение таймера не исказилось.
// +0 - если изначально установили бесконечный счет
jsonRead(parameters, "ticker", _ticker);
jsonRead(parameters, "repeat", _repeat);
jsonRead(parameters, "needSave", _needSave); // нужно сохранять счетчик в постоянную память
}
void doByInterval() {
if (!_unfin && value.valD >= 0 && !_pause) {
value.valD--;
if (_repeat && value.valD == -1) value.valD = _initValue;
if (_needSave) needSave = true;
if (value.valD == 0) {
regEvent(value.valD, "Time's up");
}
}
if (_ticker && (value.valD > 0 || _unfin) && !_pause) regEvent(value.valD, "Timer tick");
}
IoTValue execute(String command, std::vector<IoTValue> &param) {
if (command == "stop") {
_pause = true;
} else if (command == "reset") {
_pause = false;
value.valD = _initValue;
if (_initValue) value.valD = value.valD + 1;
} else if (command == "continue") {
_pause = false;
} else if (command == "int") {
if (param.size()) {
setInterval(param[0].valD);
}
}
return {};
}
~Timer() {};
};
void* getAPI_Timer(String subtype, String param) {
if (subtype == F("Timer")) {
return new Timer(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,43 @@
{
"menuSection": "Модули управления",
"configItem": [{
"name": "Таймер",
"type": "Writing",
"subtype": "Timer",
"id": "timer",
"widget": "",
"page": "",
"descr": "",
"int": 1,
"countDown": 15,
"ticker": 0,
"repeat": 0,
"needSave": 0
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "Timer",
"moduleVersion": "1.0",
"moduleDesc": "Добавляет инструмент таймеров обратного отсчета для организации периодичных операций или логических конструкций. Часто используется как вспомогательный элемент для автоматизации.",
"propInfo": {
"int": "Задает размер в секундах одного шага(тика) таймера.",
"countDown": "Начальное значение таймера, с которого начинается обратный отсчет.",
"ticker": "Генерировать(1) или нет(0) события при каждом тике таймера.",
"repeat": "Сбрасывать(1) или нет(0) таймер в начальное состояние при достижении нуля.",
"needSave": "Требуется сохранять(1) или нет(0) состояние в энерго независимую память. Функция находится в разработке."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [],
"esp8266_4mb": []
}
}

View File

@@ -1,5 +0,0 @@
[
{
"header": "Модули управления"
}
]

View File

@@ -1,6 +0,0 @@
[
{
"name": "Выберите элемент",
"num": 0
}
]

View File

@@ -1,32 +0,0 @@
[
{
"name": "LCD экран 2004",
"num": 25,
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"int": 15,
"addr": "0x27",
"size": "20,4",
"coord": "0,0",
"id2show": "id датчика"
},
{
"name": "LCD экран 1602",
"num": 26,
"type": "Reading",
"subtype": "Lcd2004",
"id": "Lcd",
"widget": "",
"page": "",
"descr": "T",
"int": 15,
"addr": "0x27",
"size": "16,2",
"coord": "0,0",
"id2show": "id датчика"
}
]

View File

@@ -1,7 +0,0 @@
[env:esp8266_4mb]
lib_deps =
marcoschwartz/LiquidCrystal_I2C@^1.1.4
[env:esp32_4mb]
lib_deps =
marcoschwartz/LiquidCrystal_I2C@^1.1.4

View File

@@ -1,5 +0,0 @@
[
{
"header": "Экраны"
}
]

View File

@@ -1,21 +0,0 @@
[
{
"name": "Датчик напряжения ADS1115",
"num": 28,
"type": "Reading",
"subtype": "Ads1115",
"id": "Ads3",
"widget": "anydataVlt",
"page": "Сенсоры",
"descr": "ADS_3",
"pin": "0",
"mode": "volt",
"gain": "3/4x",
"plus": 0,
"multiply": 1,
"round": 100,
"int": 10
}
]

View File

@@ -0,0 +1,49 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Датчик напряжения ADS1115",
"type": "Reading",
"subtype": "Ads1115",
"id": "Ads3",
"widget": "anydataVlt",
"page": "Сенсоры",
"descr": "ADS_3",
"pin": "0",
"mode": "volt",
"gain": "3/4x",
"plus": 0,
"multiply": 1,
"round": 2,
"int": 10
}],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "",
"moduleName": "Ads1115",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить относительную величину напряжения на понижающем трансформаторе.",
"propInfo": {
"pin": "GPIO номер, к которому подключен датчик.",
"mode": "",
"gain": "",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": false,
"devices": {
"esp32_4mb": [
"adafruit/Adafruit ADS1X15 @ ^2.3.0"
],
"esp8266_4mb": [
"adafruit/Adafruit ADS1X15 @ ^2.3.0"
]
}
}

View File

@@ -1,7 +0,0 @@
[env:esp8266_4mb]
lib_deps =
adafruit/Adafruit ADS1X15 @ ^2.3.0
[env:esp32_4mb]
lib_deps =
adafruit/Adafruit ADS1X15 @ ^2.3.0

View File

@@ -1,27 +0,0 @@
[{
"name": "Cенсор температуры AHT20",
"num": 12,
"type": "Reading",
"subtype": "Aht20t",
"id": "Temp20",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "AHT20 Температура",
"int": 15,
"addr": "0x38",
"round": 1
},
{
"name": "Cенсор влажности AHT20",
"num": 13,
"type": "Reading",
"subtype": "Aht20h",
"id": "Hum20",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "AHT20 Влажность",
"int": 15,
"addr": "0x38",
"round": 1
}
]

View File

@@ -0,0 +1,54 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Cенсор температуры AHT20",
"type": "Reading",
"subtype": "Aht20t",
"id": "Temp20",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "AHT20 Температура",
"int": 15,
"addr": "0x38",
"round": 1
},
{
"name": "Cенсор влажности AHT20",
"type": "Reading",
"subtype": "Aht20h",
"id": "Hum20",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "AHT20 Влажность",
"int": 15,
"addr": "0x38",
"round": 1
}],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "",
"moduleName": "Aht20",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить температуру и влажность с Aht20.",
"propInfo": {
"pin": "GPIO номер, к которому подключен датчик.",
"addr": "Адрес датчика на шине, обычно 0x38.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"Adafruit AHTX0"
],
"esp8266_4mb": [
"Adafruit AHTX0"
]
}
}

View File

@@ -1,7 +0,0 @@
[env:esp8266_4mb]
lib_deps =
Adafruit AHTX0
[env:esp32_4mb]
lib_deps =
Adafruit AHTX0

View File

@@ -3,53 +3,82 @@
extern IoTGpio IoTgpio;
//Это файл сенсора, в нем осуществляется чтение сенсора.
//для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора
//Название должно быть уникальным, коротким и отражать суть сенсора.
// Это файл сенсора, в нем осуществляется чтение сенсора.
// для добавления сенсора вам нужно скопировать этот файл и заменить в нем текст AnalogAdc на название вашего сенсора
// Название должно быть уникальным, коротким и отражать суть сенсора.
class AnalogAdc : public IoTItem {
private:
//=======================================================================================================
// Секция переменных.
//Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы
//впоследствии использовать их в loop и setup
// Это секция где Вы можете объявлять переменные и объекты arduino библиотек, что бы
// впоследствии использовать их в loop и setup
unsigned int _pin;
unsigned int _avgSteps, _avgCount;
unsigned long _avgSumm;
public:
//=======================================================================================================
// setup()
//это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора.
//Такие как ...begin и подставлять в них параметры полученные из web интерфейса.
//Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции:
// это аналог setup из arduino. Здесь вы можете выполнять методы инициализации сенсора.
// Такие как ...begin и подставлять в них параметры полученные из web интерфейса.
// Все параметры хранятся в перемененной parameters, вы можете прочитать любой параметр используя jsonRead функции:
// jsonReadStr, jsonReadBool, jsonReadInt
AnalogAdc(String parameters): IoTItem(parameters) {
_pin = jsonReadInt(parameters, "pin");
_avgSteps = jsonReadInt(parameters, "avgSteps");
_avgSumm = 0;
_avgCount = 0;
}
//=======================================================================================================
// doByInterval()
//это аналог loop из arduino, но вызываемый каждые int секунд, заданные в настройках. Здесь вы должны выполнить чтение вашего сенсора
//а затем выполнить regEvent - это регистрация произошедшего события чтения
//здесь так же доступны все переменные из секции переменных, и полученные в setup
//если у сенсора несколько величин то делайте несколько regEvent
//не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции
//и выполнить за несколько тактов
// это аналог loop из arduino, но вызываемый каждые int секунд, заданные в настройках. Здесь вы должны выполнить чтение вашего сенсора
// а затем выполнить regEvent - это регистрация произошедшего события чтения
// здесь так же доступны все переменные из секции переменных, и полученные в setup
// если у сенсора несколько величин то делайте несколько regEvent
// не используйте delay - помните, что данный loop общий для всех модулей. Если у вас планируется длительная операция, постарайтесь разбить ее на порции
// и выполнить за несколько тактов
void doByInterval() {
value.valD = IoTgpio.analogRead(_pin);
if (_avgSteps <= 1) value.valD = IoTgpio.analogRead(_pin);
regEvent(value.valD, "AnalogAdc"); //обязательный вызов хотяб один
}
//=======================================================================================================
// loop()
// полный аналог loop() из arduino. Нужно помнить, что все модули имеют равный поочередный доступ к центральному loop(), поэтому, необходимо следить
// за задержками в алгоритме и не создавать пауз. Кроме того, данная версия перегружает родительскую, поэтому doByInterval() отключается, если
// не повторить механизм расчета интервалов.
void loop() {
if (_avgSteps > 1) {
if (_avgCount > _avgSteps) {
value.valD = _avgSumm / _avgSteps;
_avgSumm = 0;
_avgCount = 0;
}
_avgSumm = _avgSumm + IoTgpio.analogRead(_pin);
_avgCount++;
}
currentMillis = millis();
difference = currentMillis - prevMillis;
if (difference >= _interval) {
prevMillis = millis();
this->doByInterval();
}
}
~AnalogAdc() {};
};
//после замены названия сенсора, на функцию можно не обращать внимания
//если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть
//создание и контроль соответствующих глобальных переменных
// после замены названия сенсора, на функцию можно не обращать внимания
// если сенсор предполагает использование общего объекта библиотеки для нескольких экземпляров сенсора, то в данной функции необходимо предусмотреть
// создание и контроль соответствующих глобальных переменных
void* getAPI_AnalogAdc(String subtype, String param) {
if (subtype == F("AnalogAdc")) {
return new AnalogAdc(param);
} else {
return nullptr;
}
if (subtype == F("AnalogAdc")) {
return new AnalogAdc(param);
} else {
return nullptr;
}
}

View File

@@ -1,18 +0,0 @@
[
{
"name": "Аналоговый сенсор",
"num": 1,
"type": "Reading",
"subtype": "AnalogAdc",
"id": "t",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Температура",
"map": "1,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 1,
"pin": 0,
"int": 15
}
]

View File

@@ -0,0 +1,42 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Аналоговый сенсор",
"type": "Reading",
"subtype": "AnalogAdc",
"id": "t",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Температура",
"map": "1,1024,1,100",
"plus": 0,
"multiply": 1,
"round": 1,
"pin": 0,
"int": 15,
"avgSteps": 1
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "AnalogAdc",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить текущее значение на аналоговом GPIO или усредненное для avgSteps измерений каждого вызова loop.",
"propInfo": {
"pin": "Аналоговый GPIO номер, к которому подключен датчик.",
"avgSteps": "Количество считываний для усреднения. При <=1, считывается одно значение за каждый период опроса.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [],
"esp8266_4mb": []
}
}

View File

@@ -1,7 +1,8 @@
[
{
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Cенсор температуры Bme280",
"num": 9,
"type": "Reading",
"subtype": "Bme280t",
"id": "tmp3",
@@ -14,7 +15,6 @@
},
{
"name": "Cенсор давления Bme280",
"num": 10,
"type": "Reading",
"subtype": "Bme280p",
"id": "Press3",
@@ -27,7 +27,6 @@
},
{
"name": "Cенсор влажности Bme280",
"num": 11,
"type": "Reading",
"subtype": "Bme280h",
"id": "Hum3",
@@ -37,5 +36,30 @@
"int": 15,
"addr": "0x77",
"round": 1
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "Serghei Crasnicov @Serghei63",
"moduleName": "Bme280",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить значения температуры, давления и влажности с Bme280.",
"propInfo": {
"addr": "Адрес датчика на шине, обычно 0x77.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"adafruit/Adafruit BME280 Library"
],
"esp8266_4mb": [
"adafruit/Adafruit BME280 Library"
]
}
]
}

View File

@@ -1,8 +0,0 @@
[env:esp8266_4mb]
lib_deps =
adafruit/Adafruit BME280 Library
[env:esp32_4mb]
lib_deps =
adafruit/Adafruit BME280 Library

View File

@@ -1,28 +0,0 @@
[
{
"name": "Cенсор температуры Bmp280",
"num": 7,
"type": "Reading",
"subtype": "Bmp280t",
"id": "tmp3",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "280 Температура",
"int": 15,
"addr": "0x77",
"round": 1
},
{
"name": "Cенсор давления Bmp280",
"num": 8,
"type": "Reading",
"subtype": "Bmp280p",
"id": "Press3",
"widget": "anydataMm",
"page": "Сенсоры",
"descr": "280 Давление",
"int": 15,
"addr": "0x77",
"round": 1
}
]

View File

@@ -0,0 +1,53 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Cенсор температуры Bmp280",
"type": "Reading",
"subtype": "Bmp280t",
"id": "tmp3",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "280 Температура",
"int": 15,
"addr": "0x77",
"round": 1
},
{
"name": "Cенсор давления Bmp280",
"type": "Reading",
"subtype": "Bmp280p",
"id": "Press3",
"widget": "anydataMm",
"page": "Сенсоры",
"descr": "280 Давление",
"int": 15,
"addr": "0x77",
"round": 1
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "Serghei Crasnicov @Serghei63",
"moduleName": "Bmp280",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить значения температуры и давления с Bmp280.",
"propInfo": {
"addr": "Адрес датчика на шине, обычно 0x77.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"adafruit/Adafruit BMP280 Library"
],
"esp8266_4mb": [
"adafruit/Adafruit BMP280 Library"
]
}
}

View File

@@ -1,8 +0,0 @@
[env:esp8266_4mb]
lib_deps =
adafruit/Adafruit BMP280 Library
[env:esp32_4mb]
lib_deps =
adafruit/Adafruit BMP280 Library

View File

@@ -1,28 +0,0 @@
[
{
"name": "Cенсор температуры dht11",
"num": 5,
"type": "Reading",
"subtype": "Dht1122t",
"id": "tmp3",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Температура",
"int": 15,
"pin": 0,
"senstype": "dht11"
},
{
"name": "Cенсор влажности dht11",
"num": 6,
"type": "Reading",
"subtype": "Dht1122h",
"id": "Hum3",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "Влажность",
"int": 15,
"pin": 0,
"senstype": "dht11"
}
]

View File

@@ -0,0 +1,53 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Cенсор температуры dht11",
"type": "Reading",
"subtype": "Dht1122t",
"id": "tmp3",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Температура",
"int": 15,
"pin": 0,
"senstype": "dht11"
},
{
"name": "Cенсор влажности dht11",
"type": "Reading",
"subtype": "Dht1122h",
"id": "Hum3",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "Влажность",
"int": 15,
"pin": 0,
"senstype": "dht11"
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "Serghei Crasnicov @Serghei63",
"moduleName": "Dht1122",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить значения температуры и влажности с dht11 или dht22.",
"propInfo": {
"senstype": "Тип сенсора dht11 или dht22.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"beegee-tokyo/DHT sensor library for ESPx"
],
"esp8266_4mb": [
"beegee-tokyo/DHT sensor library for ESPx"
]
}
}

View File

@@ -1,7 +0,0 @@
[env:esp8266_4mb]
lib_deps =
beegee-tokyo/DHT sensor library for ESPx
[env:esp32_4mb]
lib_deps =
beegee-tokyo/DHT sensor library for ESPx

View File

@@ -1,17 +0,0 @@
[
{
"name": "Cенсор температуры ds18b20",
"num": 2,
"type": "Reading",
"subtype": "Ds18b20",
"id": "dstmp",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "DS Температура",
"int": 15,
"pin": 2,
"index": 0,
"addr": "",
"round": 1
}
]

View File

@@ -0,0 +1,45 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Cенсор температуры ds18b20",
"type": "Reading",
"subtype": "Ds18b20",
"id": "dstmp",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "DS Температура",
"int": 15,
"pin": 2,
"index": 0,
"addr": "",
"round": 1
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "Ds18b20",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить значения температуры с Ds18b20.",
"propInfo": {
"pin": "GPIO номер, к которому подключена шина данных датчиков.",
"index": "Порядковый номер датчика на шине.",
"addr": "Адрес датчика на шине для точной идентификации. Можно скопировать из консоли.",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"milesburton/DallasTemperature@^3.9.1"
],
"esp8266_4mb": [
"milesburton/DallasTemperature@^3.9.1"
]
}
}

View File

@@ -1,8 +0,0 @@
[env:esp8266_4mb]
lib_deps =
milesburton/DallasTemperature@^3.9.1
[env:esp32_4mb]
lib_deps =
milesburton/DallasTemperature@^3.9.1

View File

@@ -0,0 +1,72 @@
/******************************************************************
Used Energy Monitoring Library
https://github.com/openenergymonitor/EmonLib
adapted for version 4 @Serghei63
******************************************************************/
#include "Global.h"
#include "classes/IoTItem.h"
#include <map>
extern IoTGpio IoTgpio;
#include "EmonLib.h" // Include Emon Library
EnergyMonitor emon1; // Create an instance
class Energy : public IoTItem {
private:
unsigned int _pinI; // ток
unsigned int _calibI; // ток
public:
Energy(String parameters): IoTItem(parameters) {
_pinI = jsonReadInt(parameters, "pin_I");
_calibI = jsonReadInt(parameters, "calib_I");
emon1.current(_pinI, _calibI); // Current: input pin, calibration.
}
void doByInterval() {
value.valD = emon1.calcIrms(1480); // Calculate Irms only
regEvent(value.valD, "current");
}
~Energy(){};
};
class Power : public IoTItem {
private:
unsigned int _pinU; // напряжение
unsigned int _calibU; // напряжение
public:
Power(String parameters): IoTItem(parameters) {
_pinU = jsonReadInt(parameters, "pin_U");
_calibU = jsonReadInt(parameters, "calib_U");
emon1.voltage(_pinU, _calibU, 1.7); // Voltage: input pin, calibration, phase_shift
}
void doByInterval() {
if (emon1.Irms > 0) emon1.calcVI(10, 1000); // Calculate all. No.of half wavelengths (crossings), time-out при условии, что ток не нулевой
value.valD = emon1.Vrms; //extract Vrms into Variable;
regEvent(value.valD, "voltage");
}
~Power(){};
};
void* getAPI_Emon(String subtype, String param) {
if (subtype == F("I")) {
return new Energy(param);
} else if (subtype == F("U")) {
return new Power(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,60 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Датчик тока",
"type": "Reading",
"subtype": "I",
"id": "current",
"widget": "anydataAmp",
"page": "Сенсоры",
"descr": "Датчик тока",
"int": 10,
"pin_I": 34,
"calib_I": 111.1,
"plus": 0,
"multiply": 1
},
{
"name": "Датчик напряжения",
"type": "Reading",
"subtype": "U",
"id": "voltage",
"widget": "anydataVlt",
"page": "Сенсоры",
"descr": "Датчик напряжения",
"int": 10,
"pin_U": 35,
"calib_U": 223.1,
"plus": 0,
"multiply": 1
}],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "",
"moduleName": "Emon",
"moduleVersion": "1.0",
"moduleDesc": ".",
"propInfo": {
"pin_U": "",
"calib_U": "",
"pin_I": "",
"calib_I": "",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": false,
"devices": {
"esp32_4mb": [
"openenergymonitor/EmonLib@1.1.0"
],
"esp8266_4mb": [
"openenergymonitor/EmonLib@1.1.0"
]
}
}

View File

@@ -1,26 +0,0 @@
[
{
"name": "Cенсор температуры GY21",
"num": 16,
"type": "Reading",
"subtype": "GY21t",
"id": "tmp4",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Температура",
"round": 1,
"int": 15
},
{
"name": "Cенсор влажности GY21",
"num": 17,
"type": "Reading",
"subtype": "GY21h",
"id": "Hum4",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "Влажность",
"round": 1,
"int": 15
}
]

View File

@@ -0,0 +1,50 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Cенсор температуры GY21",
"type": "Reading",
"subtype": "GY21t",
"id": "tmp4",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Температура",
"round": 1,
"int": 15
},
{
"name": "Cенсор влажности GY21",
"type": "Reading",
"subtype": "GY21h",
"id": "Hum4",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "Влажность",
"round": 1,
"int": 15
}],
"about": {
"authorName": "Alecs",
"authorContact": "https://t.me/Alecs",
"authorGit": "",
"specialThanks": "",
"moduleName": "GY21",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить значения температуры и влажности с GY21.",
"propInfo": {
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"https://github.com/JonasGMorsch/GY-21.git"
],
"esp8266_4mb": [
"https://github.com/JonasGMorsch/GY-21.git"
]
}
}

View File

@@ -1,8 +0,0 @@
[env:esp8266_4mb]
lib_deps =
https://github.com/JonasGMorsch/GY-21.git
[env:esp32_4mb]
lib_deps =
https://github.com/JonasGMorsch/GY-21.git

View File

@@ -1,28 +0,0 @@
[
{
"name": "Cенсор температуры HDC1080",
"num": 14,
"type": "Reading",
"subtype": "Hdc1080t",
"id": "Temp1080",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "1080 Температура",
"int": 15,
"addr": "0x40",
"round": 1
},
{
"name": "Cенсор влажности HDC1080",
"num": 15,
"type": "Reading",
"subtype": "Hdc1080h",
"id": "Hum1080",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "1080 Влажность",
"int": 15,
"addr": "0x40",
"round": 1
}
]

View File

@@ -0,0 +1,53 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Cенсор температуры HDC1080",
"type": "Reading",
"subtype": "Hdc1080t",
"id": "Temp1080",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "1080 Температура",
"int": 15,
"addr": "0x40",
"round": 1
},
{
"name": "Cенсор влажности HDC1080",
"type": "Reading",
"subtype": "Hdc1080h",
"id": "Hum1080",
"widget": "anydataHum",
"page": "Сенсоры",
"descr": "1080 Влажность",
"int": 15,
"addr": "0x40",
"round": 1
}],
"about": {
"authorName": "Serghei Crasnicov",
"authorContact": "https://t.me/Serghei63",
"authorGit": "https://github.com/Serghei63",
"specialThanks": "",
"moduleName": "Hdc1080",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить значения температуры и влажности с Hdc1080.",
"propInfo": {
"addr": "Адрес датчика на шине данных, обычно 0x40",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": true,
"devices": {
"esp32_4mb": [
"ClosedCube HDC1080"
],
"esp8266_4mb": [
"ClosedCube HDC1080"
]
}
}

View File

@@ -1,7 +0,0 @@
[env:esp8266_4mb]
lib_deps =
ClosedCube HDC1080
[env:esp32_4mb]
lib_deps =
ClosedCube HDC1080

View File

@@ -0,0 +1,78 @@
#include "Global.h"
#include "classes/IoTItem.h"
#include <WiegandNG.h>
#define PIN_D0 D5
#define PIN_D1 D6
WiegandNG wg;
void PrintBinary(WiegandNG &tempwg) {
volatile unsigned char *buffer=tempwg.getRawData();
unsigned int bufferSize = tempwg.getBufferSize();
unsigned int countedBits = tempwg.getBitCounted();
unsigned int countedBytes = (countedBits/8);
if ((countedBits % 8)>0) countedBytes++;
// unsigned int bitsUsed = countedBytes * 8;
for (unsigned int i=bufferSize-countedBytes; i< bufferSize;i++) {
unsigned char bufByte=buffer[i];
for(int x=0; x<8;x++) {
if ( (((bufferSize-i) *8)-x) <= countedBits) {
if((bufByte & 0x80)) {
Serial.print("1");
}
else {
Serial.print("0");
}
}
bufByte<<=1;
}
}
Serial.println();
}
class IoTWiegand : public IoTItem {
public:
IoTWiegand(String parameters) : IoTItem(parameters) {
// int pinD0;
// int pinD1;
// jsonRead(parameters, "pinD0", pinD0);
// jsonRead(parameters, "pinD1", pinD1);
unsigned int pinD0 = D5;
unsigned int pinD1 = D6;
unsigned int wiegandbits = 48;
unsigned int packetGap = 15; // 25 ms between packet
// if(!wg.begin(pinD0, pinD1, wiegandbits, packetGap)) {
// Serial.println("Out of memory!");
// }
}
void loop() {
if(wg.available()) {
wg.pause(); // pause Wiegand pin interrupts
Serial.print("Bits=");
Serial.println(wg.getBitCounted()); // display the number of bits counted
Serial.print("RAW Binary=");
PrintBinary(wg); // display raw data in binary form, raw data inclusive of PARITY
wg.clear(); // compulsory to call clear() to enable interrupts for subsequent data
}
}
~IoTWiegand(){};
};
void* getAPI_IoTWiegand(String subtype, String param) {
if (subtype == F("IoTWiegand")) {
return new IoTWiegand(param);
} else {
return nullptr;
}
}

View File

@@ -0,0 +1,42 @@
{
"menuSection": "Сенсоры",
"configItem": [{
"name": "Считыватель Wiegand",
"type": "Reading",
"subtype": "IoTWiegand",
"id": "wg",
"widget": "anydataTmp",
"page": "Сенсоры",
"descr": "Считыватель",
"int": 0,
"pinD0": 13,
"pinD1": 12
}],
"about": {
"authorName": "Ilya Belyakov",
"authorContact": "https://t.me/Biveraxe",
"authorGit": "https://github.com/biveraxe",
"specialThanks": "",
"moduleName": "IoTWiegand",
"moduleVersion": "1.0",
"moduleDesc": "Позволяет получить коды доступа по протоколу Wiegand с различных считывателей. На данный момент модуль в РАЗРАБОТКЕ",
"propInfo": {
"pinD0": "GPIO шины данных",
"pinD1": "GPIO шины данных",
"int": "Количество секунд между опросами датчика."
}
},
"defActive": false,
"devices": {
"esp32_4mb": [
"https://github.com/jpliew/Wiegand-NG-Multi-Bit-Wiegand-Library-for-Arduino"
],
"esp8266_4mb": [
"https://github.com/jpliew/Wiegand-NG-Multi-Bit-Wiegand-Library-for-Arduino"
]
}
}

Some files were not shown because too many files have changed in this diff Show More