DIN - wejscie cyfrowe#
DIN (Digital Input) to obiekt reprezentujacy wejscie cyfrowe - przycisk, czujnik kontaktowy, czujnik ruchu. Wystepuje w trzech wariantach:
- Lokalny DIN - wirtualny modul vCLU, konfigurowany w wizardzie (emuluje fizyczny modul Grenton)
- DIN z OM - obiekt z Object Manager, po sparowaniu z fizycznym CLU Grenton
- GPIO_DIN - obiekt tworzony w
user.lua, podlaczony do pinu GPIO Raspberry Pi
Wszystkie warianty maja ten sam interfejs API i te same stale. Obsluguja debounce, rozpoznawanie krotkich i dlugich nacisnieci oraz zdarzenia hold (przytrzymanie).
Lokalny DIN - moduly wirtualne#
Gdy vCLU dziala jako emulator CLU (tryb CLU w wizardzie), mozna dodac wirtualne moduly wejsc. Sa to emulacje fizycznych modulow Grenton - nie czytaja prawdziwego sprzetu, ale pojawiaja sie w OM i moga byc uzywane do testow i integracji.
Konfiguracja w wizardzie#
W kroku 2 wizarda (“Moduly”) mozna dodac moduly z wejsciami cyfrowymi:
| Typ modulu | Wejscia DIN | Wyjscia DOUT | Analog | HW Type |
|---|---|---|---|---|
| DIN8 | 8 | - | 1 | 0x14 |
| DOUT8T | 8 | 8 | 1 | 0x1e |
Kazdy modul DIN dostaje unikalna nazwe (np. DIN8_1) i numer seryjny. Obiekty I/O sa generowane automatycznie z losowymi identyfikatorami (np. DIN9518).
Jak to dziala#
Wizard → .vclu.json → config.txt + CONFIG.JSON → OM → om.lua → runtime- Uzytkownik dodaje modul w wizardzie
- vCLU zapisuje konfiguracje w
.vclu.json - Generuje
config.txtiCONFIG.JSONz wpisami TFBus - Object Manager (OM) odczytuje konfiguracje i generuje
om.lua - Przy starcie Lua laduje
om.lua- obiekty DIN sa dostepne w runtime
Dostep do obiektow#
-- Przez ID z OM
local przycisk = _:get("CLU.DIN9518")
przycisk:add_event(DIN.EVENT_ON_CLICK, function()
log.info("Klik!")
end)
-- Albo przez nazwe nadana w wizardzie
local przycisk = _:get("CLU.DIN8_1_DIN1").vclu.json#
{
"device": {
"modules": [
{
"typeId": "din8",
"serial": "181000015",
"name": "DIN8_1",
"hardwareType": 20
}
],
"ioObjects": [
{
"id": "DIN9518",
"typeId": "din",
"index": 0,
"name": "DIN8_1_DIN1",
"luaType": 3
}
]
}
}Lokalne moduly DIN nie czytaja fizycznych wejsc - stan mozna zmieniac programowo przez EventBus lub z poziomu panelu webowego. Do podlaczenia prawdziwych przyciskow i czujnikow na Raspberry Pi uzyj `GPIO_DIN`.
GPIO_DIN - tworzenie#
local btn = GPIO_DIN:new(name, pin, pull)| Parametr | Typ | Opis |
|---|---|---|
name | string | Nazwa globalna (np. "BTN1") |
pin | number | Numer pinu BCM |
pull | string | "up", "down" lub "off" (domyslnie "up") |
-- Przycisk z pull-up (typowe - przycisk zwiera pin do GND)
local btn = GPIO_DIN:new("BTN1", 27)
-- Czujnik z pull-down
local sensor = GPIO_DIN:new("SENSOR1", 22, "down")Pull-up vs pull-down#
| Typ | Opis | Kiedy uzywac |
|---|---|---|
"up" | Pin domyslnie HIGH, przycisk ciagnie do LOW | Przyciski (najczesciej) |
"down" | Pin domyslnie LOW, czujnik ciagnie do HIGH | Czujniki z wyjsciem HIGH |
"off" | Bez pull - wymaga zewnetrznego rezystora | Specjalne zastosowania |
DIN z OM - obiekty z Object Manager#
Obiekty DIN z OM sa tworzone automatycznie po sparowaniu z fizycznym CLU Grenton:
local przycisk = _:get("CLU.DIN1")
przycisk:add_event(DIN.EVENT_ON_CLICK, function()
log.info("Klik!")
end)Porownanie wariantow#
| Lokalny DIN | DIN z OM | GPIO_DIN | |
|---|---|---|---|
| Zrodlo | Wizard (vCLU) | Object Manager (OM) | user.lua |
| Sprzet | Brak (w pamieci) | Fizyczny modul Grenton | Pin GPIO Raspberry Pi |
| Konfiguracja | .vclu.json → om.lua | OM generuje om.lua | GPIO_DIN:new() w kodzie |
| Zastosowanie | Testowanie, emulacja | Produkcja z prawdziwym CLU | Produkcja na Raspberry Pi |
| API | get/set/add_event | get/set/add_event | get/set/add_event |
| GenericButton | tak | tak | tak |
expose() | tak | tak | tak |
exposeRegistry() | tak (automatycznie) | tak (automatycznie) | tak (po registerObject) |
Stale#
Cechy (Features)#
| Stala | Wartosc | Opis | R/W |
|---|---|---|---|
DIN.FEATURE_VALUE | 0 | Stan wejscia: 1=ON, 0=OFF | R |
DIN.FEATURE_INTERTION | 1 | Czas debounce (ms) | R/W |
DIN.FEATURE_HOLD_DELAY | 2 | Opoznienie hold (ms) | R/W |
DIN.FEATURE_HOLD_INTERVAL | 3 | Interwat cyklicznego hold (ms) | R/W |
Zdarzenia#
| Stala | Wartosc | Opis |
|---|---|---|
DIN.EVENT_ON_CHANGE | 0 | Zmiana wartosci (ON→OFF lub OFF→ON) |
DIN.EVENT_ON_SWITCH_ON | 1 | Przejscie w stan ON |
DIN.EVENT_ON_SWITCH_OFF | 2 | Przejscie w stan OFF |
DIN.EVENT_ON_SHORT_PRESS | 3 | Krotkie nacisniecie (po puszczeniu) |
DIN.EVENT_ON_LONG_PRESS | 4 | Dlugie nacisniecie (po puszczeniu) |
DIN.EVENT_ON_HOLD | 5 | Cykliczne zdarzenie przy przytrzymaniu |
DIN.EVENT_ON_CLICK | 6 | Klikniecie (po debounce) |
Diagram zdarzen#
Przebieg zdarzen w czasie po nacisnieciu przycisku:
Nacisniecie Puszczenie
│ │
├─── debounce (intertion) ──▶ EVENT_ON_CLICK │
│ EVENT_ON_SWITCH_ON │
│ │
├─── holdDelay ─────────────▶ (holdFlag = true) │
│ │
├─── holdInterval ──────────▶ EVENT_ON_HOLD │
├─── holdInterval ──────────▶ EVENT_ON_HOLD │
├─── holdInterval ──────────▶ EVENT_ON_HOLD │
│ ... │
│ │
├─── shortPressInterval ────▶ (shortPressFlag) │
│ │
├─── longPressInterval ─────▶ (longPressFlag) │
│ ▼
│ EVENT_ON_SWITCH_OFF
│ EVENT_ON_SHORT_PRESS (lub LONG_PRESS)- EVENT_ON_CLICK - emitowany zaraz po debounce (po nacisnieciu)
- EVENT_ON_SHORT_PRESS - emitowany po puszczeniu, jesli trzymano <
longPressInterval - EVENT_ON_LONG_PRESS - emitowany po puszczeniu, jesli trzymano >
longPressInterval - EVENT_ON_HOLD - emitowany cyklicznie co
holdIntervalms po przekroczeniuholdDelay
API#
get(feature)#
Odczytuje wartosc cechy.
local stan = btn:get(DIN.FEATURE_VALUE) -- 0 lub 1
local debounce = btn:get(DIN.FEATURE_INTERTION) -- msset(feature, value)#
Ustawia wartosc cechy (tylko parametry konfiguracyjne, nie wartosc wejscia).
-- Ustaw debounce na 50ms
btn:set(DIN.FEATURE_INTERTION, 50)
-- Ustaw opoznienie hold na 1 sekundy
btn:set(DIN.FEATURE_HOLD_DELAY, 1000)
-- Ustaw interwal hold na 200ms
btn:set(DIN.FEATURE_HOLD_INTERVAL, 200)add_event(event, callback)#
Rejestruje callback na zdarzenie.
btn:add_event(DIN.EVENT_ON_CLICK, function()
log.info("Klik!")
end)
btn:add_event(DIN.EVENT_ON_SHORT_PRESS, function()
log.info("Krotkie nacisniecie")
end)
btn:add_event(DIN.EVENT_ON_LONG_PRESS, function()
log.info("Dlugie nacisniecie")
end)
btn:add_event(DIN.EVENT_ON_HOLD, function()
log.info("Trzymam...")
end)onChange(callback)#
Rejestruje callback na zmiane wartosci. Zwraca funkcje unsubscribe. Uzywany przez system expose().
local unsub = btn:onChange(function(newValue, oldValue)
log.info("Zmiana: " .. oldValue .. " → " .. newValue)
end)
unsub() -- wyrejestrujDomyslne parametry#
| Parametr | Wartosc | Opis |
|---|---|---|
intertion (debounce) | 0 ms | Brak debounce (natychmiastowa reakcja) |
holdDelay | 500 ms | Po 500ms zaczyna emitowac EVENT_ON_HOLD |
holdInterval | 50 ms | Hold emitowany co 50ms |
shortPressInterval | 2000 ms | Nacisniecie < 2s = krotkie |
longPressInterval | 5000 ms | Nacisniecie > 5s = dlugie |
Przyklady#
Przycisk przelaczajacy lampe#
local btn = GPIO_DIN:new("BTN1", 27)
local relay = GPIO_DOUT:new("RELAY1", 17, {activeLow = true})
btn:add_event(DIN.EVENT_ON_CLICK, function()
relay:execute(DOUT.METHOD_SWITCH)
end)Krotkie/dlugie nacisniecie - rozne akcje#
local btn = GPIO_DIN:new("BTN1", 27)
btn:add_event(DIN.EVENT_ON_SHORT_PRESS, function()
log.info("Krotkie - przelacz lampe")
RELAY1:execute(DOUT.METHOD_SWITCH)
end)
btn:add_event(DIN.EVENT_ON_LONG_PRESS, function()
log.info("Dlugie - wylacz wszystko")
RELAY1:execute(DOUT.METHOD_SWITCH_OFF)
RELAY2:execute(DOUT.METHOD_SWITCH_OFF)
RELAY3:execute(DOUT.METHOD_SWITCH_OFF)
end)Czujnik ruchu z eksponowaniem#
local motion = GPIO_DIN:new("MOTION1", 22, "down")
expose(motion, "motion", {name = "Ruch korytarz"})
motion:add_event(DIN.EVENT_ON_SWITCH_ON, function()
log.info("Wykryto ruch!")
SWIATLO:execute(DOUT.METHOD_SWITCH_ON, 120000) -- 2 minuty
end)Czujnik kontaktowy (drzwi/okno)#
local drzwi = GPIO_DIN:new("DRZWI1", 23)
expose(drzwi, "sensor", {name = "Drzwi wejsciowe"})
drzwi:add_event(DIN.EVENT_ON_SWITCH_ON, function()
log.info("Drzwi otwarte")
end)
drzwi:add_event(DIN.EVENT_ON_SWITCH_OFF, function()
log.info("Drzwi zamkniete")
end)Dimmer - przytrzymaj zeby rozjasniac#
local btn = GPIO_DIN:new("BTN_DIM", 25)
local brightness = 50
btn:set(DIN.FEATURE_HOLD_DELAY, 300)
btn:set(DIN.FEATURE_HOLD_INTERVAL, 100)
btn:add_event(DIN.EVENT_ON_CLICK, function()
_:get("CLU.DIMM1"):execute(DOUT.METHOD_SWITCH)
end)
btn:add_event(DIN.EVENT_ON_HOLD, function()
brightness = clamp(brightness + 2, 0, 100)
_:get("CLU.DIMM1"):set(0, brightness)
end)Przycisk z OM#
local przycisk = _:get("CLU.DIN1")
przycisk:add_event(DIN.EVENT_ON_CLICK, function()
_:get("CLU.DOUT1"):execute(DOUT.METHOD_SWITCH)
end)
przycisk:add_event(DIN.EVENT_ON_LONG_PRESS, function()
runScene("wylacz_wszystko")
end)Zwieksz debounce dla szumiajacego czujnika#
local czujnik = GPIO_DIN:new("CZUJNIK1", 24, "up")
czujnik:set(DIN.FEATURE_INTERTION, 100) -- 100ms debouncePrzyklady mieszane - GPIO_DIN + lokalne moduly#
Przycisk GPIO steruje lokalnymi DOUT z wizarda#
-- Fizyczny przycisk na Raspberry Pi
local btn = GPIO_DIN:new("BTN1", 27)
-- Lokalne DOUT z wizarda
local lampa_salon = _:get("CLU.DOU5048")
local lampa_kuchnia = _:get("CLU.DOU4458")
-- Klik - przelacz salon
btn:add_event(DIN.EVENT_ON_CLICK, function()
lampa_salon:execute(DOUT.METHOD_SWITCH)
end)
-- Dlugie nacisniecie - wylacz wszystko
btn:add_event(DIN.EVENT_ON_LONG_PRESS, function()
lampa_salon:execute(DOUT.METHOD_SWITCH_OFF)
lampa_kuchnia:execute(DOUT.METHOD_SWITCH_OFF)
end)Czujnik ruchu GPIO + lokalny DOUT podpiety pod Tasmote#
Fizyczny czujnik ruchu na GPIO automatycznie wlacza gniazdko Tasmota (przez lokalny DOUT):
local mqtt = MQTT:new("tasmota")
mqtt:setHost("localhost"):setPort(1883):connect()
-- Czujnik ruchu na GPIO
local motion = GPIO_DIN:new("MOTION1", 22, "down")
expose(motion, "motion", {name = "Ruch korytarz"})
-- Lokalny DOUT zsynchronizowany z Tasmota
local swiatlo = _:get("CLU.DOU5048")
expose(swiatlo, "switch", {name = "Swiatlo korytarz"})
swiatlo:add_event(DOUT.EVENT_ON_SWITCH_ON, function()
mqtt:publish("cmnd/swiatlo_korytarz/POWER", "ON")
end)
swiatlo:add_event(DOUT.EVENT_ON_SWITCH_OFF, function()
mqtt:publish("cmnd/swiatlo_korytarz/POWER", "OFF")
end)
-- Ruch wykryty - wlacz swiatlo na 2 minuty
motion:add_event(DIN.EVENT_ON_SWITCH_ON, function()
swiatlo:execute(DOUT.METHOD_SWITCH_ON, 120000)
end)