0:10
hello and welcome to controllers Tech
0:13
today we will start the modbus video
0:16
series for the SDM 32 and this is the
0:19
first main video in that series
0:21
I have already created a playlist for
0:24
the modbus where I have added a few
0:26
videos from another creator
0:28
the explanation in these videos is
0:31
pretty good and it will help you
0:33
understand the basics of the modbus
0:36
if you haven't watched them yet you
0:38
should do that before continuing with
0:41
I will start directly with writing the
0:44
protocol and you might not understand a
0:47
so do check out the videos first
0:50
now let's talk about the connection
0:53
in the previous video I have covered the
0:56
is-485 to TTL module and how we
0:59
interface it with the stm32
1:02
well we have the same module here which
1:05
is connected to the stm32
1:08
the connection is the same as what we
1:10
covered in the previous video
1:12
I am going to use the computer to act
1:15
like a modbus slave and this is why we
1:17
have another one today
1:22
as you can see it only has two pins pin
1:27
and as you might have figured out
1:29
already we will connect the pin a
1:31
together and pin B together
1:33
the rs-485 to TTL module is powered with
1:37
5 volts and the USB module is anyway
1:40
connected to the computer
1:42
before we go ahead I want to make this
1:44
clear that the is-485 is not a
1:47
requirement for the modbus rather the
1:49
modbus is a protocol so it can work with
1:51
any communication standard
1:54
I am using the is-485 because it is
1:57
widely used and it has its advantages
2:01
you can simply use the rs-232 also
2:05
now let's revise a little about the
2:09
if you have watched the previous videos
2:11
in the playlist you might already be
2:13
familiar with this picture
2:15
in this video we will use the stm32 as
2:19
the master which will only perform the
2:21
read operation on holding registers and
2:26
we are starting with them as the
2:28
registers are easier to read compared to
2:32
this picture shows the function codes
2:34
that we are allowed to use in the modbus
2:38
for example if the master wants to read
2:41
a coil it will send the function code 1
2:43
or if it wants to read the holding
2:46
registers it will send the function code
2:49
in this video we will be using the
2:52
function codes for for reading input
2:54
registers and code 3 for reading holding
2:59
one more thing you can note here is how
3:01
much data we can read continuously in
3:05
so if we are reading the registers we
3:08
can only read 125 registers at a time
3:12
this is because the maximum data size in
3:15
the modbus protocol can be up to 256
3:20
out of this one bytes is occupied by the
3:22
slave address another byte for the
3:24
function code and two bytes for the CRC
3:28
the remaining 252 bytes can be used for
3:33
this data can be anything and it changes
3:36
based on Master read or write or in case
3:40
say for example if the master is sending
3:43
a query to the slave the data will
3:46
consist of the start address of the
3:47
memory and how many points the master
3:51
I am using the term points because the
3:54
master could read registers or coils
3:56
where the registers are 16 bits in size
3:58
the coils are only one bit
4:01
so when the master specifies the points
4:04
it means the quantity based on what it
4:08
so two points in registers implies two
4:10
registers which is 32 bits in total and
4:14
two points in coils implies two bits
4:17
in case the master wants to write
4:19
something into the slave memory the data
4:22
field now consists of the start address
4:24
the number of points the number of bytes
4:26
it wants to write and then the data
4:30
notice here that the number of points is
4:32
followed by the number of bytes
4:35
this is because the byte count changes
4:37
according to what the master is writing
4:40
for example if the master is writing
4:43
eight registers the byte count would be
4:45
16 since each register is 16 bits in
4:50
and if it is writing eight coils the
4:53
byte count would be 1 as each coil is
4:57
the actual data the master sends also
5:00
needs to be in the byte format only we
5:02
will see this later when we will come to
5:04
this topic about writing the data into
5:08
now let's talk about what we are going
5:12
as I mentioned before today we will
5:15
program the master to read the holding
5:17
registers and input registers
5:20
so the master will only send the query
5:24
the format for the same is shown in this
5:28
we have the slave address occupying one
5:30
byte the function co-occupying one byte
5:33
again the register start address
5:35
occupying two bytes in total the number
5:37
of registers occupying two bytes again
5:40
and finally the CRC occupying two bytes
5:44
the register start address and the
5:46
number of points are split into two
5:47
separate bytes and we have to provide
5:52
the CRC is also split into two bytes but
5:55
here we have to provide the low byte
5:58
in total the master needs to send eight
6:03
here is an example of the query command
6:06
after the slave device receives this
6:09
request it will transfer the requested
6:14
the response consists of the slave
6:16
address function code the number of
6:18
actual data bytes slave is going to
6:21
transmit the data itself and at last the
6:25
here you can see the example of slave
6:30
since the master has to transmit the CRC
6:33
it needs to generate the CRC first
6:36
this is a separate source file I have
6:39
created for the CRC all the values you
6:42
see here are copied from the PDF
6:44
provided on the modbus website
6:47
here is the protocol reference guide I
6:51
it contains all the examples you need to
6:53
understand the query and response for
6:57
anyway let's go to the bottom of this
6:59
PDF here you can see the table for the
7:10
if you go to the previous page you can
7:12
see the CRC generation function
7:15
I have used this function in the code
7:18
all right it will all connect later so
7:21
let's start the cube IDE and create a
7:32
give some name to the project and click
7:38
here I am selecting the external Crystal
7:43
the board has 8 megahertz Crystal and we
7:46
will run the controller at maximum 72
7:50
go to sys debug and enable serial wire
7:54
also select the time-based source as
7:56
systic now let's enable the uart1 in the
8:01
here you can see the pins pa9 and Pa 10
8:05
got selected as the TX and RX pins
8:08
we will keep the default setup with
8:11
board rate of 11 5 208 N1
8:14
keep this in mind as we need to
8:17
configure the same for the slave device
8:20
we will use the interrupt to receive the
8:22
data so enable it in the nvic tab
8:26
now if you remember from the previous
8:28
video we need to set an output pin to
8:31
control the rs-485 module
8:34
so I am setting the pin pa8 as output
8:37
and renaming it to TX enable pin this is
8:41
it for the configuration click save to
8:50
let's first copy the CRC Library files
8:54
into our project folder copy the source
8:57
file in the source folder and head a
8:59
file in the include folder
9:04
also we need to include the header file
9:07
let's start by creating the RX and TX
9:12
as I mentioned earlier for this tutorial
9:14
the TX data size is going to be 8 bytes
9:17
also I am not sure how much data I am
9:20
going to receive therefore I have
9:22
created a 32 byte array for receiving
9:25
just like the previous video we will
9:28
create a send data function in order to
9:30
send the data via the rs-485
9:34
here we will first put the module in the
9:36
transmitter mode then transmit the data
9:39
via the uart and finally put the module
9:41
back to the receiver mode
9:44
this is already explained in the rs-485
9:49
now in the main function we will receive
9:51
the data using the idle line interrupt
9:55
so everything we did so far is covered
9:57
in the previous video so watch it if you
10:00
don't understand this
10:02
now we will prepare our TX data buffer
10:05
as per the things we have covered so far
10:08
we will start with the slave address
10:11
the slave address is programmable in
10:13
most of the devices and let's assume my
10:16
device have the address 0 cross 0 5.
10:20
next we have to provide the function
10:23
we are reading the holding registers so
10:26
the function code is 3.
10:32
now comes the data and in the data field
10:34
we have to first enter the starting
10:36
address of the register followed by the
10:38
number of registers we want to read
10:41
but the register addressing in the
10:43
modbus is not that simple
10:48
I am using the simply modbus slave
10:50
software in the computer
10:53
the free version takes a time to load
10:56
you can download it from their website
11:02
I have installed both master and slave
11:04
softwares but today we will be using the
11:10
this is how the interface looks like
11:13
we will talk about all these parameters
11:15
in a while let's just focus on the
11:18
register address for now
11:20
here if you click the data button you
11:23
can see we have all sorts of registers
11:26
this is basically emulating as a slave
11:29
device and it have all the registers
11:31
that might be available in any modbus
11:35
here on the top you can see the function
11:37
code which we will keep to three
11:40
in case of the holding registers the
11:43
register address starts from forty
11:47
note here that the offset is also set to
11:52
as for the modbus standard this is how
11:55
it should be the first register address
11:57
should be the offset
11:59
but there are some vendors who do not
12:01
follow this and they might keep the
12:03
offset at 40 000 or probably 40 000 too
12:07
this is specific to the vendor itself
12:10
and you can find the details about it in
12:14
here we will go as per the protocol
12:16
standards and assume the offset is set
12:21
the address we need to transfer is the
12:23
difference between the first register
12:25
address and the offset
12:28
so if we want to read data from forty
12:30
thousand one we actually need to send
12:34
similarly for forty thousand two we will
12:40
then 2 for the Forty thousand three and
12:44
I am only displaying 10 values here so
12:47
the last register you see is forty
12:49
thousand ten and the address for the
12:53
the last holding register is at the
12:55
location 50 000 and the address for the
13:00
9999 or 0 cross 270f
13:04
so basically the function code 3
13:07
combined with the address 0 will
13:09
automatically mean that the master wants
13:11
to read the register 40001.
13:14
similarly if we see the function Code 4
13:17
which is reading the input registers the
13:20
register will range from 30 000 1 to 40
13:24
so the function Code 4 combined with the
13:27
address 0 will mean that the master
13:29
wants to read the register 3001.
13:33
this is how the addressing of the
13:34
registers is done on the modbus devices
13:38
now the yellow color boxes you see in
13:40
front of the registers these are the
13:44
at forty thousand one the value stored
13:50
I have stored different values at these
13:53
locations and we are programming the
13:55
master to read these values
14:01
let me input some values for these two
14:08
you can only see 10 registers because of
14:11
if you want to see more you can change
14:16
so I hope you understood the register
14:18
addressing in a modbus device
14:21
let's continue with our code
14:23
I am just keeping this explanation so
14:26
that you can see what's happening in the
14:31
let's assume I want to read from forty
14:33
thousand five and I want to read five
14:37
so the address will be 4. the address
14:40
should be two bytes long and we need to
14:42
input the high byte first so zero
14:46
the low byte will be 4.
14:50
similarly there are two bytes for the
14:52
number of registers with the high byte
14:54
as zero and low byte is 5.
14:58
so we are reading five registers and if
15:00
you remember each register being 16 bit
15:03
in size that means we will be reading 10
15:07
the last two bytes will be the CRC
15:11
to calculate the CRC we will use this
15:15
we will create a 16-bit variable to
15:18
store this CRC value
15:20
the buffer will be the TX data and the
15:23
buffer length will be how many bytes
15:25
have we stored in it so far
15:27
we have already stored six bytes and the
15:30
last two bytes will be for CRC
15:33
the 16-bit CRC will be stored in the
15:36
variable we created and now we need to
15:38
separate it and store it in our TX
15:41
so we will first store the lower byte
15:44
and then the high byte now the TX data
15:47
buffer is ready so we will send it via
15:53
after the slave device receives the
15:55
query it will respond with the register
15:59
so the stm32 will receive the data and
16:02
since we are using the interrupt for the
16:04
same the Callback will trigger
16:07
in case of the idle line interrupt this
16:09
receive event callback is called
16:12
well we don't have anything to process
16:14
for now so we will just at the
16:16
breakpoint here later
16:19
seems like we have a lot of issues
16:26
the CRC is already defined so I am
16:30
changing it to a small case
16:39
all right that's gone
16:43
I think I have switched the positions of
17:05
all right everything is fine now
17:08
let's debug the code
17:11
I have already added the TX and RX
17:13
buffer in the live expression
17:17
in the device manager you can see the
17:19
port of the is-485 to USB module
17:23
we have to use the same port in the
17:31
also make sure the configuration here is
17:34
same as what we did for the uart in the
17:37
slave ID is 5. everything is fine so
17:42
let's put a break point in the Callback
17:44
function and run the debugger I am also
17:47
putting a breakpoint before sending the
17:50
let's see in the TX buffer we have the
17:53
slave ID function code start address
17:56
number of registers and the CRC
18:00
everything seems okay
18:06
all right we have hit the Callback
18:08
function this means the master have
18:10
received some data from the slave device
18:14
let's first see what is happening on the
18:18
here everything is green which means all
18:22
here you can see the query sent by the
18:29
we have the slave ID function code
18:32
starting register address number of
18:35
registers to read and the CRC
18:41
below that everything is framed properly
18:49
since the starting register address is 4
18:52
that means that the actual register
18:54
address is 40 0005. note the data stored
18:58
at the locations starting from that
19:06
this window here shows the values sent
19:09
by the slave device in response to the
19:12
these values are the same as what we
19:15
have stored in the respective registers
19:25
this window shows the actual response
19:28
sent by the slave device
19:30
here we have the slave address the
19:33
function code then the number of data
19:35
bytes the slave is going to send
19:38
here the slave is sending 10 bytes of
19:40
data 2 bytes for each register
19:43
then we have the 2 bytes of the CRC in
19:47
before we check out this data in the
19:50
debugger note that I have switched the
19:52
number format to hexadecimal you need to
19:55
restart the debugger after making this
19:58
change or else it will not reflect
20:05
you can see we have received exactly the
20:24
the next step for us would be to extract
20:27
the 16-bit values from this response
20:31
we will write the code for the same
20:33
inside the Callback function itself
20:36
let's define a 16-bit array to store
20:40
keep in mind that the first three bytes
20:42
of the response are always fixed and the
20:45
data actually starts from the fourth
20:48
also note that the data is sent in a way
20:50
that higher byte is sent first followed
20:55
so we will shift the higher byte to the
20:57
left by eight positions and then added
21:00
it with the lower byte
21:01
this will combine two bytes into a
21:06
we will do the same for all the 10 bytes
21:31
you can see the hexadecimal values are
21:33
same as sent by the slave device
21:36
if you want to see the decimal result
21:38
you need to change the number format
21:41
and restart the debugger for the changes
21:54
here you can see the decimal values they
21:58
are exactly the same as what we stored
22:04
I hope the things were clear with the
22:08
now we will take a quick look at the
22:10
input registers also
22:13
so let's enable it in the slave software
22:17
the function code is 4. the start
22:20
register and the offset are both set to
22:25
let me input some values here in these
22:32
all right let's make the changes in the
22:35
the first change will be the function
22:39
to read the input registers we need to
22:42
send the function code for
22:46
next we will change the starting
22:55
I am giving the address 1 that means we
22:58
will start reading from the register
23:04
let's keep the rest of them the same
23:07
we will be reading five registers again
23:09
and the CRC will be calculated in the
23:12
similar manner let's build and debug the
23:19
put the breakpoint in the Callback
23:21
function and run the code again
23:24
it's not hitting the breakpoint
23:26
since it's a demo version I guess we can
23:29
only run it for some time
23:31
let me restart the software
23:41
all right everything is unchanged
23:44
even the values are stored so we will
23:47
continue with our testing now
23:54
this time we hit the break point
23:57
you can see the query has the function
23:59
code for the register address 1 and the
24:03
number of registers are five
24:05
and the data transmitted by the slave
24:07
device is same as what we stored in the
24:11
here we have got the data stored in the
24:15
the fifth one is zero because we didn't
24:18
extract it but it's fine
24:21
so this was the start of the modbus
24:23
series where we covered how to read the
24:25
holding and input registers
24:27
in the next video we will read the coils
24:33
we will start the video from where we
24:37
you can download the code from the link
24:41
keep watching and have a nice day ahead