Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
DC motor driver hat
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Software
DC motor driver hat
Commits
ed04c443
Commit
ed04c443
authored
7 months ago
by
Samuel Tardieu
Browse files
Options
Downloads
Patches
Plain Diff
Prefix commands with CMD_ in Python
parent
4ac285b7
No related branches found
No related tags found
1 merge request
!25
Prefix commands with CMD_ in Python
Pipeline
#98641
passed
7 months ago
Stage: check
Stage: build
Stage: test
Stage: deploy
Changes
1
Pipelines
2
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
controller/python/controller.py
+44
-43
44 additions, 43 deletions
controller/python/controller.py
with
44 additions
and
43 deletions
controller/python/controller.py
+
44
−
43
View file @
ed04c443
...
...
@@ -18,24 +18,24 @@ class Controller:
I2C_ADDR
=
0x57
FIRMWARE_VERSION
=
0x08
WHO_AM_I
=
0x0F
PWM_FREQUENCY
=
0x10
K_P
=
0x20
K_I
=
0x21
K_D
=
0x22
MOTOR_SHUTDOWN_TIMEOUT
=
0x28
RAW_MOTOR_SPEED
=
0x30
CONTROLLED_MOTOR_SPEED
=
0x31
ENCODER_TICKS
=
0x32
STATUS
=
0x36
RESET
=
0xE0
RESE
T_TO_BOOTLOADER
=
0xE1
DEVICE_ID
=
0xF0
DEVICE_FAMILY
=
0xF1
MCU_IDCODE
=
0xF2
FLASH_SIZE
=
0xF3
FIRMWARE_CAPABILITIES
=
0xFE
CMD_
FIRMWARE_VERSION
=
0x08
CMD_
WHO_AM_I
=
0x0F
CMD_
PWM_FREQUENCY
=
0x10
CMD_PID_
K_P
=
0x20
CMD_PID_
K_I
=
0x21
CMD_PID_
K_D
=
0x22
CMD_
MOTOR_SHUTDOWN_TIMEOUT
=
0x28
CMD_
RAW_MOTOR_SPEED
=
0x30
CMD_
CONTROLLED_MOTOR_SPEED
=
0x31
CMD_
ENCODER_TICKS
=
0x32
CMD_
STATUS
=
0x36
CMD_
RESET
=
0xE0
CMD_REBOO
T_TO_BOOTLOADER
=
0xE1
CMD_
DEVICE_ID
=
0xF0
CMD_
DEVICE_FAMILY
=
0xF1
CMD_
MCU_IDCODE
=
0xF2
CMD_
FLASH_SIZE
=
0xF3
CMD_
FIRMWARE_CAPABILITIES
=
0xFE
PID_COEFFICIENTS_FACTOR
=
1
<<
8
...
...
@@ -60,7 +60,7 @@ class Controller:
def
who_am_i
(
self
)
->
int
:
"""
Check that the motors controller board is present. This
should return the same value as Controller.I2C_ADDR.
"""
return
self
.
_read
(
self
.
WHO_AM_I
,
1
,
"
B
"
)[
0
]
return
self
.
_read
(
self
.
CMD_
WHO_AM_I
,
1
,
"
B
"
)[
0
]
def
check_who_am_i
(
self
):
"""
Check that the device answers to WHO_AM_I is correct.
"""
...
...
@@ -91,14 +91,14 @@ class Controller:
return
round
(
v
)
self
.
_write
(
self
.
RAW_MOTOR_SPEED
,
self
.
CMD_
RAW_MOTOR_SPEED
,
list
(
struct
.
pack
(
"
bb
"
,
convert
(
left
,
"
left
"
),
convert
(
right
,
"
right
"
))),
)
def
get_raw_motor_speed
(
self
)
->
Optional
[
tuple
[
int
,
int
]]:
"""
Get the left and right motor speed as a tuple, or None if in standby.
Each speed will be between -127 and 127.
"""
(
left
,
right
)
=
self
.
_read
(
self
.
RAW_MOTOR_SPEED
,
2
,
"
bb
"
)
(
left
,
right
)
=
self
.
_read
(
self
.
CMD_
RAW_MOTOR_SPEED
,
2
,
"
bb
"
)
return
(
left
,
right
)
if
left
!=
-
128
and
right
!=
-
128
else
None
def
set_motor_speed
(
self
,
left
:
int
,
right
:
int
):
...
...
@@ -113,7 +113,7 @@ class Controller:
return
v
self
.
_write
(
self
.
CONTROLLED_MOTOR_SPEED
,
self
.
CMD_
CONTROLLED_MOTOR_SPEED
,
list
(
struct
.
pack
(
"
<hh
"
,
check
(
left
,
"
left
"
),
check
(
right
,
"
right
"
))),
)
...
...
@@ -122,7 +122,7 @@ class Controller:
the speed has been set by the raw mode method or if the
motors have been put into standby mode. The speed is in
ticks by 100th of seconds.
"""
(
left
,
right
)
=
self
.
_read
(
self
.
CONTROLLED_MOTOR_SPEED
,
4
,
"
<hh
"
)
(
left
,
right
)
=
self
.
_read
(
self
.
CMD_
CONTROLLED_MOTOR_SPEED
,
4
,
"
<hh
"
)
return
(
left
,
right
)
if
left
!=
-
32768
else
None
def
standby
(
self
):
...
...
@@ -135,13 +135,13 @@ class Controller:
queried. The ticks must be retrieved before they overflow a 2
byte signed integer (-32768..32767) or the result will make no
sense. Return a pair with left and right data.
"""
return
self
.
_read
(
self
.
ENCODER_TICKS
,
4
,
"
hh
"
)
return
self
.
_read
(
self
.
CMD_
ENCODER_TICKS
,
4
,
"
hh
"
)
def
get_status
(
self
)
->
dict
[
str
,
bool
]:
"""
Return a dict with status fields:
-
"
moving
"
: True if at least one motor is moving, False otherwise
-
"
controlled
"
: True if the motors are in controlled mode, False otherwise
"""
(
status
,)
=
self
.
_read
(
self
.
STATUS
,
1
,
"
B
"
)
(
status
,)
=
self
.
_read
(
self
.
CMD_
STATUS
,
1
,
"
B
"
)
return
{
"
moving
"
:
(
status
&
1
)
!=
0
,
"
controlled
"
:
(
status
&
2
)
!=
0
}
def
set_motor_shutdown_timeout
(
self
,
duration
:
float
):
...
...
@@ -150,16 +150,16 @@ class Controller:
seconds, the maximum is 10 seconds.
"""
if
duration
<
0.1
or
duration
>
10.0
:
raise
ValueError
self
.
_write
(
self
.
MOTOR_SHUTDOWN_TIMEOUT
,
[
round
(
duration
*
10
)])
self
.
_write
(
self
.
CMD_
MOTOR_SHUTDOWN_TIMEOUT
,
[
round
(
duration
*
10
)])
def
get_motor_shutdown_timeout
(
self
)
->
float
:
"""
Get the duration in seconds after which the motors will shut down
if no valid command is received.
"""
return
self
.
_read
(
self
.
MOTOR_SHUTDOWN_TIMEOUT
,
1
,
"
B
"
)[
0
]
/
10
return
self
.
_read
(
self
.
CMD_
MOTOR_SHUTDOWN_TIMEOUT
,
1
,
"
B
"
)[
0
]
/
10
def
get_firmware_version
(
self
)
->
tuple
[
int
,
int
,
int
]:
"""
Get the firmware version (major, minor, patch).
"""
return
self
.
_read
(
self
.
FIRMWARE_VERSION
,
3
,
"
BBB
"
)
return
self
.
_read
(
self
.
CMD_
FIRMWARE_VERSION
,
3
,
"
BBB
"
)
def
check_firmware_version
(
self
):
"""
Check that the firmware uses a version compatible with this
...
...
@@ -189,31 +189,32 @@ class Controller:
if
freq
<
1
or
freq
>
100000
:
raise
ValueError
(
f
"
PWM frequency is out of [1, 100000] range:
{
freq
}
"
)
self
.
_write
(
self
.
PWM_FREQUENCY
,
[
freq
&
0xFF
,
(
freq
>>
8
)
&
0xFF
,
(
freq
>>
16
)
&
0xFF
]
self
.
CMD_PWM_FREQUENCY
,
[
freq
&
0xFF
,
(
freq
>>
8
)
&
0xFF
,
(
freq
>>
16
)
&
0xFF
],
)
def
get_pwm_frequency
(
self
):
"""
Return the PWM frequency in Hz.
"""
a
,
b
,
c
=
self
.
_read
(
self
.
PWM_FREQUENCY
,
3
,
"
BBB
"
)
a
,
b
,
c
=
self
.
_read
(
self
.
CMD_
PWM_FREQUENCY
,
3
,
"
BBB
"
)
return
a
|
(
b
<<
8
)
|
(
c
<<
16
)
def
reset
(
self
):
"""
Reset the device. Used mainly for testing.
"""
self
.
_write
(
self
.
RESET
,
[])
self
.
_write
(
self
.
CMD_
RESET
,
[])
def
reset_to_bootloader
(
self
):
"""
Reset the device to bootloader mode. Used for reprogramming.
"""
self
.
_write
(
self
.
RESE
T_TO_BOOTLOADER
,
[])
self
.
_write
(
self
.
CMD_REBOO
T_TO_BOOTLOADER
,
[])
def
get_device_id
(
self
):
"""
Return the 8 bytes composing the device id.
"""
return
list
(
self
.
_read
(
self
.
DEVICE_ID
,
8
,
"
BBBBBBBB
"
))
return
list
(
self
.
_read
(
self
.
CMD_
DEVICE_ID
,
8
,
"
BBBBBBBB
"
))
def
get_firmware_capabilities
(
self
)
->
dict
[
str
,
bool
]:
"""
Return a dict with capabilities fields:
-
"
bootloader
"
: True if the firmware runs under a bootloader, False otherwise.
"""
(
capabilities
,)
=
self
.
_read
(
self
.
FIRMWARE_CAPABILITIES
,
1
,
"
B
"
)
(
capabilities
,)
=
self
.
_read
(
self
.
CMD_
FIRMWARE_CAPABILITIES
,
1
,
"
B
"
)
return
{
"
bootloader
"
:
(
capabilities
&
1
)
!=
0
}
def
set_pid_coefficients
(
self
,
k_p
:
float
,
k_i
:
float
,
k_d
:
float
):
...
...
@@ -224,9 +225,9 @@ class Controller:
def
convert
(
v
):
return
round
(
v
*
self
.
PID_COEFFICIENTS_FACTOR
)
self
.
_write
(
self
.
K_P
,
list
(
struct
.
pack
(
"
<i
"
,
convert
(
k_p
))))
self
.
_write
(
self
.
K_I
,
list
(
struct
.
pack
(
"
<i
"
,
convert
(
k_i
))))
self
.
_write
(
self
.
K_D
,
list
(
struct
.
pack
(
"
<i
"
,
convert
(
k_d
))))
self
.
_write
(
self
.
CMD_PID_
K_P
,
list
(
struct
.
pack
(
"
<i
"
,
convert
(
k_p
))))
self
.
_write
(
self
.
CMD_PID_
K_I
,
list
(
struct
.
pack
(
"
<i
"
,
convert
(
k_i
))))
self
.
_write
(
self
.
CMD_PID_
K_D
,
list
(
struct
.
pack
(
"
<i
"
,
convert
(
k_d
))))
def
get_pid_coefficients
(
self
)
->
tuple
[
float
,
float
,
float
]:
"""
Get the PID coefficients used in the controlled mode.
"""
...
...
@@ -234,15 +235,15 @@ class Controller:
def
convert
(
v
):
return
v
/
self
.
PID_COEFFICIENTS_FACTOR
(
k_p
,)
=
self
.
_read
(
self
.
K_P
,
4
,
"
<i
"
)
(
k_i
,)
=
self
.
_read
(
self
.
K_I
,
4
,
"
<i
"
)
(
k_d
,)
=
self
.
_read
(
self
.
K_D
,
4
,
"
<i
"
)
(
k_p
,)
=
self
.
_read
(
self
.
CMD_PID_
K_P
,
4
,
"
<i
"
)
(
k_i
,)
=
self
.
_read
(
self
.
CMD_PID_
K_I
,
4
,
"
<i
"
)
(
k_d
,)
=
self
.
_read
(
self
.
CMD_PID_
K_D
,
4
,
"
<i
"
)
return
(
convert
(
k_p
),
convert
(
k_i
),
convert
(
k_d
))
def
get_device_family
(
self
)
->
Optional
[
tuple
[
int
,
int
]]:
"""
Return the microcontroller identity and continuation code
if they are read succesfully.
"""
(
id_code
,
continuation_code
)
=
self
.
_read
(
self
.
DEVICE_FAMILY
,
2
,
"
<BB
"
)
(
id_code
,
continuation_code
)
=
self
.
_read
(
self
.
CMD_
DEVICE_FAMILY
,
2
,
"
<BB
"
)
return
(
(
id_code
,
continuation_code
)
if
id_code
!=
0
or
continuation_code
!=
0
...
...
@@ -252,10 +253,10 @@ class Controller:
def
get_mcu_kind
(
self
)
->
tuple
[
int
,
int
]:
"""
Return the device id and revision id from the IDCODE field
of the DBGMCU register if they are read succesfully.
"""
(
dev_id
,
rev_id
)
=
self
.
_read
(
self
.
MCU_IDCODE
,
4
,
"
<HH
"
)
(
dev_id
,
rev_id
)
=
self
.
_read
(
self
.
CMD_
MCU_IDCODE
,
4
,
"
<HH
"
)
return
(
dev_id
,
rev_id
)
if
dev_id
!=
0
or
rev_id
!=
0
else
None
def
get_flash_size
(
self
)
->
int
:
"""
Return the flash size in kiB as declared by the microcontroller.
"""
(
flash_size
,)
=
self
.
_read
(
self
.
FLASH_SIZE
,
2
,
"
<H
"
)
(
flash_size
,)
=
self
.
_read
(
self
.
CMD_
FLASH_SIZE
,
2
,
"
<H
"
)
return
flash_size
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment