Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
H
hddtempserial
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Oleg Nikulin
hddtempserial
Commits
dabc790f
Commit
dabc790f
authored
Jun 23, 2023
by
Oleg Nikulin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Контрольная сумма crc16 modbus
parent
5812907a
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
155 additions
and
70 deletions
+155
-70
communication.py
communication.py
+20
-3
hddtempserial.py
hddtempserial.py
+7
-10
hddtempserial.ino
hddtempserial/hddtempserial.ino
+128
-57
No files found.
communication.py
View file @
dabc790f
import
serial
import
time
from
crc
import
Calculator
,
Crc16
def
open_serial
(
port
,
baudrate
):
try
:
#пытаемся открыть serial порт
...
...
@@ -20,14 +21,23 @@ def open_serial(port, baudrate):
return
serial_port
def
serial_exchange
(
serial_port
,
transmit_bytes
,
required_response_length
,
timeout
=
1
):
#если всё ок, возвращает полученный массив байт
#если required_response_length == 0, возвращает пустой массив
#если таймаут или не сходится crc, возвращает None
def
serial_exchange
(
serial_port
,
transmit_array
,
required_response_length
,
timeout
=
1
):
if
serial_port
is
None
:
raise
OSError
transmit_bytes
=
bytearray
(
transmit_array
)
crc_calculator
=
Calculator
(
Crc16
.
MODBUS
)
crc16
=
crc_calculator
.
checksum
(
transmit_bytes
)
crc16_bytes
=
crc16
.
to_bytes
(
length
=
2
,
byteorder
=
'big'
)
transmit_bytes
+=
crc16_bytes
serial_port
.
reset_input_buffer
()
serial_port
.
reset_output_buffer
()
serial_port
.
write
(
bytearray
(
transmit_bytes
)
)
serial_port
.
write
(
transmit_bytes
)
if
required_response_length
==
0
:
return
bytes
([])
...
...
@@ -42,4 +52,11 @@ def serial_exchange(serial_port, transmit_bytes, required_response_length, timeo
return
None
response
=
serial_port
.
read
(
required_response_length
)
#минимум 1 байт данных + 2 байта crc
if
len
(
response
)
>=
3
:
response_crc16
=
int
.
from_bytes
([
response
[
-
2
],
response
[
-
1
]],
byteorder
=
'big'
,
signed
=
False
)
if
not
crc_calculator
.
verify
(
response
[:
-
2
],
response_crc16
):
return
None
return
response
hddtempserial.py
View file @
dabc790f
...
...
@@ -75,18 +75,18 @@ def initialize(serial_port):
config
[
'controlGroups'
][
1
][
'copyFromGroupIndex'
],
config
[
'controlGroups'
][
2
][
'copyFromGroupIndex'
]
]
response_length
=
1
response_length
=
3
response
=
serial_exchange
(
serial_port
,
transmit_bytes
,
response_length
,
config
[
'arduinoTimeoutSec'
])
if
response
is
None
:
print
(
'Initialize
failed
'
)
print
(
'Initialize
no valid response
'
)
else
:
if
response
[
0
]
==
arduino_response_codes
.
initialize_ok
:
initialized
=
True
print
(
'Initialize ok'
)
else
:
print
(
'Initialize
not ok
'
)
print
(
'Initialize
bad response
'
)
def
poll
(
serial_port
):
...
...
@@ -102,12 +102,12 @@ def poll(serial_port):
(
temperatures
[
2
]
>>
8
)
&
0xff
,
temperatures
[
2
]
&
0xff
,
]
response_length
=
1
6
response_length
=
1
8
response
=
serial_exchange
(
serial_port
,
transmit_bytes
,
response_length
,
config
[
'arduinoTimeoutSec'
])
if
response
is
None
:
initialized
=
False
print
(
'Poll
failed
'
)
print
(
'Poll
no valid response
'
)
else
:
if
response
[
0
]
==
arduino_response_codes
.
poll_noinit
:
initialized
=
False
...
...
@@ -128,7 +128,7 @@ def poll(serial_port):
return
True
else
:
initialized
=
False
print
(
'Poll
not ok
'
)
print
(
'Poll
bad response
'
)
return
False
...
...
@@ -164,11 +164,8 @@ if __name__ == "__main__":
if
baudrate
is
None
:
print
(
'Baudrate is not specified (neither in config nor in command line)'
)
exit
()
serial_port
=
open_serial
(
port
,
baudrate
)
if
serial_port
is
None
:
print
(
'Failed to open serial port'
)
exit
()
serial_port
=
open_serial
(
port
,
baudrate
)
try
:
...
...
hddtempserial/hddtempserial.ino
View file @
dabc790f
//#include <Wire.h>
#define FAN_COUNT 6 //Количество вентиляторов
#define CONTROL_COUNT 3 //Количество групп управления
#define BAUDRATE 19200 //Скорость serial порта
...
...
@@ -161,6 +159,71 @@ bool initialized = false;
const
unsigned
short
crc16table
[
256
]
=
{
0x0000
,
0xc0c1
,
0xc181
,
0x0140
,
0xc301
,
0x03c0
,
0x0280
,
0xc241
,
0xc601
,
0x06c0
,
0x0780
,
0xc741
,
0x0500
,
0xc5c1
,
0xc481
,
0x0440
,
0xcc01
,
0x0cc0
,
0x0d80
,
0xcd41
,
0x0f00
,
0xcfc1
,
0xce81
,
0x0e40
,
0x0a00
,
0xcac1
,
0xcb81
,
0x0b40
,
0xc901
,
0x09c0
,
0x0880
,
0xc841
,
0xd801
,
0x18c0
,
0x1980
,
0xd941
,
0x1b00
,
0xdbc1
,
0xda81
,
0x1a40
,
0x1e00
,
0xdec1
,
0xdf81
,
0x1f40
,
0xdd01
,
0x1dc0
,
0x1c80
,
0xdc41
,
0x1400
,
0xd4c1
,
0xd581
,
0x1540
,
0xd701
,
0x17c0
,
0x1680
,
0xd641
,
0xd201
,
0x12c0
,
0x1380
,
0xd341
,
0x1100
,
0xd1c1
,
0xd081
,
0x1040
,
0xf001
,
0x30c0
,
0x3180
,
0xf141
,
0x3300
,
0xf3c1
,
0xf281
,
0x3240
,
0x3600
,
0xf6c1
,
0xf781
,
0x3740
,
0xf501
,
0x35c0
,
0x3480
,
0xf441
,
0x3c00
,
0xfcc1
,
0xfd81
,
0x3d40
,
0xff01
,
0x3fc0
,
0x3e80
,
0xfe41
,
0xfa01
,
0x3ac0
,
0x3b80
,
0xfb41
,
0x3900
,
0xf9c1
,
0xf881
,
0x3840
,
0x2800
,
0xe8c1
,
0xe981
,
0x2940
,
0xeb01
,
0x2bc0
,
0x2a80
,
0xea41
,
0xee01
,
0x2ec0
,
0x2f80
,
0xef41
,
0x2d00
,
0xedc1
,
0xec81
,
0x2c40
,
0xe401
,
0x24c0
,
0x2580
,
0xe541
,
0x2700
,
0xe7c1
,
0xe681
,
0x2640
,
0x2200
,
0xe2c1
,
0xe381
,
0x2340
,
0xe101
,
0x21c0
,
0x2080
,
0xe041
,
0xa001
,
0x60c0
,
0x6180
,
0xa141
,
0x6300
,
0xa3c1
,
0xa281
,
0x6240
,
0x6600
,
0xa6c1
,
0xa781
,
0x6740
,
0xa501
,
0x65c0
,
0x6480
,
0xa441
,
0x6c00
,
0xacc1
,
0xad81
,
0x6d40
,
0xaf01
,
0x6fc0
,
0x6e80
,
0xae41
,
0xaa01
,
0x6ac0
,
0x6b80
,
0xab41
,
0x6900
,
0xa9c1
,
0xa881
,
0x6840
,
0x7800
,
0xb8c1
,
0xb981
,
0x7940
,
0xbb01
,
0x7bc0
,
0x7a80
,
0xba41
,
0xbe01
,
0x7ec0
,
0x7f80
,
0xbf41
,
0x7d00
,
0xbdc1
,
0xbc81
,
0x7c40
,
0xb401
,
0x74c0
,
0x7580
,
0xb541
,
0x7700
,
0xb7c1
,
0xb681
,
0x7640
,
0x7200
,
0xb2c1
,
0xb381
,
0x7340
,
0xb101
,
0x71c0
,
0x7080
,
0xb041
,
0x5000
,
0x90c1
,
0x9181
,
0x5140
,
0x9301
,
0x53c0
,
0x5280
,
0x9241
,
0x9601
,
0x56c0
,
0x5780
,
0x9741
,
0x5500
,
0x95c1
,
0x9481
,
0x5440
,
0x9c01
,
0x5cc0
,
0x5d80
,
0x9d41
,
0x5f00
,
0x9fc1
,
0x9e81
,
0x5e40
,
0x5a00
,
0x9ac1
,
0x9b81
,
0x5b40
,
0x9901
,
0x59c0
,
0x5880
,
0x9841
,
0x8801
,
0x48c0
,
0x4980
,
0x8941
,
0x4b00
,
0x8bc1
,
0x8a81
,
0x4a40
,
0x4e00
,
0x8ec1
,
0x8f81
,
0x4f40
,
0x8d01
,
0x4dc0
,
0x4c80
,
0x8c41
,
0x4400
,
0x84c1
,
0x8581
,
0x4540
,
0x8701
,
0x47c0
,
0x4680
,
0x8641
,
0x8201
,
0x42c0
,
0x4380
,
0x8341
,
0x4100
,
0x81c1
,
0x8081
,
0x4040
};
uint16_t
crc16_calc
(
uint8_t
*
data
,
uint16_t
len
)
{
uint16_t
crc
=
0xFFFF
;
uint8_t
nTemp
;
while
(
len
--
)
{
nTemp
=
*
data
++
^
crc
;
crc
>>=
8
;
crc
^=
crc16table
[
nTemp
];
}
return
crc
;
}
uint8_t
add_crc
(
uint8_t
*
buf
,
uint8_t
len
)
{
uint16_t
crc16
=
crc16_calc
(
buf
,
len
);
buf
[
len
]
=
crc16
>>
8
;
buf
[
len
+
1
]
=
crc16
&
0xff
;
len
+=
2
;
return
len
;
}
uint16_t
get_avg_rpm
(
fan
*
fan_ptr
)
{
uint32_t
avg_rpm
=
0
;
...
...
@@ -174,7 +237,6 @@ uint16_t get_avg_rpm(fan* fan_ptr) {
void
process_command
()
{
uint8_t
cmd_code
=
0
;
uint8_t
cmd_buffer
[
32
]
=
{};
uint8_t
cmd_length
=
0
;
...
...
@@ -183,16 +245,18 @@ void process_command() {
uint8_t
response_length
=
1
;
//читаем первый байт (код команды)
if
(
Serial
.
readBytes
(
&
cmd_code
,
1
)
==
0
)
if
(
Serial
.
readBytes
(
cmd_buffer
,
1
)
==
0
)
return
;
//по коду команды понимаем сколько еще байтов надо принять
uint8_t
cmd_code
=
cmd_buffer
[
0
];
//по коду команды понимаем длину команды (с учетом байта кода команды и двух байт crc)
switch
(
cmd_code
)
{
case
pc_command_codes
:
:
initialize
:
cmd_length
=
7
;
cmd_length
=
10
;
break
;
case
pc_command_codes
:
:
poll
:
cmd_length
=
6
;
cmd_length
=
9
;
break
;
default:
break
;
...
...
@@ -200,63 +264,70 @@ void process_command() {
//читаем команду
if
(
cmd_length
>
0
)
{
uint8_t
bytes_read
=
Serial
.
readBytes
(
cmd_buffer
,
cmd_length
);
//выполняем команду
if
(
bytes_read
==
cmd_length
)
{
switch
(
cmd_code
)
{
case
pc_command_codes
:
:
initialize
:
pc_poll_interval_sec
=
cmd_buffer
[
0
];
control_a
.
target_temperature
=
cmd_buffer
[
1
];
control_b
.
target_temperature
=
cmd_buffer
[
2
];
control_c
.
target_temperature
=
cmd_buffer
[
3
];
control_a
.
copy_from
=
cmd_buffer
[
4
];
control_b
.
copy_from
=
cmd_buffer
[
5
];
control_c
.
copy_from
=
cmd_buffer
[
6
];
initialized
=
true
;
response_buffer
[
0
]
=
arduino_response_codes
::
initialize_ok
;
response_length
=
1
;
break
;
case
pc_command_codes
:
:
poll
:
control_a
.
temperature
=
cmd_buffer
[
0
]
<<
8
|
cmd_buffer
[
1
];
control_b
.
temperature
=
cmd_buffer
[
2
]
<<
8
|
cmd_buffer
[
3
];
control_c
.
temperature
=
cmd_buffer
[
4
]
<<
8
|
cmd_buffer
[
5
];
if
(
initialized
)
response_buffer
[
0
]
=
arduino_response_codes
::
poll_ok
;
else
response_buffer
[
0
]
=
arduino_response_codes
::
poll_noinit
;
for
(
int
i
=
0
;
i
<
FAN_COUNT
;
i
++
){
uint16_t
rpm
=
get_avg_rpm
(
&
fans
[
i
]);
response_buffer
[
i
*
2
+
1
]
=
rpm
>>
8
;
response_buffer
[
i
*
2
+
2
]
=
rpm
&
0xff
;
}
response_buffer
[
13
]
=
OCR1A
;
response_buffer
[
14
]
=
OCR2A
;
response_buffer
[
15
]
=
OCR2B
;
response_length
=
16
;
break
;
default:
break
;
//принимаем оставшиемся байты
uint8_t
bytes_read
=
Serial
.
readBytes
(
&
cmd_buffer
[
1
],
cmd_length
-
1
);
if
(
bytes_read
==
cmd_length
-
1
)
{
uint16_t
cmd_crc16
=
cmd_buffer
[
cmd_length
-
2
]
<<
8
|
cmd_buffer
[
cmd_length
-
1
];
uint16_t
check_crc16
=
crc16_calc
(
cmd_buffer
,
cmd_length
-
2
);
if
(
cmd_crc16
==
check_crc16
)
{
//выполняем команду
switch
(
cmd_code
)
{
case
pc_command_codes
:
:
initialize
:
pc_poll_interval_sec
=
cmd_buffer
[
1
];
control_a
.
target_temperature
=
cmd_buffer
[
2
];
control_b
.
target_temperature
=
cmd_buffer
[
3
];
control_c
.
target_temperature
=
cmd_buffer
[
4
];
control_a
.
copy_from
=
cmd_buffer
[
5
];
control_b
.
copy_from
=
cmd_buffer
[
6
];
control_c
.
copy_from
=
cmd_buffer
[
7
];
initialized
=
true
;
response_buffer
[
0
]
=
arduino_response_codes
::
initialize_ok
;
response_length
=
1
;
break
;
case
pc_command_codes
:
:
poll
:
control_a
.
temperature
=
cmd_buffer
[
1
]
<<
8
|
cmd_buffer
[
2
];
control_b
.
temperature
=
cmd_buffer
[
3
]
<<
8
|
cmd_buffer
[
4
];
control_c
.
temperature
=
cmd_buffer
[
5
]
<<
8
|
cmd_buffer
[
6
];
if
(
initialized
)
response_buffer
[
0
]
=
arduino_response_codes
::
poll_ok
;
else
response_buffer
[
0
]
=
arduino_response_codes
::
poll_noinit
;
for
(
int
i
=
0
;
i
<
FAN_COUNT
;
i
++
){
uint16_t
rpm
=
get_avg_rpm
(
&
fans
[
i
]);
response_buffer
[
i
*
2
+
1
]
=
rpm
>>
8
;
response_buffer
[
i
*
2
+
2
]
=
rpm
&
0xff
;
}
response_buffer
[
13
]
=
OCR1A
;
response_buffer
[
14
]
=
OCR2A
;
response_buffer
[
15
]
=
OCR2B
;
response_length
=
16
;
response_length
=
add_crc
(
response_buffer
,
response_length
);
break
;
default:
break
;
}
last_poll_time
=
millis
();
pc_respond
=
true
;
}
}
last_poll_time
=
millis
();
pc_respond
=
true
;
}
while
(
Serial
.
available
())
// очистка буфера
Serial
.
read
();
//ответ
Serial
.
write
(
response_buffer
,
response_length
);
response_length
=
add_crc
(
response_buffer
,
response_length
);
Serial
.
write
(
response_buffer
,
response_length
);
//посылаем ответ
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment