Skip to main content

Modbus With a Device Library - NB-IoT

Integration manual for the ACRIOS Systems converters ACR-CV-101N-R12-D and ACR-CV-101N-R12-EAC using NB-IoT, possible to use also with versions ACR-CV-101N-R-D and ACR-CV-101N-R-EAC.

Introduction


This is the documentation needed for the ACRIOS Systems Modbus to NB-IoT concentrator. The documentation refers to the default Lua script used and covers possible configuration options.

Please note, that the standard Lua script is not used here. If you wish to obtain the script, please, contact us at support@acrios.com.

Typical Use-Case

Modbus energy meters are often deployed in large numbers in many urban areas. The lack of standardization poses a significant challenge, where each Modbus meter requires separate, lengthy implementation, leading to inefficiencies, errors, and increased costs. Whereas manual readings often suffer from inaccuracies and delays, our Modbus to NB-IoT Converter is an ideal solution to seamlessly integrate all the varied Modbus meters into a unified, remote monitoring system.

Scenario:

Property managers, utility companies, and industrial facility supervisors often have to manage multiple of Modbus meters. It can become difficult to gather all the data due to lack of standardization. Therefore, an automated and easy to manage solution would resolve such issue immediately.

Solution:

Our Modbus to NB-IoT Converter allows for standardization for diverse portfolio of Modbus meters. Its implementation allows for an easy customization and swift over-the-air configuration. Our converter allows for a smooth transition from manual configuration to a unified, automated system.

Benefits:

  • Streamlined Integration: Overcoming the challenges of non-standardized Modbus communication, our converter unifies the integration process, saving time and effort.
  • Error Reduction: By eliminating manual device on-site configuration and the need for separate meter implementations, the converter significantly reduces the margin of error, ensuring accurate readings.
  • Reliable Communication: The external antenna ensures reliable signal propagation, maintaining consistent communication even in complex urban environments.
  • Future-Proof Solution: The converter’s adaptability ensures it can accommodate new Modbus meters seamlessly, making it a future-proof investment.

Converter Integration


Functions

The device contains following functions:

  • Payload length of approximately 1024 B (depends on the network)
  • Acknowledged messages
  • Setup library containing:
    • Baud rate
    • Stop bits
    • Parity
    • Function code
    • Auxiliary power supply of 12 V DC - only for “R12” versions
    • How long the device has to be powered-on (measured in seconds)
    • Registers list
  • Remote configuration
    • Which sensor from library we want to read on which address and how often
    • Device wake-up interval
    • Remote library modification
  • Time synchronization
  • Local history of unsent frames

Time Synchronization

Time is automatically synchronized with the NB-IoT network during the connection procedure.

Out of the Box Behavior

When the device is powered up, the bootloader starts. The bootloader is responsible for the correct launch of the application firmware and also allows OTA firmware update. The time the device spends in the bootloader mode depends on the initialization of the SIM module and the connectivity to the network. It could take up to 20 minutes, though it is usually much shorter under right circumstances (note that it can also be affected by the firmware version). During the bootloader, the LED is dimly lit during the bootloader procedure. If the device is connected to the serial line, you can see the AT commands printout, while the device is attempting to connect to the network.

Note that the bootloader sequence can be skipped by holding the button until the LED starts flashing (you can also see printouts of the # signs).

The bootloader in the serial line may look similarly to this:

[BOOT] NBIOT: (<) ATE0;+GSN
[BOOT] NBIOT: (>)
[BOOT] NBIOT: (>) 868333032135382
[BOOT] NBIOT: (>)
[BOOT] NBIOT: (>) OK
[BOOT] NBIOT: (<) ATE0;+CIMI
[BOOT] NBIOT: (>)
[BOOT] NBIOT: (>) ERROR
[BOOT] NBIOT: (<) ATE0;+CIMI
[BOOT] NBIOT: (>)
[BOOT] NBIOT: (>) ERROR
[BOOT] NBIOT: (<) ATE0;+CIMI

At the end of the bootloader, the device skips to the application part of the firmware, beginning with the initialization of all the necessary peripherals and loading the Lua script stored in the memory. With the Lua script initialization, the Setup configuration is loaded (referred to as the "Setup library"), which is based on the specifications outlined in the Lua script header.

This is how it looks on the first Startup():

Initialization looks as following:

[SYS]: console ready
[MEM]: init done, heap 52552 bytes, bss 8080 bytes, stack 4128 bytes
[SYS]: Reset Reason: BOR reset
[SYS]: FW version: CV_FW_2.13.1
[SYS]: Model: ACR_CV_101N_R12_D
[SYS]: SN: -1
[SYS]: date / time - 2023/11/20 / 13:16:09
[SYS]: build date / time - Nov 20 2023 / 13:01:50
[NBIOT]: wake the module up!
[NBIOT]: Initializing the module...
[NBIOT]: Received AT response, module is up!
[NBIOT]: MODEL = 'SIM7020E'
[NBIOT]: Detected: SIM7020
[RS485]: status - SUCCESS

Loading the Lua script and starting the OnStartup() section:

[LUA]: Starting onStartup() script
[STDOUT]: version: 1
[NBIOT]: Config not changed
[NBIOT]: APN set to 'auto'
[NBIOT]: Config not changed
[NBIOT]: PLMNID set to 0
[STDOUT]: Create Sensor table
[STDOUT]: set sensor value to eeprom and table
[STDOUT]: Add index lib 1 to eeprom

00 : 01 02 01 08 02 03 02 40 00 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: Add index lib 2 to eeprom

00 : 02 02 01 08 02 03 02 50 00 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: Add index lib 3 to eeprom

00 : 03 02 01 08 02 03 02 50 08 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: No History
[NBIOT]: wake the module up!
[NBIOT]: Initializing the module...
[NBIOT]: Received AT response, module is up!
[NBIOT]: MODEL = 'SIM7020E'
[NBIOT]: Detected: SIM7020
[NBIOT]: IMSI = '901405710058916'
[NBIOT]: Received SIM card is present and ready!
[NBIOT]: APN set to - 'auto'
[NBIOT]: Network not ready yet...
[NBIOT]: Network scan.....
[NBIOT]: Found: +COPS: 0
[NBIOT]: Got time from network
[NBIOT]: Setting time date...
[NBIOT]: Connected to IP network!
[NBIOT]: Time is 12:17:36+04
[NBIOT]: module setup done successfully!
[SYS]: --- New request ---
[SYS]: Battery Voltage: 3590 mV

OnWake() function:

[LUA]: Starting onWake() script
[HWAPI_COMMON]: Cannot get used count in non-existent table ID 2
[HWAPI_COMMON]: Cannot get used count in non-existent table ID 2
[NBIOT]: ActTimer (T3324): 62 s, TAUTimer (T3423): 0 s, eDRX: 0 ms, PTW: 0 ms, eDRX state: 0
[NBIOT]: Receiving... (timeout = 15000ms, nonewdatatimeout = 0ms)
[NBIOT]: Received 0 bytes
[STDOUT]: no downlink received
[STDOUT]: sleep for:1
[HWAPI_TIME]: Seconds to wait 60
[SYS]: entering sleep mode

First, it checks if the Modbus ID table has any configuration stored followed by a 2-byte "Empty configuration message" represented with 0xFF 0xFF.

Upon receiving a valid configuration frame containing Setup ID, Modbus address, and wake-up period, the device stores this information in its EEPROM. From this point forward, every time the device wakes-up, it will initiate a Modbus request to the Modbus ID hat has been configured.

For further details, please refer to the Communication Protocol Description or Example Application sections below.

Hardware Used

  1. ACR-CV-101N-R-D - Modbus to NB-IoT converter, battery powered.
  2. ACR-CV-101N-R-EAC - Modbus to NB-IoT converter, externally powered.
  3. ACR-CV-101N-R12-D - Modbus to NB-IoT converter, battery powered with AUX power supply 12V DC for connected sensors.
  4. ACR-CV-101N-R12-EAC - Modbus to NB-IoT converter, externally powered with AUX power supply 12V DC for connected sensors.

The converter allows you to connect any meter or other device equipped with an Modbus communication. Depending on the hardware version you can also connect sensors requiring power supply of 12 V DC.

Hardware Limitations

  • Hardware allows you to connect up to 96 UL.
  • For the versions with external power supply for the sensor (”R12” versions), the maximum recommended current is:
VersionRecommended Max Current
ACR-CV-101N-R12-D247,3 mA
ACR-CV-101N-R12-D21 mA
ACR-CV-101N-R12-EAC100 mA
  • The typical battery life time for the versions without auxiliary power supply for the sensors - ACR-CV-101N-R-D2 - is:
Reading and Sending IntervalEstimated Battery Lifetime
15 min2 years*
30 min3.9 years*
60 min7.7 years*

Please note that these are rough estimates because the battery lifetime is directly related to the number of readouts, connected sensors, its power consumption and required initialization delay.

Example above is calculated with a battery safety margin 30%, three readouts and 15 seconds NB-IoT Receive timeout.

Application Limitations

  • While NB-IoT is designed for low-power operation, the battery life of NB-IoT devices may still be a limitation for certain applications, especially if the devices need to operate in remote or hard-to-reach locations.

Communication Protocol Description


Setup Library

Below is the structure of the Setup library with the size of its variables.

PositionDescriptionSize
1SetupID1B
2Baudrate1B
3Stop Bits1B
4Data Bits1B
5Parity1B
6Function Code1B
7Register count1B
8Register Address2B
9RXTimeout4B
10Pre-Heat Time4B

Setup library should be sorted with the sensors starting from the lowest Pre-Heat Time and ending with the highest. I.e. the lowest index of the table ends up with the lowest Pre-Heat Time. This way it reduces the consumption of the battery.

Here is an example:

lib[1] = pack.pack("b7>h>i2",1,6,1,8,0,3,1,0,300,0)
lib[2] = pack.pack("b7>h>i2",2,6,1,8,0,3,1,0,100,2500)
lib[3] = pack.pack("b7>h>i2",3,1,1,8,0,3,2,0,100,3000)
lib[4] = pack.pack("b7>h>i2",4,1,1,8,0,3,1,0,1000,90000)

If the Setup library section of EEPROM is empty, the device loads Setup library defined in the script. Further changes made by the NB-IoT downlink commands are also reflected in the EEPROM where it is permanently stored.

Modbus ID Library

The following table describes the structure of the Modbus ID library:

Position123
DescriptionSetupIDModbus AddressWake-Up Period
Size1B1B2B

The Modbus ID library is empty until the configuration is received through NB-IoT downlinks.

Commands


Add Configuration into the Modbus ID Library (01)

This command is used to store the configuration in both temporary table and EEPROM. Thanks to this, even if the device restarts, the configuration is stored permanently.

Position1234
DescriptionCMDSetupIDModbus AddressWake-Up Period
Size1B1B1B2B
Downlink Example0x010x020x010x00 0x02
Position1
Uplink response0x01
Size1B

Add Sensor Configuration to Library (02)

Command 0x02 is used to add a sensor into the Setup library mentioned above. Below is an example:

PositionDescriptionSizeDownlink Example
1CMD1B0x02
2SetupID1B0x05
3Baudrate1B0x01
4Stop Bits1B0x01
5Data Bits1B0x08
6Parity1B0x00
7Function Code1B0x03
8Register count1B0x01
9Register Address2B0x00 0x00
10RXTimeout4B0x00 0x00 0x00 0x64
11Pre-Heat Time4B0x00 0x00 0x00 0x64
Position1
Uplink response0x02
Size1B

Modify the Index in the Table and EEPROM (03)

Command 03 manipulates with the Table Index for given Table ID. It can change the indexes of the given table and also remove them. Removal is possible only in such case when it is the last index in the table.

Setup Table ID = 1

Configuration Table ID = 2

PositionDescriptionSizeDownlink Example
1CMD1B0x03
2Table ID1B0x01
3Table Index1B0x01
4SetupID1B0x05
5Baudrate1B0x01
6Stop Bits1B0x01
7Data Bits1B0x08
8Parity1B0x00
9Function Code1B0x03
10Register count1B0x01
11Register Address2B0x00 0x00
12RXTimeout4B0x00 0x00 0x00 0x64
13Pre-Heat Time4B0x00 0x00 0x00 0x64
PositionDescriptionSizeDownlink Example
1CMD1B0x03
2Table ID1B0x02
3Table Index1B0x01
4SetupID1B0x02
5Modbus Address1B0x01
6Wake-Up Period2B0x00 0x02

This command uses a second command (CMD 2 - 0xFF) to remove index for given Table ID and Table Index. Removal is possible only in such case when it is the last index in the table.

Position1234
DescriptionCMDTable IDTable IndexCMD 2
Size1B1B1B1B
Downlink Example0x030x020x020xFF
Position1
Uplink response0x03
Size1B

Null History Counter (04)

Command 04 removes the history of sent messages stored in the EEPROM.

Position1
DescriptionCMD
Size1B
Downlink Example0x04
Position1
Uplink response0x04
Size1B

Execute Single Modbus Request (05)

Command 05 allows to execute a Modbus request without storing it into the table or EEPROM.

PositionDescriptionSizeDownlink Example
1CMD1B0x05
2Modbus Address1B0x01
3Pre-Heat Time4B0x00 0x00 0x00 0x64
4SetupID1B0x05
5Baudrate1B0x01
6Stop Bits1B0x01
7Data Bits1B0x08
8Parity1B0x00
9Function Code1B0x03
10Register count1B0x01
11Register Address2B0x00 0x00
12RXTimeout4B0x00 0x00 0x00 0x64
Position1
Uplink response0x05
Size1B

Local History of Unsent Frames

If the device detects the message was not successfully sent, It will store the message with a UNIX 4B (big-endian) timestamp.

The history is accessible during the startup of the device. It will print out a message “Press button in next 20s to get the history” and if the button is pressed, it will print out all the history stored in the memory. If needed, the history can be cleared using the CMD 04 (mentioned above).

Here is an example of what such printout could look like:

[STDOUT]: Press button in next 20s to get the history
00 : 65 67 3D FD 02 01 43 69 00 00

00 : 65 67 3E 41 01 01 17 09 10 95

00 : 65 67 3E 4B 02 01 43 69 00 00

00 : 65 67 3E 8E 01 01 17 09 10 95

00 : 65 67 3E 98 02 01 43 69 00 00

As you may have noticed in the example above, the payload has an extra four bytes. These are timestamps associated with given data.

If we take for example the one from the first message - 65 67 3D FD and convert it from big endian hex to uint32, the result is 1701264893. Which when converted from Unix to UTC is 11/29/2023 @ 1:59pm.

If the device is not able to send a message, the device will try to reinitialize the module. This process can take several minutes.

Example Application with Inepro PRO1-Mod


The example bellow uses Initial Setup Library and configures reading for the Inepro PRO1-Mod meter. You can find examples of the configuration messages sent by network server (as downlink) to configure the device.

Setup Library is loaded during the startup process and also stored in EEPROM. The library above contains Modbus configuration to read the Inepro meter with specified registers. The “preheat time” is not needed because the voltage source is not used to power the meter, it is only used as demonstration of its functionality.

Inepro PRO1-Mod

Device used: Inepro PRO1-Mod

Initial Setup Library:

-- [Setup ID][Baudrate index from the list][Stop Bits][Data Bits][Parity][Function Code]
-- [Register count][Register Address][RXTimeout][Pre Heat Time]

lib[1] = pack.pack("b7>h>i2",1,2,1,8,2,3,2,0x4000,3000,1000) -- 0x4000 = Read serial number
lib[2] = pack.pack("b7>h>i2",2,2,1,8,2,3,2,0x5000,3000,1000) -- 0x5000 = Read voltage
lib[3] = pack.pack("b7>h>i2",3,2,1,8,2,3,2,0x5008,3000,1000) -- 0x5008 = Read grid frequency

Here is the serial line output during the Setup library initialization.

[     8427][STDOUT]: Create setup table
[ 8461][STDOUT]: Load setup library to eeprom and table
[ 8511][STDOUT]: Add index lib 1 to eeprom

00 : 01 02 01 08 02 03 02 40 00 00 00 0B B8 00 00 03
10 : E8

[ 8684][STDOUT]: Add index lib 2 to eeprom

00 : 02 02 01 08 02 03 02 50 00 00 00 0B B8 00 00 03
10 : E8

[ 8857][STDOUT]: Add index lib 3 to eeprom

00 : 03 02 01 08 02 03 02 50 08 00 00 0B B8 00 00 03
10 : E8

Now the device is sending the 0xFF 0xFF (//8= in base64 format) message to the endpoint asking for configuration every minute:

{
"customerId": "05000051",
"rcvTime": 1700483335,
"srcImsi": "901400010058916",
"srcIP": "1.123.1.12",
"srcPort": "1234",
"payload": "//8="
}

Using the Downlink the Modbus ID library can be configured to use a specific Setup ID to read a given Modbus address for a defined period of time. For example with these messages:

  • 01 01 01 00 01 = Use 01 Setup ID configuration with 01 Modbus Address (the address of the meter) every 1 minute
  • 01 02 01 00 01 = Use 02 Setup ID configuration with 01 Modbus Address (the address of the meter) every 1 minute
  • 01 03 01 00 02 = Use 03 Setup ID configuration with 01 Modbus Address (the address of the meter) every 2 minutes

This is a scheduling of the downlink, the device receives its configuration:

[NBIOT]: ActTimer (T3324): 16 s, TAUTimer (T3423): 0 s, eDRX: 0 ms, PTW: 0 ms, eDRX state: 0
[NBIOT]: Receiving... (timeout = 15000ms, nonewdatatimeout = 0ms)
[NBIOT]: Received 5 bytes

00 : 01 01 01 00 01
[HWAPI_COMMON]: Cannot get used count in non-existent table ID 2
[STDOUT]: Create new table

Then it sends a confirmation message - 01 - and with the next wake up, requests the data from Inepro meter:

[SYS]: exiting sleep mode
[SYS]: --- New request ---
[SYS]: Battery Voltage: 3600 mV
[LUA]: Starting onWake() script
[STDOUT]: Sensor Settings :

00 : 01 02 01 08 02 03 02 40 00 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: Address: 1 Preheat:1000
[STDOUT]: received:

00 : 17 09 10 95

The device sends the data to the endpoint 01 01 17 09 10 95.

Scheduling the next downlink with a second command:

[NBIOT]: ActTimer (T3324): 16 s, TAUTimer (T3423): 0 s, eDRX: 0 ms, PTW: 0 ms, eDRX state: 0
[NBIOT]: Receiving... (timeout = 15000ms, nonewdatatimeout = 0ms)
[NBIOT]: Received 5 bytes

00 : 01 02 01 00 01

The device stores the configuration and sends a confirmation message - 01.

With the next wakeup it reads a voltage value:

[STDOUT]: Sensor Settings :  

00 : 02 02 01 08 02 03 02 50 00 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: Address: 1 Preheat:0
[STDOUT]: received:

00 : 43 64 33 33

Since the second reading is more than 1000 ms later (the first time preheat time applied on the address 0x4000), the device skips and reads the data immediately. The result here is 0x43643333 = 228.2 V (converted from hexadecimal float to decimal).

The endpoint receives 02 01 43 64 33 33.

With the third downlink command scheduled and confirmed - 01.

The device reads all 3 addresses, except with a difference, the third is requested only one in two minutes.

Below is a compressed version highlighting only the Modbus communication controlled by the configuration process explained above.

[STDOUT]: Sensor Settings :  
00 : 01 02 01 08 02 03 02 40 00 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: Address: 1 Preheat:1000
[STDOUT]: received:
00 : 17 09 10 95
[STDOUT]: Sensor Settings :
00 : 02 02 01 08 02 03 02 50 00 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: Address: 1 Preheat:0
[STDOUT]: received:
00 : 43 63 B3 33
[STDOUT]: Sensor Settings :
00 : 03 02 01 08 02 03 02 50 08 00 00 0B B8 00 00 03
10 : E8
[STDOUT]: Address: 1 Preheat:0
[STDOUT]: received:
00 : 42 47 E1 48

The frequency value is 49.97 Hz (42 47 E1 48 converted from hexadecimal float to decimal).

As described in the Commands section above, the table can me manipulated using the downlink messages.

For example by scheduling the following downlink - 03 02 01 01 0A 00 01, the device changes the Modbus configuration in Modbus ID table (in this case it changes only the Modbus ID to 10 instead of 1) leading to the device not being able to receive a response from the meter.

If the device receives no response from the meter, it sends two bytes (Setup ID and Modbus ID).

Which means - 01 0A in the case above.

Troubleshooting & FAQ


The device is sending an unknown payload

  • Please check if the payload is “4E 4F 20 44 41 54 41 20 52 45 43 45 49 56 45 44” - in which cases it translates to “NO DATA RECEIVED” in ASCII.

The device did not receive any response from the meter

  • Please check if the M-Bus configuration is correct - baudrate and parity. Further make sure electrical connection is done properly. You can also try to change parameter “preheat time” to a larger value because some meters may require up to six seconds (6000 ms). Make sure that only one device is connected without any prior changes to configuration.

The device is not connecting to the GUI

  • Please, make sure to use a Chromium based browser, we strongly recommend to use Google Chrome (other Chromium based browsers still may cause unexpected issues). Make also sure that the serial line is not opened on any other serial line monitor.

The device has connected, the Lua script was uploaded but it is not possible to connect anymore

  • Make sure the battery has been disconnected for a longer period of time to discharge the capacitor or alternatively short the battery pins on the PCB. Connect the two metal pins in the battery connector on the PCB with something conductive (tip of screw driver, paper clip, tip of a pen etc.). The device can connect only when in bootloader or when it is sleeping. If the device is in the application Lua script and currently running, it will not connect.

Where do I configure the Lua script?

  • Please, visit: gui.acrios.com. Make sure to use a Chromium based browser, we strongly recommend to use Google Chrome.

Where can I see a data or serial line log?

  • You can check any serial line monitor such as PuTTy or Termite. Please, make sure the serial line monitor configuration is - baud rate: 115 200, data bits: 8, stop bits: 1, parity: none.


Was anything unclear, missing or hard to understand? Please, contact us at support@acrios.com.
Further information can be found on wiki.acrios.com.