HELLOS-UNI může fungovat jako server Modbus RTU na stejném poloduplexním rozhraní RS-485, které používá HBUS. Implementace je záměrně oddělena od transportní vrstvy HBUS. Změna protokolu se projeví po restartu.
Tento dokument platí pro firmware HELLOS-UNI 4.0 a verzi mapy registrů 1.
Sériová komunikace a chování serveru
- 8 datových bitů, bez parity, 1 stop bit (8N1).
- Modbus RTU používá stejnou přenosovou rychlost jako nastavenou pro HBUS.
- Rozsah adres serveru: 1 až 247.
- Podporované funkce:
03,04,06a16. - Slova registrů i víceslovné hodnoty používají pořadí big-endian. Bajty Modbus CRC se odesílají od nejméně významného bajtu.
- 32bitová hodnota zabírá dva po sobě jdoucí registry, nejvýznamnější slovo je první.
- Při rychlosti 19200 baudů a nižší odpovídá mezera mezi rámci době přenosu 3,5 znaku. Při rychlosti nad 19200 baudů je pevně nastavena na 1,75 ms.
- Modul nikdy neposílá nevyžádané rámce Modbus. Data událostí HBUS jsou uložena v registrech událostí, odkud je čte klient.
- Všesměrová adresa nula přijímá běžné zápisy výstupů a PWM bez odpovědi. Nelze ji použít pro servisní příkaz návratu do HBUS.
Níže uvedené adresy jsou adresy Modbus PDU číslované od nuly. Software používající zápis 3xxxx nebo 4xxxx s číslováním od jedné může zobrazovat hodnotu o jednu vyšší než adresa v tomto dokumentu.
Formát a význam hodnot
0xffffznamená nedostupnou hodnotu nebo nevyužitou pozici.0x8000znamená nedostupné měření se znaménkem.- Hodnoty se znaménkem používají 16bitový dvojkový doplněk.
- Hodnoty teploty a vlhkosti jsou vynásobené 10.
- Hodnoty ADC jsou v desetinách procenta, v rozsahu 0 až 1000.
- Střída PWM je vyjádřena celými procenty od 0 do 100.
Vstupní registry - funkce 04
Systémové registry
| Adresa | Hodnota |
|---|---|
| 0 | Verze mapy registrů, aktuálně 1 |
| 1 | Stavové příznaky: bit 0 ladění, bit 1 aktualizace souborového systému, bit 2 přetečení událostí, bit 3 překročení kapacity pozic pro čidla |
| 2-3 | Doba běhu v sekundách, 32bitová hodnota bez znaménka |
| 4-5 | ID zařízení odvozené z hardwaru, 32bitová hodnota bez znaménka |
| 6-7 | Přenosová rychlost UART, 32bitová hodnota bez znaménka |
| 8 | Adresa Modbus |
| 9 | Nastavený režim: 0 HBUS, 1 Modbus RTU |
| 10 | Aktivní režim: 0 HBUS, 1 Modbus RTU |
| 11 | Obsazené pozice DS18x20, nejvýše 32 |
| 12 | Obsazené pozice SHT3x, nejvýše 6 |
| 13 | Obsazené pozice SCD4x, nejvýše 6 |
| 14-16 | Kód režimu portů A, B a C |
| 17-18 | CRC32 úplného řetězce verze softwaru |
| 19-20 | CRC32 řetězce verze hardwaru |
| 21 | Příznaky překročení kapacity pozic pro čidla: DS bit 0, SHT bit 1, SCD bit 2 |
| 22-31 | Vyhrazeno, při čtení vrací 0xffff |
Kódy režimů portů jsou v rámci verze mapy 1 stabilní:
| Kód | Režim | Kód | Režim |
|---|---|---|---|
| 0 | sensor-autodetect | 8 | output_safe |
| 1 | button_simple | 9 | pwm_50hz |
| 2 | button_double | 10 | pwm_1khz |
| 3 | input | 11 | pwm_25khz |
| 4 | input_safe | 12 | adc_raw_passive |
| 5 | impulse_counter | 13 | adc_raw_active |
| 6 | impulse_counter_safe | 14 | adc_pullup_passive |
| 7 | output | 15 | adc_pullup_active |
| 16 | encoder | 17 | encoder_reverse |
Registry stavů portů
Každý blok 12 registrů používá pořadí kanálů A0 až A3, B0 až B3 a poté C0 až C3.
| Adresa | Hodnota |
|---|---|
| 100-111 | Stav logického vstupu, 0 nebo 1 |
| 120-143 | Impulzní čítače, 12 hodnot bez znaménka o šířce 32 bitů |
| 150-161 | Hodnota ADC v desetinách procenta |
| 170-181 | Stav logického výstupu, 0 nebo 1 |
| 190-201 | Střída PWM v procentech |
Kompaktní čtení digitálních vstupů
Kompaktní blok je určen pro instalace s mnoha moduly. Klient jedním požadavkem přečte registry 32 až 46 a porovná čítače stisků s předchozím vzorkem. Díky tomu neztratí krátký stisk mezi dvěma cykly čtení a vystačí s jedním požadavkem na modul.
Bity a pozice čítačů používají pořadí kanálů A0 až A3, B0 až B3 a poté C0 až C3.
| Adresa | Hodnota |
|---|---|
| 32 | Bitová mapa aktuálních stavů logických vstupů, bity 0 až 11 |
| 33 | Bitová mapa platnosti stavů vstupů pro porty input a input_safe |
| 34 | Bitová mapa platnosti čítačů stisků pro tlačítkové a vstupní porty |
| 35-46 | 16bitový čítač stisků bez znaménka pro každý kanál |
Čítače přetékají z 65535 na nulu a po restartu modulu se vynulují. Přechod logického vstupu do aktivního stavu i stisk v režimu button_simple nebo button_double zvýší příslušný čítač. Uvolnění jej nezvyšuje. První hodnoty načtené po připojení určují výchozí stav klienta a nesmějí být vyhodnoceny jako nové stisky.
Diagnostika komunikace
Diagnostické čítače jsou 32bitové hodnoty bez znaménka, uložené s nejvýznamnějším slovem na prvním místě. Při překročení rozsahu přetečou a po restartu modulu se vynulují.
| Adresa | Hodnota |
|---|---|
| 50-51 | Přijaté platné požadavky pro tento modul |
| 52-53 | Přijaté neplatné rámce RTU nebo rámce překračující kapacitu bufferu |
| 54-55 | Platné rámce RTU adresované jinému modulu |
| 56-57 | Odpovědi úspěšně předané UART |
| 58-59 | Selhání odesílání odpovědí |
Registry událostí
Registry událostí uchovávají poslední událost pro každý fyzický kanál. Klient rozpozná novou událost podle změny sekvenčního registru. Sekvenční čísla přetékají z 65535 na nulu.
| Adresa | Hodnota |
|---|---|
| 220-231 | Sekvenční číslo události pro každý kanál |
| 240-251 | Typ poslední události pro každý kanál |
| 260-271 | Hodnota poslední události pro každý kanál, 16bitová se znaménkem |
| 280-303 | Čas poslední události v milisekundách, 12 hodnot bez znaménka o šířce 32 bitů |
| 320-343 | Kumulovaná poloha enkodéru, 12 hodnot se znaménkem o šířce 32 bitů |
Kódy typů událostí: 1 stisk tlačítka, 2 uvolnění tlačítka, 3 logický vstup, 4 změna polohy enkodéru a 5 změna ADC. Události tlačítek ukládají hodnotu 1. Hodnoty událostí ADC jsou v desetinách procenta.
Pozice čidel
Pozice DS18x20 jsou seřazeny podle 32bitového identifikátoru čidla v HBUS. Pozice SHT3x a SCD4x jsou seřazeny podle indexu HBUS. Pozice tedy zůstává stejná, dokud se nezmění sada nalezených zařízení a jejich identifikátorů.
| Adresa | Uspořádání pozic |
|---|---|
| 400-527 | 32 pozic DS18x20, každá má čtyři registry: vyšší slovo ID, nižší slovo ID, teplota se znaménkem x10, příznaky |
| 600-623 | 6 pozic SHT3x, každá má čtyři registry: index HBUS, teplota se znaménkem x10, vlhkost x10, příznaky |
| 640-669 | 6 pozic SCD4x, každá má pět registrů: index HBUS, CO2 v ppm, teplota se znaménkem x10, vlhkost x10, příznaky |
Příznaky nyní obsahují hodnotu 1 pro obsazenou pozici. Měření zahrnují nastavenou tabulku kompenzací, stejně jako odpověď HBUS na čtení všech hodnot.
Nedefinované adresy v rozsahu 0 až 669 vracejí 0xffff. Čtení nad adresou 669 vrací výjimku Modbus 02.
Holding registry - funkce 03, 06 a 16
| Adresa | Přístup | Hodnota |
|---|---|---|
| 1000-1011 | čtení/zápis | Logické výstupy A0-C3, 0 nebo 1 |
| 1020-1031 | čtení/zápis | Střída PWM A0-C3, celé číslo od 0 do 100 |
| 1999 | čtení/zápis | Servisní příkaz návratu do HBUS |
Registry kanálů, které nejsou nastaveny do odpovídajícího výstupního režimu, vracejí 0xffff a odmítají zápis. Funkce 16 ověří celý požadavek před jeho provedením. Jeden požadavek nesmí přecházet z bloku logických výstupů do bloku PWM.
Zápis hexadecimální hodnoty 0x4842 do registru 1999 funkcí 06 uloží HBUS jako nastavený režim, vrátí běžnou odpověď na zápis a restartuje modul. Tento příkaz je na všesměrové adrese nula záměrně odmítán. Při čtení registr jinak vrací nulu.
Konfigurace a obnova
Před přepnutím nastavte režim sběrnice a adresu Modbus prostřednictvím HBUS:
{"device":{"set_bus_mode":{"mode":"modbus","modbus_address":17}}}
Uložený režim se použije při příštím restartu. Zapnutý ladicí DIP přepínač při startu vynutí HBUS pouze pro tento běh a zachová uloženou přenosovou rychlost. Nastavení tak lze opravit bez vymazání modulu. Obnovení továrního nastavení odstraní konfiguraci sběrnice a soubor přenosové rychlosti a obnoví HBUS s rychlostí 19200 baudů.
Praktické příklady pro Node-RED
Následující příklady používají modul s adresou Modbus 1. Změňte unitid na nastavenou adresu cílového modulu.
Požadované nastavení sériové komunikace
V klientu node-red-contrib-modbus použijte:
- sériové připojení
- stejnou přenosovou rychlost jako v modulu
- 8 datových bitů, bez parity a 1 stop bit
- typ sériového spojení
RTU-BUFFERD
Zápis RTU-BUFFERD používá balíček Node-RED. Nejde o stejnou volbu jako bufferování fronty příkazů.
Nebufferovaný sériový ovladač RTU při testování spolehlivě zvládal pouze čtení nejvýše 13 registrů. Odpověď funkce 04 pro 13 registrů má 31 bajtů, zatímco odpověď pro 14 registrů má 33 bajtů. Sériová vrstva operačního systému může delší odpověď rozdělit do více částí a nebufferovaný ovladač může první část považovat za úplný rámec. RTU-BUFFERD shromažďuje části, dokud neobdrží očekávanou délku odpovědi Modbus. Použijte jej pro všechny příklady v této části.
Následující pomocná funkce přijímá oba běžné formáty výstupu uzlu Modbus Flex Getter:
function registerData(msg) {
if (Array.isArray(msg.payload)) {
return msg.payload;
}
if (msg.payload && Array.isArray(msg.payload.data)) {
return msg.payload.data;
}
throw new Error("Modbus response does not contain a register array");
}
Čtení úplné konfigurace modulu
Použijte uzel Function připojený k uzlu Modbus Flex Getter:
msg.payload = {
value: 0,
fc: 4,
unitid: 1,
address: 0,
quantity: 22
};
return msg;
Odpověď dekódujte dalším uzlem Function:
function registerData(msg) {
if (Array.isArray(msg.payload)) {
return msg.payload;
}
if (msg.payload && Array.isArray(msg.payload.data)) {
return msg.payload.data;
}
throw new Error("Modbus response does not contain a register array");
}
function u32(high, low) {
return ((high << 16) | low) >>> 0;
}
function hex32(value) {
return value.toString(16).padStart(8, "0");
}
const portModes = {
0: "sensor-autodetect",
1: "button_simple",
2: "button_double",
3: "input",
4: "input_safe",
5: "impulse_counter",
6: "impulse_counter_safe",
7: "output",
8: "output_safe",
9: "pwm_50hz",
10: "pwm_1khz",
11: "pwm_25khz",
12: "adc_raw_passive",
13: "adc_raw_active",
14: "adc_pullup_passive",
15: "adc_pullup_active",
16: "encoder",
17: "encoder_reverse"
};
const r = registerData(msg);
const flags = r[1];
const sensorOverflow = r[21];
msg.payload = {
firmware_api: "4.0",
register_map_version: r[0],
flags: {
raw: flags,
debug: Boolean(flags & 1),
filesystem_update: Boolean(flags & 2),
event_overflow: Boolean(flags & 4),
sensor_slot_overflow: Boolean(flags & 8)
},
uptime: u32(r[2], r[3]),
device_id: hex32(u32(r[4], r[5])),
baudrate: u32(r[6], r[7]),
modbus_address: r[8],
configured_mode: r[9] === 1 ? "modbus" : "hbus",
active_mode: r[10] === 1 ? "modbus" : "hbus",
sensors: {
ds18x20: r[11],
sht3x: r[12],
scd4x: r[13]
},
ports: {
A: portModes[r[14]] || `unknown-${r[14]}`,
B: portModes[r[15]] || `unknown-${r[15]}`,
C: portModes[r[16]] || `unknown-${r[16]}`
},
software_crc32: hex32(u32(r[17], r[18])),
hardware_crc32: hex32(u32(r[19], r[20])),
sensor_overflow: {
raw: sensorOverflow,
ds18x20: Boolean(sensorOverflow & 1),
sht3x: Boolean(sensorOverflow & 2),
scd4x: Boolean(sensorOverflow & 4)
}
};
return msg;
Tento blok obsahuje úplnou konfiguraci dostupnou přes Modbus. Alias, úprava tabulky kompenzací a další konfigurační operace specifické pro HBUS nejsou ve firmwaru 4.0 dostupné jako registry Modbus.
Zjištění připojených čidel
Výše uvedené čtení úplné konfigurace již vrací počet obsazených pozic čidel v registrech 11 až 13. Chcete-li přečíst pouze tyto počty:
msg.payload = {
value: 0,
fc: 4,
unitid: 1,
address: 11,
quantity: 3
};
return msg;
Vrácené pole obsahuje počty čidel DS18x20, SHT3x a SCD4x v tomto pořadí:
[DS18x20 count, SHT3x count, SCD4x count]
Pokud je počet čidel nula, příslušný blok nečtěte. Pro nenulový počet přečtěte přesně tolik registrů, kolik odpovídá obsazeným pozicím:
| Čidlo | Počáteční adresa | Registrů na čidlo | Počet čtených registrů |
|---|---|---|---|
| DS18x20 | 400 | 4 | count * 4 |
| SHT3x | 600 | 4 | count * 4 |
| SCD4x | 640 | 5 | count * 5 |
Čtení čidel DS18x20
Tento požadavek přečte jednu pozici DS18x20:
msg.payload = {
value: 0,
fc: 4,
unitid: 1,
address: 400,
quantity: 4
};
return msg;
Dekódování jedné nebo více pozic:
function registerData(msg) {
return Array.isArray(msg.payload) ? msg.payload : msg.payload.data;
}
function u32(high, low) {
return ((high << 16) | low) >>> 0;
}
function signed16(value) {
return value & 0x8000 ? value - 0x10000 : value;
}
const r = registerData(msg);
const sensors = [];
for (let offset = 0; offset + 3 < r.length; offset += 4) {
if (r[offset] === 0xffff && r[offset + 1] === 0xffff) {
continue;
}
sensors.push({
id: u32(r[offset], r[offset + 1]).toString(16).padStart(8, "0"),
temperature: signed16(r[offset + 2]) / 10,
valid: Boolean(r[offset + 3] & 1)
});
}
msg.payload = sensors;
return msg;
Čtení čidel SHT3x
Pro jednu pozici SHT3x čtěte od adresy 600 s počtem registrů 4. Každá pozice obsahuje index HBUS, teplotu vynásobenou 10, vlhkost vynásobenou 10 a příznaky:
msg.payload = {
value: 0,
fc: 4,
unitid: 1,
address: 600,
quantity: 4
};
return msg;
function registerData(msg) {
return Array.isArray(msg.payload) ? msg.payload : msg.payload.data;
}
function signed16(value) {
return value & 0x8000 ? value - 0x10000 : value;
}
const r = registerData(msg);
const sensors = [];
for (let offset = 0; offset + 3 < r.length; offset += 4) {
if (r[offset] === 0xffff) {
continue;
}
sensors.push({
index: r[offset],
temperature: signed16(r[offset + 1]) / 10,
humidity: r[offset + 2] / 10,
valid: Boolean(r[offset + 3] & 1)
});
}
msg.payload = sensors;
return msg;
Čtení čidel SCD4x
Pro jednu pozici SCD4x:
msg.payload = {
value: 0,
fc: 4,
unitid: 1,
address: 640,
quantity: 5
};
return msg;
Dekódování jedné nebo více pozic:
function registerData(msg) {
return Array.isArray(msg.payload) ? msg.payload : msg.payload.data;
}
function signed16(value) {
return value & 0x8000 ? value - 0x10000 : value;
}
const r = registerData(msg);
const sensors = [];
for (let offset = 0; offset + 4 < r.length; offset += 5) {
if (r[offset] === 0xffff) {
continue;
}
sensors.push({
index: r[offset],
co2: r[offset + 1],
temperature: signed16(r[offset + 2]) / 10,
humidity: r[offset + 3] / 10,
valid: Boolean(r[offset + 4] & 1)
});
}
msg.payload = sensors;
return msg;
Všechna měření čidel zahrnují nastavené kompenzační hodnoty.
Čtení digitálních vstupů a čítačů stisků
Pro získání všech 12 fyzických kanálů jedním požadavkem přečtěte registry 32 až 46:
msg.payload = {
value: 0,
fc: 4,
unitid: 1,
address: 32,
quantity: 15
};
return msg;
Pokud je jako input nebo input_safe nastaven pouze port A, stačí počet registrů 7. Přečtou se tři bitové mapy a čítače A0 až A3.
function registerData(msg) {
return Array.isArray(msg.payload) ? msg.payload : msg.payload.data;
}
const r = registerData(msg);
const stateBitmap = r[0];
const inputValidBitmap = r[1];
const pressValidBitmap = r[2];
const channels = [];
for (let channel = 0; channel < r.length - 3; channel++) {
const mask = 1 << channel;
channels.push({
index: channel,
port: ["A", "B", "C"][Math.floor(channel / 4)],
pin: channel % 4,
input_valid: Boolean(inputValidBitmap & mask),
active: Boolean(stateBitmap & mask),
press_counter_valid: Boolean(pressValidBitmap & mask),
press_counter: r[3 + channel]
});
}
msg.payload = {
state_bitmap: stateBitmap,
input_valid_bitmap: inputValidBitmap,
press_valid_bitmap: pressValidBitmap,
channels: channels
};
return msg;
Pro spolehlivé zpracování tlačítek porovnávejte každý čítač stisků s jeho hodnotou z předchozího cyklu čtení. Rozdíl bez znaménka vypočítáte takto:
const delta = (currentCounter - previousCounter) & 0xffff;
První vzorek určuje výchozí stav a nesmí vyvolat události stisků. Tento postup zachytí i krátké stisky, které začnou a skončí mezi dvěma cykly čtení.
Zápis a čtení logických výstupů
Pořadí kanálů je A0-A3, B0-B3 a C0-C3. Například B0 odpovídá holding registru 1004.
Nastavení B0 na logickou 1 pomocí uzlu Modbus Flex Write:
msg.payload = {
value: 1,
fc: 6,
unitid: 1,
address: 1004,
quantity: 1
};
return msg;
Nastavení všech čtyř pinů portu B jedním požadavkem funkce 16:
msg.payload = {
value: [1, 0, 1, 0],
fc: 16,
unitid: 1,
address: 1004,
quantity: 4
};
return msg;
Zpětné čtení čtyř stavů výstupů pomocí uzlu Modbus Flex Getter:
msg.payload = {
value: 0,
fc: 3,
unitid: 1,
address: 1004,
quantity: 4
};
return msg;
Cílový port musí být nastaven jako output nebo output_safe. Zápisy do kanálu v jiném režimu jsou odmítnuty.
Zápis a čtení výstupů PWM
Registry PWM používají celočíselnou střídu od 0 do 100. Například B0 odpovídá holding registru 1024.
Nastavení B0 na 50 procent:
msg.payload = {
value: 50,
fc: 6,
unitid: 1,
address: 1024,
quantity: 1
};
return msg;
Nastavení všech čtyř kanálů PWM na portu B:
msg.payload = {
value: [0, 25, 50, 100],
fc: 16,
unitid: 1,
address: 1024,
quantity: 4
};
return msg;
Zpětné čtení čtyř hodnot střídy pomocí uzlu Modbus Flex Getter:
msg.payload = {
value: 0,
fc: 3,
unitid: 1,
address: 1024,
quantity: 4
};
return msg;
Cílový port musí být nastaven jako pwm_50hz, pwm_1khz nebo pwm_25khz. Hodnoty nad 100 a zápisy do kanálů v jiném režimu jsou odmítnuty.
Návrat modulu do režimu HBUS
Pomocí uzlu Modbus Flex Write zapište servisní hodnotu 0x4842 (18498 v desítkové soustavě) do holding registru 1999:
msg.payload = {
value: 18498,
fc: 6,
unitid: 1,
address: 1999,
quantity: 1
};
return msg;
Modul nejprve vrátí běžnou odpověď funkce 06, uloží HBUS jako nastavený režim a poté se restartuje. Nastavená přenosová rychlost zůstane zachována. Všesměrový zápis na adresu nula je pro tuto operaci záměrně odmítán.
