Compare commits
5 commits
main
...
process_ca
Author | SHA1 | Date | |
---|---|---|---|
4d6a5f8700 | |||
207b889fef | |||
e80f04d857 | |||
28ce1bb556 | |||
58a051b217 |
123 changed files with 1181241 additions and 1180998 deletions
80
.gitignore
vendored
80
.gitignore
vendored
|
@ -1,40 +1,40 @@
|
||||||
~$*.SLDPRT
|
~$*.SLDPRT
|
||||||
~$*.SLDASM
|
~$*.SLDASM
|
||||||
*.STL
|
*.STL
|
||||||
|
|
||||||
# For PCBs designed using KiCad: http://www.kicad-pcb.org/
|
# For PCBs designed using KiCad: http://www.kicad-pcb.org/
|
||||||
# Format documentation: http://kicad-pcb.org/help/file-formats/
|
# Format documentation: http://kicad-pcb.org/help/file-formats/
|
||||||
|
|
||||||
# Temporary files
|
# Temporary files
|
||||||
*-backups/
|
*-backups/
|
||||||
*.000
|
*.000
|
||||||
*.bak
|
*.bak
|
||||||
*.bck
|
*.bck
|
||||||
*.kicad_sch.lck
|
*.kicad_sch.lck
|
||||||
*.kicad_pcb-bak
|
*.kicad_pcb-bak
|
||||||
*.kicad_pcb.lck
|
*.kicad_pcb.lck
|
||||||
*#auto_saved_files#
|
*#auto_saved_files#
|
||||||
|
|
||||||
*~
|
*~
|
||||||
_autosave-*
|
_autosave-*
|
||||||
*.tmp
|
*.tmp
|
||||||
*-cache.lib
|
*-cache.lib
|
||||||
*-rescue.lib
|
*-rescue.lib
|
||||||
*-save.pro
|
*-save.pro
|
||||||
*-save.kicad_pcb
|
*-save.kicad_pcb
|
||||||
*.sch-bak
|
*.sch-bak
|
||||||
fp-info-cache
|
fp-info-cache
|
||||||
|
|
||||||
# Netlist files (exported from Eeschema)
|
# Netlist files (exported from Eeschema)
|
||||||
*.net
|
*.net
|
||||||
|
|
||||||
# Autorouter files (exported from Pcbnew)
|
# Autorouter files (exported from Pcbnew)
|
||||||
*.dsn
|
*.dsn
|
||||||
*.ses
|
*.ses
|
||||||
|
|
||||||
# Visual Studio Code
|
# Visual Studio Code
|
||||||
*.vscode/
|
*.vscode/
|
||||||
# Platformio .pio
|
# Platformio .pio
|
||||||
.pio/
|
.pio/
|
||||||
# JetBrains CLion
|
# JetBrains CLion
|
||||||
.idea/
|
.idea/
|
||||||
|
|
164
.gitlab-ci.yml
164
.gitlab-ci.yml
|
@ -1,82 +1,82 @@
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- gen_fabrication_files
|
- gen_fabrication_files
|
||||||
|
|
||||||
### Build firmware with PlatformIO
|
### Build firmware with PlatformIO
|
||||||
|
|
||||||
build_firmware:
|
build_firmware:
|
||||||
stage: gen_fabrication_files
|
stage: gen_fabrication_files
|
||||||
image: python:3.9
|
image: python:3.9
|
||||||
rules:
|
rules:
|
||||||
- changes:
|
- changes:
|
||||||
- "controller/fw/*"
|
- "controller/fw/*"
|
||||||
- ".gitlab-ci.yml"
|
- ".gitlab-ci.yml"
|
||||||
when: on_success
|
when: on_success
|
||||||
before_script:
|
before_script:
|
||||||
- cd controller/fw/embed
|
- cd controller/fw/embed
|
||||||
- pip install -U platformio
|
- pip install -U platformio
|
||||||
- pio update
|
- pio update
|
||||||
script:
|
script:
|
||||||
- pwd
|
- pwd
|
||||||
- pio run
|
- pio run
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- controller/fw/embed/.pio/build/robotroller_reborn/firmware.elf
|
- controller/fw/embed/.pio/build/robotroller_reborn/firmware.elf
|
||||||
- controller/fw/embed/.pio/build/robotroller_reborn/firmware.bin
|
- controller/fw/embed/.pio/build/robotroller_reborn/firmware.bin
|
||||||
expire_in: 1 week
|
expire_in: 1 week
|
||||||
|
|
||||||
lint_firmware:
|
lint_firmware:
|
||||||
stage: gen_fabrication_files
|
stage: gen_fabrication_files
|
||||||
image: python:3.9
|
image: python:3.9
|
||||||
rules:
|
rules:
|
||||||
- changes:
|
- changes:
|
||||||
- "controller/fw/*"
|
- "controller/fw/*"
|
||||||
- ".gitlab-ci.yml"
|
- ".gitlab-ci.yml"
|
||||||
when: on_success
|
when: on_success
|
||||||
before_script:
|
before_script:
|
||||||
- cd controller/fw/embed/
|
- cd controller/fw/embed/
|
||||||
- pip install cpplint
|
- pip install cpplint
|
||||||
script:
|
script:
|
||||||
- pwd
|
- pwd
|
||||||
- cpplint --extensions=h,hpp,cpp --recursive --linelength=120 --filter=-build/include_subdir,-legal/copyright --output=vs7 src include test lib
|
- cpplint --extensions=h,hpp,cpp --recursive --linelength=120 --filter=-build/include_subdir,-legal/copyright --output=vs7 src include test lib
|
||||||
|
|
||||||
### Gitlab CI/CD example for KiCad
|
### Gitlab CI/CD example for KiCad
|
||||||
|
|
||||||
# workflow:
|
# workflow:
|
||||||
# rules:
|
# rules:
|
||||||
# - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
# - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
|
||||||
# - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
# - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
SCHEMATICS: "true"
|
SCHEMATICS: "true"
|
||||||
GIT_DEPTH: 1
|
GIT_DEPTH: 1
|
||||||
|
|
||||||
clone:
|
clone:
|
||||||
stage: .pre
|
stage: .pre
|
||||||
script:
|
script:
|
||||||
- echo "Git repo pre-fetching"
|
- echo "Git repo pre-fetching"
|
||||||
|
|
||||||
.kicad-pipeline:
|
.kicad-pipeline:
|
||||||
stage: gen_fabrication_files
|
stage: gen_fabrication_files
|
||||||
trigger:
|
trigger:
|
||||||
include:
|
include:
|
||||||
- remote: 'https://gitlab.com/robossembler/roboarm-diy-version/-/raw/a200bcad9708b65b51f54da9ed426d2233308b84/.kicad-pipeline.yml'
|
- remote: 'https://gitlab.com/robossembler/roboarm-diy-version/-/raw/a200bcad9708b65b51f54da9ed426d2233308b84/.kicad-pipeline.yml'
|
||||||
strategy: depend
|
strategy: depend
|
||||||
rules: !reference [.default_rules, rules]
|
rules: !reference [.default_rules, rules]
|
||||||
|
|
||||||
.default_rules:
|
.default_rules:
|
||||||
rules:
|
rules:
|
||||||
- changes:
|
- changes:
|
||||||
- "${FOLDER}/*"
|
- "${FOLDER}/*"
|
||||||
- ".gitlab-ci.yml"
|
- ".gitlab-ci.yml"
|
||||||
when: on_success
|
when: on_success
|
||||||
|
|
||||||
# Boards for building
|
# Boards for building
|
||||||
# !!! PACKAGE NAMES SHOULD BE WITHOUT SPACES !!!
|
# !!! PACKAGE NAMES SHOULD BE WITHOUT SPACES !!!
|
||||||
|
|
||||||
Robotroller-PCB:
|
Robotroller-PCB:
|
||||||
variables:
|
variables:
|
||||||
PACKAGE_NAME: 'Robotroller-PCB'
|
PACKAGE_NAME: 'Robotroller-PCB'
|
||||||
FOLDER: 'controller/hw'
|
FOLDER: 'controller/hw'
|
||||||
PROJECT_NAME: 'motor_controller_50mm'
|
PROJECT_NAME: 'motor_controller_50mm'
|
||||||
extends: .kicad-pipeline
|
extends: .kicad-pipeline
|
||||||
|
|
104
CHANGELOG.md
104
CHANGELOG.md
|
@ -1,52 +1,52 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||||
|
|
||||||
## [0.1.0] 70mm Servo - 2024-06-19
|
## [0.1.0] 70mm Servo - 2024-06-19
|
||||||
|
|
||||||
Изменения в конструкции 70 мм. двигателей
|
Изменения в конструкции 70 мм. двигателей
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
Добавлены модификации двигателей для металлического магнитопровода
|
Добавлены модификации двигателей для металлического магнитопровода
|
||||||
1. на 2 элементах статора добавены лучи, препятствующие перетиранию провода о металл сердечника
|
1. на 2 элементах статора добавены лучи, препятствующие перетиранию провода о металл сердечника
|
||||||
2. Поправлены размер фиксатора крышки мотора статора.
|
2. Поправлены размер фиксатора крышки мотора статора.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
Ротор 70 мм
|
Ротор 70 мм
|
||||||
1. Изменены размеры отверстий под установку магнитов
|
1. Изменены размеры отверстий под установку магнитов
|
||||||
2. Изменён крепеж вала ротора к подшипнику
|
2. Изменён крепеж вала ротора к подшипнику
|
||||||
3. Увеличены вентиляционные лопатки
|
3. Увеличены вентиляционные лопатки
|
||||||
4. Увеличен диаметр отверстия для установки магнита датчика угла
|
4. Увеличен диаметр отверстия для установки магнита датчика угла
|
||||||
5. Изменена верхняя крышка для улучшения процесса печати
|
5. Изменена верхняя крышка для улучшения процесса печати
|
||||||
6. Уменьшены фиксирующие магниты пластины для уменьшения вероятности трения ротора о статор
|
6. Уменьшены фиксирующие магниты пластины для уменьшения вероятности трения ротора о статор
|
||||||
7. Увеличена толщина стенок для получения более жесткой конструкции
|
7. Увеличена толщина стенок для получения более жесткой конструкции
|
||||||
|
|
||||||
Статор 70 мм
|
Статор 70 мм
|
||||||
1. Изменена форма щёчек катушек для улучшения процесса печати
|
1. Изменена форма щёчек катушек для улучшения процесса печати
|
||||||
2. Добавлено отверстие для крепления провода (концов звезды в соответствующей схеме подключения)
|
2. Добавлено отверстие для крепления провода (концов звезды в соответствующей схеме подключения)
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
## [0.4.0] PCB Controller - 2024-03-24
|
## [0.4.0] PCB Controller - 2024-03-24
|
||||||
|
|
||||||
Новая версия печатной платы контроллера двигателя.
|
Новая версия печатной платы контроллера двигателя.
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Добавлен датчик температуры.
|
- Добавлен датчик температуры.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Убраны несколько деталей, изменена трассировка значительной части проводящего слоя платы.
|
- Убраны несколько деталей, изменена трассировка значительной части проводящего слоя платы.
|
||||||
- Перенесены на верхнюю сторону все компоненты за исключением датчика угла и измерительных резисторов.
|
- Перенесены на верхнюю сторону все компоненты за исключением датчика угла и измерительных резисторов.
|
||||||
- Изменено посадочное место под дроссель.
|
- Изменено посадочное место под дроссель.
|
||||||
- Систематизированы наименования деталей.
|
- Систематизированы наименования деталей.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
- Улучшено прохождение земель и питания.
|
- Улучшено прохождение земель и питания.
|
||||||
- Поправлена шелкография.
|
- Поправлена шелкография.
|
||||||
|
|
580
LICENSE
580
LICENSE
|
@ -1,290 +1,290 @@
|
||||||
Copyright © 2015-2021, Stanislav Sgonov (stasjok@mail.ru)
|
Copyright © 2015-2021, Stanislav Sgonov (stasjok@mail.ru)
|
||||||
|
|
||||||
CERN Open Hardware Licence Version 2 - Strongly Reciprocal
|
CERN Open Hardware Licence Version 2 - Strongly Reciprocal
|
||||||
|
|
||||||
Preamble
|
Preamble
|
||||||
|
|
||||||
CERN has developed this licence to promote collaboration among
|
CERN has developed this licence to promote collaboration among
|
||||||
hardware designers and to provide a legal tool which supports the
|
hardware designers and to provide a legal tool which supports the
|
||||||
freedom to use, study, modify, share and distribute hardware designs
|
freedom to use, study, modify, share and distribute hardware designs
|
||||||
and products based on those designs. Version 2 of the CERN Open
|
and products based on those designs. Version 2 of the CERN Open
|
||||||
Hardware Licence comes in three variants: CERN-OHL-P (permissive); and
|
Hardware Licence comes in three variants: CERN-OHL-P (permissive); and
|
||||||
two reciprocal licences: CERN-OHL-W (weakly reciprocal) and this
|
two reciprocal licences: CERN-OHL-W (weakly reciprocal) and this
|
||||||
licence, CERN-OHL-S (strongly reciprocal).
|
licence, CERN-OHL-S (strongly reciprocal).
|
||||||
|
|
||||||
The CERN-OHL-S is copyright CERN 2020. Anyone is welcome to use it, in
|
The CERN-OHL-S is copyright CERN 2020. Anyone is welcome to use it, in
|
||||||
unmodified form only.
|
unmodified form only.
|
||||||
|
|
||||||
Use of this Licence does not imply any endorsement by CERN of any
|
Use of this Licence does not imply any endorsement by CERN of any
|
||||||
Licensor or their designs nor does it imply any involvement by CERN in
|
Licensor or their designs nor does it imply any involvement by CERN in
|
||||||
their development.
|
their development.
|
||||||
|
|
||||||
|
|
||||||
1 Definitions
|
1 Definitions
|
||||||
|
|
||||||
1.1 'Licence' means this CERN-OHL-S.
|
1.1 'Licence' means this CERN-OHL-S.
|
||||||
|
|
||||||
1.2 'Compatible Licence' means
|
1.2 'Compatible Licence' means
|
||||||
|
|
||||||
a) any earlier version of the CERN Open Hardware licence, or
|
a) any earlier version of the CERN Open Hardware licence, or
|
||||||
|
|
||||||
b) any version of the CERN-OHL-S, or
|
b) any version of the CERN-OHL-S, or
|
||||||
|
|
||||||
c) any licence which permits You to treat the Source to which
|
c) any licence which permits You to treat the Source to which
|
||||||
it applies as licensed under CERN-OHL-S provided that on
|
it applies as licensed under CERN-OHL-S provided that on
|
||||||
Conveyance of any such Source, or any associated Product You
|
Conveyance of any such Source, or any associated Product You
|
||||||
treat the Source in question as being licensed under
|
treat the Source in question as being licensed under
|
||||||
CERN-OHL-S.
|
CERN-OHL-S.
|
||||||
|
|
||||||
1.3 'Source' means information such as design materials or digital
|
1.3 'Source' means information such as design materials or digital
|
||||||
code which can be applied to Make or test a Product or to
|
code which can be applied to Make or test a Product or to
|
||||||
prepare a Product for use, Conveyance or sale, regardless of its
|
prepare a Product for use, Conveyance or sale, regardless of its
|
||||||
medium or how it is expressed. It may include Notices.
|
medium or how it is expressed. It may include Notices.
|
||||||
|
|
||||||
1.4 'Covered Source' means Source that is explicitly made available
|
1.4 'Covered Source' means Source that is explicitly made available
|
||||||
under this Licence.
|
under this Licence.
|
||||||
|
|
||||||
1.5 'Product' means any device, component, work or physical object,
|
1.5 'Product' means any device, component, work or physical object,
|
||||||
whether in finished or intermediate form, arising from the use,
|
whether in finished or intermediate form, arising from the use,
|
||||||
application or processing of Covered Source.
|
application or processing of Covered Source.
|
||||||
|
|
||||||
1.6 'Make' means to create or configure something, whether by
|
1.6 'Make' means to create or configure something, whether by
|
||||||
manufacture, assembly, compiling, loading or applying Covered
|
manufacture, assembly, compiling, loading or applying Covered
|
||||||
Source or another Product or otherwise.
|
Source or another Product or otherwise.
|
||||||
|
|
||||||
1.7 'Available Component' means any part, sub-assembly, library or
|
1.7 'Available Component' means any part, sub-assembly, library or
|
||||||
code which:
|
code which:
|
||||||
|
|
||||||
a) is licensed to You as Complete Source under a Compatible
|
a) is licensed to You as Complete Source under a Compatible
|
||||||
Licence; or
|
Licence; or
|
||||||
|
|
||||||
b) is available, at the time a Product or the Source containing
|
b) is available, at the time a Product or the Source containing
|
||||||
it is first Conveyed, to You and any other prospective
|
it is first Conveyed, to You and any other prospective
|
||||||
licensees
|
licensees
|
||||||
|
|
||||||
i) as a physical part with sufficient rights and
|
i) as a physical part with sufficient rights and
|
||||||
information (including any configuration and
|
information (including any configuration and
|
||||||
programming files and information about its
|
programming files and information about its
|
||||||
characteristics and interfaces) to enable it either to
|
characteristics and interfaces) to enable it either to
|
||||||
be Made itself, or to be sourced and used to Make the
|
be Made itself, or to be sourced and used to Make the
|
||||||
Product; or
|
Product; or
|
||||||
ii) as part of the normal distribution of a tool used to
|
ii) as part of the normal distribution of a tool used to
|
||||||
design or Make the Product.
|
design or Make the Product.
|
||||||
|
|
||||||
1.8 'Complete Source' means the set of all Source necessary to Make
|
1.8 'Complete Source' means the set of all Source necessary to Make
|
||||||
a Product, in the preferred form for making modifications,
|
a Product, in the preferred form for making modifications,
|
||||||
including necessary installation and interfacing information
|
including necessary installation and interfacing information
|
||||||
both for the Product, and for any included Available Components.
|
both for the Product, and for any included Available Components.
|
||||||
If the format is proprietary, it must also be made available in
|
If the format is proprietary, it must also be made available in
|
||||||
a format (if the proprietary tool can create it) which is
|
a format (if the proprietary tool can create it) which is
|
||||||
viewable with a tool available to potential licensees and
|
viewable with a tool available to potential licensees and
|
||||||
licensed under a licence approved by the Free Software
|
licensed under a licence approved by the Free Software
|
||||||
Foundation or the Open Source Initiative. Complete Source need
|
Foundation or the Open Source Initiative. Complete Source need
|
||||||
not include the Source of any Available Component, provided that
|
not include the Source of any Available Component, provided that
|
||||||
You include in the Complete Source sufficient information to
|
You include in the Complete Source sufficient information to
|
||||||
enable a recipient to Make or source and use the Available
|
enable a recipient to Make or source and use the Available
|
||||||
Component to Make the Product.
|
Component to Make the Product.
|
||||||
|
|
||||||
1.9 'Source Location' means a location where a Licensor has placed
|
1.9 'Source Location' means a location where a Licensor has placed
|
||||||
Covered Source, and which that Licensor reasonably believes will
|
Covered Source, and which that Licensor reasonably believes will
|
||||||
remain easily accessible for at least three years for anyone to
|
remain easily accessible for at least three years for anyone to
|
||||||
obtain a digital copy.
|
obtain a digital copy.
|
||||||
|
|
||||||
1.10 'Notice' means copyright, acknowledgement and trademark notices,
|
1.10 'Notice' means copyright, acknowledgement and trademark notices,
|
||||||
Source Location references, modification notices (subsection
|
Source Location references, modification notices (subsection
|
||||||
3.3(b)) and all notices that refer to this Licence and to the
|
3.3(b)) and all notices that refer to this Licence and to the
|
||||||
disclaimer of warranties that are included in the Covered
|
disclaimer of warranties that are included in the Covered
|
||||||
Source.
|
Source.
|
||||||
|
|
||||||
1.11 'Licensee' or 'You' means any person exercising rights under
|
1.11 'Licensee' or 'You' means any person exercising rights under
|
||||||
this Licence.
|
this Licence.
|
||||||
|
|
||||||
1.12 'Licensor' means a natural or legal person who creates or
|
1.12 'Licensor' means a natural or legal person who creates or
|
||||||
modifies Covered Source. A person may be a Licensee and a
|
modifies Covered Source. A person may be a Licensee and a
|
||||||
Licensor at the same time.
|
Licensor at the same time.
|
||||||
|
|
||||||
1.13 'Convey' means to communicate to the public or distribute.
|
1.13 'Convey' means to communicate to the public or distribute.
|
||||||
|
|
||||||
|
|
||||||
2 Applicability
|
2 Applicability
|
||||||
|
|
||||||
2.1 This Licence governs the use, copying, modification, Conveying
|
2.1 This Licence governs the use, copying, modification, Conveying
|
||||||
of Covered Source and Products, and the Making of Products. By
|
of Covered Source and Products, and the Making of Products. By
|
||||||
exercising any right granted under this Licence, You irrevocably
|
exercising any right granted under this Licence, You irrevocably
|
||||||
accept these terms and conditions.
|
accept these terms and conditions.
|
||||||
|
|
||||||
2.2 This Licence is granted by the Licensor directly to You, and
|
2.2 This Licence is granted by the Licensor directly to You, and
|
||||||
shall apply worldwide and without limitation in time.
|
shall apply worldwide and without limitation in time.
|
||||||
|
|
||||||
2.3 You shall not attempt to restrict by contract or otherwise the
|
2.3 You shall not attempt to restrict by contract or otherwise the
|
||||||
rights granted under this Licence to other Licensees.
|
rights granted under this Licence to other Licensees.
|
||||||
|
|
||||||
2.4 This Licence is not intended to restrict fair use, fair dealing,
|
2.4 This Licence is not intended to restrict fair use, fair dealing,
|
||||||
or any other similar right.
|
or any other similar right.
|
||||||
|
|
||||||
|
|
||||||
3 Copying, Modifying and Conveying Covered Source
|
3 Copying, Modifying and Conveying Covered Source
|
||||||
|
|
||||||
3.1 You may copy and Convey verbatim copies of Covered Source, in
|
3.1 You may copy and Convey verbatim copies of Covered Source, in
|
||||||
any medium, provided You retain all Notices.
|
any medium, provided You retain all Notices.
|
||||||
|
|
||||||
3.2 You may modify Covered Source, other than Notices, provided that
|
3.2 You may modify Covered Source, other than Notices, provided that
|
||||||
You irrevocably undertake to make that modified Covered Source
|
You irrevocably undertake to make that modified Covered Source
|
||||||
available from a Source Location should You Convey a Product in
|
available from a Source Location should You Convey a Product in
|
||||||
circumstances where the recipient does not otherwise receive a
|
circumstances where the recipient does not otherwise receive a
|
||||||
copy of the modified Covered Source. In each case subsection 3.3
|
copy of the modified Covered Source. In each case subsection 3.3
|
||||||
shall apply.
|
shall apply.
|
||||||
|
|
||||||
You may only delete Notices if they are no longer applicable to
|
You may only delete Notices if they are no longer applicable to
|
||||||
the corresponding Covered Source as modified by You and You may
|
the corresponding Covered Source as modified by You and You may
|
||||||
add additional Notices applicable to Your modifications.
|
add additional Notices applicable to Your modifications.
|
||||||
Including Covered Source in a larger work is modifying the
|
Including Covered Source in a larger work is modifying the
|
||||||
Covered Source, and the larger work becomes modified Covered
|
Covered Source, and the larger work becomes modified Covered
|
||||||
Source.
|
Source.
|
||||||
|
|
||||||
3.3 You may Convey modified Covered Source (with the effect that You
|
3.3 You may Convey modified Covered Source (with the effect that You
|
||||||
shall also become a Licensor) provided that You:
|
shall also become a Licensor) provided that You:
|
||||||
|
|
||||||
a) retain Notices as required in subsection 3.2;
|
a) retain Notices as required in subsection 3.2;
|
||||||
|
|
||||||
b) add a Notice to the modified Covered Source stating that You
|
b) add a Notice to the modified Covered Source stating that You
|
||||||
have modified it, with the date and brief description of how
|
have modified it, with the date and brief description of how
|
||||||
You have modified it;
|
You have modified it;
|
||||||
|
|
||||||
c) add a Source Location Notice for the modified Covered Source
|
c) add a Source Location Notice for the modified Covered Source
|
||||||
if You Convey in circumstances where the recipient does not
|
if You Convey in circumstances where the recipient does not
|
||||||
otherwise receive a copy of the modified Covered Source; and
|
otherwise receive a copy of the modified Covered Source; and
|
||||||
|
|
||||||
d) license the modified Covered Source under the terms and
|
d) license the modified Covered Source under the terms and
|
||||||
conditions of this Licence (or, as set out in subsection
|
conditions of this Licence (or, as set out in subsection
|
||||||
8.3, a later version, if permitted by the licence of the
|
8.3, a later version, if permitted by the licence of the
|
||||||
original Covered Source). Such modified Covered Source must
|
original Covered Source). Such modified Covered Source must
|
||||||
be licensed as a whole, but excluding Available Components
|
be licensed as a whole, but excluding Available Components
|
||||||
contained in it, which remain licensed under their own
|
contained in it, which remain licensed under their own
|
||||||
applicable licences.
|
applicable licences.
|
||||||
|
|
||||||
|
|
||||||
4 Making and Conveying Products
|
4 Making and Conveying Products
|
||||||
|
|
||||||
You may Make Products, and/or Convey them, provided that You either
|
You may Make Products, and/or Convey them, provided that You either
|
||||||
provide each recipient with a copy of the Complete Source or ensure
|
provide each recipient with a copy of the Complete Source or ensure
|
||||||
that each recipient is notified of the Source Location of the Complete
|
that each recipient is notified of the Source Location of the Complete
|
||||||
Source. That Complete Source is Covered Source, and You must
|
Source. That Complete Source is Covered Source, and You must
|
||||||
accordingly satisfy Your obligations set out in subsection 3.3. If
|
accordingly satisfy Your obligations set out in subsection 3.3. If
|
||||||
specified in a Notice, the Product must visibly and securely display
|
specified in a Notice, the Product must visibly and securely display
|
||||||
the Source Location on it or its packaging or documentation in the
|
the Source Location on it or its packaging or documentation in the
|
||||||
manner specified in that Notice.
|
manner specified in that Notice.
|
||||||
|
|
||||||
|
|
||||||
5 Research and Development
|
5 Research and Development
|
||||||
|
|
||||||
You may Convey Covered Source, modified Covered Source or Products to
|
You may Convey Covered Source, modified Covered Source or Products to
|
||||||
a legal entity carrying out development, testing or quality assurance
|
a legal entity carrying out development, testing or quality assurance
|
||||||
work on Your behalf provided that the work is performed on terms which
|
work on Your behalf provided that the work is performed on terms which
|
||||||
prevent the entity from both using the Source or Products for its own
|
prevent the entity from both using the Source or Products for its own
|
||||||
internal purposes and Conveying the Source or Products or any
|
internal purposes and Conveying the Source or Products or any
|
||||||
modifications to them to any person other than You. Any modifications
|
modifications to them to any person other than You. Any modifications
|
||||||
made by the entity shall be deemed to be made by You pursuant to
|
made by the entity shall be deemed to be made by You pursuant to
|
||||||
subsection 3.2.
|
subsection 3.2.
|
||||||
|
|
||||||
|
|
||||||
6 DISCLAIMER AND LIABILITY
|
6 DISCLAIMER AND LIABILITY
|
||||||
|
|
||||||
6.1 DISCLAIMER OF WARRANTY -- The Covered Source and any Products
|
6.1 DISCLAIMER OF WARRANTY -- The Covered Source and any Products
|
||||||
are provided 'as is' and any express or implied warranties,
|
are provided 'as is' and any express or implied warranties,
|
||||||
including, but not limited to, implied warranties of
|
including, but not limited to, implied warranties of
|
||||||
merchantability, of satisfactory quality, non-infringement of
|
merchantability, of satisfactory quality, non-infringement of
|
||||||
third party rights, and fitness for a particular purpose or use
|
third party rights, and fitness for a particular purpose or use
|
||||||
are disclaimed in respect of any Source or Product to the
|
are disclaimed in respect of any Source or Product to the
|
||||||
maximum extent permitted by law. The Licensor makes no
|
maximum extent permitted by law. The Licensor makes no
|
||||||
representation that any Source or Product does not or will not
|
representation that any Source or Product does not or will not
|
||||||
infringe any patent, copyright, trade secret or other
|
infringe any patent, copyright, trade secret or other
|
||||||
proprietary right. The entire risk as to the use, quality, and
|
proprietary right. The entire risk as to the use, quality, and
|
||||||
performance of any Source or Product shall be with You and not
|
performance of any Source or Product shall be with You and not
|
||||||
the Licensor. This disclaimer of warranty is an essential part
|
the Licensor. This disclaimer of warranty is an essential part
|
||||||
of this Licence and a condition for the grant of any rights
|
of this Licence and a condition for the grant of any rights
|
||||||
granted under this Licence.
|
granted under this Licence.
|
||||||
|
|
||||||
6.2 EXCLUSION AND LIMITATION OF LIABILITY -- The Licensor shall, to
|
6.2 EXCLUSION AND LIMITATION OF LIABILITY -- The Licensor shall, to
|
||||||
the maximum extent permitted by law, have no liability for
|
the maximum extent permitted by law, have no liability for
|
||||||
direct, indirect, special, incidental, consequential, exemplary,
|
direct, indirect, special, incidental, consequential, exemplary,
|
||||||
punitive or other damages of any character including, without
|
punitive or other damages of any character including, without
|
||||||
limitation, procurement of substitute goods or services, loss of
|
limitation, procurement of substitute goods or services, loss of
|
||||||
use, data or profits, or business interruption, however caused
|
use, data or profits, or business interruption, however caused
|
||||||
and on any theory of contract, warranty, tort (including
|
and on any theory of contract, warranty, tort (including
|
||||||
negligence), product liability or otherwise, arising in any way
|
negligence), product liability or otherwise, arising in any way
|
||||||
in relation to the Covered Source, modified Covered Source
|
in relation to the Covered Source, modified Covered Source
|
||||||
and/or the Making or Conveyance of a Product, even if advised of
|
and/or the Making or Conveyance of a Product, even if advised of
|
||||||
the possibility of such damages, and You shall hold the
|
the possibility of such damages, and You shall hold the
|
||||||
Licensor(s) free and harmless from any liability, costs,
|
Licensor(s) free and harmless from any liability, costs,
|
||||||
damages, fees and expenses, including claims by third parties,
|
damages, fees and expenses, including claims by third parties,
|
||||||
in relation to such use.
|
in relation to such use.
|
||||||
|
|
||||||
|
|
||||||
7 Patents
|
7 Patents
|
||||||
|
|
||||||
7.1 Subject to the terms and conditions of this Licence, each
|
7.1 Subject to the terms and conditions of this Licence, each
|
||||||
Licensor hereby grants to You a perpetual, worldwide,
|
Licensor hereby grants to You a perpetual, worldwide,
|
||||||
non-exclusive, no-charge, royalty-free, irrevocable (except as
|
non-exclusive, no-charge, royalty-free, irrevocable (except as
|
||||||
stated in subsections 7.2 and 8.4) patent licence to Make, have
|
stated in subsections 7.2 and 8.4) patent licence to Make, have
|
||||||
Made, use, offer to sell, sell, import, and otherwise transfer
|
Made, use, offer to sell, sell, import, and otherwise transfer
|
||||||
the Covered Source and Products, where such licence applies only
|
the Covered Source and Products, where such licence applies only
|
||||||
to those patent claims licensable by such Licensor that are
|
to those patent claims licensable by such Licensor that are
|
||||||
necessarily infringed by exercising rights under the Covered
|
necessarily infringed by exercising rights under the Covered
|
||||||
Source as Conveyed by that Licensor.
|
Source as Conveyed by that Licensor.
|
||||||
|
|
||||||
7.2 If You institute patent litigation against any entity (including
|
7.2 If You institute patent litigation against any entity (including
|
||||||
a cross-claim or counterclaim in a lawsuit) alleging that the
|
a cross-claim or counterclaim in a lawsuit) alleging that the
|
||||||
Covered Source or a Product constitutes direct or contributory
|
Covered Source or a Product constitutes direct or contributory
|
||||||
patent infringement, or You seek any declaration that a patent
|
patent infringement, or You seek any declaration that a patent
|
||||||
licensed to You under this Licence is invalid or unenforceable
|
licensed to You under this Licence is invalid or unenforceable
|
||||||
then any rights granted to You under this Licence shall
|
then any rights granted to You under this Licence shall
|
||||||
terminate as of the date such process is initiated.
|
terminate as of the date such process is initiated.
|
||||||
|
|
||||||
|
|
||||||
8 General
|
8 General
|
||||||
|
|
||||||
8.1 If any provisions of this Licence are or subsequently become
|
8.1 If any provisions of this Licence are or subsequently become
|
||||||
invalid or unenforceable for any reason, the remaining
|
invalid or unenforceable for any reason, the remaining
|
||||||
provisions shall remain effective.
|
provisions shall remain effective.
|
||||||
|
|
||||||
8.2 You shall not use any of the name (including acronyms and
|
8.2 You shall not use any of the name (including acronyms and
|
||||||
abbreviations), image, or logo by which the Licensor or CERN is
|
abbreviations), image, or logo by which the Licensor or CERN is
|
||||||
known, except where needed to comply with section 3, or where
|
known, except where needed to comply with section 3, or where
|
||||||
the use is otherwise allowed by law. Any such permitted use
|
the use is otherwise allowed by law. Any such permitted use
|
||||||
shall be factual and shall not be made so as to suggest any kind
|
shall be factual and shall not be made so as to suggest any kind
|
||||||
of endorsement or implication of involvement by the Licensor or
|
of endorsement or implication of involvement by the Licensor or
|
||||||
its personnel.
|
its personnel.
|
||||||
|
|
||||||
8.3 CERN may publish updated versions and variants of this Licence
|
8.3 CERN may publish updated versions and variants of this Licence
|
||||||
which it considers to be in the spirit of this version, but may
|
which it considers to be in the spirit of this version, but may
|
||||||
differ in detail to address new problems or concerns. New
|
differ in detail to address new problems or concerns. New
|
||||||
versions will be published with a unique version number and a
|
versions will be published with a unique version number and a
|
||||||
variant identifier specifying the variant. If the Licensor has
|
variant identifier specifying the variant. If the Licensor has
|
||||||
specified that a given variant applies to the Covered Source
|
specified that a given variant applies to the Covered Source
|
||||||
without specifying a version, You may treat that Covered Source
|
without specifying a version, You may treat that Covered Source
|
||||||
as being released under any version of the CERN-OHL with that
|
as being released under any version of the CERN-OHL with that
|
||||||
variant. If no variant is specified, the Covered Source shall be
|
variant. If no variant is specified, the Covered Source shall be
|
||||||
treated as being released under CERN-OHL-S. The Licensor may
|
treated as being released under CERN-OHL-S. The Licensor may
|
||||||
also specify that the Covered Source is subject to a specific
|
also specify that the Covered Source is subject to a specific
|
||||||
version of the CERN-OHL or any later version in which case You
|
version of the CERN-OHL or any later version in which case You
|
||||||
may apply this or any later version of CERN-OHL with the same
|
may apply this or any later version of CERN-OHL with the same
|
||||||
variant identifier published by CERN.
|
variant identifier published by CERN.
|
||||||
|
|
||||||
8.4 This Licence shall terminate with immediate effect if You fail
|
8.4 This Licence shall terminate with immediate effect if You fail
|
||||||
to comply with any of its terms and conditions.
|
to comply with any of its terms and conditions.
|
||||||
|
|
||||||
8.5 However, if You cease all breaches of this Licence, then Your
|
8.5 However, if You cease all breaches of this Licence, then Your
|
||||||
Licence from any Licensor is reinstated unless such Licensor has
|
Licence from any Licensor is reinstated unless such Licensor has
|
||||||
terminated this Licence by giving You, while You remain in
|
terminated this Licence by giving You, while You remain in
|
||||||
breach, a notice specifying the breach and requiring You to cure
|
breach, a notice specifying the breach and requiring You to cure
|
||||||
it within 30 days, and You have failed to come into compliance
|
it within 30 days, and You have failed to come into compliance
|
||||||
in all material respects by the end of the 30 day period. Should
|
in all material respects by the end of the 30 day period. Should
|
||||||
You repeat the breach after receipt of a cure notice and
|
You repeat the breach after receipt of a cure notice and
|
||||||
subsequent reinstatement, this Licence will terminate
|
subsequent reinstatement, this Licence will terminate
|
||||||
immediately and permanently. Section 6 shall continue to apply
|
immediately and permanently. Section 6 shall continue to apply
|
||||||
after any termination.
|
after any termination.
|
||||||
|
|
||||||
8.6 This Licence shall not be enforceable except by a Licensor
|
8.6 This Licence shall not be enforceable except by a Licensor
|
||||||
acting as such, and third party beneficiary rights are
|
acting as such, and third party beneficiary rights are
|
||||||
specifically excluded.
|
specifically excluded.
|
||||||
|
|
142
README.md
142
README.md
|
@ -1,71 +1,71 @@
|
||||||
# Сервопривод Робосборщика
|
# Сервопривод Робосборщика
|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
|
|
||||||
Сервопривод на базе бесщёточного двигателя постоянного тока, адаптированный для производства с помощью 3D-печати. Разработан для управления 6-осевым роботом-манипулятором [Robossembler Arm](https://gitlab.com/robossembler/roboarm-diy-version), но может использоваться и как самостоятельное изделие в составе других систем. Предусматривается две конструкции статора двигателя: один для изготовления с помощью 3D-печати, другой с помощью листовой электротехнеской стали, нарезаемой на лазерном станке.
|
Сервопривод на базе бесщёточного двигателя постоянного тока, адаптированный для производства с помощью 3D-печати. Разработан для управления 6-осевым роботом-манипулятором [Robossembler Arm](https://gitlab.com/robossembler/roboarm-diy-version), но может использоваться и как самостоятельное изделие в составе других систем. Предусматривается две конструкции статора двигателя: один для изготовления с помощью 3D-печати, другой с помощью листовой электротехнеской стали, нарезаемой на лазерном станке.
|
||||||
|
|
||||||
Ключевые особенности:
|
Ключевые особенности:
|
||||||
- Высокая мощность (допустимость редуктора)
|
- Высокая мощность (допустимость редуктора)
|
||||||
- Высокая скорость (компенсация наличия редуктора)
|
- Высокая скорость (компенсация наличия редуктора)
|
||||||
- Хорошая динамика (разгон-торможение)
|
- Хорошая динамика (разгон-торможение)
|
||||||
- Возможность электрического тормоза
|
- Возможность электрического тормоза
|
||||||
|
|
||||||
В состав репозитория включены модели редукторов двух типов для использования в составе сервопривода. Исходные файлы редукторов представлены в директории `src/REDUCTOR`. В настоящее время основным является прециссирующий редуктор с соотношением 1:43.
|
В состав репозитория включены модели редукторов двух типов для использования в составе сервопривода. Исходные файлы редукторов представлены в директории `src/REDUCTOR`. В настоящее время основным является прециссирующий редуктор с соотношением 1:43.
|
||||||
|
|
||||||
Для управления используется универсальная плата-контроллер, которая может быть использована в вариантах исполнения двигателей разных диаметров (на данный момент 50 мм и 70 мм) со сходными характеристиками обмоток. Контроллер управляется через CAN-интерфейс.
|
Для управления используется универсальная плата-контроллер, которая может быть использована в вариантах исполнения двигателей разных диаметров (на данный момент 50 мм и 70 мм) со сходными характеристиками обмоток. Контроллер управляется через CAN-интерфейс.
|
||||||
|
|
||||||
## Внешний вид
|
## Внешний вид
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Описание директорий
|
## Описание директорий
|
||||||
|
|
||||||
```[servo]
|
```[servo]
|
||||||
├── controller/ # Плата контроллер
|
├── controller/ # Плата контроллер
|
||||||
│ ├── fw/ # Исходный код прошивки микроконтроллера
|
│ ├── fw/ # Исходный код прошивки микроконтроллера
|
||||||
│ │ ├── embed/ # Инструкция по сборке и загрузке прошивки
|
│ │ ├── embed/ # Инструкция по сборке и загрузке прошивки
|
||||||
│ │ └── test/ # Тесты для проверки встроенного ПО
|
│ │ └── test/ # Тесты для проверки встроенного ПО
|
||||||
│ └── hw/ # Проект печатной платы контроллера в kicad
|
│ └── hw/ # Проект печатной платы контроллера в kicad
|
||||||
├── img/ # Изображения для README.md
|
├── img/ # Изображения для README.md
|
||||||
├── motor/ # Все файлы сборок и деталей моторов в формате Solidworks
|
├── motor/ # Все файлы сборок и деталей моторов в формате Solidworks
|
||||||
├── reducer/ # Проекты редукторов в формате Solidworks
|
├── reducer/ # Проекты редукторов в формате Solidworks
|
||||||
├── ros2_environment/ # Пакеты для управления мотором из ROS 2 с помощью ros2_control
|
├── ros2_environment/ # Пакеты для управления мотором из ROS 2 с помощью ros2_control
|
||||||
└── tools/ # Вспомогательное оборудование для тестирования, испытаний
|
└── tools/ # Вспомогательное оборудование для тестирования, испытаний
|
||||||
├── conductor-for-fasteners-70mm/ # Проект оснастки для вкручивания винтов в пластиковый статор 72мм мотора
|
├── conductor-for-fasteners-70mm/ # Проект оснастки для вкручивания винтов в пластиковый статор 72мм мотора
|
||||||
├── test-reductor-stend/ # Стенд для испытания редуктора
|
├── test-reductor-stend/ # Стенд для испытания редуктора
|
||||||
└── torque-test-stend/ # Стенд для измерения усилия сервопривода
|
└── torque-test-stend/ # Стенд для измерения усилия сервопривода
|
||||||
```
|
```
|
||||||
|
|
||||||
## Краткая инструкция по изготовлению
|
## Краткая инструкция по изготовлению
|
||||||
|
|
||||||
### Статор
|
### Статор
|
||||||
|
|
||||||
Для удобства изготовления статоров разработан станок для намотки катушек индуктивности. Исходные файлы для производства станка и инструкции размещены в репозитории [gitlab.com/robossembler/cnc/motor-wire-winder](https://gitlab.com/robossembler/cnc/motor-wire-winder).
|
Для удобства изготовления статоров разработан станок для намотки катушек индуктивности. Исходные файлы для производства станка и инструкции размещены в репозитории [gitlab.com/robossembler/cnc/motor-wire-winder](https://gitlab.com/robossembler/cnc/motor-wire-winder).
|
||||||
|
|
||||||
### Сборка
|
### Сборка
|
||||||
|
|
||||||
1. Вставить 28 магнитов в ротор
|
1. Вставить 28 магнитов в ротор
|
||||||
2. Установить подшипник в статор
|
2. Установить подшипник в статор
|
||||||
3. Установить проставку в статор между подшипником и платой
|
3. Установить проставку в статор между подшипником и платой
|
||||||
4. Припаять плату к обмоткам (схема обмоток приведена ниже) и установить ее в статор
|
4. Припаять плату к обмоткам (схема обмоток приведена ниже) и установить ее в статор
|
||||||
5. Накрыть плату крышкой
|
5. Накрыть плату крышкой
|
||||||
6. Установить фиксирующий шплинт
|
6. Установить фиксирующий шплинт
|
||||||
7. Надеть на сборку статора ротор
|
7. Надеть на сборку статора ротор
|
||||||
8. Подключить разъем программирования XP3 и прошить с помощью ST-Link-совместимого программатора
|
8. Подключить разъем программирования XP3 и прошить с помощью ST-Link-совместимого программатора
|
||||||
|
|
||||||
## Фото прототипов
|
## Фото прототипов
|
||||||
|
|
||||||
Первый прототип изготовленного печатного мотора диаметром 50мм.
|
Первый прототип изготовленного печатного мотора диаметром 50мм.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Современная версия привода диаметром 70мм.
|
Современная версия привода диаметром 70мм.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Схемы намотки
|
## Схемы намотки
|
||||||
|
|
||||||
| Двигатель 70мм | Двигатель 50мм |
|
| Двигатель 70мм | Двигатель 50мм |
|
||||||
| ----------- | ----------- |
|
| ----------- | ----------- |
|
||||||
|  |  |
|
|  |  |
|
||||||
|
|
|
@ -1,68 +1,68 @@
|
||||||
# Встроенное ПО для сервопривода на STM32F446RE
|
# Встроенное ПО для сервопривода на STM32F446RE
|
||||||
|
|
||||||
## Для разработки
|
## Для разработки
|
||||||
- [Установить platformio](#introduction)
|
- [Установить platformio](#introduction)
|
||||||
```bash
|
```bash
|
||||||
pip install -U platformio
|
pip install -U platformio
|
||||||
```
|
```
|
||||||
- Установить python3
|
- Установить python3
|
||||||
```bash
|
```bash
|
||||||
sudo apt install python3
|
sudo apt install python3
|
||||||
```
|
```
|
||||||
- Устаноивть st-link
|
- Устаноивть st-link
|
||||||
```bash
|
```bash
|
||||||
sudo apt install st-link
|
sudo apt install st-link
|
||||||
```
|
```
|
||||||
### Прошивка делится на два файла один для загрузчика другой для основной прошивки. Чтобы загрузить как описано ниже нужно находится в директории этого проекта. Нужно сделать как для bootloader так и для embed
|
### Прошивка делится на два файла один для загрузчика другой для основной прошивки. Чтобы загрузить как описано ниже нужно находится в директории этого проекта. Нужно сделать как для bootloader так и для embed
|
||||||
- [Скомпилировать проект](#build_project)
|
- [Скомпилировать проект](#build_project)
|
||||||
```bash
|
```bash
|
||||||
platformio run --environment robotroller_reborn
|
platformio run --environment robotroller_reborn
|
||||||
```
|
```
|
||||||
- [Загрузить прошивку](#upload_project)
|
- [Загрузить прошивку](#upload_project)
|
||||||
```bash
|
```bash
|
||||||
platformio run --target upload --environment robotroller_reborn
|
platformio run --target upload --environment robotroller_reborn
|
||||||
```
|
```
|
||||||
|
|
||||||
## Другой способ прошивки
|
## Другой способ прошивки
|
||||||
## Выбор интерфейса прошивки
|
## Выбор интерфейса прошивки
|
||||||
### Для основной прошивки в директории ./embed
|
### Для основной прошивки в директории ./embed
|
||||||
- Если уже есть какя-то основная прошивка, то чтобы перепрошить другую прошивку, добавляем флаг для бутлоадера
|
- Если уже есть какя-то основная прошивка, то чтобы перепрошить другую прошивку, добавляем флаг для бутлоадера
|
||||||
```bash
|
```bash
|
||||||
python3 firmw_update_flag.py [адрес устройства]
|
python3 firmw_update_flag.py [адрес устройства]
|
||||||
```
|
```
|
||||||
- Передача прошивки по CAN
|
- Передача прошивки по CAN
|
||||||
```bash
|
```bash
|
||||||
python3 firmware_can.py firmware.hex [адрес устройства]
|
python3 firmware_can.py firmware.hex [адрес устройства]
|
||||||
```
|
```
|
||||||
### St-link(нет адресации можно прошивать только по одному)
|
### St-link(нет адресации можно прошивать только по одному)
|
||||||
```bash
|
```bash
|
||||||
python3 st-link.py firmware.hex
|
python3 st-link.py firmware.hex
|
||||||
```
|
```
|
||||||
### St-link_full(полная прошивка без адресации)
|
### St-link_full(полная прошивка без адресации)
|
||||||
#### Прошивает и программатор и основную прошивку можно находится как в ./embed, так и в ./bootloader(в директории где есть данный тест в папке test).
|
#### Прошивает и программатор и основную прошивку можно находится как в ./embed, так и в ./bootloader(в директории где есть данный тест в папке test).
|
||||||
|
|
||||||
- Если до этого сохраняли адреса и данные, то они останутся даже при полной перепрошивке
|
- Если до этого сохраняли адреса и данные, то они останутся даже при полной перепрошивке
|
||||||
- Если бутлоадер не был прошит и FLASH микрокотроллера полностью стерта
|
- Если бутлоадер не был прошит и FLASH микрокотроллера полностью стерта
|
||||||
|
|
||||||
- [Скачать прошивку и бутлоадер в hex формате]
|
- [Скачать прошивку и бутлоадер в hex формате]
|
||||||
ССЫЛКА
|
ССЫЛКА
|
||||||
|
|
||||||
- [Прошить через программатор]
|
- [Прошить через программатор]
|
||||||
```bash
|
```bash
|
||||||
python3 st-link_full.py bootloader.hex firmware.hex
|
python3 st-link_full.py bootloader.hex firmware.hex
|
||||||
```
|
```
|
||||||
|
|
||||||
## Работа по CAN
|
## Работа по CAN
|
||||||
#### Для основной прошивки в директории ./embed
|
#### Для основной прошивки в директории ./embed
|
||||||
- Установка адреса(если до этого не был установлен адрес, то адрес устройства = 0)
|
- Установка адреса(если до этого не был установлен адрес, то адрес устройства = 0)
|
||||||
```bash
|
```bash
|
||||||
python3 set_id.py [адрес устройства]
|
python3 set_id.py [адрес устройства]
|
||||||
```
|
```
|
||||||
|
|
||||||
- Установка PID коэффициентов для угла
|
- Установка PID коэффициентов для угла
|
||||||
```bash
|
```bash
|
||||||
python3 writePID_angle_parametrs.py [адрес устройства]
|
python3 writePID_angle_parametrs.py [адрес устройства]
|
||||||
```
|
```
|
||||||
-Чтение PID коэффициентов для угла
|
-Чтение PID коэффициентов для угла
|
||||||
```bash
|
```bash
|
||||||
python3 readPID_angle_parametrs.py [адрес устройства]
|
python3 readPID_angle_parametrs.py [адрес устройства]
|
|
@ -1 +1 @@
|
||||||
Checks: '-*, -misc-definitions-in-headers'
|
Checks: '-*, -misc-definitions-in-headers'
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
CompileFlags:
|
CompileFlags:
|
||||||
Add:
|
Add:
|
||||||
[
|
[
|
||||||
# -mlong-calls,
|
# -mlong-calls,
|
||||||
-DSSIZE_MAX,
|
-DSSIZE_MAX,
|
||||||
-DLWIP_NO_UNISTD_H=1,
|
-DLWIP_NO_UNISTD_H=1,
|
||||||
-Dssize_t=long,
|
-Dssize_t=long,
|
||||||
-D_SSIZE_T_DECLARED,
|
-D_SSIZE_T_DECLARED,
|
||||||
]
|
]
|
||||||
Remove:
|
Remove:
|
||||||
[
|
[
|
||||||
-fno-tree-switch-conversion,
|
-fno-tree-switch-conversion,
|
||||||
-mtext-section-literals,
|
-mtext-section-literals,
|
||||||
-mlongcalls,
|
-mlongcalls,
|
||||||
-fstrict-volatile-bitfields,
|
-fstrict-volatile-bitfields,
|
||||||
-free,
|
-free,
|
||||||
-fipa-pta,
|
-fipa-pta,
|
||||||
]
|
]
|
||||||
|
|
18
controller/fw/bootloader/.gitignore
vendored
18
controller/fw/bootloader/.gitignore
vendored
|
@ -1,9 +1,9 @@
|
||||||
.pio
|
.pio
|
||||||
.vscode/.browse.c_cpp.db*
|
.vscode/.browse.c_cpp.db*
|
||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
.cache/
|
.cache/
|
||||||
.metadata/
|
.metadata/
|
||||||
cubemx_config/
|
cubemx_config/
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
Import("env")
|
Import("env")
|
||||||
|
|
||||||
# Получаем путь к компилятору из окружения PlatformIO
|
# Получаем путь к компилятору из окружения PlatformIO
|
||||||
gcc_path = env.subst("$CC")
|
gcc_path = env.subst("$CC")
|
||||||
|
|
||||||
# Выполняем команду для получения версии компилятора
|
# Выполняем команду для получения версии компилятора
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run([gcc_path, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
result = subprocess.run([gcc_path, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print(f"GCC version: {result.stdout}")
|
print(f"GCC version: {result.stdout}")
|
||||||
else:
|
else:
|
||||||
print(f"Failed to get GCC version: {result.stderr}")
|
print(f"Failed to get GCC version: {result.stderr}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error while getting GCC version: {e}")
|
print(f"Error while getting GCC version: {e}")
|
||||||
|
|
||||||
# Дополнительно проверяем путь к компилятору
|
# Дополнительно проверяем путь к компилятору
|
||||||
print(f"Compiler path: {gcc_path}")
|
print(f"Compiler path: {gcc_path}")
|
||||||
|
|
|
@ -1,299 +1,299 @@
|
||||||
#MicroXplorer Configuration settings - do not modify
|
#MicroXplorer Configuration settings - do not modify
|
||||||
ADC2.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_15
|
ADC2.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_15
|
||||||
ADC2.Channel-5\#ChannelRegularConversion=ADC_CHANNEL_8
|
ADC2.Channel-5\#ChannelRegularConversion=ADC_CHANNEL_8
|
||||||
ADC2.Channel-6\#ChannelRegularConversion=ADC_CHANNEL_9
|
ADC2.Channel-6\#ChannelRegularConversion=ADC_CHANNEL_9
|
||||||
ADC2.EOCSelection=ADC_EOC_SEQ_CONV
|
ADC2.EOCSelection=ADC_EOC_SEQ_CONV
|
||||||
ADC2.IPParameters=Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,NbrOfConversionFlag,InjNumberOfConversion,NbrOfConversion,Rank-5\#ChannelRegularConversion,Channel-5\#ChannelRegularConversion,SamplingTime-5\#ChannelRegularConversion,Rank-6\#ChannelRegularConversion,Channel-6\#ChannelRegularConversion,SamplingTime-6\#ChannelRegularConversion,EOCSelection
|
ADC2.IPParameters=Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,NbrOfConversionFlag,InjNumberOfConversion,NbrOfConversion,Rank-5\#ChannelRegularConversion,Channel-5\#ChannelRegularConversion,SamplingTime-5\#ChannelRegularConversion,Rank-6\#ChannelRegularConversion,Channel-6\#ChannelRegularConversion,SamplingTime-6\#ChannelRegularConversion,EOCSelection
|
||||||
ADC2.InjNumberOfConversion=0
|
ADC2.InjNumberOfConversion=0
|
||||||
ADC2.NbrOfConversion=3
|
ADC2.NbrOfConversion=3
|
||||||
ADC2.NbrOfConversionFlag=1
|
ADC2.NbrOfConversionFlag=1
|
||||||
ADC2.Rank-1\#ChannelRegularConversion=1
|
ADC2.Rank-1\#ChannelRegularConversion=1
|
||||||
ADC2.Rank-5\#ChannelRegularConversion=2
|
ADC2.Rank-5\#ChannelRegularConversion=2
|
||||||
ADC2.Rank-6\#ChannelRegularConversion=3
|
ADC2.Rank-6\#ChannelRegularConversion=3
|
||||||
ADC2.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
ADC2.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
||||||
ADC2.SamplingTime-5\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
ADC2.SamplingTime-5\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
||||||
ADC2.SamplingTime-6\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
ADC2.SamplingTime-6\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
||||||
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configTIMER_TASK_PRIORITY
|
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configTIMER_TASK_PRIORITY
|
||||||
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
||||||
FREERTOS.configENABLE_FPU=1
|
FREERTOS.configENABLE_FPU=1
|
||||||
FREERTOS.configTIMER_TASK_PRIORITY=1
|
FREERTOS.configTIMER_TASK_PRIORITY=1
|
||||||
File.Version=6
|
File.Version=6
|
||||||
GPIO.groupedBy=Group By Peripherals
|
GPIO.groupedBy=Group By Peripherals
|
||||||
KeepUserPlacement=false
|
KeepUserPlacement=false
|
||||||
Mcu.CPN=STM32F446RET6
|
Mcu.CPN=STM32F446RET6
|
||||||
Mcu.Family=STM32F4
|
Mcu.Family=STM32F4
|
||||||
Mcu.IP0=ADC2
|
Mcu.IP0=ADC2
|
||||||
Mcu.IP1=FREERTOS
|
Mcu.IP1=FREERTOS
|
||||||
Mcu.IP2=NVIC
|
Mcu.IP2=NVIC
|
||||||
Mcu.IP3=RCC
|
Mcu.IP3=RCC
|
||||||
Mcu.IP4=SPI2
|
Mcu.IP4=SPI2
|
||||||
Mcu.IP5=SYS
|
Mcu.IP5=SYS
|
||||||
Mcu.IP6=TIM1
|
Mcu.IP6=TIM1
|
||||||
Mcu.IP7=TIM3
|
Mcu.IP7=TIM3
|
||||||
Mcu.IP8=TIM5
|
Mcu.IP8=TIM5
|
||||||
Mcu.IP9=USART1
|
Mcu.IP9=USART1
|
||||||
Mcu.IPNb=10
|
Mcu.IPNb=10
|
||||||
Mcu.Name=STM32F446R(C-E)Tx
|
Mcu.Name=STM32F446R(C-E)Tx
|
||||||
Mcu.Package=LQFP64
|
Mcu.Package=LQFP64
|
||||||
Mcu.Pin0=PC1
|
Mcu.Pin0=PC1
|
||||||
Mcu.Pin1=PC5
|
Mcu.Pin1=PC5
|
||||||
Mcu.Pin10=PC9
|
Mcu.Pin10=PC9
|
||||||
Mcu.Pin11=PA8
|
Mcu.Pin11=PA8
|
||||||
Mcu.Pin12=PA9
|
Mcu.Pin12=PA9
|
||||||
Mcu.Pin13=PA10
|
Mcu.Pin13=PA10
|
||||||
Mcu.Pin14=PA11
|
Mcu.Pin14=PA11
|
||||||
Mcu.Pin15=PA12
|
Mcu.Pin15=PA12
|
||||||
Mcu.Pin16=PA13
|
Mcu.Pin16=PA13
|
||||||
Mcu.Pin17=PA14
|
Mcu.Pin17=PA14
|
||||||
Mcu.Pin18=PC10
|
Mcu.Pin18=PC10
|
||||||
Mcu.Pin19=PC11
|
Mcu.Pin19=PC11
|
||||||
Mcu.Pin2=PB0
|
Mcu.Pin2=PB0
|
||||||
Mcu.Pin20=PC12
|
Mcu.Pin20=PC12
|
||||||
Mcu.Pin21=PD2
|
Mcu.Pin21=PD2
|
||||||
Mcu.Pin22=PB6
|
Mcu.Pin22=PB6
|
||||||
Mcu.Pin23=PB7
|
Mcu.Pin23=PB7
|
||||||
Mcu.Pin24=VP_FREERTOS_VS_CMSIS_V2
|
Mcu.Pin24=VP_FREERTOS_VS_CMSIS_V2
|
||||||
Mcu.Pin25=VP_SYS_VS_tim2
|
Mcu.Pin25=VP_SYS_VS_tim2
|
||||||
Mcu.Pin26=VP_TIM1_VS_ClockSourceINT
|
Mcu.Pin26=VP_TIM1_VS_ClockSourceINT
|
||||||
Mcu.Pin27=VP_TIM3_VS_ClockSourceINT
|
Mcu.Pin27=VP_TIM3_VS_ClockSourceINT
|
||||||
Mcu.Pin28=VP_TIM5_VS_ClockSourceINT
|
Mcu.Pin28=VP_TIM5_VS_ClockSourceINT
|
||||||
Mcu.Pin3=PB1
|
Mcu.Pin3=PB1
|
||||||
Mcu.Pin4=PB10
|
Mcu.Pin4=PB10
|
||||||
Mcu.Pin5=PB14
|
Mcu.Pin5=PB14
|
||||||
Mcu.Pin6=PB15
|
Mcu.Pin6=PB15
|
||||||
Mcu.Pin7=PC6
|
Mcu.Pin7=PC6
|
||||||
Mcu.Pin8=PC7
|
Mcu.Pin8=PC7
|
||||||
Mcu.Pin9=PC8
|
Mcu.Pin9=PC8
|
||||||
Mcu.PinsNb=29
|
Mcu.PinsNb=29
|
||||||
Mcu.ThirdPartyNb=0
|
Mcu.ThirdPartyNb=0
|
||||||
Mcu.UserConstants=
|
Mcu.UserConstants=
|
||||||
Mcu.UserName=STM32F446RETx
|
Mcu.UserName=STM32F446RETx
|
||||||
MxCube.Version=6.5.0
|
MxCube.Version=6.5.0
|
||||||
MxDb.Version=DB.6.0.50
|
MxDb.Version=DB.6.0.50
|
||||||
NVIC.ADC_IRQn=true\:5\:0\:true\:true\:true\:1\:true\:true\:true\:true
|
NVIC.ADC_IRQn=true\:5\:0\:true\:true\:true\:1\:true\:true\:true\:true
|
||||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.ForceEnableDMAVector=true
|
NVIC.ForceEnableDMAVector=true
|
||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||||
NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
||||||
NVIC.SavedPendsvIrqHandlerGenerated=true
|
NVIC.SavedPendsvIrqHandlerGenerated=true
|
||||||
NVIC.SavedSvcallIrqHandlerGenerated=true
|
NVIC.SavedSvcallIrqHandlerGenerated=true
|
||||||
NVIC.SavedSystickIrqHandlerGenerated=true
|
NVIC.SavedSystickIrqHandlerGenerated=true
|
||||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
|
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
|
||||||
NVIC.TIM2_IRQn=true\:15\:0\:true\:false\:true\:false\:false\:true\:true
|
NVIC.TIM2_IRQn=true\:15\:0\:true\:false\:true\:false\:false\:true\:true
|
||||||
NVIC.TIM3_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
NVIC.TIM3_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||||
NVIC.TimeBase=TIM2_IRQn
|
NVIC.TimeBase=TIM2_IRQn
|
||||||
NVIC.TimeBaseIP=TIM2
|
NVIC.TimeBaseIP=TIM2
|
||||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
PA10.Signal=S_TIM1_CH3
|
PA10.Signal=S_TIM1_CH3
|
||||||
PA11.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PA11.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PA11.GPIO_Label=EN_U
|
PA11.GPIO_Label=EN_U
|
||||||
PA11.GPIO_PuPd=GPIO_PULLDOWN
|
PA11.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PA11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
PA11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
||||||
PA11.Locked=true
|
PA11.Locked=true
|
||||||
PA11.Signal=GPIO_Output
|
PA11.Signal=GPIO_Output
|
||||||
PA12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PA12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PA12.GPIO_Label=EN_V
|
PA12.GPIO_Label=EN_V
|
||||||
PA12.GPIO_PuPd=GPIO_PULLDOWN
|
PA12.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PA12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
PA12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
||||||
PA12.Locked=true
|
PA12.Locked=true
|
||||||
PA12.Signal=GPIO_Output
|
PA12.Signal=GPIO_Output
|
||||||
PA13.Mode=Serial_Wire
|
PA13.Mode=Serial_Wire
|
||||||
PA13.Signal=SYS_JTMS-SWDIO
|
PA13.Signal=SYS_JTMS-SWDIO
|
||||||
PA14.Mode=Serial_Wire
|
PA14.Mode=Serial_Wire
|
||||||
PA14.Signal=SYS_JTCK-SWCLK
|
PA14.Signal=SYS_JTCK-SWCLK
|
||||||
PA8.Signal=S_TIM1_CH1
|
PA8.Signal=S_TIM1_CH1
|
||||||
PA9.Signal=S_TIM1_CH2
|
PA9.Signal=S_TIM1_CH2
|
||||||
PB0.GPIOParameters=GPIO_Label
|
PB0.GPIOParameters=GPIO_Label
|
||||||
PB0.GPIO_Label=SENSE2
|
PB0.GPIO_Label=SENSE2
|
||||||
PB0.Locked=true
|
PB0.Locked=true
|
||||||
PB0.Signal=ADCx_IN8
|
PB0.Signal=ADCx_IN8
|
||||||
PB1.GPIOParameters=GPIO_Label
|
PB1.GPIOParameters=GPIO_Label
|
||||||
PB1.GPIO_Label=SENSE1
|
PB1.GPIO_Label=SENSE1
|
||||||
PB1.Locked=true
|
PB1.Locked=true
|
||||||
PB1.Signal=ADCx_IN9
|
PB1.Signal=ADCx_IN9
|
||||||
PB10.Locked=true
|
PB10.Locked=true
|
||||||
PB10.Mode=Full_Duplex_Master
|
PB10.Mode=Full_Duplex_Master
|
||||||
PB10.Signal=SPI2_SCK
|
PB10.Signal=SPI2_SCK
|
||||||
PB14.Locked=true
|
PB14.Locked=true
|
||||||
PB14.Mode=Full_Duplex_Master
|
PB14.Mode=Full_Duplex_Master
|
||||||
PB14.Signal=SPI2_MISO
|
PB14.Signal=SPI2_MISO
|
||||||
PB15.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
PB15.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
||||||
PB15.GPIO_Label=AS5045_CS
|
PB15.GPIO_Label=AS5045_CS
|
||||||
PB15.GPIO_PuPd=GPIO_PULLUP
|
PB15.GPIO_PuPd=GPIO_PULLUP
|
||||||
PB15.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
PB15.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
||||||
PB15.Locked=true
|
PB15.Locked=true
|
||||||
PB15.PinState=GPIO_PIN_SET
|
PB15.PinState=GPIO_PIN_SET
|
||||||
PB15.Signal=GPIO_Output
|
PB15.Signal=GPIO_Output
|
||||||
PB6.Mode=Asynchronous
|
PB6.Mode=Asynchronous
|
||||||
PB6.Signal=USART1_TX
|
PB6.Signal=USART1_TX
|
||||||
PB7.Mode=Asynchronous
|
PB7.Mode=Asynchronous
|
||||||
PB7.Signal=USART1_RX
|
PB7.Signal=USART1_RX
|
||||||
PC1.Mode=Full_Duplex_Master
|
PC1.Mode=Full_Duplex_Master
|
||||||
PC1.Signal=SPI2_MOSI
|
PC1.Signal=SPI2_MOSI
|
||||||
PC10.GPIOParameters=GPIO_Label
|
PC10.GPIOParameters=GPIO_Label
|
||||||
PC10.GPIO_Label=LED1
|
PC10.GPIO_Label=LED1
|
||||||
PC10.Locked=true
|
PC10.Locked=true
|
||||||
PC10.Signal=GPIO_Output
|
PC10.Signal=GPIO_Output
|
||||||
PC11.GPIOParameters=GPIO_Label
|
PC11.GPIOParameters=GPIO_Label
|
||||||
PC11.GPIO_Label=LED2
|
PC11.GPIO_Label=LED2
|
||||||
PC11.Locked=true
|
PC11.Locked=true
|
||||||
PC11.Signal=GPIO_Output
|
PC11.Signal=GPIO_Output
|
||||||
PC12.GPIOParameters=GPIO_Label
|
PC12.GPIOParameters=GPIO_Label
|
||||||
PC12.GPIO_Label=LED3
|
PC12.GPIO_Label=LED3
|
||||||
PC12.Locked=true
|
PC12.Locked=true
|
||||||
PC12.Signal=GPIO_Output
|
PC12.Signal=GPIO_Output
|
||||||
PC5.GPIOParameters=GPIO_Label
|
PC5.GPIOParameters=GPIO_Label
|
||||||
PC5.GPIO_Label=SENSE3
|
PC5.GPIO_Label=SENSE3
|
||||||
PC5.Locked=true
|
PC5.Locked=true
|
||||||
PC5.Signal=ADCx_IN15
|
PC5.Signal=ADCx_IN15
|
||||||
PC6.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PC6.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PC6.GPIO_Label=EN_W
|
PC6.GPIO_Label=EN_W
|
||||||
PC6.GPIO_PuPd=GPIO_PULLDOWN
|
PC6.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PC6.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
PC6.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
||||||
PC6.Locked=true
|
PC6.Locked=true
|
||||||
PC6.Signal=GPIO_Output
|
PC6.Signal=GPIO_Output
|
||||||
PC7.GPIOParameters=GPIO_Label
|
PC7.GPIOParameters=GPIO_Label
|
||||||
PC7.GPIO_Label=DRV_FAULT
|
PC7.GPIO_Label=DRV_FAULT
|
||||||
PC7.Locked=true
|
PC7.Locked=true
|
||||||
PC7.Signal=GPIO_Input
|
PC7.Signal=GPIO_Input
|
||||||
PC8.GPIOParameters=GPIO_Label
|
PC8.GPIOParameters=GPIO_Label
|
||||||
PC8.GPIO_Label=DRV_RESET
|
PC8.GPIO_Label=DRV_RESET
|
||||||
PC8.Locked=true
|
PC8.Locked=true
|
||||||
PC8.Signal=GPIO_Output
|
PC8.Signal=GPIO_Output
|
||||||
PC9.GPIOParameters=GPIO_Label
|
PC9.GPIOParameters=GPIO_Label
|
||||||
PC9.GPIO_Label=DRV_SLEEP
|
PC9.GPIO_Label=DRV_SLEEP
|
||||||
PC9.Locked=true
|
PC9.Locked=true
|
||||||
PC9.Signal=GPIO_Output
|
PC9.Signal=GPIO_Output
|
||||||
PD2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PD2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PD2.GPIO_Label=spi1_cs
|
PD2.GPIO_Label=spi1_cs
|
||||||
PD2.GPIO_PuPd=GPIO_PULLDOWN
|
PD2.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PD2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
PD2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
||||||
PD2.Locked=true
|
PD2.Locked=true
|
||||||
PD2.Signal=GPIO_Output
|
PD2.Signal=GPIO_Output
|
||||||
PinOutPanel.RotationAngle=0
|
PinOutPanel.RotationAngle=0
|
||||||
ProjectManager.AskForMigrate=true
|
ProjectManager.AskForMigrate=true
|
||||||
ProjectManager.BackupPrevious=false
|
ProjectManager.BackupPrevious=false
|
||||||
ProjectManager.CompilerOptimize=6
|
ProjectManager.CompilerOptimize=6
|
||||||
ProjectManager.ComputerToolchain=false
|
ProjectManager.ComputerToolchain=false
|
||||||
ProjectManager.CoupleFile=true
|
ProjectManager.CoupleFile=true
|
||||||
ProjectManager.CustomerFirmwarePackage=
|
ProjectManager.CustomerFirmwarePackage=
|
||||||
ProjectManager.DefaultFWLocation=true
|
ProjectManager.DefaultFWLocation=true
|
||||||
ProjectManager.DeletePrevious=true
|
ProjectManager.DeletePrevious=true
|
||||||
ProjectManager.DeviceId=STM32F446RETx
|
ProjectManager.DeviceId=STM32F446RETx
|
||||||
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.27.1
|
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.27.1
|
||||||
ProjectManager.FreePins=false
|
ProjectManager.FreePins=false
|
||||||
ProjectManager.HalAssertFull=false
|
ProjectManager.HalAssertFull=false
|
||||||
ProjectManager.HeapSize=0x200
|
ProjectManager.HeapSize=0x200
|
||||||
ProjectManager.KeepUserCode=true
|
ProjectManager.KeepUserCode=true
|
||||||
ProjectManager.LastFirmware=true
|
ProjectManager.LastFirmware=true
|
||||||
ProjectManager.LibraryCopy=1
|
ProjectManager.LibraryCopy=1
|
||||||
ProjectManager.MainLocation=Src
|
ProjectManager.MainLocation=Src
|
||||||
ProjectManager.NoMain=false
|
ProjectManager.NoMain=false
|
||||||
ProjectManager.PreviousToolchain=STM32CubeIDE
|
ProjectManager.PreviousToolchain=STM32CubeIDE
|
||||||
ProjectManager.ProjectBuild=false
|
ProjectManager.ProjectBuild=false
|
||||||
ProjectManager.ProjectFileName=cubemx_config.ioc
|
ProjectManager.ProjectFileName=cubemx_config.ioc
|
||||||
ProjectManager.ProjectName=cubemx_config
|
ProjectManager.ProjectName=cubemx_config
|
||||||
ProjectManager.RegisterCallBack=
|
ProjectManager.RegisterCallBack=
|
||||||
ProjectManager.StackSize=0x400
|
ProjectManager.StackSize=0x400
|
||||||
ProjectManager.TargetToolchain=Other Toolchains (GPDSC)
|
ProjectManager.TargetToolchain=Other Toolchains (GPDSC)
|
||||||
ProjectManager.ToolChainLocation=
|
ProjectManager.ToolChainLocation=
|
||||||
ProjectManager.UnderRoot=false
|
ProjectManager.UnderRoot=false
|
||||||
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_TIM1_Init-TIM1-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_TIM3_Init-TIM3-false-HAL-true,7-MX_ADC2_Init-ADC2-false-HAL-true,8-MX_TIM5_Init-TIM5-false-HAL-true
|
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_TIM1_Init-TIM1-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_TIM3_Init-TIM3-false-HAL-true,7-MX_ADC2_Init-ADC2-false-HAL-true,8-MX_TIM5_Init-TIM5-false-HAL-true
|
||||||
RCC.AHBFreq_Value=180000000
|
RCC.AHBFreq_Value=180000000
|
||||||
RCC.APB1CLKDivider=RCC_HCLK_DIV4
|
RCC.APB1CLKDivider=RCC_HCLK_DIV4
|
||||||
RCC.APB1Freq_Value=45000000
|
RCC.APB1Freq_Value=45000000
|
||||||
RCC.APB1TimFreq_Value=90000000
|
RCC.APB1TimFreq_Value=90000000
|
||||||
RCC.APB2CLKDivider=RCC_HCLK_DIV2
|
RCC.APB2CLKDivider=RCC_HCLK_DIV2
|
||||||
RCC.APB2Freq_Value=90000000
|
RCC.APB2Freq_Value=90000000
|
||||||
RCC.APB2TimFreq_Value=180000000
|
RCC.APB2TimFreq_Value=180000000
|
||||||
RCC.CECFreq_Value=32786.88524590164
|
RCC.CECFreq_Value=32786.88524590164
|
||||||
RCC.CortexFreq_Value=180000000
|
RCC.CortexFreq_Value=180000000
|
||||||
RCC.FCLKCortexFreq_Value=180000000
|
RCC.FCLKCortexFreq_Value=180000000
|
||||||
RCC.FMPI2C1Freq_Value=45000000
|
RCC.FMPI2C1Freq_Value=45000000
|
||||||
RCC.FamilyName=M
|
RCC.FamilyName=M
|
||||||
RCC.HCLKFreq_Value=180000000
|
RCC.HCLKFreq_Value=180000000
|
||||||
RCC.HSE_VALUE=8000000
|
RCC.HSE_VALUE=8000000
|
||||||
RCC.I2S1Freq_Value=96000000
|
RCC.I2S1Freq_Value=96000000
|
||||||
RCC.I2S2Freq_Value=96000000
|
RCC.I2S2Freq_Value=96000000
|
||||||
RCC.IPParameters=AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CECFreq_Value,CortexFreq_Value,FCLKCortexFreq_Value,FMPI2C1Freq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,I2S1Freq_Value,I2S2Freq_Value,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLI2SPCLKFreq_Value,PLLI2SQCLKFreq_Value,PLLI2SRCLKFreq_Value,PLLI2SoutputFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLRCLKFreq_Value,PLLSAIPCLKFreq_Value,PLLSAIQCLKFreq_Value,PLLSAIoutputFreq_Value,PWRFreq_Value,SAIAFreq_Value,SAIBFreq_Value,SDIOFreq_Value,SPDIFRXFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USBFreq_Value,VCOI2SInputFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAIInputFreq_Value,VCOSAIOutputFreq_Value
|
RCC.IPParameters=AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CECFreq_Value,CortexFreq_Value,FCLKCortexFreq_Value,FMPI2C1Freq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,I2S1Freq_Value,I2S2Freq_Value,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLI2SPCLKFreq_Value,PLLI2SQCLKFreq_Value,PLLI2SRCLKFreq_Value,PLLI2SoutputFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLRCLKFreq_Value,PLLSAIPCLKFreq_Value,PLLSAIQCLKFreq_Value,PLLSAIoutputFreq_Value,PWRFreq_Value,SAIAFreq_Value,SAIBFreq_Value,SDIOFreq_Value,SPDIFRXFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USBFreq_Value,VCOI2SInputFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAIInputFreq_Value,VCOSAIOutputFreq_Value
|
||||||
RCC.MCO2PinFreq_Value=180000000
|
RCC.MCO2PinFreq_Value=180000000
|
||||||
RCC.PLLCLKFreq_Value=180000000
|
RCC.PLLCLKFreq_Value=180000000
|
||||||
RCC.PLLI2SPCLKFreq_Value=96000000
|
RCC.PLLI2SPCLKFreq_Value=96000000
|
||||||
RCC.PLLI2SQCLKFreq_Value=96000000
|
RCC.PLLI2SQCLKFreq_Value=96000000
|
||||||
RCC.PLLI2SRCLKFreq_Value=96000000
|
RCC.PLLI2SRCLKFreq_Value=96000000
|
||||||
RCC.PLLI2SoutputFreq_Value=96000000
|
RCC.PLLI2SoutputFreq_Value=96000000
|
||||||
RCC.PLLM=8
|
RCC.PLLM=8
|
||||||
RCC.PLLN=180
|
RCC.PLLN=180
|
||||||
RCC.PLLQCLKFreq_Value=180000000
|
RCC.PLLQCLKFreq_Value=180000000
|
||||||
RCC.PLLRCLKFreq_Value=180000000
|
RCC.PLLRCLKFreq_Value=180000000
|
||||||
RCC.PLLSAIPCLKFreq_Value=96000000
|
RCC.PLLSAIPCLKFreq_Value=96000000
|
||||||
RCC.PLLSAIQCLKFreq_Value=96000000
|
RCC.PLLSAIQCLKFreq_Value=96000000
|
||||||
RCC.PLLSAIoutputFreq_Value=96000000
|
RCC.PLLSAIoutputFreq_Value=96000000
|
||||||
RCC.PWRFreq_Value=180000000
|
RCC.PWRFreq_Value=180000000
|
||||||
RCC.SAIAFreq_Value=96000000
|
RCC.SAIAFreq_Value=96000000
|
||||||
RCC.SAIBFreq_Value=96000000
|
RCC.SAIBFreq_Value=96000000
|
||||||
RCC.SDIOFreq_Value=180000000
|
RCC.SDIOFreq_Value=180000000
|
||||||
RCC.SPDIFRXFreq_Value=180000000
|
RCC.SPDIFRXFreq_Value=180000000
|
||||||
RCC.SYSCLKFreq_VALUE=180000000
|
RCC.SYSCLKFreq_VALUE=180000000
|
||||||
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
||||||
RCC.USBFreq_Value=180000000
|
RCC.USBFreq_Value=180000000
|
||||||
RCC.VCOI2SInputFreq_Value=1000000
|
RCC.VCOI2SInputFreq_Value=1000000
|
||||||
RCC.VCOI2SOutputFreq_Value=192000000
|
RCC.VCOI2SOutputFreq_Value=192000000
|
||||||
RCC.VCOInputFreq_Value=2000000
|
RCC.VCOInputFreq_Value=2000000
|
||||||
RCC.VCOOutputFreq_Value=360000000
|
RCC.VCOOutputFreq_Value=360000000
|
||||||
RCC.VCOSAIInputFreq_Value=1000000
|
RCC.VCOSAIInputFreq_Value=1000000
|
||||||
RCC.VCOSAIOutputFreq_Value=192000000
|
RCC.VCOSAIOutputFreq_Value=192000000
|
||||||
SH.ADCx_IN15.0=ADC2_IN15,IN15
|
SH.ADCx_IN15.0=ADC2_IN15,IN15
|
||||||
SH.ADCx_IN15.ConfNb=1
|
SH.ADCx_IN15.ConfNb=1
|
||||||
SH.ADCx_IN8.0=ADC2_IN8,IN8
|
SH.ADCx_IN8.0=ADC2_IN8,IN8
|
||||||
SH.ADCx_IN8.ConfNb=1
|
SH.ADCx_IN8.ConfNb=1
|
||||||
SH.ADCx_IN9.0=ADC2_IN9,IN9
|
SH.ADCx_IN9.0=ADC2_IN9,IN9
|
||||||
SH.ADCx_IN9.ConfNb=1
|
SH.ADCx_IN9.ConfNb=1
|
||||||
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
|
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
|
||||||
SH.S_TIM1_CH1.ConfNb=1
|
SH.S_TIM1_CH1.ConfNb=1
|
||||||
SH.S_TIM1_CH2.0=TIM1_CH2,PWM Generation2 CH2
|
SH.S_TIM1_CH2.0=TIM1_CH2,PWM Generation2 CH2
|
||||||
SH.S_TIM1_CH2.ConfNb=1
|
SH.S_TIM1_CH2.ConfNb=1
|
||||||
SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3
|
SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3
|
||||||
SH.S_TIM1_CH3.ConfNb=1
|
SH.S_TIM1_CH3.ConfNb=1
|
||||||
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_64
|
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_64
|
||||||
SPI2.CLKPhase=SPI_PHASE_1EDGE
|
SPI2.CLKPhase=SPI_PHASE_1EDGE
|
||||||
SPI2.CLKPolarity=SPI_POLARITY_LOW
|
SPI2.CLKPolarity=SPI_POLARITY_LOW
|
||||||
SPI2.CalculateBaudRate=703.125 KBits/s
|
SPI2.CalculateBaudRate=703.125 KBits/s
|
||||||
SPI2.DataSize=SPI_DATASIZE_16BIT
|
SPI2.DataSize=SPI_DATASIZE_16BIT
|
||||||
SPI2.Direction=SPI_DIRECTION_2LINES
|
SPI2.Direction=SPI_DIRECTION_2LINES
|
||||||
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPhase,BaudRatePrescaler,CLKPolarity
|
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPhase,BaudRatePrescaler,CLKPolarity
|
||||||
SPI2.Mode=SPI_MODE_MASTER
|
SPI2.Mode=SPI_MODE_MASTER
|
||||||
SPI2.VirtualType=VM_MASTER
|
SPI2.VirtualType=VM_MASTER
|
||||||
TIM1.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
|
TIM1.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
|
||||||
TIM1.BreakState=TIM_BREAK_DISABLE
|
TIM1.BreakState=TIM_BREAK_DISABLE
|
||||||
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
||||||
TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
||||||
TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
||||||
TIM1.CounterMode=TIM_COUNTERMODE_CENTERALIGNED1
|
TIM1.CounterMode=TIM_COUNTERMODE_CENTERALIGNED1
|
||||||
TIM1.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,TIM_MasterOutputTrigger,AutoReloadPreload,BreakState,OffStateRunMode,OffStateIDLEMode,CounterMode,Period
|
TIM1.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,TIM_MasterOutputTrigger,AutoReloadPreload,BreakState,OffStateRunMode,OffStateIDLEMode,CounterMode,Period
|
||||||
TIM1.OffStateIDLEMode=TIM_OSSI_DISABLE
|
TIM1.OffStateIDLEMode=TIM_OSSI_DISABLE
|
||||||
TIM1.OffStateRunMode=TIM_OSSR_DISABLE
|
TIM1.OffStateRunMode=TIM_OSSR_DISABLE
|
||||||
TIM1.Period=2399
|
TIM1.Period=2399
|
||||||
TIM1.TIM_MasterOutputTrigger=TIM_TRGO_RESET
|
TIM1.TIM_MasterOutputTrigger=TIM_TRGO_RESET
|
||||||
TIM3.IPParameters=Period,Prescaler
|
TIM3.IPParameters=Period,Prescaler
|
||||||
TIM3.Period=99
|
TIM3.Period=99
|
||||||
TIM3.Prescaler=89
|
TIM3.Prescaler=89
|
||||||
USART1.IPParameters=VirtualMode
|
USART1.IPParameters=VirtualMode
|
||||||
USART1.VirtualMode=VM_ASYNC
|
USART1.VirtualMode=VM_ASYNC
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
||||||
VP_SYS_VS_tim2.Mode=TIM2
|
VP_SYS_VS_tim2.Mode=TIM2
|
||||||
VP_SYS_VS_tim2.Signal=SYS_VS_tim2
|
VP_SYS_VS_tim2.Signal=SYS_VS_tim2
|
||||||
VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
||||||
VP_TIM3_VS_ClockSourceINT.Mode=Internal
|
VP_TIM3_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
|
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
|
||||||
VP_TIM5_VS_ClockSourceINT.Mode=Internal
|
VP_TIM5_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM5_VS_ClockSourceINT.Signal=TIM5_VS_ClockSourceINT
|
VP_TIM5_VS_ClockSourceINT.Signal=TIM5_VS_ClockSourceINT
|
||||||
board=custom
|
board=custom
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import os
|
import os
|
||||||
Import("env")
|
Import("env")
|
||||||
|
|
||||||
# include toolchain paths
|
# include toolchain paths
|
||||||
env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True)
|
env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True)
|
||||||
|
|
||||||
# override compilation DB path
|
# override compilation DB path
|
||||||
env.Replace(COMPILATIONDB_PATH="compile_commands.json")
|
env.Replace(COMPILATIONDB_PATH="compile_commands.json")
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
Import("env")
|
Import("env")
|
||||||
|
|
||||||
hex_name = "bootloader.hex"
|
hex_name = "bootloader.hex"
|
||||||
# Custom HEX from ELF
|
# Custom HEX from ELF
|
||||||
env.AddPostAction(
|
env.AddPostAction(
|
||||||
"$BUILD_DIR/${PROGNAME}.elf",
|
"$BUILD_DIR/${PROGNAME}.elf",
|
||||||
env.VerboseAction(" ".join([
|
env.VerboseAction(" ".join([
|
||||||
"$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
|
"$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
|
||||||
"$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/{}".format(hex_name)
|
"$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/{}".format(hex_name)
|
||||||
]), "Building $BUILD_DIR/{}".format(hex_name))
|
]), "Building $BUILD_DIR/{}".format(hex_name))
|
||||||
)
|
)
|
|
@ -1,86 +1,86 @@
|
||||||
#ifndef FLASH_H_
|
#ifndef FLASH_H_
|
||||||
#define FLASH_H_
|
#define FLASH_H_
|
||||||
#include "stm32f446xx.h"
|
#include "stm32f446xx.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
/* no padding for this struct, beacuse storing 8 bytes*/
|
/* no padding for this struct, beacuse storing 8 bytes*/
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint8_t data_id; // data_id = id register of can
|
uint8_t data_id; // data_id = id register of can
|
||||||
uint8_t data_type;
|
uint8_t data_type;
|
||||||
uint16_t crc;
|
uint16_t crc;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
// uint32_t write_ptr_now;
|
// uint32_t write_ptr_now;
|
||||||
}FLASH_RECORD;
|
}FLASH_RECORD;
|
||||||
enum {
|
enum {
|
||||||
addr_id = 0,
|
addr_id = 0,
|
||||||
pid_p = 1,
|
pid_p = 1,
|
||||||
pid_i,
|
pid_i,
|
||||||
pid_d,
|
pid_d,
|
||||||
firmw,
|
firmw,
|
||||||
foc_id,
|
foc_id,
|
||||||
angl,
|
angl,
|
||||||
vel
|
vel
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* for saved in FLASH float data*/
|
/* for saved in FLASH float data*/
|
||||||
union{
|
union{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
float f;
|
float f;
|
||||||
}conv_float_to_int;
|
}conv_float_to_int;
|
||||||
|
|
||||||
#define FLASH_RECORD_SIZE sizeof(FLASH_RECORD) //size flash struct
|
#define FLASH_RECORD_SIZE sizeof(FLASH_RECORD) //size flash struct
|
||||||
|
|
||||||
// Flash sectors for STM32F407
|
// Flash sectors for STM32F407
|
||||||
#define APP_ADDRESS 0x08008000
|
#define APP_ADDRESS 0x08008000
|
||||||
#define UPDATE_FLAG 0xDEADBEEF // flag forz update firmware
|
#define UPDATE_FLAG 0xDEADBEEF // flag forz update firmware
|
||||||
#define BOOT_CAN_ID 0x01 // CAN ID bootloader
|
#define BOOT_CAN_ID 0x01 // CAN ID bootloader
|
||||||
#define BOOT_CAN_END 0x02 // CAN ID end of transfer
|
#define BOOT_CAN_END 0x02 // CAN ID end of transfer
|
||||||
#define DATA_CAN_ID 0x03 // CAN ID packet data
|
#define DATA_CAN_ID 0x03 // CAN ID packet data
|
||||||
#define ACK_CAN_ID 0x05 // CAN ID acknowledge
|
#define ACK_CAN_ID 0x05 // CAN ID acknowledge
|
||||||
#define MAX_FW_SIZE 0x3FFF // Max size firmware = 256 kB
|
#define MAX_FW_SIZE 0x3FFF // Max size firmware = 256 kB
|
||||||
#define PARAM_COUNT 5 // count data in flash
|
#define PARAM_COUNT 5 // count data in flash
|
||||||
#define SECTOR_6 0x08040000 // 128KB
|
#define SECTOR_6 0x08040000 // 128KB
|
||||||
#define SECTOR_6_END (SECTOR_6 + 128 * 1024) // sector 6 end
|
#define SECTOR_6_END (SECTOR_6 + 128 * 1024) // sector 6 end
|
||||||
// Flash keys for unlocking flash memory
|
// Flash keys for unlocking flash memory
|
||||||
#define BYTE32 0
|
#define BYTE32 0
|
||||||
#define BYTE8 1
|
#define BYTE8 1
|
||||||
//FLASH SET ONE PROGRAMM WORD
|
//FLASH SET ONE PROGRAMM WORD
|
||||||
#define FLASH_8BYTE FLASH->CR &= ~FLASH_CR_PSIZE & ~FLASH_CR_PSIZE_1
|
#define FLASH_8BYTE FLASH->CR &= ~FLASH_CR_PSIZE & ~FLASH_CR_PSIZE_1
|
||||||
#define FLASH_32BYTE \
|
#define FLASH_32BYTE \
|
||||||
FLASH->CR = (FLASH->CR & ~FLASH_CR_PSIZE) | (0x2 << FLASH_CR_PSIZE_Pos)
|
FLASH->CR = (FLASH->CR & ~FLASH_CR_PSIZE) | (0x2 << FLASH_CR_PSIZE_Pos)
|
||||||
|
|
||||||
// Flash command bits
|
// Flash command bits
|
||||||
#define FLASH_LOCK FLASH->CR |= FLASH_CR_LOCK
|
#define FLASH_LOCK FLASH->CR |= FLASH_CR_LOCK
|
||||||
#define FLASH_UNLOCK FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2
|
#define FLASH_UNLOCK FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2
|
||||||
|
|
||||||
|
|
||||||
// Flash status flags
|
// Flash status flags
|
||||||
#define FLASH_BUSY (FLASH->SR & FLASH_SR_BSY)
|
#define FLASH_BUSY (FLASH->SR & FLASH_SR_BSY)
|
||||||
#define FLASH_ERROR (FLASH->SR & (FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR))
|
#define FLASH_ERROR (FLASH->SR & (FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR))
|
||||||
|
|
||||||
//for bootloader
|
//for bootloader
|
||||||
typedef void(*pFunction)(void);
|
typedef void(*pFunction)(void);
|
||||||
|
|
||||||
|
|
||||||
/* for start addr in FLASH */
|
/* for start addr in FLASH */
|
||||||
static uint32_t write_ptr = SECTOR_6;
|
static uint32_t write_ptr = SECTOR_6;
|
||||||
static uint32_t ptr_fl = APP_ADDRESS;
|
static uint32_t ptr_fl = APP_ADDRESS;
|
||||||
// Function prototypes
|
// Function prototypes
|
||||||
void flash_unlock(void);
|
void flash_unlock(void);
|
||||||
void flash_lock(void);
|
void flash_lock(void);
|
||||||
void erase_sector(uint8_t sector);
|
void erase_sector(uint8_t sector);
|
||||||
void flash_program_word(uint32_t address, uint32_t data,uint32_t byte_len);
|
void flash_program_word(uint32_t address, uint32_t data,uint32_t byte_len);
|
||||||
uint8_t flash_read_word(uint32_t address);
|
uint8_t flash_read_word(uint32_t address);
|
||||||
FLASH_RECORD* load_params();
|
FLASH_RECORD* load_params();
|
||||||
void compact_page();
|
void compact_page();
|
||||||
void flash_read(uint32_t addr,FLASH_RECORD* ptr);
|
void flash_read(uint32_t addr,FLASH_RECORD* ptr);
|
||||||
uint16_t validate_crc16(uint8_t *data,uint32_t length);
|
uint16_t validate_crc16(uint8_t *data,uint32_t length);
|
||||||
void flash_write(uint32_t addr, FLASH_RECORD* record);
|
void flash_write(uint32_t addr, FLASH_RECORD* record);
|
||||||
void write_flash_page(const uint8_t* data, uint16_t len);
|
void write_flash_page(const uint8_t* data, uint16_t len);
|
||||||
void erase_flash_pages();
|
void erase_flash_pages();
|
||||||
void write_param(uint8_t param_id,uint32_t val);
|
void write_param(uint8_t param_id,uint32_t val);
|
||||||
uint16_t calc_crc_struct(FLASH_RECORD* res);
|
uint16_t calc_crc_struct(FLASH_RECORD* res);
|
||||||
#endif /* FLASH_H_ */
|
#endif /* FLASH_H_ */
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#pragma region "Motor and sensor setup"
|
#pragma region "Motor and sensor setup"
|
||||||
#define LED1 PC10
|
#define LED1 PC10
|
||||||
#define LED2 PC11
|
#define LED2 PC11
|
||||||
#define HARDWARE_SERIAL_RX_PIN PB7
|
#define HARDWARE_SERIAL_RX_PIN PB7
|
||||||
#define HARDWARE_SERIAL_TX_PIN PB6
|
#define HARDWARE_SERIAL_TX_PIN PB6
|
||||||
#define AS5045_CS PB15
|
#define AS5045_CS PB15
|
||||||
#define AS5045_MISO PB14
|
#define AS5045_MISO PB14
|
||||||
#define AS5045_MOSI PC1
|
#define AS5045_MOSI PC1
|
||||||
#define AS5045_SCLK PB10
|
#define AS5045_SCLK PB10
|
||||||
#define CURRENT_SENSOR_1 PB1
|
#define CURRENT_SENSOR_1 PB1
|
||||||
#define CURRENT_SENSOR_2 PB0
|
#define CURRENT_SENSOR_2 PB0
|
||||||
#define CURRENT_SENSOR_3 PC5
|
#define CURRENT_SENSOR_3 PC5
|
||||||
#define TIM1_CH1 PA8
|
#define TIM1_CH1 PA8
|
||||||
#define TIM1_CH2 PA9
|
#define TIM1_CH2 PA9
|
||||||
#define TIM1_CH3 PA10
|
#define TIM1_CH3 PA10
|
||||||
#define EN_W_GATE_DRIVER PC6
|
#define EN_W_GATE_DRIVER PC6
|
||||||
#define EN_U_GATE_DRIVER PA11
|
#define EN_U_GATE_DRIVER PA11
|
||||||
#define EN_V_GATE_DRIVER PA12
|
#define EN_V_GATE_DRIVER PA12
|
||||||
#define SLEEP_DRIVER PC9
|
#define SLEEP_DRIVER PC9
|
||||||
#define RESET_DRIVER PC8
|
#define RESET_DRIVER PC8
|
||||||
#define FAULT_DRIVER PC7
|
#define FAULT_DRIVER PC7
|
||||||
#define POLE_PAIRS 14
|
#define POLE_PAIRS 14
|
||||||
#define CAN2_TX PB13
|
#define CAN2_TX PB13
|
||||||
#define CAN2_RX PB12
|
#define CAN2_RX PB12
|
||||||
#define CAN1_TX PB9
|
#define CAN1_TX PB9
|
||||||
#define CAN1_RX PB8
|
#define CAN1_RX PB8
|
||||||
#define GM6208_RESISTANCE 31
|
#define GM6208_RESISTANCE 31
|
||||||
#define OWN_RESISTANCE 26
|
#define OWN_RESISTANCE 26
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#if !defined(HAL_CAN_MODULE_ENABLED)
|
#if !defined(HAL_CAN_MODULE_ENABLED)
|
||||||
#define HAL_CAN_MODULE_ENABLED
|
#define HAL_CAN_MODULE_ENABLED
|
||||||
#endif
|
#endif
|
||||||
#include "stm32f4xx_hal.h"
|
#include "stm32f4xx_hal.h"
|
||||||
#include "stm32f4xx_hal_can.h"
|
#include "stm32f4xx_hal_can.h"
|
||||||
#include <STM32_CAN.h>
|
#include <STM32_CAN.h>
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
#ifndef REG_CAH_H_
|
#ifndef REG_CAH_H_
|
||||||
#define REG_CAH_H_
|
#define REG_CAH_H_
|
||||||
|
|
||||||
#define APP_ADDR 0x0800400 // 16KB - Application
|
#define APP_ADDR 0x0800400 // 16KB - Application
|
||||||
#define ADDR_VAR 0x8040000
|
#define ADDR_VAR 0x8040000
|
||||||
|
|
||||||
|
|
||||||
#define REG_READ 0x07
|
#define REG_READ 0x07
|
||||||
#define REG_WRITE 0x08
|
#define REG_WRITE 0x08
|
||||||
|
|
||||||
|
|
||||||
/* Startup ID device */
|
/* Startup ID device */
|
||||||
#define START_ID 0x00
|
#define START_ID 0x00
|
||||||
|
|
||||||
/* CAN REGISTER ID */
|
/* CAN REGISTER ID */
|
||||||
#define REG_ID 0x01
|
#define REG_ID 0x01
|
||||||
#define REG_BAUDRATE 0x02
|
#define REG_BAUDRATE 0x02
|
||||||
|
|
||||||
#define REG_MOTOR_POSPID_Kp 0x30
|
#define REG_MOTOR_POSPID_Kp 0x30
|
||||||
#define REG_MOTOR_POSPID_Ki 0x31
|
#define REG_MOTOR_POSPID_Ki 0x31
|
||||||
#define REG_MOTOR_POSPID_Kd 0x32
|
#define REG_MOTOR_POSPID_Kd 0x32
|
||||||
|
|
||||||
#define REG_MOTOR_VELPID_Kp 0x40
|
#define REG_MOTOR_VELPID_Kp 0x40
|
||||||
#define REG_MOTOR_VELPID_Ki 0x41
|
#define REG_MOTOR_VELPID_Ki 0x41
|
||||||
#define REG_MOTOR_VELPID_Kd 0x42
|
#define REG_MOTOR_VELPID_Kd 0x42
|
||||||
|
|
||||||
#define REG_MOTOR_IMPPID_Kp 0x50
|
#define REG_MOTOR_IMPPID_Kp 0x50
|
||||||
#define REG_MOTOR_IMPPID_Kd 0x51
|
#define REG_MOTOR_IMPPID_Kd 0x51
|
||||||
|
|
||||||
#define REG_RESET 0x88
|
#define REG_RESET 0x88
|
||||||
#define REG_LED_BLINK 0x8B
|
#define REG_LED_BLINK 0x8B
|
||||||
|
|
||||||
#define FOC_STATE 0x60
|
#define FOC_STATE 0x60
|
||||||
|
|
||||||
#define MOTOR_VELOCITY 0x70
|
#define MOTOR_VELOCITY 0x70
|
||||||
#define MOTOR_ENABLED 0x71
|
#define MOTOR_ENABLED 0x71
|
||||||
#define MOTOR_ANGLE 0x72
|
#define MOTOR_ANGLE 0x72
|
||||||
#endif // REG_CAH_H_
|
#endif // REG_CAH_H_
|
||||||
|
|
|
@ -1,31 +1,31 @@
|
||||||
; PlatformIO Project Configuration File
|
; PlatformIO Project Configuration File
|
||||||
;
|
;
|
||||||
; Build options: build flags, source filter
|
; Build options: build flags, source filter
|
||||||
; Upload options: custom upload port, speed and extra flags
|
; Upload options: custom upload port, speed and extra flags
|
||||||
; Library options: dependencies, extra library storages
|
; Library options: dependencies, extra library storages
|
||||||
; Advanced options: extra scripting
|
; Advanced options: extra scripting
|
||||||
;
|
;
|
||||||
; Please visit documentation for the other options and examples
|
; Please visit documentation for the other options and examples
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
|
|
||||||
[env:robotroller_reborn]
|
[env:robotroller_reborn]
|
||||||
platform = ststm32
|
platform = ststm32
|
||||||
board = genericSTM32F446RE
|
board = genericSTM32F446RE
|
||||||
framework = arduino
|
framework = arduino
|
||||||
upload_protocol = stlink
|
upload_protocol = stlink
|
||||||
debug_tool = stlink
|
debug_tool = stlink
|
||||||
monitor_speed = 19200
|
monitor_speed = 19200
|
||||||
monitor_parity = N
|
monitor_parity = N
|
||||||
build_flags =
|
build_flags =
|
||||||
-DSTM32F446xx
|
-DSTM32F446xx
|
||||||
-D HAL_CAN_MODULE_ENABLED
|
-D HAL_CAN_MODULE_ENABLED
|
||||||
-D SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH
|
-D SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH
|
||||||
lib_deps =
|
lib_deps =
|
||||||
askuric/Simple FOC@^2.3.4
|
askuric/Simple FOC@^2.3.4
|
||||||
pazi88/STM32_CAN@^1.1.2
|
pazi88/STM32_CAN@^1.1.2
|
||||||
|
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
pre:gen_compile_commands.py
|
pre:gen_compile_commands.py
|
||||||
post:hex_compile.py
|
post:hex_compile.py
|
||||||
|
|
|
@ -1,272 +1,272 @@
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "hal_conf_extra.h"
|
#include "hal_conf_extra.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void flash_unlock(){
|
void flash_unlock(){
|
||||||
|
|
||||||
// Check if flash is locked
|
// Check if flash is locked
|
||||||
if(!(FLASH->CR & FLASH_CR_LOCK)) {
|
if(!(FLASH->CR & FLASH_CR_LOCK)) {
|
||||||
return; // Already unlocked
|
return; // Already unlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write flash key sequence to unlock
|
// Write flash key sequence to unlock
|
||||||
FLASH->KEYR = 0x45670123; // First key
|
FLASH->KEYR = 0x45670123; // First key
|
||||||
FLASH->KEYR = 0xCDEF89AB; // Second key
|
FLASH->KEYR = 0xCDEF89AB; // Second key
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flash_lock() {
|
void flash_lock() {
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
return; // Already locked
|
return; // Already locked
|
||||||
}
|
}
|
||||||
FLASH->CR |= FLASH_CR_LOCK; // Lock flash memory
|
FLASH->CR |= FLASH_CR_LOCK; // Lock flash memory
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase_sector(uint8_t sector){
|
void erase_sector(uint8_t sector){
|
||||||
|
|
||||||
// Wait if flash is busy
|
// Wait if flash is busy
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Check if flash is locked and unlock if needed
|
// Check if flash is locked and unlock if needed
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sector erase bit and sector number
|
// Set sector erase bit and sector number
|
||||||
FLASH->CR |= FLASH_CR_SER;
|
FLASH->CR |= FLASH_CR_SER;
|
||||||
FLASH->CR &= ~FLASH_CR_SNB;
|
FLASH->CR &= ~FLASH_CR_SNB;
|
||||||
FLASH->CR |= (sector << FLASH_CR_SNB_Pos) & FLASH_CR_SNB_Msk;
|
FLASH->CR |= (sector << FLASH_CR_SNB_Pos) & FLASH_CR_SNB_Msk;
|
||||||
|
|
||||||
// Start erase
|
// Start erase
|
||||||
FLASH->CR |= FLASH_CR_STRT;
|
FLASH->CR |= FLASH_CR_STRT;
|
||||||
|
|
||||||
// Wait for erase to complete
|
// Wait for erase to complete
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Clear sector erase bit
|
// Clear sector erase bit
|
||||||
FLASH->CR &= ~FLASH_CR_SER;
|
FLASH->CR &= ~FLASH_CR_SER;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flash_program_word(uint32_t address,uint32_t data,uint32_t byte_len){
|
void flash_program_word(uint32_t address,uint32_t data,uint32_t byte_len){
|
||||||
|
|
||||||
// Wait if flash is busy
|
// Wait if flash is busy
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
// Check if flash is locked and unlock if needed
|
// Check if flash is locked and unlock if needed
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set program bit 32bit programm size and Write data to address
|
// Set program bit 32bit programm size and Write data to address
|
||||||
if(byte_len == 1) {
|
if(byte_len == 1) {
|
||||||
FLASH_8BYTE;
|
FLASH_8BYTE;
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
*(volatile uint8_t*)address = (uint8_t)data;
|
*(volatile uint8_t*)address = (uint8_t)data;
|
||||||
} else {
|
} else {
|
||||||
FLASH_32BYTE;
|
FLASH_32BYTE;
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
*(volatile uint32_t*)address = data;
|
*(volatile uint32_t*)address = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for programming to complete
|
// Wait for programming to complete
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Clear program bit
|
// Clear program bit
|
||||||
FLASH->CR &= ~FLASH_CR_PG;
|
FLASH->CR &= ~FLASH_CR_PG;
|
||||||
|
|
||||||
}
|
}
|
||||||
void flash_write(uint32_t addr, FLASH_RECORD* record){
|
void flash_write(uint32_t addr, FLASH_RECORD* record){
|
||||||
|
|
||||||
uint32_t* data = (uint32_t*)record;
|
uint32_t* data = (uint32_t*)record;
|
||||||
uint32_t size = FLASH_RECORD_SIZE / 4; //count words in struct
|
uint32_t size = FLASH_RECORD_SIZE / 4; //count words in struct
|
||||||
// Wait if flash is busy
|
// Wait if flash is busy
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Check if flash is locked and unlock if needed
|
// Check if flash is locked and unlock if needed
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set program bit and write data to flash
|
// Set program bit and write data to flash
|
||||||
FLASH_32BYTE;
|
FLASH_32BYTE;
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
|
|
||||||
for(int i = 0;i < size;i++){
|
for(int i = 0;i < size;i++){
|
||||||
*(volatile uint32_t*)(addr + (i * 4)) = data[i];
|
*(volatile uint32_t*)(addr + (i * 4)) = data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear program bit
|
// Clear program bit
|
||||||
FLASH->CR &= ~FLASH_CR_PG;
|
FLASH->CR &= ~FLASH_CR_PG;
|
||||||
write_ptr = addr + (size * 4); //increase variable storing addr
|
write_ptr = addr + (size * 4); //increase variable storing addr
|
||||||
flash_lock();
|
flash_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t flash_read_word(uint32_t address){
|
uint8_t flash_read_word(uint32_t address){
|
||||||
|
|
||||||
// Check if address is valid
|
// Check if address is valid
|
||||||
if(address < FLASH_BASE || address > FLASH_END) {
|
if(address < FLASH_BASE || address > FLASH_END) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read byte from flash memory
|
// Read byte from flash memory
|
||||||
return *((volatile uint8_t*)address);
|
return *((volatile uint8_t*)address);
|
||||||
|
|
||||||
}
|
}
|
||||||
// Wait if flash
|
// Wait if flash
|
||||||
// bool validata_crc(FLASH_RECORD* crc){
|
// bool validata_crc(FLASH_RECORD* crc){
|
||||||
// return crc->crc == 0x6933? true : false;
|
// return crc->crc == 0x6933? true : false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
uint16_t validate_crc16(uint8_t *data, uint32_t length) {
|
uint16_t validate_crc16(uint8_t *data, uint32_t length) {
|
||||||
uint16_t crc = 0xFFFF; // start value for CRC MODBUS
|
uint16_t crc = 0xFFFF; // start value for CRC MODBUS
|
||||||
while (length--) {
|
while (length--) {
|
||||||
crc ^= *data++; // XOR
|
crc ^= *data++; // XOR
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
if (crc & 0x0001) {
|
if (crc & 0x0001) {
|
||||||
crc = (crc >> 1) ^ 0xA001; // polynome 0x8005 (reverse)
|
crc = (crc >> 1) ^ 0xA001; // polynome 0x8005 (reverse)
|
||||||
} else {
|
} else {
|
||||||
crc >>= 1;
|
crc >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t calc_crc_struct(FLASH_RECORD* res){
|
uint16_t calc_crc_struct(FLASH_RECORD* res){
|
||||||
|
|
||||||
uint8_t arr_res[FLASH_RECORD_SIZE - 2];
|
uint8_t arr_res[FLASH_RECORD_SIZE - 2];
|
||||||
uint16_t crc_res;
|
uint16_t crc_res;
|
||||||
/* sorting data without CRC */
|
/* sorting data without CRC */
|
||||||
arr_res[0] = res->data_id;
|
arr_res[0] = res->data_id;
|
||||||
arr_res[1] = res->data_type;
|
arr_res[1] = res->data_type;
|
||||||
|
|
||||||
/* from 32 to 8 bit */
|
/* from 32 to 8 bit */
|
||||||
for(int i = 0;i < 4;i++)
|
for(int i = 0;i < 4;i++)
|
||||||
arr_res[i + 2] = (uint8_t)(res->value >> i * 8);
|
arr_res[i + 2] = (uint8_t)(res->value >> i * 8);
|
||||||
|
|
||||||
crc_res = validate_crc16(arr_res,FLASH_RECORD_SIZE - 2);
|
crc_res = validate_crc16(arr_res,FLASH_RECORD_SIZE - 2);
|
||||||
return crc_res;
|
return crc_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* read struct from FLASH */
|
/* read struct from FLASH */
|
||||||
void flash_read(uint32_t addr,FLASH_RECORD* ptr){
|
void flash_read(uint32_t addr,FLASH_RECORD* ptr){
|
||||||
uint8_t* flash_ptr = (uint8_t*)addr;
|
uint8_t* flash_ptr = (uint8_t*)addr;
|
||||||
uint8_t* dest = (uint8_t*)ptr;
|
uint8_t* dest = (uint8_t*)ptr;
|
||||||
for(int i = 0;i < FLASH_RECORD_SIZE;i++)
|
for(int i = 0;i < FLASH_RECORD_SIZE;i++)
|
||||||
dest[i] = flash_ptr[i];
|
dest[i] = flash_ptr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void compact_page(){
|
void compact_page(){
|
||||||
FLASH_RECORD latest[PARAM_COUNT] = {0};
|
FLASH_RECORD latest[PARAM_COUNT] = {0};
|
||||||
for(int i = (uint32_t)SECTOR_6;i < (uint32_t)SECTOR_6_END;i += FLASH_RECORD_SIZE) {
|
for(int i = (uint32_t)SECTOR_6;i < (uint32_t)SECTOR_6_END;i += FLASH_RECORD_SIZE) {
|
||||||
FLASH_RECORD rec;
|
FLASH_RECORD rec;
|
||||||
flash_read(i,&rec);
|
flash_read(i,&rec);
|
||||||
uint16_t calculated_crc = calc_crc_struct(&rec);
|
uint16_t calculated_crc = calc_crc_struct(&rec);
|
||||||
|
|
||||||
if (calculated_crc == rec.crc && rec.data_id < PARAM_COUNT) {
|
if (calculated_crc == rec.crc && rec.data_id < PARAM_COUNT) {
|
||||||
// if the crc does not match, we check further
|
// if the crc does not match, we check further
|
||||||
latest[rec.data_id] = rec;
|
latest[rec.data_id] = rec;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// if
|
// if
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
erase_sector(6);
|
erase_sector(6);
|
||||||
write_ptr = SECTOR_6; // Сброс на начало
|
write_ptr = SECTOR_6; // Сброс на начало
|
||||||
for (int i = 0; i < PARAM_COUNT; i++) {
|
for (int i = 0; i < PARAM_COUNT; i++) {
|
||||||
if (latest[i].data_id != 0xFF) {
|
if (latest[i].data_id != 0xFF) {
|
||||||
// alignment
|
// alignment
|
||||||
if (write_ptr % 4 != 0) {
|
if (write_ptr % 4 != 0) {
|
||||||
write_ptr += (4 - (write_ptr % 4));
|
write_ptr += (4 - (write_ptr % 4));
|
||||||
}
|
}
|
||||||
flash_write(write_ptr, &latest[i]);
|
flash_write(write_ptr, &latest[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_param(uint8_t param_id, uint32_t val) {
|
void write_param(uint8_t param_id, uint32_t val) {
|
||||||
FLASH_RECORD param_flash;
|
FLASH_RECORD param_flash;
|
||||||
// __disable_irq(); // Interrupt off
|
// __disable_irq(); // Interrupt off
|
||||||
param_flash.data_id = param_id;
|
param_flash.data_id = param_id;
|
||||||
param_flash.value = val;
|
param_flash.value = val;
|
||||||
param_flash.data_type = sizeof(uint8_t);
|
param_flash.data_type = sizeof(uint8_t);
|
||||||
param_flash.crc = calc_crc_struct(¶m_flash);
|
param_flash.crc = calc_crc_struct(¶m_flash);
|
||||||
|
|
||||||
// check alignment
|
// check alignment
|
||||||
if (write_ptr % 8 != 0) {
|
if (write_ptr % 8 != 0) {
|
||||||
write_ptr += (8 - (write_ptr % 8));
|
write_ptr += (8 - (write_ptr % 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check buffer overflow
|
// check buffer overflow
|
||||||
if (write_ptr + FLASH_RECORD_SIZE >= SECTOR_6_END) {
|
if (write_ptr + FLASH_RECORD_SIZE >= SECTOR_6_END) {
|
||||||
compact_page(); // after compact_page update
|
compact_page(); // after compact_page update
|
||||||
// alignment
|
// alignment
|
||||||
if (write_ptr % 8 != 0) {
|
if (write_ptr % 8 != 0) {
|
||||||
write_ptr += (8 - (write_ptr % 8));
|
write_ptr += (8 - (write_ptr % 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_write(write_ptr, ¶m_flash); //inside the function, the write_ptr pointer is automatically incremented by the size of the structure
|
flash_write(write_ptr, ¶m_flash); //inside the function, the write_ptr pointer is automatically incremented by the size of the structure
|
||||||
|
|
||||||
// __enable_irq(); // Interrupt on
|
// __enable_irq(); // Interrupt on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void write_flash_page(const uint8_t* data, uint16_t len) { // Добавлен const
|
void write_flash_page(const uint8_t* data, uint16_t len) { // Добавлен const
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
uint32_t word = 0;
|
uint32_t word = 0;
|
||||||
for (uint16_t i = 0; i < len; i += 4) {
|
for (uint16_t i = 0; i < len; i += 4) {
|
||||||
memcpy(&word, &data[i], 4); // Безопасное копирование
|
memcpy(&word, &data[i], 4); // Безопасное копирование
|
||||||
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, ptr_fl + i, word);
|
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, ptr_fl + i, word);
|
||||||
}
|
}
|
||||||
ptr_fl += len;
|
ptr_fl += len;
|
||||||
flash_lock();
|
flash_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void erase_flash_pages() {
|
void erase_flash_pages() {
|
||||||
FLASH_EraseInitTypeDef erase;
|
FLASH_EraseInitTypeDef erase;
|
||||||
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
|
erase.TypeErase = FLASH_TYPEERASE_SECTORS;
|
||||||
erase.Sector = FLASH_SECTOR_2;
|
erase.Sector = FLASH_SECTOR_2;
|
||||||
erase.NbSectors = 4;
|
erase.NbSectors = 4;
|
||||||
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
erase.VoltageRange = FLASH_VOLTAGE_RANGE_3;
|
||||||
|
|
||||||
uint32_t error;
|
uint32_t error;
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
HAL_FLASHEx_Erase(&erase, &error);
|
HAL_FLASHEx_Erase(&erase, &error);
|
||||||
flash_lock();
|
flash_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FLASH_RECORD* load_params(){
|
FLASH_RECORD* load_params(){
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
static FLASH_RECORD latest[PARAM_COUNT] = {0};
|
static FLASH_RECORD latest[PARAM_COUNT] = {0};
|
||||||
FLASH_RECORD res;
|
FLASH_RECORD res;
|
||||||
|
|
||||||
for(uint32_t addr = SECTOR_6;addr < SECTOR_6_END;addr +=FLASH_RECORD_SIZE) {
|
for(uint32_t addr = SECTOR_6;addr < SECTOR_6_END;addr +=FLASH_RECORD_SIZE) {
|
||||||
flash_read(addr,&res);
|
flash_read(addr,&res);
|
||||||
|
|
||||||
|
|
||||||
uint16_t calculated_crc = calc_crc_struct(&res);
|
uint16_t calculated_crc = calc_crc_struct(&res);
|
||||||
if (calculated_crc != res.crc || res.data_id >= PARAM_COUNT) continue;
|
if (calculated_crc != res.crc || res.data_id >= PARAM_COUNT) continue;
|
||||||
|
|
||||||
else{
|
else{
|
||||||
latest[res.data_id] = res;
|
latest[res.data_id] = res;
|
||||||
write_ptr = addr + FLASH_RECORD_SIZE;
|
write_ptr = addr + FLASH_RECORD_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,171 +1,171 @@
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <STM32_CAN.h>
|
#include <STM32_CAN.h>
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
STM32_CAN Can(CAN2, DEF);
|
STM32_CAN Can(CAN2, DEF);
|
||||||
|
|
||||||
volatile bool fw_update = false;
|
volatile bool fw_update = false;
|
||||||
volatile bool app_valid = false;
|
volatile bool app_valid = false;
|
||||||
|
|
||||||
volatile uint32_t fw_size = 0;
|
volatile uint32_t fw_size = 0;
|
||||||
volatile uint16_t fw_crc = 0;
|
volatile uint16_t fw_crc = 0;
|
||||||
volatile uint32_t jump;
|
volatile uint32_t jump;
|
||||||
static FLASH_RECORD *flash_record = {0};
|
static FLASH_RECORD *flash_record = {0};
|
||||||
static uint32_t ptr_flash;
|
static uint32_t ptr_flash;
|
||||||
|
|
||||||
volatile uint32_t msg_id;
|
volatile uint32_t msg_id;
|
||||||
volatile uint16_t id_x;
|
volatile uint16_t id_x;
|
||||||
volatile uint8_t msg_ch;
|
volatile uint8_t msg_ch;
|
||||||
|
|
||||||
// Прототипы функций
|
// Прототипы функций
|
||||||
void jump_to_app();
|
void jump_to_app();
|
||||||
void process_can_message(const CAN_message_t &msg);
|
void process_can_message(const CAN_message_t &msg);
|
||||||
void erase_flash_pages();
|
void erase_flash_pages();
|
||||||
bool verify_firmware();
|
bool verify_firmware();
|
||||||
void send_ack(uint8_t status);
|
void send_ack(uint8_t status);
|
||||||
bool is_app_valid();
|
bool is_app_valid();
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.setRx(HARDWARE_SERIAL_RX_PIN);
|
Serial.setRx(HARDWARE_SERIAL_RX_PIN);
|
||||||
Serial.setTx(HARDWARE_SERIAL_TX_PIN);
|
Serial.setTx(HARDWARE_SERIAL_TX_PIN);
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
Can.begin();
|
Can.begin();
|
||||||
Can.setBaudRate(1000000);
|
Can.setBaudRate(1000000);
|
||||||
TIM_TypeDef *Instance = TIM2;
|
TIM_TypeDef *Instance = TIM2;
|
||||||
HardwareTimer *SendTimer = new HardwareTimer(Instance);
|
HardwareTimer *SendTimer = new HardwareTimer(Instance);
|
||||||
SendTimer->setOverflow(100, HERTZ_FORMAT); // 50 Hz
|
SendTimer->setOverflow(100, HERTZ_FORMAT); // 50 Hz
|
||||||
SendTimer->resume();
|
SendTimer->resume();
|
||||||
Can.setFilter(0, 0, STD);
|
Can.setFilter(0, 0, STD);
|
||||||
|
|
||||||
// Настройка GPIO
|
// Настройка GPIO
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
|
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
|
||||||
GPIOC->MODER |= GPIO_MODER_MODE10_0 | GPIO_MODER_MODE11_0;
|
GPIOC->MODER |= GPIO_MODER_MODE10_0 | GPIO_MODER_MODE11_0;
|
||||||
GPIOC->ODR &= ~GPIO_ODR_OD11;
|
GPIOC->ODR &= ~GPIO_ODR_OD11;
|
||||||
GPIOC->ODR |= GPIO_ODR_OD10;
|
GPIOC->ODR |= GPIO_ODR_OD10;
|
||||||
|
|
||||||
flash_record = load_params();
|
flash_record = load_params();
|
||||||
if(flash_record[firmw].value == UPDATE_FLAG) {
|
if(flash_record[firmw].value == UPDATE_FLAG) {
|
||||||
fw_update = true;
|
fw_update = true;
|
||||||
for(int i = 0; i < 5;i++){
|
for(int i = 0; i < 5;i++){
|
||||||
GPIOC->ODR ^= GPIO_ODR_OD10; // Indecate message
|
GPIOC->ODR ^= GPIO_ODR_OD10; // Indecate message
|
||||||
delay(100);
|
delay(100);
|
||||||
}
|
}
|
||||||
// write_param(firmw,0); //reset flasg
|
// write_param(firmw,0); //reset flasg
|
||||||
erase_flash_pages();
|
erase_flash_pages();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
// for st-link update, because he doesnt reset flag_update
|
// for st-link update, because he doesnt reset flag_update
|
||||||
if(is_app_valid()) jump_to_app(); //firmware exist
|
if(is_app_valid()) jump_to_app(); //firmware exist
|
||||||
else fw_update = true; //firmware doesnt exist, but we in bootloader
|
else fw_update = true; //firmware doesnt exist, but we in bootloader
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIOC->ODR |= GPIO_ODR_OD10;
|
GPIOC->ODR |= GPIO_ODR_OD10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void process_can_message(const CAN_message_t &msg) {
|
void process_can_message(const CAN_message_t &msg) {
|
||||||
msg_id = msg.id;
|
msg_id = msg.id;
|
||||||
/* 0x697
|
/* 0x697
|
||||||
69 - slave addr
|
69 - slave addr
|
||||||
7 || 8 - REG_READ or REG_WRITE */
|
7 || 8 - REG_READ or REG_WRITE */
|
||||||
|
|
||||||
id_x = (msg_id >> 4) & 0xFFFF; // saved address
|
id_x = (msg_id >> 4) & 0xFFFF; // saved address
|
||||||
msg_ch = msg_id & 0xF; // saved id
|
msg_ch = msg_id & 0xF; // saved id
|
||||||
if(id_x == flash_record[addr_id].value){
|
if(id_x == flash_record[addr_id].value){
|
||||||
switch(msg_ch) {
|
switch(msg_ch) {
|
||||||
case BOOT_CAN_ID:
|
case BOOT_CAN_ID:
|
||||||
if(msg.buf[0] == 0x01) { // start transfer
|
if(msg.buf[0] == 0x01) { // start transfer
|
||||||
fw_size = *(uint32_t*)&msg.buf[1]; //size of firmware
|
fw_size = *(uint32_t*)&msg.buf[1]; //size of firmware
|
||||||
fw_crc = *(uint16_t*)&msg.buf[5]; //crc
|
fw_crc = *(uint16_t*)&msg.buf[5]; //crc
|
||||||
ptr_flash = APP_ADDRESS;
|
ptr_flash = APP_ADDRESS;
|
||||||
send_ack(0x01);
|
send_ack(0x01);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DATA_CAN_ID: // Data packet
|
case DATA_CAN_ID: // Data packet
|
||||||
if(ptr_flash < (APP_ADDRESS + fw_size)) {
|
if(ptr_flash < (APP_ADDRESS + fw_size)) {
|
||||||
write_flash_page((const uint8_t*)msg.buf, msg.len);
|
write_flash_page((const uint8_t*)msg.buf, msg.len);
|
||||||
ptr_flash += msg.len;
|
ptr_flash += msg.len;
|
||||||
send_ack(0x02);
|
send_ack(0x02);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BOOT_CAN_END: // End of transfer
|
case BOOT_CAN_END: // End of transfer
|
||||||
if(verify_firmware()) {
|
if(verify_firmware()) {
|
||||||
send_ack(0xAA);
|
send_ack(0xAA);
|
||||||
write_param(firmw,0); //reset flag set 0
|
write_param(firmw,0); //reset flag set 0
|
||||||
fw_update = false; //reset flag
|
fw_update = false; //reset flag
|
||||||
// erase_sector(7);
|
// erase_sector(7);
|
||||||
delay(500);
|
delay(500);
|
||||||
NVIC_SystemReset();
|
NVIC_SystemReset();
|
||||||
} else {
|
} else {
|
||||||
send_ack(0x55);
|
send_ack(0x55);
|
||||||
erase_flash_pages(); //if error
|
erase_flash_pages(); //if error
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void jump_to_app() {
|
void jump_to_app() {
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
jump = *(volatile uint32_t*)(APP_ADDRESS + 4);
|
jump = *(volatile uint32_t*)(APP_ADDRESS + 4);
|
||||||
void (*app_entry)(void);
|
void (*app_entry)(void);
|
||||||
app_entry = (void (*)(void))jump;
|
app_entry = (void (*)(void))jump;
|
||||||
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < 8; i++) {
|
for (uint32_t i = 0; i < 8; i++) {
|
||||||
NVIC->ICPR[i] = 0xFFFFFFFF;
|
NVIC->ICPR[i] = 0xFFFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
__set_MSP(*(volatile uint32_t*)APP_ADDRESS);
|
__set_MSP(*(volatile uint32_t*)APP_ADDRESS);
|
||||||
// SCB->VTOR = (uint32_t)0x08008004;
|
// SCB->VTOR = (uint32_t)0x08008004;
|
||||||
app_entry();
|
app_entry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool verify_firmware() {
|
bool verify_firmware() {
|
||||||
uint16_t calculated_crc = 0;
|
uint16_t calculated_crc = 0;
|
||||||
calculated_crc = validate_crc16((uint8_t*)APP_ADDRESS,fw_size);
|
calculated_crc = validate_crc16((uint8_t*)APP_ADDRESS,fw_size);
|
||||||
return (calculated_crc == fw_crc);
|
return (calculated_crc == fw_crc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_ack(uint8_t status) {
|
void send_ack(uint8_t status) {
|
||||||
|
|
||||||
CAN_message_t ack;
|
CAN_message_t ack;
|
||||||
ack.id = ACK_CAN_ID;
|
ack.id = ACK_CAN_ID;
|
||||||
ack.len = 1;
|
ack.len = 1;
|
||||||
ack.buf[0] = status;
|
ack.buf[0] = status;
|
||||||
Can.write(ack);
|
Can.write(ack);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_app_valid() {
|
bool is_app_valid() {
|
||||||
|
|
||||||
volatile uint32_t* app_vector = (volatile uint32_t*)APP_ADDRESS;
|
volatile uint32_t* app_vector = (volatile uint32_t*)APP_ADDRESS;
|
||||||
|
|
||||||
// Check stack pointer
|
// Check stack pointer
|
||||||
bool sp_valid = (app_vector[0] >= 0x20000000) &&
|
bool sp_valid = (app_vector[0] >= 0x20000000) &&
|
||||||
(app_vector[0] <= (0x20000000 + 128*1024)); // Для STM32 с 128K RAM
|
(app_vector[0] <= (0x20000000 + 128*1024)); // Для STM32 с 128K RAM
|
||||||
|
|
||||||
// check reset_handler
|
// check reset_handler
|
||||||
bool pc_valid = (app_vector[1] >= 0x08000000) &&
|
bool pc_valid = (app_vector[1] >= 0x08000000) &&
|
||||||
(app_vector[1] <= (0x08000000 + 1024*1024)); // Для 1MB Flash
|
(app_vector[1] <= (0x08000000 + 1024*1024)); // Для 1MB Flash
|
||||||
|
|
||||||
// check two words on reset value
|
// check two words on reset value
|
||||||
bool not_erased = (app_vector[0] != 0xFFFFFFFF) &&
|
bool not_erased = (app_vector[0] != 0xFFFFFFFF) &&
|
||||||
(app_vector[1] != 0xFFFFFFFF);
|
(app_vector[1] != 0xFFFFFFFF);
|
||||||
|
|
||||||
return sp_valid && pc_valid && not_erased;
|
return sp_valid && pc_valid && not_erased;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if(fw_update) {
|
if(fw_update) {
|
||||||
CAN_message_t msg;
|
CAN_message_t msg;
|
||||||
while(Can.read(msg))
|
while(Can.read(msg))
|
||||||
process_can_message(msg);
|
process_can_message(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,141 +1,141 @@
|
||||||
import can
|
import can
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from intelhex import IntelHex
|
from intelhex import IntelHex
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_CHANNEL = 'socketcan'
|
CAN_CHANNEL = 'socketcan'
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
CAN_BITRATE = 1000000
|
CAN_BITRATE = 1000000
|
||||||
#ch =int(input("Введите id устройства:"))
|
#ch =int(input("Введите id устройства:"))
|
||||||
ch = int(sys.argv[2])
|
ch = int(sys.argv[2])
|
||||||
BOOT_CAN_ID = (ch * 16) + 1
|
BOOT_CAN_ID = (ch * 16) + 1
|
||||||
DATA_CAN_ID = (ch * 16) + 3
|
DATA_CAN_ID = (ch * 16) + 3
|
||||||
BOOT_CAN_END = (ch * 16) + 2
|
BOOT_CAN_END = (ch * 16) + 2
|
||||||
ACK_CAN_ID = 0x05
|
ACK_CAN_ID = 0x05
|
||||||
|
|
||||||
#конфиг для crc16 ibm
|
#конфиг для crc16 ibm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def debug_print(msg):
|
def debug_print(msg):
|
||||||
print(f"[DEBUG] {msg}")
|
print(f"[DEBUG] {msg}")
|
||||||
|
|
||||||
def calculate_crc16(data: bytes) -> int:
|
def calculate_crc16(data: bytes) -> int:
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
def send_firmware(hex_file):
|
def send_firmware(hex_file):
|
||||||
try:
|
try:
|
||||||
debug_print("Инициализация CAN...")
|
debug_print("Инициализация CAN...")
|
||||||
bus = can.interface.Bus(
|
bus = can.interface.Bus(
|
||||||
channel=CAN_INTERFACE,
|
channel=CAN_INTERFACE,
|
||||||
bustype=CAN_CHANNEL,
|
bustype=CAN_CHANNEL,
|
||||||
bitrate=CAN_BITRATE
|
bitrate=CAN_BITRATE
|
||||||
)
|
)
|
||||||
|
|
||||||
debug_print("Чтение HEX-файла...")
|
debug_print("Чтение HEX-файла...")
|
||||||
ih = IntelHex(hex_file)
|
ih = IntelHex(hex_file)
|
||||||
binary_data = ih.tobinstr() # Исправлено на tobinstr()
|
binary_data = ih.tobinstr() # Исправлено на tobinstr()
|
||||||
fw_size = len(binary_data)
|
fw_size = len(binary_data)
|
||||||
debug_print(f"Размер прошивки: {fw_size} байт")
|
debug_print(f"Размер прошивки: {fw_size} байт")
|
||||||
|
|
||||||
# Расчет CRC
|
# Расчет CRC
|
||||||
debug_print("Расчёт CRC...")
|
debug_print("Расчёт CRC...")
|
||||||
# calculator = Calculator(Crc16.IBM)
|
# calculator = Calculator(Crc16.IBM)
|
||||||
fw_crc = calculate_crc16(binary_data)
|
fw_crc = calculate_crc16(binary_data)
|
||||||
debug_print(f"CRC: 0x{fw_crc:04X}")
|
debug_print(f"CRC: 0x{fw_crc:04X}")
|
||||||
|
|
||||||
# Отправка START
|
# Отправка START
|
||||||
start_data = bytearray([0x01])
|
start_data = bytearray([0x01])
|
||||||
start_data += fw_size.to_bytes(4, 'little')
|
start_data += fw_size.to_bytes(4, 'little')
|
||||||
start_data += fw_crc.to_bytes(2, 'little')
|
start_data += fw_crc.to_bytes(2, 'little')
|
||||||
|
|
||||||
debug_print(f"START: {list(start_data)}")
|
debug_print(f"START: {list(start_data)}")
|
||||||
start_msg = can.Message(
|
start_msg = can.Message(
|
||||||
arbitration_id=BOOT_CAN_ID,
|
arbitration_id=BOOT_CAN_ID,
|
||||||
data=bytes(start_data),
|
data=bytes(start_data),
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(start_msg)
|
bus.send(start_msg)
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
debug_print(f"Ошибка отправки START: {str(e)}")
|
debug_print(f"Ошибка отправки START: {str(e)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Ожидание ACK
|
# Ожидание ACK
|
||||||
debug_print("Ожидание ACK...")
|
debug_print("Ожидание ACK...")
|
||||||
ack = wait_for_ack(bus)
|
ack = wait_for_ack(bus)
|
||||||
if not ack:
|
if not ack:
|
||||||
debug_print("Таймаут ACK START")
|
debug_print("Таймаут ACK START")
|
||||||
return
|
return
|
||||||
debug_print(f"Получен ACK: {list(ack.data)}")
|
debug_print(f"Получен ACK: {list(ack.data)}")
|
||||||
|
|
||||||
# Отправка данных
|
# Отправка данных
|
||||||
packet_size = 8
|
packet_size = 8
|
||||||
for i in range(0, len(binary_data), packet_size):
|
for i in range(0, len(binary_data), packet_size):
|
||||||
chunk = binary_data[i:i+packet_size]
|
chunk = binary_data[i:i+packet_size]
|
||||||
# Дополнение до 8 байт
|
# Дополнение до 8 байт
|
||||||
if len(chunk) < 8:
|
if len(chunk) < 8:
|
||||||
chunk += b'\xFF' * (8 - len(chunk))
|
chunk += b'\xFF' * (8 - len(chunk))
|
||||||
|
|
||||||
debug_print(f"Пакет {i//8}: {list(chunk)}")
|
debug_print(f"Пакет {i//8}: {list(chunk)}")
|
||||||
data_msg = can.Message(
|
data_msg = can.Message(
|
||||||
arbitration_id=DATA_CAN_ID,
|
arbitration_id=DATA_CAN_ID,
|
||||||
data=chunk,
|
data=chunk,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(data_msg)
|
bus.send(data_msg)
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
debug_print(f"Ошибка отправки данных: {str(e)}")
|
debug_print(f"Ошибка отправки данных: {str(e)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
ack = wait_for_ack(bus)
|
ack = wait_for_ack(bus)
|
||||||
if not ack:
|
if not ack:
|
||||||
debug_print("Таймаут ACK DATA")
|
debug_print("Таймаут ACK DATA")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Финал
|
# Финал
|
||||||
debug_print("Отправка FINISH...")
|
debug_print("Отправка FINISH...")
|
||||||
finish_msg = can.Message(
|
finish_msg = can.Message(
|
||||||
arbitration_id=BOOT_CAN_END,
|
arbitration_id=BOOT_CAN_END,
|
||||||
data=bytes([0xAA]),
|
data=bytes([0xAA]),
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(finish_msg)
|
bus.send(finish_msg)
|
||||||
|
|
||||||
ack = wait_for_ack(bus, timeout=1.0)
|
ack = wait_for_ack(bus, timeout=1.0)
|
||||||
if ack and ack.data[0] == 0xAA:
|
if ack and ack.data[0] == 0xAA:
|
||||||
debug_print("Прошивка подтверждена!")
|
debug_print("Прошивка подтверждена!")
|
||||||
else:
|
else:
|
||||||
debug_print("Ошибка верификации!")
|
debug_print("Ошибка верификации!")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_print(f"Критическая ошибка: {str(e)}")
|
debug_print(f"Критическая ошибка: {str(e)}")
|
||||||
finally:
|
finally:
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
||||||
def wait_for_ack(bus, timeout=1.0):
|
def wait_for_ack(bus, timeout=1.0):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1) # Неблокирующий режим
|
msg = bus.recv(timeout=0.1) # Неблокирующий режим
|
||||||
if msg and msg.arbitration_id == ACK_CAN_ID:
|
if msg and msg.arbitration_id == ACK_CAN_ID:
|
||||||
return msg
|
return msg
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print("Использование: sudo python3 can_flasher.py firmware.hex")
|
print("Использование: sudo python3 can_flasher.py firmware.hex")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
send_firmware(sys.argv[1])
|
send_firmware(sys.argv[1])
|
||||||
|
|
|
@ -1,70 +1,70 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства (по умолчанию)
|
OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства (по умолчанию)
|
||||||
REG_WRITE = 0x8 # Код команды чтения
|
REG_WRITE = 0x8 # Код команды чтения
|
||||||
REG_ID = 0x55 # Адрес регистра с Firmware Update
|
REG_ID = 0x55 # Адрес регистра с Firmware Update
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
# Инициализация CAN-интерфейса
|
# Инициализация CAN-интерфейса
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
# ======= 1. Запрос текущего ID устройства =======
|
# ======= 1. Запрос текущего ID устройства =======
|
||||||
|
|
||||||
# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ
|
# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ
|
||||||
can_id_read = (OLD_DEVICE_ID << 4) | REG_WRITE
|
can_id_read = (OLD_DEVICE_ID << 4) | REG_WRITE
|
||||||
|
|
||||||
# Данные для запроса: [регистр, резервный байт]
|
# Данные для запроса: [регистр, резервный байт]
|
||||||
data_read = [REG_ID, 0x00]
|
data_read = [REG_ID, 0x00]
|
||||||
|
|
||||||
# Формируем полные данные для расчета CRC:
|
# Формируем полные данные для расчета CRC:
|
||||||
# - CAN ID разбивается на 2 байта (little-endian)
|
# - CAN ID разбивается на 2 байта (little-endian)
|
||||||
# - Добавляем данные запроса
|
# - Добавляем данные запроса
|
||||||
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
||||||
|
|
||||||
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, 'little'))
|
crc_bytes = list(crc.to_bytes(2, 'little'))
|
||||||
|
|
||||||
# Собираем итоговый пакет: данные + CRC
|
# Собираем итоговый пакет: данные + CRC
|
||||||
packet_read = data_read + crc_bytes
|
packet_read = data_read + crc_bytes
|
||||||
|
|
||||||
print("Переход в boot режим", packet_read)
|
print("Переход в boot режим", packet_read)
|
||||||
send_can_message(bus, can_id_read, packet_read)
|
send_can_message(bus, can_id_read, packet_read)
|
||||||
|
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Использование: python3 firmware_test.py address")
|
print("Использование: python3 firmware_test.py address")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -1,78 +1,78 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
def flash_hex_with_stlink(hex_file_path):
|
def flash_hex_with_stlink(hex_file_path):
|
||||||
if not os.path.isfile(hex_file_path):
|
if not os.path.isfile(hex_file_path):
|
||||||
print(f"❌ Файл не найден: {hex_file_path}")
|
print(f"❌ Файл не найден: {hex_file_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
command = [
|
command = [
|
||||||
"st-flash",
|
"st-flash",
|
||||||
"--format", "ihex",
|
"--format", "ihex",
|
||||||
"write",
|
"write",
|
||||||
hex_file_path
|
hex_file_path
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(f"⚡️ Прошиваем {hex_file_path} через ST-Link...")
|
print(f"⚡️ Прошиваем {hex_file_path} через ST-Link...")
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
command,
|
command,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=30
|
timeout=30
|
||||||
)
|
)
|
||||||
|
|
||||||
print("▬▬▬ STDOUT ▬▬▬")
|
print("▬▬▬ STDOUT ▬▬▬")
|
||||||
print(result.stdout)
|
print(result.stdout)
|
||||||
|
|
||||||
print("▬▬▬ STDERR ▬▬▬")
|
print("▬▬▬ STDERR ▬▬▬")
|
||||||
print(result.stderr)
|
print(result.stderr)
|
||||||
|
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print("✅ Прошивка успешно завершена!")
|
print("✅ Прошивка успешно завершена!")
|
||||||
|
|
||||||
# Добавленный блок сброса
|
# Добавленный блок сброса
|
||||||
try:
|
try:
|
||||||
print("🔄 Выполняем сброс устройства...")
|
print("🔄 Выполняем сброс устройства...")
|
||||||
reset_result = subprocess.run(
|
reset_result = subprocess.run(
|
||||||
["st-info", "--reset"],
|
["st-info", "--reset"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
if reset_result.returncode == 0:
|
if reset_result.returncode == 0:
|
||||||
print("♻️ Устройство успешно сброшено!")
|
print("♻️ Устройство успешно сброшено!")
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ Ошибка (код: {reset_result.returncode})")
|
print(f"⚠️ Ошибка (код: {reset_result.returncode})")
|
||||||
print("▬▬▬ STDERR сброса ▬▬▬")
|
print("▬▬▬ STDERR сброса ▬▬▬")
|
||||||
print(reset_result.stderr)
|
print(reset_result.stderr)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"❌ Ошибка прошивки (код: {result.returncode})")
|
print(f"❌ Ошибка прошивки (код: {result.returncode})")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("❌ st-flash не найден! Установите stlink-tools.")
|
print("❌ st-flash не найден! Установите stlink-tools.")
|
||||||
return False
|
return False
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
print("❌ Таймаут операции! Проверьте подключение ST-Link.")
|
print("❌ Таймаут операции! Проверьте подключение ST-Link.")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Неизвестная ошибка: {str(e)}")
|
print(f"❌ Неизвестная ошибка: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Использование: python stlink_flash.py <firmware.hex>")
|
print("Использование: python stlink_flash.py <firmware.hex>")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if flash_hex_with_stlink(sys.argv[1]):
|
if flash_hex_with_stlink(sys.argv[1]):
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -1,100 +1,100 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
def flash_hex_with_stlink(hex_file_path, component_name):
|
def flash_hex_with_stlink(hex_file_path, component_name):
|
||||||
if not os.path.isfile(hex_file_path):
|
if not os.path.isfile(hex_file_path):
|
||||||
print(f"❌ Файл {component_name} не найден: {hex_file_path}")
|
print(f"❌ Файл {component_name} не найден: {hex_file_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
command = [
|
command = [
|
||||||
"st-flash",
|
"st-flash",
|
||||||
"--format", "ihex",
|
"--format", "ihex",
|
||||||
"write",
|
"write",
|
||||||
hex_file_path
|
hex_file_path
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(f"⚡️ Прошиваем {component_name} ({hex_file_path}) через ST-Link...")
|
print(f"⚡️ Прошиваем {component_name} ({hex_file_path}) через ST-Link...")
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
command,
|
command,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=30
|
timeout=30
|
||||||
)
|
)
|
||||||
|
|
||||||
print("▬▬▬ STDOUT ▬▬▬")
|
print("▬▬▬ STDOUT ▬▬▬")
|
||||||
print(result.stdout)
|
print(result.stdout)
|
||||||
|
|
||||||
print("▬▬▬ STDERR ▬▬▬")
|
print("▬▬▬ STDERR ▬▬▬")
|
||||||
print(result.stderr)
|
print(result.stderr)
|
||||||
|
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print(f"✅ {component_name} успешно прошит!")
|
print(f"✅ {component_name} успешно прошит!")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"❌ Ошибка прошивки {component_name} (код: {result.returncode})")
|
print(f"❌ Ошибка прошивки {component_name} (код: {result.returncode})")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("❌ st-flash не найден! Установите stlink-tools.")
|
print("❌ st-flash не найден! Установите stlink-tools.")
|
||||||
return False
|
return False
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
print(f"❌ Таймаут операции при прошивке {component_name}! Проверьте подключение ST-Link.")
|
print(f"❌ Таймаут операции при прошивке {component_name}! Проверьте подключение ST-Link.")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Неизвестная ошибка при прошивке {component_name}: {str(e)}")
|
print(f"❌ Неизвестная ошибка при прошивке {component_name}: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def reset_device():
|
def reset_device():
|
||||||
try:
|
try:
|
||||||
print("🔄 Выполняем сброс(перезагрузку) устройства...")
|
print("🔄 Выполняем сброс(перезагрузку) устройства...")
|
||||||
reset_result = subprocess.run(
|
reset_result = subprocess.run(
|
||||||
["st-info", "--reset"],
|
["st-info", "--reset"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
if reset_result.returncode == 0:
|
if reset_result.returncode == 0:
|
||||||
print("♻️ Устройство успешно сброшено!")
|
print("♻️ Устройство успешно сброшено!")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ Ошибка при сбросе (код: {reset_result.returncode})")
|
print(f"⚠️ Ошибка при сбросе (код: {reset_result.returncode})")
|
||||||
print("▬▬▬ STDERR сброса ▬▬▬")
|
print("▬▬▬ STDERR сброса ▬▬▬")
|
||||||
print(reset_result.stderr)
|
print(reset_result.stderr)
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print("Использование: python stlink_flash.py <bootloader.hex> <application.hex>")
|
print("Использование: python stlink_flash.py <bootloader.hex> <application.hex>")
|
||||||
print("Пример: python stlink_flash.py bootloader.hex firmware.hex")
|
print("Пример: python stlink_flash.py bootloader.hex firmware.hex")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
bootloader_path = sys.argv[1]
|
bootloader_path = sys.argv[1]
|
||||||
app_path = sys.argv[2]
|
app_path = sys.argv[2]
|
||||||
|
|
||||||
# Прошиваем сначала бутлоадер
|
# Прошиваем сначала бутлоадер
|
||||||
if not flash_hex_with_stlink(bootloader_path, "Bootloader"):
|
if not flash_hex_with_stlink(bootloader_path, "Bootloader"):
|
||||||
print("\n💥 Ошибка прошивки бутлоадера!")
|
print("\n💥 Ошибка прошивки бутлоадера!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Сбрасываем устройство после прошивки бутлоадера
|
# Сбрасываем устройство после прошивки бутлоадера
|
||||||
reset_device()
|
reset_device()
|
||||||
time.sleep(1) # Короткая пауза
|
time.sleep(1) # Короткая пауза
|
||||||
|
|
||||||
# Прошиваем основное приложение
|
# Прошиваем основное приложение
|
||||||
if not flash_hex_with_stlink(app_path, "Application"):
|
if not flash_hex_with_stlink(app_path, "Application"):
|
||||||
print("\n💥 Ошибка прошивки основного приложения!")
|
print("\n💥 Ошибка прошивки основного приложения!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Финальный сброс устройства
|
# Финальный сброс устройства
|
||||||
reset_device()
|
reset_device()
|
||||||
|
|
||||||
print("\n🎉 Все компоненты успешно прошиты!")
|
print("\n🎉 Все компоненты успешно прошиты!")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Checks: '-*, -misc-definitions-in-headers'
|
Checks: '-*, -misc-definitions-in-headers'
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
CompileFlags:
|
CompileFlags:
|
||||||
Add:
|
Add:
|
||||||
[
|
[
|
||||||
# -mlong-calls,
|
# -mlong-calls,
|
||||||
-DSSIZE_MAX,
|
-DSSIZE_MAX,
|
||||||
-DLWIP_NO_UNISTD_H=1,
|
-DLWIP_NO_UNISTD_H=1,
|
||||||
-Dssize_t=long,
|
-Dssize_t=long,
|
||||||
-D_SSIZE_T_DECLARED,
|
-D_SSIZE_T_DECLARED,
|
||||||
]
|
]
|
||||||
Remove:
|
Remove:
|
||||||
[
|
[
|
||||||
-fno-tree-switch-conversion,
|
-fno-tree-switch-conversion,
|
||||||
-mtext-section-literals,
|
-mtext-section-literals,
|
||||||
-mlongcalls,
|
-mlongcalls,
|
||||||
-fstrict-volatile-bitfields,
|
-fstrict-volatile-bitfields,
|
||||||
-free,
|
-free,
|
||||||
-fipa-pta,
|
-fipa-pta,
|
||||||
]
|
]
|
||||||
|
|
20
controller/fw/embed/.gitignore
vendored
20
controller/fw/embed/.gitignore
vendored
|
@ -1,10 +1,10 @@
|
||||||
.pio
|
.pio
|
||||||
.vscode/.browse.c_cpp.db*
|
.vscode/.browse.c_cpp.db*
|
||||||
.vscode/c_cpp_properties.json
|
.vscode/c_cpp_properties.json
|
||||||
.vscode/launch.json
|
.vscode/launch.json
|
||||||
.vscode/ipch
|
.vscode/ipch
|
||||||
.cache/
|
.cache/
|
||||||
.metadata/
|
.metadata/
|
||||||
cubemx_config/
|
cubemx_config/
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
../embed.rar
|
../embed.rar
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
Import("env")
|
Import("env")
|
||||||
|
|
||||||
# Получаем путь к компилятору из окружения PlatformIO
|
# Получаем путь к компилятору из окружения PlatformIO
|
||||||
gcc_path = env.subst("$CC")
|
gcc_path = env.subst("$CC")
|
||||||
|
|
||||||
# Выполняем команду для получения версии компилятора
|
# Выполняем команду для получения версии компилятора
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = subprocess.run([gcc_path, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
result = subprocess.run([gcc_path, "--version"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print(f"GCC version: {result.stdout}")
|
print(f"GCC version: {result.stdout}")
|
||||||
else:
|
else:
|
||||||
print(f"Failed to get GCC version: {result.stderr}")
|
print(f"Failed to get GCC version: {result.stderr}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error while getting GCC version: {e}")
|
print(f"Error while getting GCC version: {e}")
|
||||||
|
|
||||||
# Дополнительно проверяем путь к компилятору
|
# Дополнительно проверяем путь к компилятору
|
||||||
print(f"Compiler path: {gcc_path}")
|
print(f"Compiler path: {gcc_path}")
|
||||||
|
|
|
@ -1,299 +1,299 @@
|
||||||
#MicroXplorer Configuration settings - do not modify
|
#MicroXplorer Configuration settings - do not modify
|
||||||
ADC2.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_15
|
ADC2.Channel-1\#ChannelRegularConversion=ADC_CHANNEL_15
|
||||||
ADC2.Channel-5\#ChannelRegularConversion=ADC_CHANNEL_8
|
ADC2.Channel-5\#ChannelRegularConversion=ADC_CHANNEL_8
|
||||||
ADC2.Channel-6\#ChannelRegularConversion=ADC_CHANNEL_9
|
ADC2.Channel-6\#ChannelRegularConversion=ADC_CHANNEL_9
|
||||||
ADC2.EOCSelection=ADC_EOC_SEQ_CONV
|
ADC2.EOCSelection=ADC_EOC_SEQ_CONV
|
||||||
ADC2.IPParameters=Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,NbrOfConversionFlag,InjNumberOfConversion,NbrOfConversion,Rank-5\#ChannelRegularConversion,Channel-5\#ChannelRegularConversion,SamplingTime-5\#ChannelRegularConversion,Rank-6\#ChannelRegularConversion,Channel-6\#ChannelRegularConversion,SamplingTime-6\#ChannelRegularConversion,EOCSelection
|
ADC2.IPParameters=Rank-1\#ChannelRegularConversion,Channel-1\#ChannelRegularConversion,SamplingTime-1\#ChannelRegularConversion,NbrOfConversionFlag,InjNumberOfConversion,NbrOfConversion,Rank-5\#ChannelRegularConversion,Channel-5\#ChannelRegularConversion,SamplingTime-5\#ChannelRegularConversion,Rank-6\#ChannelRegularConversion,Channel-6\#ChannelRegularConversion,SamplingTime-6\#ChannelRegularConversion,EOCSelection
|
||||||
ADC2.InjNumberOfConversion=0
|
ADC2.InjNumberOfConversion=0
|
||||||
ADC2.NbrOfConversion=3
|
ADC2.NbrOfConversion=3
|
||||||
ADC2.NbrOfConversionFlag=1
|
ADC2.NbrOfConversionFlag=1
|
||||||
ADC2.Rank-1\#ChannelRegularConversion=1
|
ADC2.Rank-1\#ChannelRegularConversion=1
|
||||||
ADC2.Rank-5\#ChannelRegularConversion=2
|
ADC2.Rank-5\#ChannelRegularConversion=2
|
||||||
ADC2.Rank-6\#ChannelRegularConversion=3
|
ADC2.Rank-6\#ChannelRegularConversion=3
|
||||||
ADC2.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
ADC2.SamplingTime-1\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
||||||
ADC2.SamplingTime-5\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
ADC2.SamplingTime-5\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
||||||
ADC2.SamplingTime-6\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
ADC2.SamplingTime-6\#ChannelRegularConversion=ADC_SAMPLETIME_3CYCLES
|
||||||
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configTIMER_TASK_PRIORITY
|
FREERTOS.IPParameters=Tasks01,configENABLE_FPU,configTIMER_TASK_PRIORITY
|
||||||
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
FREERTOS.Tasks01=defaultTask,24,128,StartDefaultTask,Default,NULL,Dynamic,NULL,NULL
|
||||||
FREERTOS.configENABLE_FPU=1
|
FREERTOS.configENABLE_FPU=1
|
||||||
FREERTOS.configTIMER_TASK_PRIORITY=1
|
FREERTOS.configTIMER_TASK_PRIORITY=1
|
||||||
File.Version=6
|
File.Version=6
|
||||||
GPIO.groupedBy=Group By Peripherals
|
GPIO.groupedBy=Group By Peripherals
|
||||||
KeepUserPlacement=false
|
KeepUserPlacement=false
|
||||||
Mcu.CPN=STM32F446RET6
|
Mcu.CPN=STM32F446RET6
|
||||||
Mcu.Family=STM32F4
|
Mcu.Family=STM32F4
|
||||||
Mcu.IP0=ADC2
|
Mcu.IP0=ADC2
|
||||||
Mcu.IP1=FREERTOS
|
Mcu.IP1=FREERTOS
|
||||||
Mcu.IP2=NVIC
|
Mcu.IP2=NVIC
|
||||||
Mcu.IP3=RCC
|
Mcu.IP3=RCC
|
||||||
Mcu.IP4=SPI2
|
Mcu.IP4=SPI2
|
||||||
Mcu.IP5=SYS
|
Mcu.IP5=SYS
|
||||||
Mcu.IP6=TIM1
|
Mcu.IP6=TIM1
|
||||||
Mcu.IP7=TIM3
|
Mcu.IP7=TIM3
|
||||||
Mcu.IP8=TIM5
|
Mcu.IP8=TIM5
|
||||||
Mcu.IP9=USART1
|
Mcu.IP9=USART1
|
||||||
Mcu.IPNb=10
|
Mcu.IPNb=10
|
||||||
Mcu.Name=STM32F446R(C-E)Tx
|
Mcu.Name=STM32F446R(C-E)Tx
|
||||||
Mcu.Package=LQFP64
|
Mcu.Package=LQFP64
|
||||||
Mcu.Pin0=PC1
|
Mcu.Pin0=PC1
|
||||||
Mcu.Pin1=PC5
|
Mcu.Pin1=PC5
|
||||||
Mcu.Pin10=PC9
|
Mcu.Pin10=PC9
|
||||||
Mcu.Pin11=PA8
|
Mcu.Pin11=PA8
|
||||||
Mcu.Pin12=PA9
|
Mcu.Pin12=PA9
|
||||||
Mcu.Pin13=PA10
|
Mcu.Pin13=PA10
|
||||||
Mcu.Pin14=PA11
|
Mcu.Pin14=PA11
|
||||||
Mcu.Pin15=PA12
|
Mcu.Pin15=PA12
|
||||||
Mcu.Pin16=PA13
|
Mcu.Pin16=PA13
|
||||||
Mcu.Pin17=PA14
|
Mcu.Pin17=PA14
|
||||||
Mcu.Pin18=PC10
|
Mcu.Pin18=PC10
|
||||||
Mcu.Pin19=PC11
|
Mcu.Pin19=PC11
|
||||||
Mcu.Pin2=PB0
|
Mcu.Pin2=PB0
|
||||||
Mcu.Pin20=PC12
|
Mcu.Pin20=PC12
|
||||||
Mcu.Pin21=PD2
|
Mcu.Pin21=PD2
|
||||||
Mcu.Pin22=PB6
|
Mcu.Pin22=PB6
|
||||||
Mcu.Pin23=PB7
|
Mcu.Pin23=PB7
|
||||||
Mcu.Pin24=VP_FREERTOS_VS_CMSIS_V2
|
Mcu.Pin24=VP_FREERTOS_VS_CMSIS_V2
|
||||||
Mcu.Pin25=VP_SYS_VS_tim2
|
Mcu.Pin25=VP_SYS_VS_tim2
|
||||||
Mcu.Pin26=VP_TIM1_VS_ClockSourceINT
|
Mcu.Pin26=VP_TIM1_VS_ClockSourceINT
|
||||||
Mcu.Pin27=VP_TIM3_VS_ClockSourceINT
|
Mcu.Pin27=VP_TIM3_VS_ClockSourceINT
|
||||||
Mcu.Pin28=VP_TIM5_VS_ClockSourceINT
|
Mcu.Pin28=VP_TIM5_VS_ClockSourceINT
|
||||||
Mcu.Pin3=PB1
|
Mcu.Pin3=PB1
|
||||||
Mcu.Pin4=PB10
|
Mcu.Pin4=PB10
|
||||||
Mcu.Pin5=PB14
|
Mcu.Pin5=PB14
|
||||||
Mcu.Pin6=PB15
|
Mcu.Pin6=PB15
|
||||||
Mcu.Pin7=PC6
|
Mcu.Pin7=PC6
|
||||||
Mcu.Pin8=PC7
|
Mcu.Pin8=PC7
|
||||||
Mcu.Pin9=PC8
|
Mcu.Pin9=PC8
|
||||||
Mcu.PinsNb=29
|
Mcu.PinsNb=29
|
||||||
Mcu.ThirdPartyNb=0
|
Mcu.ThirdPartyNb=0
|
||||||
Mcu.UserConstants=
|
Mcu.UserConstants=
|
||||||
Mcu.UserName=STM32F446RETx
|
Mcu.UserName=STM32F446RETx
|
||||||
MxCube.Version=6.5.0
|
MxCube.Version=6.5.0
|
||||||
MxDb.Version=DB.6.0.50
|
MxDb.Version=DB.6.0.50
|
||||||
NVIC.ADC_IRQn=true\:5\:0\:true\:true\:true\:1\:true\:true\:true\:true
|
NVIC.ADC_IRQn=true\:5\:0\:true\:true\:true\:1\:true\:true\:true\:true
|
||||||
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.ForceEnableDMAVector=true
|
NVIC.ForceEnableDMAVector=true
|
||||||
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
NVIC.PendSV_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:false\:false
|
||||||
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
|
||||||
NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
NVIC.SPI2_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||||
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:false\:false\:false\:false\:false
|
||||||
NVIC.SavedPendsvIrqHandlerGenerated=true
|
NVIC.SavedPendsvIrqHandlerGenerated=true
|
||||||
NVIC.SavedSvcallIrqHandlerGenerated=true
|
NVIC.SavedSvcallIrqHandlerGenerated=true
|
||||||
NVIC.SavedSystickIrqHandlerGenerated=true
|
NVIC.SavedSystickIrqHandlerGenerated=true
|
||||||
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
|
NVIC.SysTick_IRQn=true\:15\:0\:false\:false\:false\:true\:false\:true\:false
|
||||||
NVIC.TIM2_IRQn=true\:15\:0\:true\:false\:true\:false\:false\:true\:true
|
NVIC.TIM2_IRQn=true\:15\:0\:true\:false\:true\:false\:false\:true\:true
|
||||||
NVIC.TIM3_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
NVIC.TIM3_IRQn=true\:5\:0\:false\:false\:true\:true\:true\:true\:true
|
||||||
NVIC.TimeBase=TIM2_IRQn
|
NVIC.TimeBase=TIM2_IRQn
|
||||||
NVIC.TimeBaseIP=TIM2
|
NVIC.TimeBaseIP=TIM2
|
||||||
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false\:false
|
||||||
PA10.Signal=S_TIM1_CH3
|
PA10.Signal=S_TIM1_CH3
|
||||||
PA11.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PA11.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PA11.GPIO_Label=EN_U
|
PA11.GPIO_Label=EN_U
|
||||||
PA11.GPIO_PuPd=GPIO_PULLDOWN
|
PA11.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PA11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
PA11.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
||||||
PA11.Locked=true
|
PA11.Locked=true
|
||||||
PA11.Signal=GPIO_Output
|
PA11.Signal=GPIO_Output
|
||||||
PA12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PA12.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PA12.GPIO_Label=EN_V
|
PA12.GPIO_Label=EN_V
|
||||||
PA12.GPIO_PuPd=GPIO_PULLDOWN
|
PA12.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PA12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
PA12.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
||||||
PA12.Locked=true
|
PA12.Locked=true
|
||||||
PA12.Signal=GPIO_Output
|
PA12.Signal=GPIO_Output
|
||||||
PA13.Mode=Serial_Wire
|
PA13.Mode=Serial_Wire
|
||||||
PA13.Signal=SYS_JTMS-SWDIO
|
PA13.Signal=SYS_JTMS-SWDIO
|
||||||
PA14.Mode=Serial_Wire
|
PA14.Mode=Serial_Wire
|
||||||
PA14.Signal=SYS_JTCK-SWCLK
|
PA14.Signal=SYS_JTCK-SWCLK
|
||||||
PA8.Signal=S_TIM1_CH1
|
PA8.Signal=S_TIM1_CH1
|
||||||
PA9.Signal=S_TIM1_CH2
|
PA9.Signal=S_TIM1_CH2
|
||||||
PB0.GPIOParameters=GPIO_Label
|
PB0.GPIOParameters=GPIO_Label
|
||||||
PB0.GPIO_Label=SENSE2
|
PB0.GPIO_Label=SENSE2
|
||||||
PB0.Locked=true
|
PB0.Locked=true
|
||||||
PB0.Signal=ADCx_IN8
|
PB0.Signal=ADCx_IN8
|
||||||
PB1.GPIOParameters=GPIO_Label
|
PB1.GPIOParameters=GPIO_Label
|
||||||
PB1.GPIO_Label=SENSE1
|
PB1.GPIO_Label=SENSE1
|
||||||
PB1.Locked=true
|
PB1.Locked=true
|
||||||
PB1.Signal=ADCx_IN9
|
PB1.Signal=ADCx_IN9
|
||||||
PB10.Locked=true
|
PB10.Locked=true
|
||||||
PB10.Mode=Full_Duplex_Master
|
PB10.Mode=Full_Duplex_Master
|
||||||
PB10.Signal=SPI2_SCK
|
PB10.Signal=SPI2_SCK
|
||||||
PB14.Locked=true
|
PB14.Locked=true
|
||||||
PB14.Mode=Full_Duplex_Master
|
PB14.Mode=Full_Duplex_Master
|
||||||
PB14.Signal=SPI2_MISO
|
PB14.Signal=SPI2_MISO
|
||||||
PB15.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
PB15.GPIOParameters=GPIO_Speed,PinState,GPIO_PuPd,GPIO_Label
|
||||||
PB15.GPIO_Label=AS5045_CS
|
PB15.GPIO_Label=AS5045_CS
|
||||||
PB15.GPIO_PuPd=GPIO_PULLUP
|
PB15.GPIO_PuPd=GPIO_PULLUP
|
||||||
PB15.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
PB15.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
||||||
PB15.Locked=true
|
PB15.Locked=true
|
||||||
PB15.PinState=GPIO_PIN_SET
|
PB15.PinState=GPIO_PIN_SET
|
||||||
PB15.Signal=GPIO_Output
|
PB15.Signal=GPIO_Output
|
||||||
PB6.Mode=Asynchronous
|
PB6.Mode=Asynchronous
|
||||||
PB6.Signal=USART1_TX
|
PB6.Signal=USART1_TX
|
||||||
PB7.Mode=Asynchronous
|
PB7.Mode=Asynchronous
|
||||||
PB7.Signal=USART1_RX
|
PB7.Signal=USART1_RX
|
||||||
PC1.Mode=Full_Duplex_Master
|
PC1.Mode=Full_Duplex_Master
|
||||||
PC1.Signal=SPI2_MOSI
|
PC1.Signal=SPI2_MOSI
|
||||||
PC10.GPIOParameters=GPIO_Label
|
PC10.GPIOParameters=GPIO_Label
|
||||||
PC10.GPIO_Label=LED1
|
PC10.GPIO_Label=LED1
|
||||||
PC10.Locked=true
|
PC10.Locked=true
|
||||||
PC10.Signal=GPIO_Output
|
PC10.Signal=GPIO_Output
|
||||||
PC11.GPIOParameters=GPIO_Label
|
PC11.GPIOParameters=GPIO_Label
|
||||||
PC11.GPIO_Label=LED2
|
PC11.GPIO_Label=LED2
|
||||||
PC11.Locked=true
|
PC11.Locked=true
|
||||||
PC11.Signal=GPIO_Output
|
PC11.Signal=GPIO_Output
|
||||||
PC12.GPIOParameters=GPIO_Label
|
PC12.GPIOParameters=GPIO_Label
|
||||||
PC12.GPIO_Label=LED3
|
PC12.GPIO_Label=LED3
|
||||||
PC12.Locked=true
|
PC12.Locked=true
|
||||||
PC12.Signal=GPIO_Output
|
PC12.Signal=GPIO_Output
|
||||||
PC5.GPIOParameters=GPIO_Label
|
PC5.GPIOParameters=GPIO_Label
|
||||||
PC5.GPIO_Label=SENSE3
|
PC5.GPIO_Label=SENSE3
|
||||||
PC5.Locked=true
|
PC5.Locked=true
|
||||||
PC5.Signal=ADCx_IN15
|
PC5.Signal=ADCx_IN15
|
||||||
PC6.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PC6.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PC6.GPIO_Label=EN_W
|
PC6.GPIO_Label=EN_W
|
||||||
PC6.GPIO_PuPd=GPIO_PULLDOWN
|
PC6.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PC6.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
PC6.GPIO_Speed=GPIO_SPEED_FREQ_HIGH
|
||||||
PC6.Locked=true
|
PC6.Locked=true
|
||||||
PC6.Signal=GPIO_Output
|
PC6.Signal=GPIO_Output
|
||||||
PC7.GPIOParameters=GPIO_Label
|
PC7.GPIOParameters=GPIO_Label
|
||||||
PC7.GPIO_Label=DRV_FAULT
|
PC7.GPIO_Label=DRV_FAULT
|
||||||
PC7.Locked=true
|
PC7.Locked=true
|
||||||
PC7.Signal=GPIO_Input
|
PC7.Signal=GPIO_Input
|
||||||
PC8.GPIOParameters=GPIO_Label
|
PC8.GPIOParameters=GPIO_Label
|
||||||
PC8.GPIO_Label=DRV_RESET
|
PC8.GPIO_Label=DRV_RESET
|
||||||
PC8.Locked=true
|
PC8.Locked=true
|
||||||
PC8.Signal=GPIO_Output
|
PC8.Signal=GPIO_Output
|
||||||
PC9.GPIOParameters=GPIO_Label
|
PC9.GPIOParameters=GPIO_Label
|
||||||
PC9.GPIO_Label=DRV_SLEEP
|
PC9.GPIO_Label=DRV_SLEEP
|
||||||
PC9.Locked=true
|
PC9.Locked=true
|
||||||
PC9.Signal=GPIO_Output
|
PC9.Signal=GPIO_Output
|
||||||
PD2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
PD2.GPIOParameters=GPIO_Speed,GPIO_PuPd,GPIO_Label
|
||||||
PD2.GPIO_Label=spi1_cs
|
PD2.GPIO_Label=spi1_cs
|
||||||
PD2.GPIO_PuPd=GPIO_PULLDOWN
|
PD2.GPIO_PuPd=GPIO_PULLDOWN
|
||||||
PD2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
PD2.GPIO_Speed=GPIO_SPEED_FREQ_VERY_HIGH
|
||||||
PD2.Locked=true
|
PD2.Locked=true
|
||||||
PD2.Signal=GPIO_Output
|
PD2.Signal=GPIO_Output
|
||||||
PinOutPanel.RotationAngle=0
|
PinOutPanel.RotationAngle=0
|
||||||
ProjectManager.AskForMigrate=true
|
ProjectManager.AskForMigrate=true
|
||||||
ProjectManager.BackupPrevious=false
|
ProjectManager.BackupPrevious=false
|
||||||
ProjectManager.CompilerOptimize=6
|
ProjectManager.CompilerOptimize=6
|
||||||
ProjectManager.ComputerToolchain=false
|
ProjectManager.ComputerToolchain=false
|
||||||
ProjectManager.CoupleFile=true
|
ProjectManager.CoupleFile=true
|
||||||
ProjectManager.CustomerFirmwarePackage=
|
ProjectManager.CustomerFirmwarePackage=
|
||||||
ProjectManager.DefaultFWLocation=true
|
ProjectManager.DefaultFWLocation=true
|
||||||
ProjectManager.DeletePrevious=true
|
ProjectManager.DeletePrevious=true
|
||||||
ProjectManager.DeviceId=STM32F446RETx
|
ProjectManager.DeviceId=STM32F446RETx
|
||||||
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.27.1
|
ProjectManager.FirmwarePackage=STM32Cube FW_F4 V1.27.1
|
||||||
ProjectManager.FreePins=false
|
ProjectManager.FreePins=false
|
||||||
ProjectManager.HalAssertFull=false
|
ProjectManager.HalAssertFull=false
|
||||||
ProjectManager.HeapSize=0x200
|
ProjectManager.HeapSize=0x200
|
||||||
ProjectManager.KeepUserCode=true
|
ProjectManager.KeepUserCode=true
|
||||||
ProjectManager.LastFirmware=true
|
ProjectManager.LastFirmware=true
|
||||||
ProjectManager.LibraryCopy=1
|
ProjectManager.LibraryCopy=1
|
||||||
ProjectManager.MainLocation=Src
|
ProjectManager.MainLocation=Src
|
||||||
ProjectManager.NoMain=false
|
ProjectManager.NoMain=false
|
||||||
ProjectManager.PreviousToolchain=STM32CubeIDE
|
ProjectManager.PreviousToolchain=STM32CubeIDE
|
||||||
ProjectManager.ProjectBuild=false
|
ProjectManager.ProjectBuild=false
|
||||||
ProjectManager.ProjectFileName=cubemx_config.ioc
|
ProjectManager.ProjectFileName=cubemx_config.ioc
|
||||||
ProjectManager.ProjectName=cubemx_config
|
ProjectManager.ProjectName=cubemx_config
|
||||||
ProjectManager.RegisterCallBack=
|
ProjectManager.RegisterCallBack=
|
||||||
ProjectManager.StackSize=0x400
|
ProjectManager.StackSize=0x400
|
||||||
ProjectManager.TargetToolchain=Other Toolchains (GPDSC)
|
ProjectManager.TargetToolchain=Other Toolchains (GPDSC)
|
||||||
ProjectManager.ToolChainLocation=
|
ProjectManager.ToolChainLocation=
|
||||||
ProjectManager.UnderRoot=false
|
ProjectManager.UnderRoot=false
|
||||||
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_TIM1_Init-TIM1-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_TIM3_Init-TIM3-false-HAL-true,7-MX_ADC2_Init-ADC2-false-HAL-true,8-MX_TIM5_Init-TIM5-false-HAL-true
|
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-SystemClock_Config-RCC-false-HAL-false,3-MX_TIM1_Init-TIM1-false-HAL-true,4-MX_USART1_UART_Init-USART1-false-HAL-true,5-MX_SPI2_Init-SPI2-false-HAL-true,6-MX_TIM3_Init-TIM3-false-HAL-true,7-MX_ADC2_Init-ADC2-false-HAL-true,8-MX_TIM5_Init-TIM5-false-HAL-true
|
||||||
RCC.AHBFreq_Value=180000000
|
RCC.AHBFreq_Value=180000000
|
||||||
RCC.APB1CLKDivider=RCC_HCLK_DIV4
|
RCC.APB1CLKDivider=RCC_HCLK_DIV4
|
||||||
RCC.APB1Freq_Value=45000000
|
RCC.APB1Freq_Value=45000000
|
||||||
RCC.APB1TimFreq_Value=90000000
|
RCC.APB1TimFreq_Value=90000000
|
||||||
RCC.APB2CLKDivider=RCC_HCLK_DIV2
|
RCC.APB2CLKDivider=RCC_HCLK_DIV2
|
||||||
RCC.APB2Freq_Value=90000000
|
RCC.APB2Freq_Value=90000000
|
||||||
RCC.APB2TimFreq_Value=180000000
|
RCC.APB2TimFreq_Value=180000000
|
||||||
RCC.CECFreq_Value=32786.88524590164
|
RCC.CECFreq_Value=32786.88524590164
|
||||||
RCC.CortexFreq_Value=180000000
|
RCC.CortexFreq_Value=180000000
|
||||||
RCC.FCLKCortexFreq_Value=180000000
|
RCC.FCLKCortexFreq_Value=180000000
|
||||||
RCC.FMPI2C1Freq_Value=45000000
|
RCC.FMPI2C1Freq_Value=45000000
|
||||||
RCC.FamilyName=M
|
RCC.FamilyName=M
|
||||||
RCC.HCLKFreq_Value=180000000
|
RCC.HCLKFreq_Value=180000000
|
||||||
RCC.HSE_VALUE=8000000
|
RCC.HSE_VALUE=8000000
|
||||||
RCC.I2S1Freq_Value=96000000
|
RCC.I2S1Freq_Value=96000000
|
||||||
RCC.I2S2Freq_Value=96000000
|
RCC.I2S2Freq_Value=96000000
|
||||||
RCC.IPParameters=AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CECFreq_Value,CortexFreq_Value,FCLKCortexFreq_Value,FMPI2C1Freq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,I2S1Freq_Value,I2S2Freq_Value,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLI2SPCLKFreq_Value,PLLI2SQCLKFreq_Value,PLLI2SRCLKFreq_Value,PLLI2SoutputFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLRCLKFreq_Value,PLLSAIPCLKFreq_Value,PLLSAIQCLKFreq_Value,PLLSAIoutputFreq_Value,PWRFreq_Value,SAIAFreq_Value,SAIBFreq_Value,SDIOFreq_Value,SPDIFRXFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USBFreq_Value,VCOI2SInputFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAIInputFreq_Value,VCOSAIOutputFreq_Value
|
RCC.IPParameters=AHBFreq_Value,APB1CLKDivider,APB1Freq_Value,APB1TimFreq_Value,APB2CLKDivider,APB2Freq_Value,APB2TimFreq_Value,CECFreq_Value,CortexFreq_Value,FCLKCortexFreq_Value,FMPI2C1Freq_Value,FamilyName,HCLKFreq_Value,HSE_VALUE,I2S1Freq_Value,I2S2Freq_Value,MCO2PinFreq_Value,PLLCLKFreq_Value,PLLI2SPCLKFreq_Value,PLLI2SQCLKFreq_Value,PLLI2SRCLKFreq_Value,PLLI2SoutputFreq_Value,PLLM,PLLN,PLLQCLKFreq_Value,PLLRCLKFreq_Value,PLLSAIPCLKFreq_Value,PLLSAIQCLKFreq_Value,PLLSAIoutputFreq_Value,PWRFreq_Value,SAIAFreq_Value,SAIBFreq_Value,SDIOFreq_Value,SPDIFRXFreq_Value,SYSCLKFreq_VALUE,SYSCLKSource,USBFreq_Value,VCOI2SInputFreq_Value,VCOI2SOutputFreq_Value,VCOInputFreq_Value,VCOOutputFreq_Value,VCOSAIInputFreq_Value,VCOSAIOutputFreq_Value
|
||||||
RCC.MCO2PinFreq_Value=180000000
|
RCC.MCO2PinFreq_Value=180000000
|
||||||
RCC.PLLCLKFreq_Value=180000000
|
RCC.PLLCLKFreq_Value=180000000
|
||||||
RCC.PLLI2SPCLKFreq_Value=96000000
|
RCC.PLLI2SPCLKFreq_Value=96000000
|
||||||
RCC.PLLI2SQCLKFreq_Value=96000000
|
RCC.PLLI2SQCLKFreq_Value=96000000
|
||||||
RCC.PLLI2SRCLKFreq_Value=96000000
|
RCC.PLLI2SRCLKFreq_Value=96000000
|
||||||
RCC.PLLI2SoutputFreq_Value=96000000
|
RCC.PLLI2SoutputFreq_Value=96000000
|
||||||
RCC.PLLM=8
|
RCC.PLLM=8
|
||||||
RCC.PLLN=180
|
RCC.PLLN=180
|
||||||
RCC.PLLQCLKFreq_Value=180000000
|
RCC.PLLQCLKFreq_Value=180000000
|
||||||
RCC.PLLRCLKFreq_Value=180000000
|
RCC.PLLRCLKFreq_Value=180000000
|
||||||
RCC.PLLSAIPCLKFreq_Value=96000000
|
RCC.PLLSAIPCLKFreq_Value=96000000
|
||||||
RCC.PLLSAIQCLKFreq_Value=96000000
|
RCC.PLLSAIQCLKFreq_Value=96000000
|
||||||
RCC.PLLSAIoutputFreq_Value=96000000
|
RCC.PLLSAIoutputFreq_Value=96000000
|
||||||
RCC.PWRFreq_Value=180000000
|
RCC.PWRFreq_Value=180000000
|
||||||
RCC.SAIAFreq_Value=96000000
|
RCC.SAIAFreq_Value=96000000
|
||||||
RCC.SAIBFreq_Value=96000000
|
RCC.SAIBFreq_Value=96000000
|
||||||
RCC.SDIOFreq_Value=180000000
|
RCC.SDIOFreq_Value=180000000
|
||||||
RCC.SPDIFRXFreq_Value=180000000
|
RCC.SPDIFRXFreq_Value=180000000
|
||||||
RCC.SYSCLKFreq_VALUE=180000000
|
RCC.SYSCLKFreq_VALUE=180000000
|
||||||
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
RCC.SYSCLKSource=RCC_SYSCLKSOURCE_PLLCLK
|
||||||
RCC.USBFreq_Value=180000000
|
RCC.USBFreq_Value=180000000
|
||||||
RCC.VCOI2SInputFreq_Value=1000000
|
RCC.VCOI2SInputFreq_Value=1000000
|
||||||
RCC.VCOI2SOutputFreq_Value=192000000
|
RCC.VCOI2SOutputFreq_Value=192000000
|
||||||
RCC.VCOInputFreq_Value=2000000
|
RCC.VCOInputFreq_Value=2000000
|
||||||
RCC.VCOOutputFreq_Value=360000000
|
RCC.VCOOutputFreq_Value=360000000
|
||||||
RCC.VCOSAIInputFreq_Value=1000000
|
RCC.VCOSAIInputFreq_Value=1000000
|
||||||
RCC.VCOSAIOutputFreq_Value=192000000
|
RCC.VCOSAIOutputFreq_Value=192000000
|
||||||
SH.ADCx_IN15.0=ADC2_IN15,IN15
|
SH.ADCx_IN15.0=ADC2_IN15,IN15
|
||||||
SH.ADCx_IN15.ConfNb=1
|
SH.ADCx_IN15.ConfNb=1
|
||||||
SH.ADCx_IN8.0=ADC2_IN8,IN8
|
SH.ADCx_IN8.0=ADC2_IN8,IN8
|
||||||
SH.ADCx_IN8.ConfNb=1
|
SH.ADCx_IN8.ConfNb=1
|
||||||
SH.ADCx_IN9.0=ADC2_IN9,IN9
|
SH.ADCx_IN9.0=ADC2_IN9,IN9
|
||||||
SH.ADCx_IN9.ConfNb=1
|
SH.ADCx_IN9.ConfNb=1
|
||||||
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
|
SH.S_TIM1_CH1.0=TIM1_CH1,PWM Generation1 CH1
|
||||||
SH.S_TIM1_CH1.ConfNb=1
|
SH.S_TIM1_CH1.ConfNb=1
|
||||||
SH.S_TIM1_CH2.0=TIM1_CH2,PWM Generation2 CH2
|
SH.S_TIM1_CH2.0=TIM1_CH2,PWM Generation2 CH2
|
||||||
SH.S_TIM1_CH2.ConfNb=1
|
SH.S_TIM1_CH2.ConfNb=1
|
||||||
SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3
|
SH.S_TIM1_CH3.0=TIM1_CH3,PWM Generation3 CH3
|
||||||
SH.S_TIM1_CH3.ConfNb=1
|
SH.S_TIM1_CH3.ConfNb=1
|
||||||
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_64
|
SPI2.BaudRatePrescaler=SPI_BAUDRATEPRESCALER_64
|
||||||
SPI2.CLKPhase=SPI_PHASE_1EDGE
|
SPI2.CLKPhase=SPI_PHASE_1EDGE
|
||||||
SPI2.CLKPolarity=SPI_POLARITY_LOW
|
SPI2.CLKPolarity=SPI_POLARITY_LOW
|
||||||
SPI2.CalculateBaudRate=703.125 KBits/s
|
SPI2.CalculateBaudRate=703.125 KBits/s
|
||||||
SPI2.DataSize=SPI_DATASIZE_16BIT
|
SPI2.DataSize=SPI_DATASIZE_16BIT
|
||||||
SPI2.Direction=SPI_DIRECTION_2LINES
|
SPI2.Direction=SPI_DIRECTION_2LINES
|
||||||
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPhase,BaudRatePrescaler,CLKPolarity
|
SPI2.IPParameters=VirtualType,Mode,Direction,CalculateBaudRate,DataSize,CLKPhase,BaudRatePrescaler,CLKPolarity
|
||||||
SPI2.Mode=SPI_MODE_MASTER
|
SPI2.Mode=SPI_MODE_MASTER
|
||||||
SPI2.VirtualType=VM_MASTER
|
SPI2.VirtualType=VM_MASTER
|
||||||
TIM1.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
|
TIM1.AutoReloadPreload=TIM_AUTORELOAD_PRELOAD_ENABLE
|
||||||
TIM1.BreakState=TIM_BREAK_DISABLE
|
TIM1.BreakState=TIM_BREAK_DISABLE
|
||||||
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
TIM1.Channel-PWM\ Generation1\ CH1=TIM_CHANNEL_1
|
||||||
TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
TIM1.Channel-PWM\ Generation2\ CH2=TIM_CHANNEL_2
|
||||||
TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
TIM1.Channel-PWM\ Generation3\ CH3=TIM_CHANNEL_3
|
||||||
TIM1.CounterMode=TIM_COUNTERMODE_CENTERALIGNED1
|
TIM1.CounterMode=TIM_COUNTERMODE_CENTERALIGNED1
|
||||||
TIM1.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,TIM_MasterOutputTrigger,AutoReloadPreload,BreakState,OffStateRunMode,OffStateIDLEMode,CounterMode,Period
|
TIM1.IPParameters=Channel-PWM Generation1 CH1,Channel-PWM Generation2 CH2,Channel-PWM Generation3 CH3,TIM_MasterOutputTrigger,AutoReloadPreload,BreakState,OffStateRunMode,OffStateIDLEMode,CounterMode,Period
|
||||||
TIM1.OffStateIDLEMode=TIM_OSSI_DISABLE
|
TIM1.OffStateIDLEMode=TIM_OSSI_DISABLE
|
||||||
TIM1.OffStateRunMode=TIM_OSSR_DISABLE
|
TIM1.OffStateRunMode=TIM_OSSR_DISABLE
|
||||||
TIM1.Period=2399
|
TIM1.Period=2399
|
||||||
TIM1.TIM_MasterOutputTrigger=TIM_TRGO_RESET
|
TIM1.TIM_MasterOutputTrigger=TIM_TRGO_RESET
|
||||||
TIM3.IPParameters=Period,Prescaler
|
TIM3.IPParameters=Period,Prescaler
|
||||||
TIM3.Period=99
|
TIM3.Period=99
|
||||||
TIM3.Prescaler=89
|
TIM3.Prescaler=89
|
||||||
USART1.IPParameters=VirtualMode
|
USART1.IPParameters=VirtualMode
|
||||||
USART1.VirtualMode=VM_ASYNC
|
USART1.VirtualMode=VM_ASYNC
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
VP_FREERTOS_VS_CMSIS_V2.Mode=CMSIS_V2
|
||||||
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
VP_FREERTOS_VS_CMSIS_V2.Signal=FREERTOS_VS_CMSIS_V2
|
||||||
VP_SYS_VS_tim2.Mode=TIM2
|
VP_SYS_VS_tim2.Mode=TIM2
|
||||||
VP_SYS_VS_tim2.Signal=SYS_VS_tim2
|
VP_SYS_VS_tim2.Signal=SYS_VS_tim2
|
||||||
VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
VP_TIM1_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
VP_TIM1_VS_ClockSourceINT.Signal=TIM1_VS_ClockSourceINT
|
||||||
VP_TIM3_VS_ClockSourceINT.Mode=Internal
|
VP_TIM3_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
|
VP_TIM3_VS_ClockSourceINT.Signal=TIM3_VS_ClockSourceINT
|
||||||
VP_TIM5_VS_ClockSourceINT.Mode=Internal
|
VP_TIM5_VS_ClockSourceINT.Mode=Internal
|
||||||
VP_TIM5_VS_ClockSourceINT.Signal=TIM5_VS_ClockSourceINT
|
VP_TIM5_VS_ClockSourceINT.Signal=TIM5_VS_ClockSourceINT
|
||||||
board=custom
|
board=custom
|
||||||
|
|
|
@ -1,178 +1,178 @@
|
||||||
/**
|
/**
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @file LinkerScript.ld
|
* @file LinkerScript.ld
|
||||||
* @author Auto-generated by STM32CubeIDE
|
* @author Auto-generated by STM32CubeIDE
|
||||||
* @brief Linker script for STM32F446RCTx Device from STM32F4 series
|
* @brief Linker script for STM32F446RCTx Device from STM32F4 series
|
||||||
* 256Kbytes FLASH
|
* 256Kbytes FLASH
|
||||||
* 128Kbytes RAM
|
* 128Kbytes RAM
|
||||||
*
|
*
|
||||||
* Set heap size, stack size and stack location according
|
* Set heap size, stack size and stack location according
|
||||||
* to application requirements.
|
* to application requirements.
|
||||||
*
|
*
|
||||||
* Set memory bank area and size if external memory is used
|
* Set memory bank area and size if external memory is used
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
* @attention
|
* @attention
|
||||||
*
|
*
|
||||||
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
* <h2><center>© Copyright (c) 2020 STMicroelectronics.
|
||||||
* All rights reserved.</center></h2>
|
* All rights reserved.</center></h2>
|
||||||
*
|
*
|
||||||
* This software component is licensed by ST under BSD 3-Clause license,
|
* This software component is licensed by ST under BSD 3-Clause license,
|
||||||
* the "License"; You may not use this file except in compliance with the
|
* the "License"; You may not use this file except in compliance with the
|
||||||
* License. You may obtain a copy of the License at:
|
* License. You may obtain a copy of the License at:
|
||||||
* opensource.org/licenses/BSD-3-Clause
|
* opensource.org/licenses/BSD-3-Clause
|
||||||
*
|
*
|
||||||
******************************************************************************
|
******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Entry Point */
|
/* Entry Point */
|
||||||
ENTRY(Reset_Handler)
|
ENTRY(Reset_Handler)
|
||||||
|
|
||||||
/* Highest address of the user mode stack */
|
/* Highest address of the user mode stack */
|
||||||
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
|
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
|
||||||
|
|
||||||
_Min_Heap_Size = 0x200; /* required amount of heap */
|
_Min_Heap_Size = 0x200; /* required amount of heap */
|
||||||
_Min_Stack_Size = 0x400; /* required amount of stack */
|
_Min_Stack_Size = 0x400; /* required amount of stack */
|
||||||
|
|
||||||
|
|
||||||
/* Memories definition */
|
/* Memories definition */
|
||||||
MEMORY
|
MEMORY
|
||||||
{
|
{
|
||||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = LD_MAX_DATA_SIZE
|
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = LD_MAX_DATA_SIZE
|
||||||
FLASH (rx) : ORIGIN = 0x8000000 + 0x8000, LENGTH = 512K - 0x8000
|
FLASH (rx) : ORIGIN = 0x8000000 + 0x8000, LENGTH = 512K - 0x8000
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sections */
|
/* Sections */
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
/* The startup code into "FLASH" Rom type memory */
|
/* The startup code into "FLASH" Rom type memory */
|
||||||
.isr_vector :
|
.isr_vector :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
KEEP(*(.isr_vector)) /* Startup code */
|
KEEP(*(.isr_vector)) /* Startup code */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
/* The program code and other data into "FLASH" Rom type memory */
|
/* The program code and other data into "FLASH" Rom type memory */
|
||||||
.text :
|
.text :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
*(.text) /* .text sections (code) */
|
*(.text) /* .text sections (code) */
|
||||||
*(.text*) /* .text* sections (code) */
|
*(.text*) /* .text* sections (code) */
|
||||||
*(.glue_7) /* glue arm to thumb code */
|
*(.glue_7) /* glue arm to thumb code */
|
||||||
*(.glue_7t) /* glue thumb to arm code */
|
*(.glue_7t) /* glue thumb to arm code */
|
||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
|
|
||||||
KEEP (*(.init))
|
KEEP (*(.init))
|
||||||
KEEP (*(.fini))
|
KEEP (*(.fini))
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_etext = .; /* define a global symbols at end of code */
|
_etext = .; /* define a global symbols at end of code */
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
/* Constant data into "FLASH" Rom type memory */
|
/* Constant data into "FLASH" Rom type memory */
|
||||||
.rodata :
|
.rodata :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
.ARM.extab (READONLY) : {
|
.ARM.extab (READONLY) : {
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
.ARM (READONLY) : {
|
.ARM (READONLY) : {
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
__exidx_start = .;
|
__exidx_start = .;
|
||||||
*(.ARM.exidx*)
|
*(.ARM.exidx*)
|
||||||
__exidx_end = .;
|
__exidx_end = .;
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
.preinit_array (READONLY) :
|
.preinit_array (READONLY) :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
KEEP (*(.preinit_array*))
|
KEEP (*(.preinit_array*))
|
||||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
.init_array (READONLY) :
|
.init_array (READONLY) :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
PROVIDE_HIDDEN (__init_array_start = .);
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
KEEP (*(SORT(.init_array.*)))
|
KEEP (*(SORT(.init_array.*)))
|
||||||
KEEP (*(.init_array*))
|
KEEP (*(.init_array*))
|
||||||
PROVIDE_HIDDEN (__init_array_end = .);
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
.fini_array (READONLY) :
|
.fini_array (READONLY) :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
KEEP (*(SORT(.fini_array.*)))
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
KEEP (*(.fini_array*))
|
KEEP (*(.fini_array*))
|
||||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
} >FLASH
|
} >FLASH
|
||||||
|
|
||||||
/* Used by the startup to initialize data */
|
/* Used by the startup to initialize data */
|
||||||
_sidata = LOADADDR(.data);
|
_sidata = LOADADDR(.data);
|
||||||
|
|
||||||
/* Initialized data sections into "RAM" Ram type memory */
|
/* Initialized data sections into "RAM" Ram type memory */
|
||||||
.data :
|
.data :
|
||||||
{
|
{
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_sdata = .; /* create a global symbol at data start */
|
_sdata = .; /* create a global symbol at data start */
|
||||||
*(.data) /* .data sections */
|
*(.data) /* .data sections */
|
||||||
*(.data*) /* .data* sections */
|
*(.data*) /* .data* sections */
|
||||||
*(.RamFunc) /* .RamFunc sections */
|
*(.RamFunc) /* .RamFunc sections */
|
||||||
*(.RamFunc*) /* .RamFunc* sections */
|
*(.RamFunc*) /* .RamFunc* sections */
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_edata = .; /* define a global symbol at data end */
|
_edata = .; /* define a global symbol at data end */
|
||||||
|
|
||||||
} >RAM AT> FLASH
|
} >RAM AT> FLASH
|
||||||
|
|
||||||
/* Uninitialized data section into "RAM" Ram type memory */
|
/* Uninitialized data section into "RAM" Ram type memory */
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
.bss :
|
.bss :
|
||||||
{
|
{
|
||||||
/* This is used by the startup in order to initialize the .bss section */
|
/* This is used by the startup in order to initialize the .bss section */
|
||||||
_sbss = .; /* define a global symbol at bss start */
|
_sbss = .; /* define a global symbol at bss start */
|
||||||
__bss_start__ = _sbss;
|
__bss_start__ = _sbss;
|
||||||
*(.bss)
|
*(.bss)
|
||||||
*(.bss*)
|
*(.bss*)
|
||||||
*(COMMON)
|
*(COMMON)
|
||||||
|
|
||||||
. = ALIGN(4);
|
. = ALIGN(4);
|
||||||
_ebss = .; /* define a global symbol at bss end */
|
_ebss = .; /* define a global symbol at bss end */
|
||||||
__bss_end__ = _ebss;
|
__bss_end__ = _ebss;
|
||||||
} >RAM
|
} >RAM
|
||||||
|
|
||||||
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
|
/* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */
|
||||||
._user_heap_stack :
|
._user_heap_stack :
|
||||||
{
|
{
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
PROVIDE ( end = . );
|
PROVIDE ( end = . );
|
||||||
PROVIDE ( _end = . );
|
PROVIDE ( _end = . );
|
||||||
. = . + _Min_Heap_Size;
|
. = . + _Min_Heap_Size;
|
||||||
. = . + _Min_Stack_Size;
|
. = . + _Min_Stack_Size;
|
||||||
. = ALIGN(8);
|
. = ALIGN(8);
|
||||||
} >RAM
|
} >RAM
|
||||||
|
|
||||||
/* Remove information from the compiler libraries */
|
/* Remove information from the compiler libraries */
|
||||||
/DISCARD/ :
|
/DISCARD/ :
|
||||||
{
|
{
|
||||||
libc.a ( * )
|
libc.a ( * )
|
||||||
libm.a ( * )
|
libm.a ( * )
|
||||||
libgcc.a ( * )
|
libgcc.a ( * )
|
||||||
}
|
}
|
||||||
|
|
||||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import os
|
import os
|
||||||
Import("env")
|
Import("env")
|
||||||
|
|
||||||
# include toolchain paths
|
# include toolchain paths
|
||||||
env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True)
|
env.Replace(COMPILATIONDB_INCLUDE_TOOLCHAIN=True)
|
||||||
|
|
||||||
# override compilation DB path
|
# override compilation DB path
|
||||||
env.Replace(COMPILATIONDB_PATH="compile_commands.json")
|
env.Replace(COMPILATIONDB_PATH="compile_commands.json")
|
|
@ -1,10 +1,10 @@
|
||||||
Import("env")
|
Import("env")
|
||||||
|
|
||||||
# Custom HEX from ELF
|
# Custom HEX from ELF
|
||||||
env.AddPostAction(
|
env.AddPostAction(
|
||||||
"$BUILD_DIR/${PROGNAME}.elf",
|
"$BUILD_DIR/${PROGNAME}.elf",
|
||||||
env.VerboseAction(" ".join([
|
env.VerboseAction(" ".join([
|
||||||
"$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
|
"$OBJCOPY", "-O", "ihex", "-R", ".eeprom",
|
||||||
"$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex"
|
"$BUILD_DIR/${PROGNAME}.elf", "$BUILD_DIR/${PROGNAME}.hex"
|
||||||
]), "Building $BUILD_DIR/${PROGNAME}.hex")
|
]), "Building $BUILD_DIR/${PROGNAME}.hex")
|
||||||
)
|
)
|
|
@ -1,31 +1,31 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <AS5045.h>
|
#include <AS5045.h>
|
||||||
#include <DRV8313.h>
|
#include <DRV8313.h>
|
||||||
#include <SimpleFOC.h>
|
#include <SimpleFOC.h>
|
||||||
#include <STM32_CAN.h>
|
#include <STM32_CAN.h>
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
|
|
||||||
extern STM32_CAN Can;
|
extern STM32_CAN Can;
|
||||||
extern SPIClass spi;
|
extern SPIClass spi;
|
||||||
extern MagneticSensorAS5045 encoder;
|
extern MagneticSensorAS5045 encoder;
|
||||||
extern BLDCMotor motor;
|
extern BLDCMotor motor;
|
||||||
extern DRV8313Driver driver;
|
extern DRV8313Driver driver;
|
||||||
extern LowsideCurrentSense current_sense;
|
extern LowsideCurrentSense current_sense;
|
||||||
extern Commander command;
|
extern Commander command;
|
||||||
|
|
||||||
struct MotorControlInputs {
|
struct MotorControlInputs {
|
||||||
float target_angle = 0.0;
|
float target_angle = 0.0;
|
||||||
float target_velocity = 0.0;
|
float target_velocity = 0.0;
|
||||||
bool motor_enabled = false;
|
bool motor_enabled = false;
|
||||||
bool foc_state = false;
|
bool foc_state = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern MotorControlInputs motor_control_inputs;
|
extern MotorControlInputs motor_control_inputs;
|
||||||
|
|
||||||
void doMotor(char *cmd);
|
void doMotor(char *cmd);
|
||||||
void setup_foc(MagneticSensorAS5045 *encoder, BLDCMotor *motor,
|
void setup_foc(MagneticSensorAS5045 *encoder, BLDCMotor *motor,
|
||||||
DRV8313Driver *driver, LowsideCurrentSense *current_sense,
|
DRV8313Driver *driver, LowsideCurrentSense *current_sense,
|
||||||
FLASH_RECORD* pid_data);
|
FLASH_RECORD* pid_data);
|
||||||
|
|
||||||
void foc_step(BLDCMotor *motor);
|
void foc_step(BLDCMotor *motor);
|
||||||
|
|
|
@ -1,86 +1,87 @@
|
||||||
#ifndef FLASH_H_
|
#ifndef FLASH_H_
|
||||||
#define FLASH_H_
|
#define FLASH_H_
|
||||||
#include "stm32f446xx.h"
|
#include "stm32f446xx.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
/* for addr in FLASH */
|
/* for addr in FLASH */
|
||||||
|
|
||||||
/* no padding for this struct, beacuse storing 8 bytes*/
|
/* no padding for this struct, beacuse storing 8 bytes*/
|
||||||
typedef struct{
|
typedef struct{
|
||||||
uint8_t data_id; // data_id = id register of can
|
uint8_t data_id; // data_id = id register of can
|
||||||
uint8_t data_type;
|
uint8_t data_type;
|
||||||
uint16_t crc;
|
uint16_t crc;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
// uint32_t write_ptr_now;
|
// uint32_t write_ptr_now;
|
||||||
}FLASH_RECORD;
|
}FLASH_RECORD;
|
||||||
enum {
|
enum {
|
||||||
addr_id = 0,
|
addr_id = 0,
|
||||||
pid_p = 1,
|
pid_p = 1,
|
||||||
pid_i,
|
pid_i,
|
||||||
pid_d,
|
pid_d,
|
||||||
firmw,
|
firmw,
|
||||||
foc_id,
|
foc_id,
|
||||||
angl,
|
angl,
|
||||||
vel
|
vel,
|
||||||
};
|
torq
|
||||||
|
};
|
||||||
/* for saved in FLASH float data*/
|
|
||||||
union{
|
/* for saved in FLASH float data*/
|
||||||
uint32_t i;
|
union{
|
||||||
float f;
|
uint32_t i;
|
||||||
}conv_float_to_int;
|
float f;
|
||||||
|
}conv_float_to_int;
|
||||||
#define FLASH_RECORD_SIZE sizeof(FLASH_RECORD) //size flash struct
|
|
||||||
#define PARAM_COUNT 5 // count data in flash
|
#define FLASH_RECORD_SIZE sizeof(FLASH_RECORD) //size flash struct
|
||||||
#define FIRMWARE_FLAG (uint32_t)0xDEADBEEF
|
#define PARAM_COUNT 5 // count data in flash
|
||||||
// Flash sectors for STM32F407
|
#define FIRMWARE_FLAG (uint32_t)0xDEADBEEF
|
||||||
|
// Flash sectors for STM32F407
|
||||||
#define SECTOR_2 0x08008000 // 16KB
|
|
||||||
#define SECTOR_3 0x0800C000 // 16KB
|
#define SECTOR_2 0x08008000 // 16KB
|
||||||
#define SECTOR_4 0x08010000 // 64KB
|
#define SECTOR_3 0x0800C000 // 16KB
|
||||||
#define SECTOR_5 0x08020000 // 128KB
|
#define SECTOR_4 0x08010000 // 64KB
|
||||||
#define SECTOR_6 0x08040000 // 128KB
|
#define SECTOR_5 0x08020000 // 128KB
|
||||||
#define SECTOR_6_END (SECTOR_6 + 128 * 1024) // sector 6 end
|
#define SECTOR_6 0x08040000 // 128KB
|
||||||
#define SECTOR_7 0x08060000 // 128KB
|
#define SECTOR_6_END (SECTOR_6 + 128 * 1024) // sector 6 end
|
||||||
|
#define SECTOR_7 0x08060000 // 128KB
|
||||||
|
|
||||||
#define FLAG_BOOT (0x08040000 + 4)
|
|
||||||
// Flash keys for unlocking flash memory
|
#define FLAG_BOOT (0x08040000 + 4)
|
||||||
#define BYTE32 0
|
// Flash keys for unlocking flash memory
|
||||||
#define BYTE8 1
|
#define BYTE32 0
|
||||||
#define UPDATE_FLAG 0xDEADBEEF // Unique 32bit value
|
#define BYTE8 1
|
||||||
//FLASH SET ONE PROGRAMM WORD
|
#define UPDATE_FLAG 0xDEADBEEF // Unique 32bit value
|
||||||
#define FLASH_8BYTE FLASH->CR &= ~FLASH_CR_PSIZE & ~FLASH_CR_PSIZE_1
|
//FLASH SET ONE PROGRAMM WORD
|
||||||
#define FLASH_32BYTE \
|
#define FLASH_8BYTE FLASH->CR &= ~FLASH_CR_PSIZE & ~FLASH_CR_PSIZE_1
|
||||||
FLASH->CR = (FLASH->CR & ~FLASH_CR_PSIZE) | (0x2 << FLASH_CR_PSIZE_Pos)
|
#define FLASH_32BYTE \
|
||||||
|
FLASH->CR = (FLASH->CR & ~FLASH_CR_PSIZE) | (0x2 << FLASH_CR_PSIZE_Pos)
|
||||||
// Flash command bits
|
|
||||||
#define FLASH_LOCK FLASH->CR |= FLASH_CR_LOCK
|
// Flash command bits
|
||||||
#define FLASH_UNLOCK FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2
|
#define FLASH_LOCK FLASH->CR |= FLASH_CR_LOCK
|
||||||
|
#define FLASH_UNLOCK FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2
|
||||||
|
|
||||||
// Flash status flags
|
|
||||||
#define FLASH_BUSY (FLASH->SR & FLASH_SR_BSY)
|
// Flash status flags
|
||||||
#define FLASH_ERROR (FLASH->SR & (FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR))
|
#define FLASH_BUSY (FLASH->SR & FLASH_SR_BSY)
|
||||||
static uint32_t write_ptr = SECTOR_6;
|
#define FLASH_ERROR (FLASH->SR & (FLASH_SR_WRPERR | FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR))
|
||||||
//for bootloader
|
static uint32_t write_ptr = SECTOR_6;
|
||||||
typedef void(*pFunction)(void);
|
//for bootloader
|
||||||
|
typedef void(*pFunction)(void);
|
||||||
|
|
||||||
// Function prototypes
|
|
||||||
void flash_unlock(void);
|
// Function prototypes
|
||||||
void flash_lock(void);
|
void flash_unlock(void);
|
||||||
void erase_sector(uint8_t sector);
|
void flash_lock(void);
|
||||||
void flash_program_word(uint32_t address, uint32_t data,uint32_t byte_len);
|
void erase_sector(uint8_t sector);
|
||||||
uint8_t flash_read_word(uint32_t address);
|
void flash_program_word(uint32_t address, uint32_t data,uint32_t byte_len);
|
||||||
FLASH_RECORD* load_params();
|
uint8_t flash_read_word(uint32_t address);
|
||||||
void compact_page();
|
FLASH_RECORD* load_params();
|
||||||
void flash_read(uint32_t addr,FLASH_RECORD* ptr);
|
void compact_page();
|
||||||
uint16_t validate_crc16(uint8_t *data,uint32_t length);
|
void flash_read(uint32_t addr,FLASH_RECORD* ptr);
|
||||||
void flash_write(uint32_t addr, FLASH_RECORD* record);
|
uint16_t validate_crc16(uint8_t *data,uint32_t length);
|
||||||
bool validaate_crc(FLASH_RECORD* crc);
|
void flash_write(uint32_t addr, FLASH_RECORD* record);
|
||||||
|
bool validaate_crc(FLASH_RECORD* crc);
|
||||||
void write_param(uint8_t param_id,uint32_t val);
|
|
||||||
|
void write_param(uint8_t param_id,uint32_t val);
|
||||||
#endif /* FLASH_H_ */
|
|
||||||
|
#endif /* FLASH_H_ */
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#pragma region "Motor and sensor setup"
|
#pragma region "Motor and sensor setup"
|
||||||
#define LED1 PC10
|
#define LED1 PC10
|
||||||
#define LED2 PC11
|
#define LED2 PC11
|
||||||
#define HARDWARE_SERIAL_RX_PIN PB7
|
#define HARDWARE_SERIAL_RX_PIN PB7
|
||||||
#define HARDWARE_SERIAL_TX_PIN PB6
|
#define HARDWARE_SERIAL_TX_PIN PB6
|
||||||
#define AS5045_CS PB15
|
#define AS5045_CS PB15
|
||||||
#define AS5045_MISO PB14
|
#define AS5045_MISO PB14
|
||||||
#define AS5045_MOSI PC1
|
#define AS5045_MOSI PC1
|
||||||
#define AS5045_SCLK PB10
|
#define AS5045_SCLK PB10
|
||||||
#define CURRENT_SENSOR_1 PB1
|
#define CURRENT_SENSOR_1 PB1
|
||||||
#define CURRENT_SENSOR_2 PB0
|
#define CURRENT_SENSOR_2 PB0
|
||||||
#define CURRENT_SENSOR_3 PC5
|
#define CURRENT_SENSOR_3 PC5
|
||||||
#define TIM1_CH1 PA8
|
#define TIM1_CH1 PA8
|
||||||
#define TIM1_CH2 PA9
|
#define TIM1_CH2 PA9
|
||||||
#define TIM1_CH3 PA10
|
#define TIM1_CH3 PA10
|
||||||
#define EN_W_GATE_DRIVER PC6
|
#define EN_W_GATE_DRIVER PC6
|
||||||
#define EN_U_GATE_DRIVER PA11
|
#define EN_U_GATE_DRIVER PA11
|
||||||
#define EN_V_GATE_DRIVER PA12
|
#define EN_V_GATE_DRIVER PA12
|
||||||
#define SLEEP_DRIVER PC9
|
#define SLEEP_DRIVER PC9
|
||||||
#define RESET_DRIVER PC8
|
#define RESET_DRIVER PC8
|
||||||
#define FAULT_DRIVER PC7
|
#define FAULT_DRIVER PC7
|
||||||
#define POLE_PAIRS 14
|
#define POLE_PAIRS 14
|
||||||
#define CAN2_TX PB13
|
#define CAN2_TX PB13
|
||||||
#define CAN2_RX PB12
|
#define CAN2_RX PB12
|
||||||
#define CAN1_TX PB9
|
#define CAN1_TX PB9
|
||||||
#define CAN1_RX PB8
|
#define CAN1_RX PB8
|
||||||
#define GM6208_RESISTANCE 31
|
#define GM6208_RESISTANCE 31
|
||||||
#define OWN_RESISTANCE 26
|
#define OWN_RESISTANCE 26
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
#if !defined(HAL_CAN_MODULE_ENABLED)
|
#if !defined(HAL_CAN_MODULE_ENABLED)
|
||||||
#define HAL_CAN_MODULE_ENABLED
|
#define HAL_CAN_MODULE_ENABLED
|
||||||
#endif
|
#endif
|
||||||
#include "stm32f4xx_hal.h"
|
#include "stm32f4xx_hal.h"
|
||||||
#include "stm32f4xx_hal_can.h"
|
#include "stm32f4xx_hal_can.h"
|
||||||
#include <STM32_CAN.h>
|
#include <STM32_CAN.h>
|
||||||
|
|
|
@ -1,27 +1,36 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "STM32_CAN.h"
|
#include "STM32_CAN.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "reg_cah.h"
|
#include "reg_cah.h"
|
||||||
|
|
||||||
extern FLASH_RECORD *flash_rec;
|
#define CAN_TIMEOUT 5
|
||||||
extern volatile uint16_t msg_id;
|
#define CAN_SILENCE_TIMEOUT 5
|
||||||
extern volatile uint16_t id_x;
|
#define MAX_CAN_READS 2
|
||||||
extern volatile uint8_t msg_ch;
|
extern FLASH_RECORD *flash_rec;
|
||||||
extern volatile uint8_t crc_h;
|
extern volatile uint16_t msg_id;
|
||||||
extern volatile uint8_t crc_l;
|
extern volatile uint16_t id_x;
|
||||||
|
extern volatile uint8_t msg_ch;
|
||||||
|
extern volatile uint8_t crc_h;
|
||||||
void send_velocity();
|
extern volatile uint8_t crc_l;
|
||||||
void send_angle();
|
extern volatile bool send_blocked;
|
||||||
void send_motor_enabled();
|
|
||||||
void send_motor_enabled();
|
static volatile bool need_send_angle = false;
|
||||||
void send_id();
|
static volatile bool need_send_velocity = false;
|
||||||
void firmware_update();
|
|
||||||
void send_pid_angle(uint8_t param_pid);
|
void send_velocity();
|
||||||
// void send_motor_torque();
|
void send_angle();
|
||||||
void send_pid(uint8_t param_pid);
|
void send_motor_enabled();
|
||||||
void setup_id(uint8_t my_id);
|
void send_motor_enabled();
|
||||||
void setup_angle(float target_angle);
|
void send_id();
|
||||||
void setup_pid_angle(uint8_t param_pid, float data);
|
void firmware_update();
|
||||||
void listen_can(const CAN_message_t &msg);
|
void send_pid_angle(uint8_t param_pid);
|
||||||
|
void send_with_confirmation(void (*send_func)(void));
|
||||||
|
// void send_torque();
|
||||||
|
void send_pid(uint8_t param_pid);
|
||||||
|
void setup_id(uint8_t my_id);
|
||||||
|
void setup_angle(float target_angle);
|
||||||
|
void setup_velocity(float target_velocity);
|
||||||
|
void process_can_messages();
|
||||||
|
|
||||||
|
void listen_can(const CAN_message_t &msg);
|
||||||
|
|
|
@ -1,48 +1,55 @@
|
||||||
#ifndef REG_CAH_H_
|
#pragma once
|
||||||
#define REG_CAH_H_
|
|
||||||
|
|
||||||
#define APP_ADDR 0x0800400 // 16KB - Application
|
enum{
|
||||||
#define ADDR_VAR 0x8040000
|
error_foc = 0,
|
||||||
|
error_canRX,
|
||||||
|
error_canTX
|
||||||
#define REG_READ 0x07
|
};
|
||||||
#define REG_WRITE 0x08
|
|
||||||
|
#define APP_ADDR 0x0800400 // 16KB - Application
|
||||||
|
#define ADDR_VAR 0x8040000
|
||||||
/* Startup ID device */
|
|
||||||
#define START_ID 0x00
|
|
||||||
|
#define REG_READ 0x07
|
||||||
/* CAN REGISTER ID */
|
#define REG_WRITE 0x08
|
||||||
#define REG_ID 0x01
|
|
||||||
#define REG_BAUDRATE 0x02
|
|
||||||
|
/* Startup ID device */
|
||||||
#define REG_MOTOR_POSPID_Kp 0x30
|
#define START_ID 0x00
|
||||||
#define REG_MOTOR_POSPID_Ki 0x31
|
|
||||||
#define REG_MOTOR_POSPID_Kd 0x32
|
/* CAN REGISTER ID */
|
||||||
|
#define REG_ID 0x01
|
||||||
#define REG_MOTOR_VELPID_Kp 0x40
|
#define REG_BAUDRATE 0x02
|
||||||
#define REG_MOTOR_VELPID_Ki 0x41
|
|
||||||
#define REG_MOTOR_VELPID_Kd 0x42
|
#define DATA_TYPE_ANGLE 0x03
|
||||||
|
#define DATA_TYPE_VELOCITY 0x04
|
||||||
#define REG_MOTOR_IMPPID_Kp 0x50
|
#define DATA_TYPE_TORQUE 0x05
|
||||||
#define REG_MOTOR_IMPPID_Kd 0x51
|
|
||||||
|
#define REG_MOTOR_POSPID_Kp 0x30
|
||||||
#define REG_RESET 0x88
|
#define REG_MOTOR_POSPID_Ki 0x31
|
||||||
#define REG_LED_BLINK 0x8B
|
#define REG_MOTOR_POSPID_Kd 0x32
|
||||||
|
|
||||||
#define FOC_STATE 0x60
|
#define REG_MOTOR_VELPID_Kp 0x40
|
||||||
|
#define REG_MOTOR_VELPID_Ki 0x41
|
||||||
#define MOTOR_VELOCITY 0x70
|
#define REG_MOTOR_VELPID_Kd 0x42
|
||||||
#define MOTOR_ENABLED 0x71
|
|
||||||
#define MOTOR_ANGLE 0x72
|
#define REG_MOTOR_IMPPID_Kp 0x50
|
||||||
#define MOTOR_TORQUE 0x73
|
#define REG_MOTOR_IMPPID_Kd 0x51
|
||||||
|
|
||||||
#define FIRMWARE_UPDATE 0x55
|
#define REG_RESET 0x88
|
||||||
|
#define REG_LED_BLINK 0x8B
|
||||||
//For send
|
|
||||||
#define CAN_MSG_MAX_LEN 7
|
#define FOC_STATE 0x60
|
||||||
#define CRC_SIZE 2
|
|
||||||
#define ID_SIZE sizeof(uint8_t)
|
#define MOTOR_VELOCITY 0x70
|
||||||
|
#define MOTOR_ENABLED 0x71
|
||||||
|
#define MOTOR_ANGLE 0x72
|
||||||
#endif // REG_CAH_H_
|
#define MOTOR_TORQUE 0x73
|
||||||
|
|
||||||
|
#define FIRMWARE_UPDATE 0x55
|
||||||
|
|
||||||
|
//For send
|
||||||
|
#define CAN_MSG_MAX_LEN 7
|
||||||
|
#define CRC_SIZE 2
|
||||||
|
#define ID_SIZE sizeof(uint8_t)
|
||||||
|
|
|
@ -1,44 +1,44 @@
|
||||||
#include "AS5045.h"
|
#include "AS5045.h"
|
||||||
|
|
||||||
|
|
||||||
MagneticSensorAS5045::MagneticSensorAS5045(uint16_t as5040_cs, uint16_t as5040_mosi, uint16_t as5040_miso,
|
MagneticSensorAS5045::MagneticSensorAS5045(uint16_t as5040_cs, uint16_t as5040_mosi, uint16_t as5040_miso,
|
||||||
uint16_t as5040_sclk): AS5040_CS_(as5040_cs),
|
uint16_t as5040_sclk): AS5040_CS_(as5040_cs),
|
||||||
AS5040_MOSI_(as5040_mosi),
|
AS5040_MOSI_(as5040_mosi),
|
||||||
AS5040_MISO_(as5040_miso),
|
AS5040_MISO_(as5040_miso),
|
||||||
AS5040_SCLK_(as5040_sclk),
|
AS5040_SCLK_(as5040_sclk),
|
||||||
spi(nullptr),
|
spi(nullptr),
|
||||||
settings(AS5145SSISettings) {
|
settings(AS5145SSISettings) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MagneticSensorAS5045::~MagneticSensorAS5045() = default;
|
MagneticSensorAS5045::~MagneticSensorAS5045() = default;
|
||||||
|
|
||||||
auto MagneticSensorAS5045::init(SPIClass *_spi) -> void {
|
auto MagneticSensorAS5045::init(SPIClass *_spi) -> void {
|
||||||
this->spi = _spi;
|
this->spi = _spi;
|
||||||
settings = AS5145SSISettings;
|
settings = AS5145SSISettings;
|
||||||
pinMode(AS5040_CS_, OUTPUT);
|
pinMode(AS5040_CS_, OUTPUT);
|
||||||
pinMode(AS5040_MISO_, INPUT);
|
pinMode(AS5040_MISO_, INPUT);
|
||||||
pinMode(AS5040_MOSI_, OUTPUT);
|
pinMode(AS5040_MOSI_, OUTPUT);
|
||||||
pinMode(AS5040_SCLK_, OUTPUT);
|
pinMode(AS5040_SCLK_, OUTPUT);
|
||||||
|
|
||||||
spi->setMISO(AS5040_MISO_);
|
spi->setMISO(AS5040_MISO_);
|
||||||
spi->setMOSI(AS5040_MOSI_);
|
spi->setMOSI(AS5040_MOSI_);
|
||||||
spi->setSCLK(AS5040_SCLK_);
|
spi->setSCLK(AS5040_SCLK_);
|
||||||
spi->begin();
|
spi->begin();
|
||||||
this->Sensor::init();
|
this->Sensor::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
float MagneticSensorAS5045::getSensorAngle() {
|
float MagneticSensorAS5045::getSensorAngle() {
|
||||||
float angle_data = readRawAngleSSI();
|
float angle_data = readRawAngleSSI();
|
||||||
angle_data = (static_cast<float>(angle_data) / AS5045_CPR) * _2PI;
|
angle_data = (static_cast<float>(angle_data) / AS5045_CPR) * _2PI;
|
||||||
return angle_data;
|
return angle_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t MagneticSensorAS5045::readRawAngleSSI() const {
|
uint16_t MagneticSensorAS5045::readRawAngleSSI() const {
|
||||||
spi->beginTransaction(settings);
|
spi->beginTransaction(settings);
|
||||||
digitalWrite(AS5040_CS_, LOW);
|
digitalWrite(AS5040_CS_, LOW);
|
||||||
uint16_t value = spi->transfer16(0x0000);
|
uint16_t value = spi->transfer16(0x0000);
|
||||||
digitalWrite(AS5040_CS_, HIGH);
|
digitalWrite(AS5040_CS_, HIGH);
|
||||||
spi->endTransaction();
|
spi->endTransaction();
|
||||||
delayMicroseconds(30);
|
delayMicroseconds(30);
|
||||||
return (value >> 3) & 0x1FFF; // TODO(vanyabeat): Add error checking MAGNETIC OWERFLOW and etc.
|
return (value >> 3) & 0x1FFF; // TODO(vanyabeat): Add error checking MAGNETIC OWERFLOW and etc.
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SimpleFOC.h"
|
#include "SimpleFOC.h"
|
||||||
#include "SPI.h"
|
#include "SPI.h"
|
||||||
|
|
||||||
#ifndef MSBFIRST
|
#ifndef MSBFIRST
|
||||||
#define MSBFIRST BitOrder::MSBFIRST
|
#define MSBFIRST BitOrder::MSBFIRST
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define AS5045_BITORDER MSBFIRST
|
#define AS5045_BITORDER MSBFIRST
|
||||||
#define AS5045_CPR 4096.0f
|
#define AS5045_CPR 4096.0f
|
||||||
#define _2PI 6.28318530718f
|
#define _2PI 6.28318530718f
|
||||||
|
|
||||||
static SPISettings AS5145SSISettings(1000000, AS5045_BITORDER, SPI_MODE0);
|
static SPISettings AS5145SSISettings(1000000, AS5045_BITORDER, SPI_MODE0);
|
||||||
|
|
||||||
class MagneticSensorAS5045 final: public Sensor {
|
class MagneticSensorAS5045 final: public Sensor {
|
||||||
public:
|
public:
|
||||||
MagneticSensorAS5045(uint16_t as5040_cs, uint16_t as5040_mosi, uint16_t as5040_miso, uint16_t as5040_sclk);
|
MagneticSensorAS5045(uint16_t as5040_cs, uint16_t as5040_mosi, uint16_t as5040_miso, uint16_t as5040_sclk);
|
||||||
|
|
||||||
virtual ~MagneticSensorAS5045();
|
virtual ~MagneticSensorAS5045();
|
||||||
|
|
||||||
float getSensorAngle() override;
|
float getSensorAngle() override;
|
||||||
|
|
||||||
virtual void init(SPIClass *_spi = &SPI);
|
virtual void init(SPIClass *_spi = &SPI);
|
||||||
|
|
||||||
[[nodiscard]] uint16_t readRawAngleSSI() const;
|
[[nodiscard]] uint16_t readRawAngleSSI() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint16_t AS5040_CS_, AS5040_MOSI_, AS5040_MISO_, AS5040_SCLK_;
|
uint16_t AS5040_CS_, AS5040_MOSI_, AS5040_MISO_, AS5040_SCLK_;
|
||||||
SPIClass *spi;
|
SPIClass *spi;
|
||||||
SPISettings settings;
|
SPISettings settings;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
name=AS5045
|
name=AS5045
|
||||||
version=1.0.1
|
version=1.0.1
|
||||||
author=vanyabeat <vanyabeat@protonmail.com>
|
author=vanyabeat <vanyabeat@protonmail.com>
|
||||||
maintainer=vanyabeat <vanyabeat@protonmail.com>
|
maintainer=vanyabeat <vanyabeat@protonmail.com>
|
||||||
sentence=Simple library to work with AS5040 and Simple FOC (for Robotroller in Robosemmbler) Fork from https://github.com/runger1101001
|
sentence=Simple library to work with AS5040 and Simple FOC (for Robotroller in Robosemmbler) Fork from https://github.com/runger1101001
|
||||||
paragraph=Simple library to work with AS5040 and Simple FOC and simple library intended for hobby comunity to run the AS5040 magnetic sensor using FOC algorithm. It is intended to support as many BLDC/Stepper motor+sensor+driver combinations as possible and in the same time maintain simplicity of usage. Library supports Arudino devices such as Arduino UNO, MEGA, NANO and similar, stm32 boards such as Nucleo and Bluepill, ESP32 and Teensy boards.
|
paragraph=Simple library to work with AS5040 and Simple FOC and simple library intended for hobby comunity to run the AS5040 magnetic sensor using FOC algorithm. It is intended to support as many BLDC/Stepper motor+sensor+driver combinations as possible and in the same time maintain simplicity of usage. Library supports Arudino devices such as Arduino UNO, MEGA, NANO and similar, stm32 boards such as Nucleo and Bluepill, ESP32 and Teensy boards.
|
||||||
category=Device Control
|
category=Device Control
|
||||||
url=https://docs.simplefoc.com
|
url=https://docs.simplefoc.com
|
||||||
architectures=*
|
architectures=*
|
||||||
includes=SimpleFOC.h
|
includes=SimpleFOC.h
|
|
@ -1,42 +1,42 @@
|
||||||
#include "DRV8313.h"
|
#include "DRV8313.h"
|
||||||
|
|
||||||
DRV8313Driver::DRV8313Driver(int phA, int phB, int phC, int en1, int en2, int en3, int slp, int rst,
|
DRV8313Driver::DRV8313Driver(int phA, int phB, int phC, int en1, int en2, int en3, int slp, int rst,
|
||||||
int flt) : BLDCDriver3PWM(phA, phB, phC, en1, en2, en3), slp_pin(slp), rst_pin(rst),
|
int flt) : BLDCDriver3PWM(phA, phB, phC, en1, en2, en3), slp_pin(slp), rst_pin(rst),
|
||||||
flt_pin(flt) {
|
flt_pin(flt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int DRV8313Driver::init() {
|
int DRV8313Driver::init() {
|
||||||
// Get state from flt pin
|
// Get state from flt pin
|
||||||
if (_isset(flt_pin)) {
|
if (_isset(flt_pin)) {
|
||||||
pinMode(flt_pin, INPUT);
|
pinMode(flt_pin, INPUT);
|
||||||
if (digitalRead(flt_pin) == HIGH) {
|
if (digitalRead(flt_pin) == HIGH) {
|
||||||
// if the fault pin is high the driver is in fault state
|
// if the fault pin is high the driver is in fault state
|
||||||
// reset the driver
|
// reset the driver
|
||||||
if (_isset(rst_pin)) {
|
if (_isset(rst_pin)) {
|
||||||
pinMode(rst_pin, OUTPUT);
|
pinMode(rst_pin, OUTPUT);
|
||||||
digitalWrite(rst_pin, LOW);
|
digitalWrite(rst_pin, LOW);
|
||||||
delay(1);
|
delay(1);
|
||||||
digitalWrite(rst_pin, HIGH);
|
digitalWrite(rst_pin, HIGH);
|
||||||
delay(1);
|
delay(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return BLDCDriver3PWM::init();
|
return BLDCDriver3PWM::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DRV8313Driver::enable() {
|
void DRV8313Driver::enable() {
|
||||||
// Enable the driver
|
// Enable the driver
|
||||||
if (_isset(slp_pin)) {
|
if (_isset(slp_pin)) {
|
||||||
pinMode(slp_pin, OUTPUT);
|
pinMode(slp_pin, OUTPUT);
|
||||||
digitalWrite(slp_pin, HIGH);
|
digitalWrite(slp_pin, HIGH);
|
||||||
}
|
}
|
||||||
BLDCDriver3PWM::enable();
|
BLDCDriver3PWM::enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DRV8313Driver::disable() {
|
void DRV8313Driver::disable() {
|
||||||
if (_isset(slp_pin)) {
|
if (_isset(slp_pin)) {
|
||||||
pinMode(slp_pin, OUTPUT);
|
pinMode(slp_pin, OUTPUT);
|
||||||
digitalWrite(slp_pin, LOW);
|
digitalWrite(slp_pin, LOW);
|
||||||
}
|
}
|
||||||
BLDCDriver3PWM::disable();
|
BLDCDriver3PWM::disable();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SimpleFOC.h"
|
#include "SimpleFOC.h"
|
||||||
|
|
||||||
class DRV8313Driver : public BLDCDriver3PWM {
|
class DRV8313Driver : public BLDCDriver3PWM {
|
||||||
public:
|
public:
|
||||||
DRV8313Driver(int phA, int phB, int phC, int en1 = NOT_SET, int en2 = NOT_SET, int en3 = NOT_SET, int slp = NOT_SET,
|
DRV8313Driver(int phA, int phB, int phC, int en1 = NOT_SET, int en2 = NOT_SET, int en3 = NOT_SET, int slp = NOT_SET,
|
||||||
int rst = NOT_SET, int flt = NOT_SET);
|
int rst = NOT_SET, int flt = NOT_SET);
|
||||||
|
|
||||||
int init() override;
|
int init() override;
|
||||||
|
|
||||||
void enable() override;
|
void enable() override;
|
||||||
|
|
||||||
void disable() override;
|
void disable() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int slp_pin;
|
int slp_pin;
|
||||||
int rst_pin;
|
int rst_pin;
|
||||||
int flt_pin;
|
int flt_pin;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
name=DRV8313 Simple FOC
|
name=DRV8313 Simple FOC
|
||||||
version=1.0.0
|
version=1.0.0
|
||||||
author=vanyabeat <vanyabeat@protonmail.com>
|
author=vanyabeat <vanyabeat@protonmail.com>
|
||||||
maintainer=vanyabeat <vanyabeat@protonmail.com>
|
maintainer=vanyabeat <vanyabeat@protonmail.com>
|
||||||
sentence=Simple library to work with DRV8313 and Simple FOC (for Robotroller in Robosemmbler)
|
sentence=Simple library to work with DRV8313 and Simple FOC (for Robotroller in Robosemmbler)
|
||||||
paragraph=Simple library to work with DRV8313 and Simple FOC and simple library intended for hobby comunity to run the BLDC and Stepper motor using FOC algorithm. It is intended to support as many BLDC/Stepper motor+sensor+driver combinations as possible and in the same time maintain simplicity of usage. Library supports Arudino devices such as Arduino UNO, MEGA, NANO and similar, stm32 boards such as Nucleo and Bluepill, ESP32 and Teensy boards.
|
paragraph=Simple library to work with DRV8313 and Simple FOC and simple library intended for hobby comunity to run the BLDC and Stepper motor using FOC algorithm. It is intended to support as many BLDC/Stepper motor+sensor+driver combinations as possible and in the same time maintain simplicity of usage. Library supports Arudino devices such as Arduino UNO, MEGA, NANO and similar, stm32 boards such as Nucleo and Bluepill, ESP32 and Teensy boards.
|
||||||
category=Device Control
|
category=Device Control
|
||||||
url=https://docs.simplefoc.com
|
url=https://docs.simplefoc.com
|
||||||
architectures=*
|
architectures=*
|
||||||
includes=SimpleFOC.h
|
includes=SimpleFOC.h
|
|
@ -1,46 +1,46 @@
|
||||||
|
|
||||||
This directory is intended for project specific (private) libraries.
|
This directory is intended for project specific (private) libraries.
|
||||||
PlatformIO will compile them to static libraries and link into executable file.
|
PlatformIO will compile them to static libraries and link into executable file.
|
||||||
|
|
||||||
The source code of each library should be placed in a an own separate directory
|
The source code of each library should be placed in a an own separate directory
|
||||||
("lib/your_library_name/[here are source files]").
|
("lib/your_library_name/[here are source files]").
|
||||||
|
|
||||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||||
|
|
||||||
|--lib
|
|--lib
|
||||||
| |
|
| |
|
||||||
| |--Bar
|
| |--Bar
|
||||||
| | |--docs
|
| | |--docs
|
||||||
| | |--examples
|
| | |--examples
|
||||||
| | |--src
|
| | |--src
|
||||||
| | |- Bar.c
|
| | |- Bar.c
|
||||||
| | |- Bar.h
|
| | |- Bar.h
|
||||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||||
| |
|
| |
|
||||||
| |--Foo
|
| |--Foo
|
||||||
| | |- Foo.c
|
| | |- Foo.c
|
||||||
| | |- Foo.h
|
| | |- Foo.h
|
||||||
| |
|
| |
|
||||||
| |- README --> THIS FILE
|
| |- README --> THIS FILE
|
||||||
|
|
|
|
||||||
|- platformio.ini
|
|- platformio.ini
|
||||||
|--src
|
|--src
|
||||||
|- main.c
|
|- main.c
|
||||||
|
|
||||||
and a contents of `src/main.c`:
|
and a contents of `src/main.c`:
|
||||||
```
|
```
|
||||||
#include <Foo.h>
|
#include <Foo.h>
|
||||||
#include <Bar.h>
|
#include <Bar.h>
|
||||||
|
|
||||||
int main (void)
|
int main (void)
|
||||||
{
|
{
|
||||||
...
|
...
|
||||||
}
|
}
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
PlatformIO Library Dependency Finder will find automatically dependent
|
PlatformIO Library Dependency Finder will find automatically dependent
|
||||||
libraries scanning project source files.
|
libraries scanning project source files.
|
||||||
|
|
||||||
More information about PlatformIO Library Dependency Finder
|
More information about PlatformIO Library Dependency Finder
|
||||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
[env:robotroller_reborn]
|
[env:robotroller_reborn]
|
||||||
platform = ststm32
|
platform = ststm32
|
||||||
board = genericSTM32F446RE
|
board = genericSTM32F446RE
|
||||||
framework = arduino
|
framework = arduino
|
||||||
upload_protocol = stlink
|
upload_protocol = stlink
|
||||||
debug_tool = stlink
|
debug_tool = stlink
|
||||||
monitor_speed = 19200
|
monitor_speed = 19200
|
||||||
monitor_parity = N
|
monitor_parity = N
|
||||||
|
|
||||||
board_upload.offset_address = 0x08008000
|
board_upload.offset_address = 0x08008000
|
||||||
board_build.ldscript = ${PROJECT_DIR}/custom_script.ld
|
board_build.ldscript = ${PROJECT_DIR}/custom_script.ld
|
||||||
|
|
||||||
build_flags =
|
build_flags =
|
||||||
-D STM32F446xx
|
-D STM32F446xx
|
||||||
-D HAL_CAN_MODULE_ENABLED
|
-D HAL_CAN_MODULE_ENABLED
|
||||||
-D SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH
|
-D SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH
|
||||||
|
|
||||||
lib_deps =
|
lib_deps =
|
||||||
askuric/Simple FOC@^2.3.4
|
askuric/Simple FOC@^2.3.4
|
||||||
pazi88/STM32_CAN@^1.1.2
|
pazi88/STM32_CAN@^1.1.2
|
||||||
|
|
||||||
extra_scripts =
|
extra_scripts =
|
||||||
pre:gen_compile_commands.py
|
pre:gen_compile_commands.py
|
||||||
post:hex_compile.py
|
post:hex_compile.py
|
||||||
|
|
|
@ -1,75 +1,75 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
|
|
||||||
void setup_foc(MagneticSensorAS5045 *encoder, BLDCMotor *motor,
|
void setup_foc(MagneticSensorAS5045 *encoder, BLDCMotor *motor,
|
||||||
DRV8313Driver *driver, LowsideCurrentSense *current_sense,
|
DRV8313Driver *driver, LowsideCurrentSense *current_sense,
|
||||||
FLASH_RECORD* pid_data) {
|
FLASH_RECORD* pid_data) {
|
||||||
encoder->init(&spi);
|
encoder->init(&spi);
|
||||||
|
|
||||||
/* convert data from flash int value to float*/
|
/* convert data from flash int value to float*/
|
||||||
conv_float_to_int.i = pid_data[pid_p].value;
|
conv_float_to_int.i = pid_data[pid_p].value;
|
||||||
float p = conv_float_to_int.f;
|
float p = conv_float_to_int.f;
|
||||||
|
|
||||||
conv_float_to_int.i = pid_data[pid_i].value;
|
conv_float_to_int.i = pid_data[pid_i].value;
|
||||||
float i = conv_float_to_int.f;
|
float i = conv_float_to_int.f;
|
||||||
|
|
||||||
conv_float_to_int.i = pid_data[pid_d].value;
|
conv_float_to_int.i = pid_data[pid_d].value;
|
||||||
float d = conv_float_to_int.f;
|
float d = conv_float_to_int.f;
|
||||||
|
|
||||||
// Driver configuration
|
// Driver configuration
|
||||||
driver->pwm_frequency = 20000;
|
driver->pwm_frequency = 20000;
|
||||||
driver->voltage_power_supply = 24;
|
driver->voltage_power_supply = 24;
|
||||||
driver->voltage_limit = 24;
|
driver->voltage_limit = 24;
|
||||||
driver->init();
|
driver->init();
|
||||||
|
|
||||||
// Current sense initialization
|
// Current sense initialization
|
||||||
current_sense->linkDriver(driver);
|
current_sense->linkDriver(driver);
|
||||||
current_sense->init();
|
current_sense->init();
|
||||||
|
|
||||||
// Motor configuration
|
// Motor configuration
|
||||||
motor->linkSensor(encoder);
|
motor->linkSensor(encoder);
|
||||||
motor->linkDriver(driver);
|
motor->linkDriver(driver);
|
||||||
motor->linkCurrentSense(current_sense);
|
motor->linkCurrentSense(current_sense);
|
||||||
motor->controller = MotionControlType::angle;
|
motor->controller = MotionControlType::angle;
|
||||||
motor->torque_controller = TorqueControlType::voltage;
|
motor->torque_controller = TorqueControlType::voltage;
|
||||||
motor->foc_modulation = FOCModulationType::SpaceVectorPWM;
|
motor->foc_modulation = FOCModulationType::SpaceVectorPWM;
|
||||||
|
|
||||||
// PID Configuration
|
// PID Configuration
|
||||||
motor->PID_velocity.P = 0.5f;
|
motor->PID_velocity.P = 0.5f;
|
||||||
motor->PID_velocity.I = 2.0f;
|
motor->PID_velocity.I = 2.0f;
|
||||||
motor->PID_velocity.D = 0.0f;
|
motor->PID_velocity.D = 0.0f;
|
||||||
|
|
||||||
motor->LPF_velocity.Tf = 0.01f;
|
motor->LPF_velocity.Tf = 0.01f;
|
||||||
motor->P_angle.P = p;
|
motor->P_angle.P = p;
|
||||||
motor->P_angle.I = i;
|
motor->P_angle.I = i;
|
||||||
motor->P_angle.D = d;
|
motor->P_angle.D = d;
|
||||||
motor->LPF_angle.Tf = 0.02f;
|
motor->LPF_angle.Tf = 0.02f;
|
||||||
|
|
||||||
// Motor limits
|
// Motor limits
|
||||||
motor->velocity_limit = 40; // Speed limit in rad/s (382 rpm)
|
motor->velocity_limit = 40; // Speed limit in rad/s (382 rpm)
|
||||||
motor->voltage_limit = 24;
|
motor->voltage_limit = 24;
|
||||||
motor->current_limit = 0.5;
|
motor->current_limit = 0.5;
|
||||||
|
|
||||||
motor->sensor_direction = Direction::CCW;
|
motor->sensor_direction = Direction::CCW;
|
||||||
motor->init();
|
motor->init();
|
||||||
motor->initFOC();
|
motor->initFOC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void foc_step(BLDCMotor *motor) {
|
void foc_step(BLDCMotor *motor) {
|
||||||
if (motor_control_inputs.target_velocity != 0 ||
|
if (motor_control_inputs.target_velocity != 0 ||
|
||||||
motor->controller == MotionControlType::velocity) {
|
motor->controller == MotionControlType::velocity) {
|
||||||
if (motor->controller != MotionControlType::velocity) {
|
if (motor->controller != MotionControlType::velocity) {
|
||||||
motor->controller = MotionControlType::velocity;
|
motor->controller = MotionControlType::velocity;
|
||||||
}
|
}
|
||||||
motor->target = motor_control_inputs.target_velocity;
|
motor->target = motor_control_inputs.target_velocity;
|
||||||
} else {
|
} else {
|
||||||
if (motor->controller != MotionControlType::angle) {
|
if (motor->controller != MotionControlType::angle) {
|
||||||
motor->controller = MotionControlType::angle;
|
motor->controller = MotionControlType::angle;
|
||||||
}
|
}
|
||||||
motor->target = motor_control_inputs.target_angle;
|
motor->target = motor_control_inputs.target_angle;
|
||||||
}
|
}
|
||||||
|
|
||||||
motor->loopFOC();
|
motor->loopFOC();
|
||||||
motor->move();
|
motor->move();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,251 +1,251 @@
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "hal_conf_extra.h"
|
#include "hal_conf_extra.h"
|
||||||
|
|
||||||
|
|
||||||
void flash_unlock(){
|
void flash_unlock(){
|
||||||
// Check if flash is locked
|
// Check if flash is locked
|
||||||
if(!(FLASH->CR & FLASH_CR_LOCK)) {
|
if(!(FLASH->CR & FLASH_CR_LOCK)) {
|
||||||
return; // Already unlocked
|
return; // Already unlocked
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write flash key sequence to unlock
|
// Write flash key sequence to unlock
|
||||||
FLASH->KEYR = 0x45670123; // First key
|
FLASH->KEYR = 0x45670123; // First key
|
||||||
FLASH->KEYR = 0xCDEF89AB; // Second key
|
FLASH->KEYR = 0xCDEF89AB; // Second key
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flash_lock() {
|
void flash_lock() {
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
return; // Already locked
|
return; // Already locked
|
||||||
}
|
}
|
||||||
FLASH->CR |= FLASH_CR_LOCK; // Lock flash memory
|
FLASH->CR |= FLASH_CR_LOCK; // Lock flash memory
|
||||||
}
|
}
|
||||||
|
|
||||||
void erase_sector(uint8_t sector){
|
void erase_sector(uint8_t sector){
|
||||||
|
|
||||||
// Wait if flash is busy
|
// Wait if flash is busy
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Check if flash is locked and unlock if needed
|
// Check if flash is locked and unlock if needed
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set sector erase bit and sector number
|
// Set sector erase bit and sector number
|
||||||
FLASH->CR |= FLASH_CR_SER;
|
FLASH->CR |= FLASH_CR_SER;
|
||||||
FLASH->CR &= ~FLASH_CR_SNB;
|
FLASH->CR &= ~FLASH_CR_SNB;
|
||||||
FLASH->CR |= (sector << FLASH_CR_SNB_Pos) & FLASH_CR_SNB_Msk;
|
FLASH->CR |= (sector << FLASH_CR_SNB_Pos) & FLASH_CR_SNB_Msk;
|
||||||
|
|
||||||
// Start erase
|
// Start erase
|
||||||
FLASH->CR |= FLASH_CR_STRT;
|
FLASH->CR |= FLASH_CR_STRT;
|
||||||
|
|
||||||
// Wait for erase to complete
|
// Wait for erase to complete
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Clear sector erase bit
|
// Clear sector erase bit
|
||||||
FLASH->CR &= ~FLASH_CR_SER;
|
FLASH->CR &= ~FLASH_CR_SER;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void flash_program_word(uint32_t address,uint32_t data,uint32_t byte_len){
|
void flash_program_word(uint32_t address,uint32_t data,uint32_t byte_len){
|
||||||
|
|
||||||
// Wait if flash is busy
|
// Wait if flash is busy
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
// Check if flash is locked and unlock if needed
|
// Check if flash is locked and unlock if needed
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set program bit 32bit programm size and Write data to address
|
// Set program bit 32bit programm size and Write data to address
|
||||||
if(byte_len == 1) {
|
if(byte_len == 1) {
|
||||||
FLASH_8BYTE;
|
FLASH_8BYTE;
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
*(volatile uint8_t*)address = (uint8_t)data;
|
*(volatile uint8_t*)address = (uint8_t)data;
|
||||||
} else {
|
} else {
|
||||||
FLASH_32BYTE;
|
FLASH_32BYTE;
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
*(volatile uint32_t*)address = data;
|
*(volatile uint32_t*)address = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for programming to complete
|
// Wait for programming to complete
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Clear program bit
|
// Clear program bit
|
||||||
FLASH->CR &= ~FLASH_CR_PG;
|
FLASH->CR &= ~FLASH_CR_PG;
|
||||||
|
|
||||||
}
|
}
|
||||||
void flash_write(uint32_t addr, FLASH_RECORD* record){
|
void flash_write(uint32_t addr, FLASH_RECORD* record){
|
||||||
|
|
||||||
uint32_t* data = (uint32_t*)record;
|
uint32_t* data = (uint32_t*)record;
|
||||||
uint32_t size = FLASH_RECORD_SIZE / 4; //count words in struct
|
uint32_t size = FLASH_RECORD_SIZE / 4; //count words in struct
|
||||||
// Wait if flash is busy
|
// Wait if flash is busy
|
||||||
while(FLASH_BUSY);
|
while(FLASH_BUSY);
|
||||||
|
|
||||||
// Check if flash is locked and unlock if needed
|
// Check if flash is locked and unlock if needed
|
||||||
if(FLASH->CR & FLASH_CR_LOCK) {
|
if(FLASH->CR & FLASH_CR_LOCK) {
|
||||||
flash_unlock();
|
flash_unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set program bit and write data to flash
|
// Set program bit and write data to flash
|
||||||
FLASH_32BYTE;
|
FLASH_32BYTE;
|
||||||
FLASH->CR |= FLASH_CR_PG;
|
FLASH->CR |= FLASH_CR_PG;
|
||||||
|
|
||||||
for(int i = 0;i < size;i++){
|
for(int i = 0;i < size;i++){
|
||||||
*(volatile uint32_t*)(addr + (i * 4)) = data[i];
|
*(volatile uint32_t*)(addr + (i * 4)) = data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear program bit
|
// Clear program bit
|
||||||
FLASH->CR &= ~FLASH_CR_PG;
|
FLASH->CR &= ~FLASH_CR_PG;
|
||||||
write_ptr = addr + (size * 4); //increase variable storing addr
|
write_ptr = addr + (size * 4); //increase variable storing addr
|
||||||
flash_lock();
|
flash_lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t flash_read_word(uint32_t address){
|
uint8_t flash_read_word(uint32_t address){
|
||||||
|
|
||||||
// Check if address is valid
|
// Check if address is valid
|
||||||
if(address < FLASH_BASE || address > FLASH_END) {
|
if(address < FLASH_BASE || address > FLASH_END) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read byte from flash memory
|
// Read byte from flash memory
|
||||||
return *((volatile uint8_t*)address);
|
return *((volatile uint8_t*)address);
|
||||||
|
|
||||||
}
|
}
|
||||||
// Wait if flash
|
// Wait if flash
|
||||||
// bool validata_crc(FLASH_RECORD* crc){
|
// bool validata_crc(FLASH_RECORD* crc){
|
||||||
// return crc->crc == 0x6933? true : false;
|
// return crc->crc == 0x6933? true : false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
uint16_t validate_crc16(uint8_t *data, uint32_t length) {
|
uint16_t validate_crc16(uint8_t *data, uint32_t length) {
|
||||||
uint16_t crc = 0xFFFF; // start value for CRC MODBUS
|
uint16_t crc = 0xFFFF; // start value for CRC MODBUS
|
||||||
while (length--) {
|
while (length--) {
|
||||||
crc ^= *data++; // XOR
|
crc ^= *data++; // XOR
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
if (crc & 0x0001) {
|
if (crc & 0x0001) {
|
||||||
crc = (crc >> 1) ^ 0xA001; // polynome 0x8005 (reverse)
|
crc = (crc >> 1) ^ 0xA001; // polynome 0x8005 (reverse)
|
||||||
} else {
|
} else {
|
||||||
crc >>= 1;
|
crc >>= 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t calc_crc_struct(FLASH_RECORD* res){
|
uint16_t calc_crc_struct(FLASH_RECORD* res){
|
||||||
|
|
||||||
uint8_t arr_res[FLASH_RECORD_SIZE - 2];
|
uint8_t arr_res[FLASH_RECORD_SIZE - 2];
|
||||||
uint16_t crc_res;
|
uint16_t crc_res;
|
||||||
/* sorting data without CRC */
|
/* sorting data without CRC */
|
||||||
arr_res[0] = res->data_id;
|
arr_res[0] = res->data_id;
|
||||||
arr_res[1] = res->data_type;
|
arr_res[1] = res->data_type;
|
||||||
|
|
||||||
/* from 32 to 8 bit */
|
/* from 32 to 8 bit */
|
||||||
for(int i = 0;i < 4;i++)
|
for(int i = 0;i < 4;i++)
|
||||||
arr_res[i + 2] = (uint8_t)(res->value >> i * 8);
|
arr_res[i + 2] = (uint8_t)(res->value >> i * 8);
|
||||||
|
|
||||||
crc_res = validate_crc16(arr_res,FLASH_RECORD_SIZE - 2);
|
crc_res = validate_crc16(arr_res,FLASH_RECORD_SIZE - 2);
|
||||||
return crc_res;
|
return crc_res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void disable_flash_protection() {
|
void disable_flash_protection() {
|
||||||
HAL_FLASH_Unlock();
|
HAL_FLASH_Unlock();
|
||||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
|
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR);
|
||||||
HAL_FLASH_Lock();
|
HAL_FLASH_Lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read struct from FLASH */
|
/* read struct from FLASH */
|
||||||
void flash_read(uint32_t addr,FLASH_RECORD* ptr){
|
void flash_read(uint32_t addr,FLASH_RECORD* ptr){
|
||||||
disable_flash_protection();
|
disable_flash_protection();
|
||||||
uint8_t* flash_ptr = (uint8_t*)addr;
|
uint8_t* flash_ptr = (uint8_t*)addr;
|
||||||
uint8_t* dest = (uint8_t*)ptr;
|
uint8_t* dest = (uint8_t*)ptr;
|
||||||
for(int i = 0;i < FLASH_RECORD_SIZE;i++)
|
for(int i = 0;i < FLASH_RECORD_SIZE;i++)
|
||||||
dest[i] = flash_ptr[i];
|
dest[i] = flash_ptr[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
void compact_page(){
|
void compact_page(){
|
||||||
FLASH_RECORD latest[PARAM_COUNT] = {0};
|
FLASH_RECORD latest[PARAM_COUNT] = {0};
|
||||||
for(int i = (uint32_t)SECTOR_6;i < (uint32_t)SECTOR_7;i += FLASH_RECORD_SIZE) {
|
for(int i = (uint32_t)SECTOR_6;i < (uint32_t)SECTOR_7;i += FLASH_RECORD_SIZE) {
|
||||||
FLASH_RECORD rec;
|
FLASH_RECORD rec;
|
||||||
flash_read(i,&rec);
|
flash_read(i,&rec);
|
||||||
uint16_t calculated_crc = calc_crc_struct(&rec);
|
uint16_t calculated_crc = calc_crc_struct(&rec);
|
||||||
|
|
||||||
if (calculated_crc == rec.crc && rec.data_id < PARAM_COUNT) {
|
if (calculated_crc == rec.crc && rec.data_id < PARAM_COUNT) {
|
||||||
// if the crc does not match, we check further
|
// if the crc does not match, we check further
|
||||||
latest[rec.data_id] = rec;
|
latest[rec.data_id] = rec;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// if
|
// if
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
erase_sector(6);
|
erase_sector(6);
|
||||||
write_ptr = SECTOR_6; // Сброс на начало
|
write_ptr = SECTOR_6; // Сброс на начало
|
||||||
for (int i = 0; i < PARAM_COUNT; i++) {
|
for (int i = 0; i < PARAM_COUNT; i++) {
|
||||||
if (latest[i].data_id != 0xFF) {
|
if (latest[i].data_id != 0xFF) {
|
||||||
// alignment
|
// alignment
|
||||||
if (write_ptr % 4 != 0) {
|
if (write_ptr % 4 != 0) {
|
||||||
write_ptr += (4 - (write_ptr % 4));
|
write_ptr += (4 - (write_ptr % 4));
|
||||||
}
|
}
|
||||||
flash_write(write_ptr, &latest[i]);
|
flash_write(write_ptr, &latest[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_param(uint8_t param_id, uint32_t val) {
|
void write_param(uint8_t param_id, uint32_t val) {
|
||||||
FLASH_RECORD param_flash;
|
FLASH_RECORD param_flash;
|
||||||
// __disable_irq(); // Interrupt off
|
// __disable_irq(); // Interrupt off
|
||||||
param_flash.data_id = param_id;
|
param_flash.data_id = param_id;
|
||||||
param_flash.value = val;
|
param_flash.value = val;
|
||||||
param_flash.data_type = sizeof(uint8_t);
|
param_flash.data_type = sizeof(uint8_t);
|
||||||
param_flash.crc = calc_crc_struct(¶m_flash);
|
param_flash.crc = calc_crc_struct(¶m_flash);
|
||||||
|
|
||||||
// check alignment
|
// check alignment
|
||||||
if (write_ptr % 8 != 0) {
|
if (write_ptr % 8 != 0) {
|
||||||
write_ptr += (8 - (write_ptr % 8));
|
write_ptr += (8 - (write_ptr % 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check buffer overflow
|
// check buffer overflow
|
||||||
if (write_ptr + FLASH_RECORD_SIZE >= SECTOR_6_END) {
|
if (write_ptr + FLASH_RECORD_SIZE >= SECTOR_6_END) {
|
||||||
compact_page(); // after compact_page update
|
compact_page(); // after compact_page update
|
||||||
// alignment
|
// alignment
|
||||||
if (write_ptr % 8 != 0) {
|
if (write_ptr % 8 != 0) {
|
||||||
write_ptr += (8 - (write_ptr % 8));
|
write_ptr += (8 - (write_ptr % 8));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
flash_write(write_ptr, ¶m_flash); //inside the function, the write_ptr pointer is automatically incremented by the size of the structure
|
flash_write(write_ptr, ¶m_flash); //inside the function, the write_ptr pointer is automatically incremented by the size of the structure
|
||||||
|
|
||||||
// __enable_irq(); // Interrupt on
|
// __enable_irq(); // Interrupt on
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FLASH_RECORD* load_params(){
|
FLASH_RECORD* load_params(){
|
||||||
__disable_irq();
|
__disable_irq();
|
||||||
static FLASH_RECORD latest[PARAM_COUNT] = {0};
|
static FLASH_RECORD latest[PARAM_COUNT] = {0};
|
||||||
FLASH_RECORD res;
|
FLASH_RECORD res;
|
||||||
|
|
||||||
for(uint32_t addr = SECTOR_6;addr < SECTOR_6_END;addr +=FLASH_RECORD_SIZE) {
|
for(uint32_t addr = SECTOR_6;addr < SECTOR_6_END;addr +=FLASH_RECORD_SIZE) {
|
||||||
flash_read(addr,&res);
|
flash_read(addr,&res);
|
||||||
|
|
||||||
|
|
||||||
uint16_t calculated_crc = calc_crc_struct(&res);
|
uint16_t calculated_crc = calc_crc_struct(&res);
|
||||||
if (calculated_crc != res.crc || res.data_id >= PARAM_COUNT) continue;
|
if (calculated_crc != res.crc || res.data_id >= PARAM_COUNT) continue;
|
||||||
|
|
||||||
else{
|
else{
|
||||||
latest[res.data_id] = res;
|
latest[res.data_id] = res;
|
||||||
write_ptr = addr + FLASH_RECORD_SIZE;
|
write_ptr = addr + FLASH_RECORD_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__enable_irq();
|
__enable_irq();
|
||||||
return latest;
|
return latest;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,115 +1,119 @@
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include "stm32f446xx.h"
|
#include "stm32f446xx.h"
|
||||||
#include <SimpleFOC.h>
|
#include <SimpleFOC.h>
|
||||||
#include <STM32_CAN.h>
|
#include <STM32_CAN.h>
|
||||||
#include <AS5045.h>
|
#include <AS5045.h>
|
||||||
#include <DRV8313.h>
|
#include <DRV8313.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include "common/base_classes/FOCMotor.h"
|
#include "common/base_classes/FOCMotor.h"
|
||||||
#include "hal_conf_extra.h"
|
#include "hal_conf_extra.h"
|
||||||
#include "wiring_analog.h"
|
#include "wiring_analog.h"
|
||||||
#include "wiring_constants.h"
|
#include "wiring_constants.h"
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
#include "hal_conf_extra.h"
|
||||||
#include "reg_cah.h"
|
#include "reg_cah.h"
|
||||||
#include "flash.h"
|
#include "flash.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "process_can.h"
|
#include "process_can.h"
|
||||||
|
|
||||||
void SysTick_Handler(void) {
|
|
||||||
HAL_IncTick();
|
void SysTick_Handler(void) {
|
||||||
}
|
HAL_IncTick();
|
||||||
|
}
|
||||||
STM32_CAN Can(CAN2, DEF);
|
|
||||||
/* for FLASH */
|
STM32_CAN Can(CAN2, DEF);
|
||||||
uint32_t flash_flag;
|
/* for FLASH */
|
||||||
uint8_t flag_can = 0;
|
uint32_t flash_flag;
|
||||||
uint32_t flash_error;
|
uint8_t flag_can = 0;
|
||||||
FLASH_EraseInitTypeDef pEraseInit;
|
uint32_t flash_error;
|
||||||
uint32_t SectorError;
|
FLASH_EraseInitTypeDef pEraseInit;
|
||||||
|
uint32_t SectorError;
|
||||||
|
uint32_t timeout;
|
||||||
/* bool for test CAN */
|
|
||||||
volatile bool CAN_GET = false;
|
/* bool for test CAN */
|
||||||
|
volatile bool CAN_GET = false;
|
||||||
volatile float kt = 0.1; // Torque calculation constant
|
|
||||||
|
volatile float kt = 0.1; // Torque calculation constant
|
||||||
FLASH_RECORD* flash_rec;
|
|
||||||
|
FLASH_RECORD* flash_rec;
|
||||||
|
|
||||||
SPIClass spi;
|
|
||||||
MagneticSensorAS5045 encoder(AS5045_CS, AS5045_MOSI, AS5045_MISO, AS5045_SCLK);
|
SPIClass spi;
|
||||||
|
MagneticSensorAS5045 encoder(AS5045_CS, AS5045_MOSI, AS5045_MISO, AS5045_SCLK);
|
||||||
BLDCMotor motor(POLE_PAIRS);
|
|
||||||
|
BLDCMotor motor(POLE_PAIRS);
|
||||||
DRV8313Driver driver(TIM1_CH1, TIM1_CH2, TIM1_CH3, EN_W_GATE_DRIVER,
|
|
||||||
EN_U_GATE_DRIVER, EN_V_GATE_DRIVER, SLEEP_DRIVER,
|
DRV8313Driver driver(TIM1_CH1, TIM1_CH2, TIM1_CH3, EN_W_GATE_DRIVER,
|
||||||
RESET_DRIVER, FAULT_DRIVER);
|
EN_U_GATE_DRIVER, EN_V_GATE_DRIVER, SLEEP_DRIVER,
|
||||||
LowsideCurrentSense current_sense(0.01, 10.0, CURRENT_SENSOR_1,
|
RESET_DRIVER, FAULT_DRIVER);
|
||||||
CURRENT_SENSOR_2, CURRENT_SENSOR_3);
|
LowsideCurrentSense current_sense(0.01, 10.0, CURRENT_SENSOR_1,
|
||||||
|
CURRENT_SENSOR_2, CURRENT_SENSOR_3);
|
||||||
// Commander command(Serial);
|
|
||||||
|
// Commander command(Serial);
|
||||||
MotorControlInputs motor_control_inputs;
|
|
||||||
|
MotorControlInputs motor_control_inputs;
|
||||||
volatile uint16_t msg_id;
|
|
||||||
volatile uint16_t id_x;
|
volatile uint16_t msg_id;
|
||||||
volatile uint8_t msg_ch;
|
volatile uint16_t id_x;
|
||||||
volatile uint8_t crc_h;
|
volatile uint8_t msg_ch;
|
||||||
volatile uint8_t crc_l;
|
volatile uint8_t crc_h;
|
||||||
|
volatile uint8_t crc_l;
|
||||||
void setup(){
|
|
||||||
SCB->VTOR = (volatile uint32_t)0x08008004;
|
volatile bool rx_can = false;
|
||||||
|
CAN_message_t msg;
|
||||||
Serial.setRx(HARDWARE_SERIAL_RX_PIN);
|
|
||||||
Serial.setTx(HARDWARE_SERIAL_TX_PIN);
|
void setup(){
|
||||||
Serial.begin(115200);
|
SCB->VTOR = (volatile uint32_t)0x08008004;
|
||||||
|
Serial.setRx(HARDWARE_SERIAL_RX_PIN);
|
||||||
pinMode(PC11, OUTPUT);
|
Serial.setTx(HARDWARE_SERIAL_TX_PIN);
|
||||||
pinMode(PC10,OUTPUT);
|
Serial.begin(115200);
|
||||||
GPIOC->ODR &= ~GPIO_ODR_OD10;
|
|
||||||
// Can.enableMBInterrupts();
|
pinMode(PC11, OUTPUT);
|
||||||
Can.begin();
|
pinMode(PC10,OUTPUT);
|
||||||
Can.setBaudRate(1000000);
|
GPIOC->ODR &= ~GPIO_ODR_OD10;
|
||||||
// Настройка прерываний CAN
|
// Can.enableMBInterrupts();
|
||||||
CAN2->IER |= CAN_IER_FMPIE0;
|
Can.begin();
|
||||||
flash_rec = load_params(); //for update write_ptr
|
Can.setBaudRate(1000000);
|
||||||
if(flash_rec[firmw].value == FIRMWARE_FLAG) NVIC_SystemReset(); //if in flash go to the bootloader
|
|
||||||
|
flash_rec = load_params(); //for update write_ptr
|
||||||
// Initialize FOC system
|
if(flash_rec[firmw].value == FIRMWARE_FLAG) NVIC_SystemReset(); //if in flash go to the bootloader
|
||||||
setup_foc(&encoder, &motor, &driver, ¤t_sense,flash_rec);
|
|
||||||
|
// Initialize FOC system
|
||||||
CAN2->IER |= CAN_IER_FMPIE0 | // Сообщение в FIFO0
|
setup_foc(&encoder, &motor, &driver, ¤t_sense,flash_rec);
|
||||||
CAN_IER_FFIE0 | // FIFO0 full
|
|
||||||
CAN_IER_FOVIE0; // FIFO0 overflow
|
// Default motor configuration
|
||||||
|
GPIOC->ODR |= GPIO_ODR_OD11; //set LED
|
||||||
|
motor.torque_controller = TorqueControlType::foc_current;
|
||||||
// Default motor configuration
|
motor.controller = MotionControlType::torque;
|
||||||
GPIOC->ODR |= GPIO_ODR_OD11; //set LED
|
__enable_irq();
|
||||||
motor.torque_controller = TorqueControlType::foc_current;
|
|
||||||
motor.controller = MotionControlType::torque;
|
}
|
||||||
__enable_irq();
|
|
||||||
|
bool is_can_busy() {
|
||||||
}
|
return (CAN2->TSR & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait_for_can_tx_complete() {
|
||||||
void loop() {
|
uint32_t start_time = HAL_GetTick();
|
||||||
__enable_irq();
|
|
||||||
foc_step(&motor);
|
while (!(CAN2->TSR & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2))) {
|
||||||
CAN_message_t msg;
|
if (HAL_GetTick() - start_time > 500) break;
|
||||||
|
}
|
||||||
// Process incoming CAN messages
|
CAN2->TSR |= CAN_TSR_ABRQ0 | CAN_TSR_ABRQ1 | CAN_TSR_ABRQ2;
|
||||||
while (Can.read(msg)) {
|
}
|
||||||
listen_can(msg);
|
|
||||||
CAN_GET = true;
|
void loop() {
|
||||||
}
|
send_velocity();
|
||||||
/* If receive data from CAN */
|
HAL_Delay(1);
|
||||||
if(CAN_GET) {
|
send_angle();
|
||||||
|
HAL_Delay(1);
|
||||||
CAN_GET = false;
|
if(rx_can){
|
||||||
}
|
Can.read(msg);
|
||||||
}
|
listen_can(msg);
|
||||||
|
rx_can = false;
|
||||||
|
HAL_Delay(1);
|
||||||
|
}
|
||||||
|
foc_step(&motor);
|
||||||
|
}
|
||||||
|
|
|
@ -1,245 +1,333 @@
|
||||||
#include "process_can.h"
|
#include "process_can.h"
|
||||||
|
|
||||||
|
|
||||||
static CAN_message_t CAN_TX_msg;
|
static CAN_message_t CAN_TX_msg;
|
||||||
static CAN_message_t CAN_inMsg;
|
static CAN_message_t CAN_inMsg;
|
||||||
|
static uint8_t data_type = DATA_TYPE_ANGLE;
|
||||||
|
volatile bool send_blocked = false;
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void send_can_with_id_crc(uint8_t id, uint8_t message_type, T* data) {
|
void send_can_with_id_crc(uint8_t id, uint8_t message_type, T* data) {
|
||||||
// Create CAN message
|
// Create CAN message
|
||||||
CAN_message_t msg_l;
|
CAN_message_t msg_l;
|
||||||
msg_l.id = id;
|
msg_l.id = id;
|
||||||
// msg_l.len = 8; // Protocol-defined message length
|
// msg_l.len = 8; // Protocol-defined message length
|
||||||
memcpy(&msg_l.buf[0], &message_type, sizeof(uint8_t));
|
memcpy(&msg_l.buf[0], &message_type, sizeof(uint8_t));
|
||||||
memcpy(&msg_l.buf[1], data, sizeof(T));
|
memcpy(&msg_l.buf[1], data, sizeof(T));
|
||||||
|
|
||||||
// Prepare CRC calculation buffer (ID + data)
|
// Prepare CRC calculation buffer (ID + data)
|
||||||
uint8_t crc_data[CAN_MSG_MAX_LEN];
|
uint8_t crc_data[CAN_MSG_MAX_LEN];
|
||||||
|
|
||||||
// Copy message ID
|
// Copy message ID
|
||||||
memcpy(crc_data, (uint8_t*)&msg_l.id, sizeof(T));
|
memcpy(crc_data, (uint8_t*)&msg_l.id, sizeof(T));
|
||||||
// Copy all data bytes
|
// Copy all data bytes
|
||||||
memcpy(crc_data + 1, msg_l.buf, 6);
|
memcpy(crc_data + 1, msg_l.buf, 6);
|
||||||
|
|
||||||
// Calculate CRC
|
// Calculate CRC
|
||||||
uint16_t crc_value = validate_crc16(crc_data, CAN_MSG_MAX_LEN);
|
uint16_t crc_value = validate_crc16(crc_data, CAN_MSG_MAX_LEN);
|
||||||
|
|
||||||
// Insert CRC into buffer
|
// Insert CRC into buffer
|
||||||
// memcpy(&msg_l.buf[6], &crc_value, sizeof(uint16_t));
|
// memcpy(&msg_l.buf[6], &crc_value, sizeof(uint16_t));
|
||||||
msg_l.buf[6] = crc_value & 0xFF;
|
msg_l.buf[6] = crc_value & 0xFF;
|
||||||
msg_l.buf[7] = (crc_value >> 8) & 0xFF;
|
msg_l.buf[7] = (crc_value >> 8) & 0xFF;
|
||||||
|
|
||||||
// Send message
|
// Send message
|
||||||
Can.write(msg_l);
|
Can.write(msg_l);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_velocity() {
|
void send_velocity() {
|
||||||
float current_velocity = motor.shaftVelocity();
|
float current_velocity = motor.shaftVelocity();
|
||||||
if (flash_rec == nullptr) { // Null check
|
if (flash_rec == nullptr) { // Null check
|
||||||
// Error handling: logging, alerts, etc.
|
// Error handling: logging, alerts, etc.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float value = flash_rec[vel].value;
|
// float value = flash_rec[vel].value;
|
||||||
uint8_t id = flash_rec[addr_id].value;
|
uint8_t id = flash_rec[addr_id].value;
|
||||||
send_can_with_id_crc(id,'V',&value);
|
send_can_with_id_crc(id,'V',¤t_velocity);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_angle() {
|
void send_angle() {
|
||||||
float current_angle = motor.shaftAngle();
|
float current_angle = motor.shaftAngle();
|
||||||
if (flash_rec == nullptr) { // Null check
|
if (flash_rec == nullptr) { // Null check
|
||||||
// Error handling: logging, alerts, etc.
|
// Error handling: logging, alerts, etc.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t id = flash_rec[addr_id].value;
|
uint8_t id = flash_rec[addr_id].value;
|
||||||
send_can_with_id_crc(id,'A',¤t_angle);
|
send_can_with_id_crc(id,'A',¤t_angle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void send_motor_enabled() {
|
void send_motor_enabled() {
|
||||||
/* Firmware data reading */
|
/* Firmware data reading */
|
||||||
if (flash_rec == nullptr) { // Null check
|
if (flash_rec == nullptr) { // Null check
|
||||||
// Error handling: logging, alerts, etc.
|
// Error handling: logging, alerts, etc.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
uint8_t value = motor_control_inputs.motor_enabled; //copy current motor state
|
uint8_t value = motor_control_inputs.motor_enabled; //copy current motor state
|
||||||
uint8_t id = flash_rec[addr_id].value;
|
uint8_t id = flash_rec[addr_id].value;
|
||||||
send_can_with_id_crc(id,'M',&value);
|
send_can_with_id_crc(id,'M',&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_id() {
|
|
||||||
/* Firmware data reading */
|
// void send_torque() {
|
||||||
if (flash_rec == nullptr) { // Null check
|
// float i_q = motor.current.q; // Q-axis current (A)
|
||||||
// Error handling: logging, alerts, etc.
|
// float torque = 100 * i_q; // Torque calculation
|
||||||
return;
|
// if (flash_rec == nullptr) return;
|
||||||
}
|
// uint8_t id = flash_rec[addr_id].value;
|
||||||
|
// send_can_with_id_crc(id, 'T', &torque);
|
||||||
uint8_t id = flash_rec[addr_id].value;
|
// }
|
||||||
send_can_with_id_crc(id,'I',&id);
|
|
||||||
}
|
void send_id() {
|
||||||
|
/* Firmware data reading */
|
||||||
// void send_motor_torque() {
|
if (flash_rec == nullptr) { // Null check
|
||||||
// float i_q = motor.current.q; // Q-axis current (A)
|
// Error handling: logging, alerts, etc.
|
||||||
// float torque = kt * i_q; // Torque calculation
|
return;
|
||||||
// torque *= 100;
|
}
|
||||||
// CAN_TX_msg.id = flash_rec->value;
|
|
||||||
// CAN_TX_msg.buf[0] = 'T';
|
uint8_t id = flash_rec[addr_id].value;
|
||||||
// CAN_TX_msg.len = 5;
|
send_can_with_id_crc(id,'I',&id);
|
||||||
// memcpy(&CAN_TX_msg.buf[1], &torque, sizeof(torque));
|
}
|
||||||
// Can.write(CAN_TX_msg);
|
|
||||||
// }
|
void send_error(uint8_t error_code){
|
||||||
|
uint8_t id = flash_rec[addr_id].value;
|
||||||
void send_pid_angle(uint8_t param_pid){
|
send_can_with_id_crc(id,'P',&error_code);
|
||||||
if (flash_rec == nullptr) { // Null check
|
}
|
||||||
return;
|
|
||||||
}
|
void send_pid_angle(uint8_t param_pid){
|
||||||
uint8_t id = flash_rec[addr_id].value;
|
if (flash_rec == nullptr) { // Null check
|
||||||
conv_float_to_int.i = flash_rec[param_pid].value;
|
return;
|
||||||
uint32_t data = conv_float_to_int.i;
|
}
|
||||||
switch(param_pid){
|
uint8_t id = flash_rec[addr_id].value;
|
||||||
case pid_p:
|
conv_float_to_int.i = flash_rec[param_pid].value;
|
||||||
param_pid = REG_MOTOR_POSPID_Kp;
|
uint32_t data = conv_float_to_int.i;
|
||||||
break;
|
switch(param_pid){
|
||||||
|
case pid_p:
|
||||||
case pid_i:
|
param_pid = REG_MOTOR_POSPID_Kp;
|
||||||
param_pid = REG_MOTOR_POSPID_Ki;
|
break;
|
||||||
break;
|
|
||||||
|
case pid_i:
|
||||||
case pid_d:
|
param_pid = REG_MOTOR_POSPID_Ki;
|
||||||
param_pid = REG_MOTOR_POSPID_Kd;
|
break;
|
||||||
break;
|
|
||||||
}
|
case pid_d:
|
||||||
|
param_pid = REG_MOTOR_POSPID_Kd;
|
||||||
send_can_with_id_crc(id,param_pid,&data);
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_id(uint8_t my_id) {
|
send_can_with_id_crc(id,param_pid,&data);
|
||||||
write_param(addr_id,my_id);
|
}
|
||||||
}
|
|
||||||
|
void setup_id(uint8_t my_id) {
|
||||||
void firmware_update(){
|
write_param(addr_id,my_id);
|
||||||
write_param(firmw,FIRMWARE_FLAG);
|
}
|
||||||
NVIC_SystemReset();
|
|
||||||
}
|
void firmware_update(){
|
||||||
|
write_param(firmw,FIRMWARE_FLAG);
|
||||||
void setup_angle(float target_angle) {
|
NVIC_SystemReset();
|
||||||
motor.enable(); // Enable motor if disabled
|
}
|
||||||
// motor.controller = MotionControlType::angle;
|
|
||||||
motor_control_inputs.target_angle = target_angle;
|
void setup_angle(float target_angle) {
|
||||||
// motor.move(target_angle);
|
motor.enable(); // Enable motor if disabled
|
||||||
}
|
// motor.controller = MotionControlType::angle;
|
||||||
|
motor_control_inputs.target_angle = target_angle;
|
||||||
// void setup_pid_angle(uint8_t param_pid, uint32_t data){
|
// motor.move(target_angle);
|
||||||
// conv_float_to_int.f = data;
|
}
|
||||||
// switch (param_pid) {
|
|
||||||
// case pid_p:
|
/**
|
||||||
// motor.P_angle.P = conv_float_to_int.f;
|
* @brief Set the up velocity object
|
||||||
// break;
|
*
|
||||||
// case pid_i:
|
* @param target_velocity
|
||||||
// motor.P_angle.I = conv_float_to_int.f;
|
*/
|
||||||
// break;
|
void setup_velocity(float target_velocity) {
|
||||||
// case pid_d:
|
motor.enable();
|
||||||
// motor.P_angle.D = conv_float_to_int.f;
|
motor_control_inputs.target_velocity = target_velocity;
|
||||||
// break;
|
}
|
||||||
// default:
|
|
||||||
// break;
|
void send_data_type(uint8_t type_d){
|
||||||
// }
|
uint8_t id = flash_rec[addr_id].value;
|
||||||
|
send_can_with_id_crc(id,'D',&type_d);
|
||||||
// write_param(param_pid,data);
|
}
|
||||||
// }
|
|
||||||
|
// Вспомогательные функции
|
||||||
|
void send_with_confirmation(void (*send_func)(void)) {
|
||||||
void listen_can(const CAN_message_t &msg) {
|
uint32_t t_start = HAL_GetTick();
|
||||||
msg_id = msg.id;
|
send_func();
|
||||||
msg_ch = msg_id & 0xF; // Extract message channel
|
|
||||||
uint16_t id_x = (msg_id >> 4) & 0x7FF; // Extract device address
|
// Ожидание подтверждения отправки
|
||||||
|
while (!(CAN2->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2))) {
|
||||||
/* CRC Calculation */
|
if (HAL_GetTick() - t_start > CAN_TIMEOUT) break;
|
||||||
uint16_t received_crc = (msg.buf[msg.len - 2]) | (msg.buf[msg.len - 1] << 8);
|
}
|
||||||
uint8_t data[10] = {0}; // Message buffer for CRC verification
|
}
|
||||||
|
|
||||||
// Copy message ID (2 bytes)
|
void process_can_messages() {
|
||||||
memcpy(data, (uint8_t*)&msg_id, sizeof(msg_id));
|
static uint32_t last_received = HAL_GetTick();
|
||||||
// Copy message data (excluding CRC bytes)
|
CAN_message_t msg;
|
||||||
memcpy(data + sizeof(msg_id), msg.buf, msg.len - 2);
|
uint8_t count = 0;
|
||||||
|
|
||||||
// Calculate CRC
|
// block send while data cant
|
||||||
uint16_t calculated_crc = validate_crc16(data, sizeof(msg_id) + msg.len - 2);
|
send_blocked = true;
|
||||||
|
|
||||||
// Verify CRC match
|
while(count < MAX_CAN_READS && Can.read(msg)) {
|
||||||
if (calculated_crc != received_crc) {
|
listen_can(msg);
|
||||||
return; // Ignore message on CRC mismatch
|
last_received = HAL_GetTick();
|
||||||
}
|
count++;
|
||||||
flash_rec = load_params();
|
}
|
||||||
/* Message Structure: 0x691
|
|
||||||
69 - Device address
|
// Проверка таймаута молчания
|
||||||
1 - Action code */
|
if(HAL_GetTick() - last_received > CAN_SILENCE_TIMEOUT) {
|
||||||
if(id_x == flash_rec[addr_id].value){
|
// Разблокируем отправку при отсутствии сообщений
|
||||||
if(msg_ch == REG_WRITE){
|
send_blocked = false;
|
||||||
switch(msg.buf[0]) {
|
}
|
||||||
case REG_ID:
|
}
|
||||||
setup_id(msg.buf[1]);
|
|
||||||
break;
|
/**
|
||||||
case REG_LED_BLINK:
|
* @brief Function for process data from CAN
|
||||||
for (int i = 0; i < 10; i++) {
|
* @details Function check your ID deviceю. Compare receive and calculated CRC.
|
||||||
GPIOC->ODR ^= GPIO_ODR_OD10;
|
* If ID && CRC == TRUE, then process message or dont send data.
|
||||||
delay(100);
|
* If if and crc = true:
|
||||||
}
|
* Check CAN_REG
|
||||||
break;
|
* Gives your data type
|
||||||
|
* Write with data or send data
|
||||||
case MOTOR_ANGLE:
|
* @param msg
|
||||||
memcpy(&motor_control_inputs.target_angle, &msg.buf[1],
|
*/
|
||||||
sizeof(motor_control_inputs.target_angle));
|
void listen_can(const CAN_message_t &msg) {
|
||||||
setup_angle(motor_control_inputs.target_angle);
|
msg_id = msg.id;
|
||||||
break;
|
msg_ch = msg_id & 0xF; // Extract message channel
|
||||||
|
uint16_t id_x = (msg_id >> 4) & 0x7FF; // Extract device address
|
||||||
case REG_MOTOR_POSPID_Kp:
|
/* CRC Calculation */
|
||||||
memcpy(&motor.P_angle.P, &msg.buf[1], sizeof(float));
|
uint16_t received_crc = (msg.buf[msg.len - 2]) | (msg.buf[msg.len - 1] << 8);
|
||||||
conv_float_to_int.f = motor.P_angle.P;
|
uint8_t data[10] = {0}; // Message buffer for CRC verification
|
||||||
write_param(pid_p,conv_float_to_int.i);
|
|
||||||
break;
|
// Copy message ID (2 bytes)
|
||||||
|
memcpy(data, (uint8_t*)&msg_id, sizeof(msg_id));
|
||||||
case REG_MOTOR_POSPID_Ki:
|
// Copy message data (excluding CRC bytes)
|
||||||
memcpy(&motor.P_angle.I, &msg.buf[1], sizeof(float));
|
memcpy(data + sizeof(msg_id), msg.buf, msg.len - 2);
|
||||||
conv_float_to_int.f = motor.P_angle.I;
|
|
||||||
write_param(pid_i,conv_float_to_int.i);
|
// Calculate CRC
|
||||||
break;
|
uint16_t calculated_crc = validate_crc16(data, sizeof(msg_id) + msg.len - 2);
|
||||||
|
|
||||||
case REG_MOTOR_POSPID_Kd:
|
// Verify CRC match
|
||||||
memcpy(&motor.P_angle.D, &msg.buf[1], sizeof(float));
|
if (calculated_crc != received_crc) {
|
||||||
conv_float_to_int.f = motor.P_angle.D;
|
return; // Ignore message on CRC mismatch
|
||||||
write_param(pid_d,conv_float_to_int.i);
|
}
|
||||||
break;
|
flash_rec = load_params();
|
||||||
|
|
||||||
case FIRMWARE_UPDATE:
|
/* Message Structure: 0x691
|
||||||
firmware_update();
|
69 - Device address
|
||||||
break;
|
1 - Action code */
|
||||||
|
if(id_x != flash_rec[addr_id].value){
|
||||||
case MOTOR_ENABLED:
|
return;
|
||||||
if (msg.buf[1] == 1) {
|
}
|
||||||
motor.enable();
|
if(msg_ch == REG_WRITE){
|
||||||
motor_control_inputs.motor_enabled = 1;
|
switch(msg.buf[0]) {
|
||||||
} else {
|
case REG_ID:
|
||||||
motor.disable();
|
setup_id(msg.buf[1]);
|
||||||
motor_control_inputs.motor_enabled = 0;
|
break;
|
||||||
}
|
case REG_LED_BLINK:
|
||||||
default:
|
for (int i = 0; i < 10; i++) {
|
||||||
break;
|
GPIOC->ODR ^= GPIO_ODR_OD10;
|
||||||
}
|
delay(100);
|
||||||
}
|
}
|
||||||
else if (msg_ch == REG_READ) {
|
break;
|
||||||
switch (msg.buf[0]) {
|
|
||||||
case REG_ID: send_id(); break;
|
case MOTOR_ANGLE:
|
||||||
case MOTOR_VELOCITY: send_velocity(); break;
|
memcpy(&motor_control_inputs.target_angle, &msg.buf[1],
|
||||||
case MOTOR_ANGLE: send_angle(); break;
|
sizeof(motor_control_inputs.target_angle));
|
||||||
case MOTOR_ENABLED: send_motor_enabled(); break;
|
setup_angle(motor_control_inputs.target_angle);
|
||||||
// case MOTOR_TORQUE: send_motor_torque(); break;
|
break;
|
||||||
// case FOC_STATE: send_foc_state(); break;
|
|
||||||
case REG_MOTOR_POSPID_Kp: send_pid_angle(pid_p); break;
|
case REG_MOTOR_POSPID_Kp:
|
||||||
case REG_MOTOR_POSPID_Ki: send_pid_angle(pid_i); break;
|
memcpy(&motor.P_angle.P, &msg.buf[1], sizeof(float));
|
||||||
case REG_MOTOR_POSPID_Kd: send_pid_angle(pid_d); break;
|
conv_float_to_int.f = motor.P_angle.P;
|
||||||
default: break;
|
write_param(pid_p,conv_float_to_int.i);
|
||||||
}
|
break;
|
||||||
}
|
|
||||||
}
|
case REG_MOTOR_POSPID_Ki:
|
||||||
}
|
memcpy(&motor.P_angle.I, &msg.buf[1], sizeof(float));
|
||||||
|
conv_float_to_int.f = motor.P_angle.I;
|
||||||
|
write_param(pid_i,conv_float_to_int.i);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case REG_MOTOR_POSPID_Kd:
|
||||||
|
memcpy(&motor.P_angle.D, &msg.buf[1], sizeof(float));
|
||||||
|
conv_float_to_int.f = motor.P_angle.D;
|
||||||
|
write_param(pid_d,conv_float_to_int.i);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DATA_TYPE_ANGLE:
|
||||||
|
data_type = DATA_TYPE_ANGLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DATA_TYPE_VELOCITY:
|
||||||
|
data_type = DATA_TYPE_VELOCITY;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DATA_TYPE_TORQUE:
|
||||||
|
data_type = DATA_TYPE_TORQUE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FIRMWARE_UPDATE:
|
||||||
|
firmware_update();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MOTOR_ENABLED:
|
||||||
|
if (msg.buf[1] == 1) {
|
||||||
|
motor.enable();
|
||||||
|
motor_control_inputs.motor_enabled = 1;
|
||||||
|
} else {
|
||||||
|
motor.disable();
|
||||||
|
motor_control_inputs.motor_enabled = 0;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (msg_ch == REG_READ) {
|
||||||
|
switch (msg.buf[0]) {
|
||||||
|
case REG_ID: send_id(); break;
|
||||||
|
case MOTOR_VELOCITY: send_velocity(); break;
|
||||||
|
case MOTOR_ANGLE: send_angle(); break;
|
||||||
|
case MOTOR_ENABLED: send_motor_enabled(); break;
|
||||||
|
case DATA_TYPE_ANGLE: send_data_type(uint8_t(DATA_TYPE_ANGLE)); break;
|
||||||
|
case DATA_TYPE_VELOCITY: send_data_type(uint8_t(DATA_TYPE_VELOCITY)); break;
|
||||||
|
case DATA_TYPE_TORQUE: send_data_type(uint8_t(DATA_TYPE_TORQUE)); break;
|
||||||
|
// case MOTOR_TORQUE: send_motor_torque(); break;
|
||||||
|
// case FOC_STATE: send_foc_state(); break;
|
||||||
|
case REG_MOTOR_POSPID_Kp: send_pid_angle(pid_p); break;
|
||||||
|
case REG_MOTOR_POSPID_Ki: send_pid_angle(pid_i); break;
|
||||||
|
case REG_MOTOR_POSPID_Kd: send_pid_angle(pid_d); break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If msg_ch != REG_WRITE or REG_READ, then SimpleFOC*/
|
||||||
|
else{
|
||||||
|
switch(data_type) {
|
||||||
|
/* Read after write*/
|
||||||
|
case DATA_TYPE_ANGLE:
|
||||||
|
send_angle();
|
||||||
|
delay(200);
|
||||||
|
memcpy(&motor_control_inputs.target_angle, &msg.buf[1], sizeof(float));
|
||||||
|
setup_angle(motor_control_inputs.target_angle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DATA_TYPE_VELOCITY:{
|
||||||
|
send_velocity();
|
||||||
|
float vel = 0.0f;
|
||||||
|
memcpy(&vel, &msg.buf[1], sizeof(float));
|
||||||
|
setup_velocity(vel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case DATA_TYPE_TORQUE:
|
||||||
|
// send_torque();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
send_error(error_foc);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HAL_Delay(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,86 +1,86 @@
|
||||||
# CAN Communication Scripts
|
# CAN Communication Scripts
|
||||||
|
|
||||||
This repository contains Python scripts for testing and interacting with a CAN bus system. These scripts enable sending and receiving CAN messages to control a motor, set angles, and adjust velocities.
|
This repository contains Python scripts for testing and interacting with a CAN bus system. These scripts enable sending and receiving CAN messages to control a motor, set angles, and adjust velocities.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
1. **Python 3.7+** installed on your system.
|
1. **Python 3.7+** installed on your system.
|
||||||
2. **`python-can` library** installed. Install it via pip:
|
2. **`python-can` library** installed. Install it via pip:
|
||||||
```bash
|
```bash
|
||||||
pip install python-can
|
pip install python-can
|
||||||
```
|
```
|
||||||
3. **SocketCAN interface** properly configured on your Linux system. The default channel is `can0`.
|
3. **SocketCAN interface** properly configured on your Linux system. The default channel is `can0`.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### 1. Receiving CAN Messages
|
### 1. Receiving CAN Messages
|
||||||
|
|
||||||
The script `python_can.py` listens to the CAN bus and processes incoming messages.
|
The script `python_can.py` listens to the CAN bus and processes incoming messages.
|
||||||
|
|
||||||
#### Run:
|
#### Run:
|
||||||
```bash
|
```bash
|
||||||
python3 python_can.py
|
python3 python_can.py
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Features:
|
#### Features:
|
||||||
- Processes messages with data length 5.
|
- Processes messages with data length 5.
|
||||||
- Parses the first byte (`flag`) to determine the type:
|
- Parses the first byte (`flag`) to determine the type:
|
||||||
- `'A'`: Angle (float).
|
- `'A'`: Angle (float).
|
||||||
- `'V'`: Velocity (float).
|
- `'V'`: Velocity (float).
|
||||||
- `'E'`: Enable/disable status (boolean).
|
- `'E'`: Enable/disable status (boolean).
|
||||||
|
|
||||||
### 2. Enabling or Disabling the Motor
|
### 2. Enabling or Disabling the Motor
|
||||||
|
|
||||||
The script `python_enable_motor.py` sends commands to enable or disable the motor.
|
The script `python_enable_motor.py` sends commands to enable or disable the motor.
|
||||||
|
|
||||||
#### Run:
|
#### Run:
|
||||||
```bash
|
```bash
|
||||||
python3 python_enable_motor.py <0|1>
|
python3 python_enable_motor.py <0|1>
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Arguments:
|
#### Arguments:
|
||||||
- `0`: Disable the motor.
|
- `0`: Disable the motor.
|
||||||
- `1`: Enable the motor.
|
- `1`: Enable the motor.
|
||||||
|
|
||||||
### 3. Sending Target Angle
|
### 3. Sending Target Angle
|
||||||
|
|
||||||
The script `python_send_angle.py` sends a target angle to the CAN bus.
|
The script `python_send_angle.py` sends a target angle to the CAN bus.
|
||||||
|
|
||||||
#### Run:
|
#### Run:
|
||||||
```bash
|
```bash
|
||||||
python3 python_send_angle.py
|
python3 python_send_angle.py
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Behavior:
|
#### Behavior:
|
||||||
- Sends a message with a predefined target angle every second.
|
- Sends a message with a predefined target angle every second.
|
||||||
- Adjust the target angle in the script (`target_angle` variable).
|
- Adjust the target angle in the script (`target_angle` variable).
|
||||||
|
|
||||||
### 4. Sending Target Velocity
|
### 4. Sending Target Velocity
|
||||||
|
|
||||||
The script `python_send_velocity.py` sends a target velocity to the CAN bus.
|
The script `python_send_velocity.py` sends a target velocity to the CAN bus.
|
||||||
|
|
||||||
#### Run:
|
#### Run:
|
||||||
```bash
|
```bash
|
||||||
python3 python_send_velocity.py
|
python3 python_send_velocity.py
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Behavior:
|
#### Behavior:
|
||||||
- Sends a message with a predefined target velocity every second.
|
- Sends a message with a predefined target velocity every second.
|
||||||
- Adjust the target velocity in the script (`target_speed` variable).
|
- Adjust the target velocity in the script (`target_speed` variable).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
### CAN Interface
|
### CAN Interface
|
||||||
The scripts use the following default CAN bus settings:
|
The scripts use the following default CAN bus settings:
|
||||||
- **Channel**: `can0`
|
- **Channel**: `can0`
|
||||||
- **Bitrate**: `1 Mbps`
|
- **Bitrate**: `1 Mbps`
|
||||||
|
|
||||||
If your configuration differs, update the `Bus()` initialization in the scripts.
|
If your configuration differs, update the `Bus()` initialization in the scripts.
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
1. **"Error initializing CAN bus"**:
|
1. **"Error initializing CAN bus"**:
|
||||||
- Ensure your CAN interface is correctly configured and active:
|
- Ensure your CAN interface is correctly configured and active:
|
||||||
```bash
|
```bash
|
||||||
sudo ip link set can0 up type can bitrate 1000000
|
sudo ip link set can0 up type can bitrate 1000000
|
||||||
```
|
```
|
||||||
|
|
|
@ -1,54 +1,54 @@
|
||||||
import can
|
import can
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# Function to send the motor enable/disable command
|
# Function to send the motor enable/disable command
|
||||||
def send_motor_enable(bus, enable):
|
def send_motor_enable(bus, enable):
|
||||||
"""
|
"""
|
||||||
Sends a command to enable or disable the motor.
|
Sends a command to enable or disable the motor.
|
||||||
|
|
||||||
:param bus: The CAN bus
|
:param bus: The CAN bus
|
||||||
:param enable: 1 to enable the motor, 0 to disable it
|
:param enable: 1 to enable the motor, 0 to disable it
|
||||||
"""
|
"""
|
||||||
msg = can.Message()
|
msg = can.Message()
|
||||||
msg.arbitration_id = 1 # Message ID
|
msg.arbitration_id = 1 # Message ID
|
||||||
msg.is_extended_id = False
|
msg.is_extended_id = False
|
||||||
msg.dlc = 2 # Message length (flag + 1 byte of data)
|
msg.dlc = 2 # Message length (flag + 1 byte of data)
|
||||||
msg.data = [ord('E'), enable] # 'E' for the command, followed by 0 or 1
|
msg.data = [ord('E'), enable] # 'E' for the command, followed by 0 or 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
state = "enabled" if enable else "disabled"
|
state = "enabled" if enable else "disabled"
|
||||||
print(f"Sent message to {state} motor")
|
print(f"Sent message to {state} motor")
|
||||||
print(f"Message data: {msg.data}")
|
print(f"Message data: {msg.data}")
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Message failed to send: {e}")
|
print(f"Message failed to send: {e}")
|
||||||
sys.exit(1) # Exit the program on failure
|
sys.exit(1) # Exit the program on failure
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# CAN interface setup
|
# CAN interface setup
|
||||||
bus = None # Define outside the try block for proper shutdown
|
bus = None # Define outside the try block for proper shutdown
|
||||||
try:
|
try:
|
||||||
bus = can.interface.Bus(channel='can0', bustype='socketcan', bitrate=1000000) # Ensure the bitrate matches the microcontroller settings
|
bus = can.interface.Bus(channel='can0', bustype='socketcan', bitrate=1000000) # Ensure the bitrate matches the microcontroller settings
|
||||||
print("CAN bus initialized.")
|
print("CAN bus initialized.")
|
||||||
|
|
||||||
# Ensure the state is passed via arguments
|
# Ensure the state is passed via arguments
|
||||||
if len(sys.argv) != 2 or sys.argv[1] not in ['0', '1']:
|
if len(sys.argv) != 2 or sys.argv[1] not in ['0', '1']:
|
||||||
print("Usage: python3 script_name.py <0|1>")
|
print("Usage: python3 script_name.py <0|1>")
|
||||||
print("0 - Disable motor, 1 - Enable motor")
|
print("0 - Disable motor, 1 - Enable motor")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
enable = int(sys.argv[1])
|
enable = int(sys.argv[1])
|
||||||
send_motor_enable(bus, enable)
|
send_motor_enable(bus, enable)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error initializing CAN bus: {e}")
|
print(f"Error initializing CAN bus: {e}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Ensure the bus is properly shut down
|
# Ensure the bus is properly shut down
|
||||||
if bus is not None:
|
if bus is not None:
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
print("CAN bus shut down.")
|
print("CAN bus shut down.")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,141 +1,141 @@
|
||||||
import can
|
import can
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
from intelhex import IntelHex
|
from intelhex import IntelHex
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_CHANNEL = 'socketcan'
|
CAN_CHANNEL = 'socketcan'
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
CAN_BITRATE = 1000000
|
CAN_BITRATE = 1000000
|
||||||
#ch =int(input("Введите id устройства:"))
|
#ch =int(input("Введите id устройства:"))
|
||||||
ch = int(sys.argv[2])
|
ch = int(sys.argv[2])
|
||||||
BOOT_CAN_ID = (ch * 16) + 1
|
BOOT_CAN_ID = (ch * 16) + 1
|
||||||
DATA_CAN_ID = (ch * 16) + 3
|
DATA_CAN_ID = (ch * 16) + 3
|
||||||
BOOT_CAN_END = (ch * 16) + 2
|
BOOT_CAN_END = (ch * 16) + 2
|
||||||
ACK_CAN_ID = 0x05
|
ACK_CAN_ID = 0x05
|
||||||
|
|
||||||
#конфиг для crc16 ibm
|
#конфиг для crc16 ibm
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def debug_print(msg):
|
def debug_print(msg):
|
||||||
print(f"[DEBUG] {msg}")
|
print(f"[DEBUG] {msg}")
|
||||||
|
|
||||||
def calculate_crc16(data: bytes) -> int:
|
def calculate_crc16(data: bytes) -> int:
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
def send_firmware(hex_file):
|
def send_firmware(hex_file):
|
||||||
try:
|
try:
|
||||||
debug_print("Инициализация CAN...")
|
debug_print("Инициализация CAN...")
|
||||||
bus = can.interface.Bus(
|
bus = can.interface.Bus(
|
||||||
channel=CAN_INTERFACE,
|
channel=CAN_INTERFACE,
|
||||||
bustype=CAN_CHANNEL,
|
bustype=CAN_CHANNEL,
|
||||||
bitrate=CAN_BITRATE
|
bitrate=CAN_BITRATE
|
||||||
)
|
)
|
||||||
|
|
||||||
debug_print("Чтение HEX-файла...")
|
debug_print("Чтение HEX-файла...")
|
||||||
ih = IntelHex(hex_file)
|
ih = IntelHex(hex_file)
|
||||||
binary_data = ih.tobinstr() # Исправлено на tobinstr()
|
binary_data = ih.tobinstr() # Исправлено на tobinstr()
|
||||||
fw_size = len(binary_data)
|
fw_size = len(binary_data)
|
||||||
debug_print(f"Размер прошивки: {fw_size} байт")
|
debug_print(f"Размер прошивки: {fw_size} байт")
|
||||||
|
|
||||||
# Расчет CRC
|
# Расчет CRC
|
||||||
debug_print("Расчёт CRC...")
|
debug_print("Расчёт CRC...")
|
||||||
# calculator = Calculator(Crc16.IBM)
|
# calculator = Calculator(Crc16.IBM)
|
||||||
fw_crc = calculate_crc16(binary_data)
|
fw_crc = calculate_crc16(binary_data)
|
||||||
debug_print(f"CRC: 0x{fw_crc:04X}")
|
debug_print(f"CRC: 0x{fw_crc:04X}")
|
||||||
|
|
||||||
# Отправка START
|
# Отправка START
|
||||||
start_data = bytearray([0x01])
|
start_data = bytearray([0x01])
|
||||||
start_data += fw_size.to_bytes(4, 'little')
|
start_data += fw_size.to_bytes(4, 'little')
|
||||||
start_data += fw_crc.to_bytes(2, 'little')
|
start_data += fw_crc.to_bytes(2, 'little')
|
||||||
|
|
||||||
debug_print(f"START: {list(start_data)}")
|
debug_print(f"START: {list(start_data)}")
|
||||||
start_msg = can.Message(
|
start_msg = can.Message(
|
||||||
arbitration_id=BOOT_CAN_ID,
|
arbitration_id=BOOT_CAN_ID,
|
||||||
data=bytes(start_data),
|
data=bytes(start_data),
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(start_msg)
|
bus.send(start_msg)
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
debug_print(f"Ошибка отправки START: {str(e)}")
|
debug_print(f"Ошибка отправки START: {str(e)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Ожидание ACK
|
# Ожидание ACK
|
||||||
debug_print("Ожидание ACK...")
|
debug_print("Ожидание ACK...")
|
||||||
ack = wait_for_ack(bus)
|
ack = wait_for_ack(bus)
|
||||||
if not ack:
|
if not ack:
|
||||||
debug_print("Таймаут ACK START")
|
debug_print("Таймаут ACK START")
|
||||||
return
|
return
|
||||||
debug_print(f"Получен ACK: {list(ack.data)}")
|
debug_print(f"Получен ACK: {list(ack.data)}")
|
||||||
|
|
||||||
# Отправка данных
|
# Отправка данных
|
||||||
packet_size = 8
|
packet_size = 8
|
||||||
for i in range(0, len(binary_data), packet_size):
|
for i in range(0, len(binary_data), packet_size):
|
||||||
chunk = binary_data[i:i+packet_size]
|
chunk = binary_data[i:i+packet_size]
|
||||||
# Дополнение до 8 байт
|
# Дополнение до 8 байт
|
||||||
if len(chunk) < 8:
|
if len(chunk) < 8:
|
||||||
chunk += b'\xFF' * (8 - len(chunk))
|
chunk += b'\xFF' * (8 - len(chunk))
|
||||||
|
|
||||||
debug_print(f"Пакет {i//8}: {list(chunk)}")
|
debug_print(f"Пакет {i//8}: {list(chunk)}")
|
||||||
data_msg = can.Message(
|
data_msg = can.Message(
|
||||||
arbitration_id=DATA_CAN_ID,
|
arbitration_id=DATA_CAN_ID,
|
||||||
data=chunk,
|
data=chunk,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(data_msg)
|
bus.send(data_msg)
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
debug_print(f"Ошибка отправки данных: {str(e)}")
|
debug_print(f"Ошибка отправки данных: {str(e)}")
|
||||||
return
|
return
|
||||||
|
|
||||||
ack = wait_for_ack(bus)
|
ack = wait_for_ack(bus)
|
||||||
if not ack:
|
if not ack:
|
||||||
debug_print("Таймаут ACK DATA")
|
debug_print("Таймаут ACK DATA")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Финал
|
# Финал
|
||||||
debug_print("Отправка FINISH...")
|
debug_print("Отправка FINISH...")
|
||||||
finish_msg = can.Message(
|
finish_msg = can.Message(
|
||||||
arbitration_id=BOOT_CAN_END,
|
arbitration_id=BOOT_CAN_END,
|
||||||
data=bytes([0xAA]),
|
data=bytes([0xAA]),
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(finish_msg)
|
bus.send(finish_msg)
|
||||||
|
|
||||||
ack = wait_for_ack(bus, timeout=1.0)
|
ack = wait_for_ack(bus, timeout=1.0)
|
||||||
if ack and ack.data[0] == 0xAA:
|
if ack and ack.data[0] == 0xAA:
|
||||||
debug_print("Прошивка подтверждена!")
|
debug_print("Прошивка подтверждена!")
|
||||||
else:
|
else:
|
||||||
debug_print("Ошибка верификации!")
|
debug_print("Ошибка верификации!")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
debug_print(f"Критическая ошибка: {str(e)}")
|
debug_print(f"Критическая ошибка: {str(e)}")
|
||||||
finally:
|
finally:
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
||||||
def wait_for_ack(bus, timeout=1.0):
|
def wait_for_ack(bus, timeout=1.0):
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1) # Неблокирующий режим
|
msg = bus.recv(timeout=0.1) # Неблокирующий режим
|
||||||
if msg and msg.arbitration_id == ACK_CAN_ID:
|
if msg and msg.arbitration_id == ACK_CAN_ID:
|
||||||
return msg
|
return msg
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print("Использование: sudo python3 can_flasher.py firmware.hex")
|
print("Использование: sudo python3 can_flasher.py firmware.hex")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
send_firmware(sys.argv[1])
|
send_firmware(sys.argv[1])
|
||||||
|
|
|
@ -1,70 +1,70 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства (по умолчанию)
|
OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства (по умолчанию)
|
||||||
REG_WRITE = 0x8 # Код команды чтения
|
REG_WRITE = 0x8 # Код команды чтения
|
||||||
REG_ID = 0x55 # Адрес регистра с Firmware Update
|
REG_ID = 0x55 # Адрес регистра с Firmware Update
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
# Инициализация CAN-интерфейса
|
# Инициализация CAN-интерфейса
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
# ======= 1. Запрос текущего ID устройства =======
|
# ======= 1. Запрос текущего ID устройства =======
|
||||||
|
|
||||||
# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ
|
# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ
|
||||||
can_id_read = (OLD_DEVICE_ID << 4) | REG_WRITE
|
can_id_read = (OLD_DEVICE_ID << 4) | REG_WRITE
|
||||||
|
|
||||||
# Данные для запроса: [регистр, резервный байт]
|
# Данные для запроса: [регистр, резервный байт]
|
||||||
data_read = [REG_ID, 0x00]
|
data_read = [REG_ID, 0x00]
|
||||||
|
|
||||||
# Формируем полные данные для расчета CRC:
|
# Формируем полные данные для расчета CRC:
|
||||||
# - CAN ID разбивается на 2 байта (little-endian)
|
# - CAN ID разбивается на 2 байта (little-endian)
|
||||||
# - Добавляем данные запроса
|
# - Добавляем данные запроса
|
||||||
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
||||||
|
|
||||||
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, 'little'))
|
crc_bytes = list(crc.to_bytes(2, 'little'))
|
||||||
|
|
||||||
# Собираем итоговый пакет: данные + CRC
|
# Собираем итоговый пакет: данные + CRC
|
||||||
packet_read = data_read + crc_bytes
|
packet_read = data_read + crc_bytes
|
||||||
|
|
||||||
print("Переход в boot режим", packet_read)
|
print("Переход в boot режим", packet_read)
|
||||||
send_can_message(bus, can_id_read, packet_read)
|
send_can_message(bus, can_id_read, packet_read)
|
||||||
|
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Использование: python3 firmware_test.py address")
|
print("Использование: python3 firmware_test.py address")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -1,103 +1,103 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import struct
|
import struct
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
OLD_DEVICE_ID = 0x00 # Текущий ID устройства (по умолчанию)
|
OLD_DEVICE_ID = 0x00 # Текущий ID устройства (по умолчанию)
|
||||||
REG_READ = 0x7 # Код команды чтения
|
REG_READ = 0x7 # Код команды чтения
|
||||||
REG_ID = 0x30 # Адрес регистра с REG_PMOTOR_POSPID_Kp устройства
|
REG_ID = 0x30 # Адрес регистра с REG_PMOTOR_POSPID_Kp устройства
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def receive_response(bus, timeout=1.0):
|
def receive_response(bus, timeout=1.0):
|
||||||
"""Ожидание ответа от устройства"""
|
"""Ожидание ответа от устройства"""
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1)
|
msg = bus.recv(timeout=0.1)
|
||||||
if msg:
|
if msg:
|
||||||
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
return msg
|
return msg
|
||||||
print("[Ошибка] Таймаут")
|
print("[Ошибка] Таймаут")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
# Инициализация CAN-интерфейса
|
# Инициализация CAN-интерфейса
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
# ======= 1. Запрос текущего ID устройства =======
|
# ======= 1. Запрос текущего ID устройства =======
|
||||||
|
|
||||||
# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ
|
# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ
|
||||||
can_id_read = (OLD_DEVICE_ID << 4) | REG_READ
|
can_id_read = (OLD_DEVICE_ID << 4) | REG_READ
|
||||||
|
|
||||||
# Данные для запроса: [регистр, резервный байт]
|
# Данные для запроса: [регистр, резервный байт]
|
||||||
data_read = [REG_ID, 0x00]
|
data_read = [REG_ID, 0x00]
|
||||||
|
|
||||||
# Формируем полные данные для расчета CRC:
|
# Формируем полные данные для расчета CRC:
|
||||||
# - CAN ID разбивается на 2 байта (little-endian)
|
# - CAN ID разбивается на 2 байта (little-endian)
|
||||||
# - Добавляем данные запроса
|
# - Добавляем данные запроса
|
||||||
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
||||||
|
|
||||||
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, 'little'))
|
crc_bytes = list(crc.to_bytes(2, 'little'))
|
||||||
|
|
||||||
# Собираем итоговый пакет: данные + CRC
|
# Собираем итоговый пакет: данные + CRC
|
||||||
packet_read = data_read + crc_bytes
|
packet_read = data_read + crc_bytes
|
||||||
|
|
||||||
print("Запрос на чтение ID:", packet_read)
|
print("Запрос на чтение ID:", packet_read)
|
||||||
send_can_message(bus, can_id_read, packet_read)
|
send_can_message(bus, can_id_read, packet_read)
|
||||||
|
|
||||||
# ======= 2. Получение и проверка ответа =======
|
# ======= 2. Получение и проверка ответа =======
|
||||||
response = receive_response(bus)
|
response = receive_response(bus)
|
||||||
if response:
|
if response:
|
||||||
data = response.data
|
data = response.data
|
||||||
|
|
||||||
if len(data) < 4:
|
if len(data) < 4:
|
||||||
print("Слишком короткий ответ")
|
print("Слишком короткий ответ")
|
||||||
|
|
||||||
# Проверяем минимальную длину ответа (данные + CRC)
|
# Проверяем минимальную длину ответа (данные + CRC)
|
||||||
else:
|
else:
|
||||||
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
||||||
#buff with id and data without CRC
|
#buff with id and data without CRC
|
||||||
full_data = list(id_bytes) + list(data[:-2])
|
full_data = list(id_bytes) + list(data[:-2])
|
||||||
print(f"Received full_data: {list(full_data)}")
|
print(f"Received full_data: {list(full_data)}")
|
||||||
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
||||||
#calc CRC
|
#calc CRC
|
||||||
calc_crc = validate_crc16(full_data)
|
calc_crc = validate_crc16(full_data)
|
||||||
|
|
||||||
print(f"Расчитанный CRC PYTHON : 0x{calc_crc:02X}")
|
print(f"Расчитанный CRC PYTHON : 0x{calc_crc:02X}")
|
||||||
if received_crc == calc_crc:
|
if received_crc == calc_crc:
|
||||||
# Если CRC совпадает, проверяем структуру ответа:
|
# Если CRC совпадает, проверяем структуру ответа:
|
||||||
kp_value = struct.unpack('<f', bytes(data[1:5]))[0]
|
kp_value = struct.unpack('<f', bytes(data[1:5]))[0]
|
||||||
print(f"Текущий Kp устройства: {kp_value:.3f}")
|
print(f"Текущий Kp устройства: {kp_value:.3f}")
|
||||||
else:
|
else:
|
||||||
print("Ошибка: CRC не совпадает")
|
print("Ошибка: CRC не совпадает")
|
||||||
else:
|
else:
|
||||||
print("Устройство не ответило")
|
print("Устройство не ответило")
|
||||||
|
|
||||||
# Завершаем работу с шиной
|
# Завершаем работу с шиной
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
|
@ -1,115 +1,115 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
OLD_DEVICE_ID = 0x00
|
OLD_DEVICE_ID = 0x00
|
||||||
NEW_DEVICE_ID = 0x69
|
NEW_DEVICE_ID = 0x69
|
||||||
REG_WRITE = 0x8
|
REG_WRITE = 0x8
|
||||||
REG_READ = 0x7
|
REG_READ = 0x7
|
||||||
REG_ID = 0x1
|
REG_ID = 0x1
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def receive_response(bus, timeout=2.0):
|
def receive_response(bus, timeout=2.0):
|
||||||
"""Ожидание ответа"""
|
"""Ожидание ответа"""
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1)
|
msg = bus.recv(timeout=0.1)
|
||||||
if msg:
|
if msg:
|
||||||
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
return msg
|
return msg
|
||||||
print("[Ошибка] Таймаут")
|
print("[Ошибка] Таймаут")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Функция расчета CRC16 (MODBUS)"""
|
"""Функция расчета CRC16 (MODBUS)"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
# Инициализация
|
# Инициализация
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
# ======= 1. Отправляем команду изменить ID =======
|
# ======= 1. Отправляем команду изменить ID =======
|
||||||
|
|
||||||
# Весь буфер: id + команда + параметры
|
# Весь буфер: id + команда + параметры
|
||||||
OLD_WITH_REG = (OLD_DEVICE_ID << 4) | REG_WRITE
|
OLD_WITH_REG = (OLD_DEVICE_ID << 4) | REG_WRITE
|
||||||
id_bytes = list(OLD_WITH_REG.to_bytes(2, byteorder='little'))
|
id_bytes = list(OLD_WITH_REG.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Важные части сообщения: address (id), команда, параметры
|
# Важные части сообщения: address (id), команда, параметры
|
||||||
data_write = [REG_ID, NEW_DEVICE_ID] # команда изменить ID
|
data_write = [REG_ID, NEW_DEVICE_ID] # команда изменить ID
|
||||||
|
|
||||||
# Полностью собираем массив для CRC (включая id и команду)
|
# Полностью собираем массив для CRC (включая id и команду)
|
||||||
full_data_for_crc = id_bytes + data_write
|
full_data_for_crc = id_bytes + data_write
|
||||||
|
|
||||||
# Расчет CRC по всему пакету
|
# Расчет CRC по всему пакету
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Итоговый пакет: команда + параметры + CRC
|
# Итоговый пакет: команда + параметры + CRC
|
||||||
packet_write = data_write + crc_bytes
|
packet_write = data_write + crc_bytes
|
||||||
|
|
||||||
print("Отправляем: команда изменить ID + CRC:", packet_write)
|
print("Отправляем: команда изменить ID + CRC:", packet_write)
|
||||||
# Отправляем с `OLD_DEVICE_ID` в качестве адреса
|
# Отправляем с `OLD_DEVICE_ID` в качестве адреса
|
||||||
send_can_message(bus, (OLD_DEVICE_ID << 4) | REG_WRITE, packet_write)
|
send_can_message(bus, (OLD_DEVICE_ID << 4) | REG_WRITE, packet_write)
|
||||||
|
|
||||||
time.sleep(0.5)
|
time.sleep(0.5)
|
||||||
|
|
||||||
# ======= 2. Запрашиваем текущий ID (используем новый адрес) =======
|
# ======= 2. Запрашиваем текущий ID (используем новый адрес) =======
|
||||||
|
|
||||||
# Теперь для запроса используем **уже новый id**
|
# Теперь для запроса используем **уже новый id**
|
||||||
NEW_WITH_REG = (NEW_DEVICE_ID << 4) | REG_READ
|
NEW_WITH_REG = (NEW_DEVICE_ID << 4) | REG_READ
|
||||||
current_id_bytes = list(NEW_WITH_REG.to_bytes(2, byteorder='little'))
|
current_id_bytes = list(NEW_WITH_REG.to_bytes(2, byteorder='little'))
|
||||||
data_read = [REG_ID, 0x00]
|
data_read = [REG_ID, 0x00]
|
||||||
|
|
||||||
full_data_for_crc = current_id_bytes + data_read
|
full_data_for_crc = current_id_bytes + data_read
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
packet_read = data_read + crc_bytes
|
packet_read = data_read + crc_bytes
|
||||||
|
|
||||||
print("Запрос на чтение ID + CRC (после смены):", packet_read)
|
print("Запрос на чтение ID + CRC (после смены):", packet_read)
|
||||||
send_can_message(bus, (NEW_DEVICE_ID << 4) | REG_READ, packet_read)
|
send_can_message(bus, (NEW_DEVICE_ID << 4) | REG_READ, packet_read)
|
||||||
|
|
||||||
# ======= 3. Получение и проверка ответа =======
|
# ======= 3. Получение и проверка ответа =======
|
||||||
|
|
||||||
response = receive_response(bus)
|
response = receive_response(bus)
|
||||||
if response:
|
if response:
|
||||||
data = response.data
|
data = response.data
|
||||||
if len(data) < 4:
|
if len(data) < 4:
|
||||||
print("Ответ слишком короткий")
|
print("Ответ слишком короткий")
|
||||||
else:
|
else:
|
||||||
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
||||||
print("Полученный CRC: ", received_crc)
|
print("Полученный CRC: ", received_crc)
|
||||||
# Расчет CRC по всему пакету без CRC
|
# Расчет CRC по всему пакету без CRC
|
||||||
calc_crc = validate_crc16(data[:-2])
|
calc_crc = validate_crc16(data[:-2])
|
||||||
if received_crc == calc_crc:
|
if received_crc == calc_crc:
|
||||||
if data[0] == ord('I') and data[1] == NEW_DEVICE_ID:
|
if data[0] == ord('I') and data[1] == NEW_DEVICE_ID:
|
||||||
print(f"\nУСПЕХ! ID устройства изменен на 0x{NEW_DEVICE_ID:02X}")
|
print(f"\nУСПЕХ! ID устройства изменен на 0x{NEW_DEVICE_ID:02X}")
|
||||||
else:
|
else:
|
||||||
print(f"Некорректный ответ: {list(data)}")
|
print(f"Некорректный ответ: {list(data)}")
|
||||||
else:
|
else:
|
||||||
print("CRC не совпадает, данные повреждены.")
|
print("CRC не совпадает, данные повреждены.")
|
||||||
else:
|
else:
|
||||||
print("Нет ответа от устройства.")
|
print("Нет ответа от устройства.")
|
||||||
|
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
|
@ -1,126 +1,126 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
DEVICE_ID = int(sys.argv[1]) # ID ADDR for servo
|
DEVICE_ID = int(sys.argv[1]) # ID ADDR for servo
|
||||||
REG_READ = 0x7 # Код команды чтения
|
REG_READ = 0x7 # Код команды чтения
|
||||||
REG_MOTOR_POSPID_Kp = 0x30
|
REG_MOTOR_POSPID_Kp = 0x30
|
||||||
REG_MOTOR_POSPID_Ki = 0x31
|
REG_MOTOR_POSPID_Ki = 0x31
|
||||||
REG_MOTOR_POSPID_Kd = 0x32
|
REG_MOTOR_POSPID_Kd = 0x32
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Расчет CRC16 (MODBUS)"""
|
"""Расчет CRC16 (MODBUS)"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
def send_read_request(bus, device_id, register):
|
def send_read_request(bus, device_id, register):
|
||||||
"""Отправка запроса на чтение регистра"""
|
"""Отправка запроса на чтение регистра"""
|
||||||
can_id = (device_id << 4) | REG_READ
|
can_id = (device_id << 4) | REG_READ
|
||||||
data_part = [register, 0x00]
|
data_part = [register, 0x00]
|
||||||
|
|
||||||
# Расчет CRC для CAN ID (2 байта) + данные
|
# Расчет CRC для CAN ID (2 байта) + данные
|
||||||
full_data_for_crc = list(can_id.to_bytes(2, 'little')) + data_part
|
full_data_for_crc = list(can_id.to_bytes(2, 'little')) + data_part
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, 'little'))
|
crc_bytes = list(crc.to_bytes(2, 'little'))
|
||||||
|
|
||||||
# Формирование итогового пакета
|
# Формирование итогового пакета
|
||||||
packet = data_part + crc_bytes
|
packet = data_part + crc_bytes
|
||||||
send_can_message(bus, can_id, packet)
|
send_can_message(bus, can_id, packet)
|
||||||
|
|
||||||
def receive_pid_response(bus, timeout=1.0):
|
def receive_pid_response(bus, timeout=1.0):
|
||||||
"""Получение и проверка ответа с PID-значением"""
|
"""Получение и проверка ответа с PID-значением"""
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1)
|
msg = bus.recv(timeout=0.1)
|
||||||
if msg and msg.arbitration_id == DEVICE_ID:
|
if msg and msg.arbitration_id == DEVICE_ID:
|
||||||
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
|
|
||||||
if len(msg.data) < 8:
|
if len(msg.data) < 8:
|
||||||
print("Ошибка: Слишком короткий ответ")
|
print("Ошибка: Слишком короткий ответ")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Извлечение данных и CRC
|
# Извлечение данных и CRC
|
||||||
data = msg.data
|
data = msg.data
|
||||||
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
||||||
|
|
||||||
# Подготовка данных для проверки CRC
|
# Подготовка данных для проверки CRC
|
||||||
id_bytes = msg.arbitration_id.to_bytes(1, 'little')
|
id_bytes = msg.arbitration_id.to_bytes(1, 'little')
|
||||||
full_data = list(id_bytes) + list(data[:-2])
|
full_data = list(id_bytes) + list(data[:-2])
|
||||||
|
|
||||||
# Проверка CRC
|
# Проверка CRC
|
||||||
calc_crc = validate_crc16(full_data)
|
calc_crc = validate_crc16(full_data)
|
||||||
if calc_crc != received_crc:
|
if calc_crc != received_crc:
|
||||||
print(f"Ошибка CRC: ожидалось 0x{calc_crc:04X}, получено 0x{received_crc:04X}")
|
print(f"Ошибка CRC: ожидалось 0x{calc_crc:04X}, получено 0x{received_crc:04X}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Извлечение float значения
|
# Извлечение float значения
|
||||||
try:
|
try:
|
||||||
value = struct.unpack('<f', bytes(data[1:5]))[0]
|
value = struct.unpack('<f', bytes(data[1:5]))[0]
|
||||||
return value
|
return value
|
||||||
except struct.error:
|
except struct.error:
|
||||||
print("Ошибка распаковки float")
|
print("Ошибка распаковки float")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
print("Таймаут ожидания ответа")
|
print("Таймаут ожидания ответа")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Основная логика чтения PID-коэффициентов"""
|
"""Основная логика чтения PID-коэффициентов"""
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Чтение коэффициентов с задержкой
|
# Чтение коэффициентов с задержкой
|
||||||
print("\nЧтение Kp...")
|
print("\nЧтение Kp...")
|
||||||
send_read_request(bus, DEVICE_ID, REG_MOTOR_POSPID_Kp)
|
send_read_request(bus, DEVICE_ID, REG_MOTOR_POSPID_Kp)
|
||||||
kp = receive_pid_response(bus)
|
kp = receive_pid_response(bus)
|
||||||
if kp is not None:
|
if kp is not None:
|
||||||
print(f"Текущий Kp: {kp:.3f}")
|
print(f"Текущий Kp: {kp:.3f}")
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
print("\nЧтение Ki...")
|
print("\nЧтение Ki...")
|
||||||
send_read_request(bus, DEVICE_ID, REG_MOTOR_POSPID_Ki)
|
send_read_request(bus, DEVICE_ID, REG_MOTOR_POSPID_Ki)
|
||||||
ki = receive_pid_response(bus)
|
ki = receive_pid_response(bus)
|
||||||
if ki is not None:
|
if ki is not None:
|
||||||
print(f"Текущий Ki: {ki:.3f}")
|
print(f"Текущий Ki: {ki:.3f}")
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
print("\nЧтение Kd...")
|
print("\nЧтение Kd...")
|
||||||
send_read_request(bus, DEVICE_ID, REG_MOTOR_POSPID_Kd)
|
send_read_request(bus, DEVICE_ID, REG_MOTOR_POSPID_Kd)
|
||||||
kd = receive_pid_response(bus)
|
kd = receive_pid_response(bus)
|
||||||
if kd is not None:
|
if kd is not None:
|
||||||
print(f"Текущий Kd: {kd:.3f}")
|
print(f"Текущий Kd: {kd:.3f}")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Используйте python3 read_pid.py addr")
|
print("Используйте python3 read_pid.py addr")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,98 +1,98 @@
|
||||||
import can
|
import can
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
# Константы
|
# Константы
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
DEVICE_ID = 0x27 # ID ADDR for servo
|
DEVICE_ID = 0x27 # ID ADDR for servo
|
||||||
REG_WRITE = 0x7
|
REG_WRITE = 0x7
|
||||||
REG_POS = 0x72 # MOTOR+ANGLE = 0x72
|
REG_POS = 0x72 # MOTOR+ANGLE = 0x72
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
# Calculate CRC16
|
# Calculate CRC16
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
|
|
||||||
def receive_response(bus, timeout=1.0):
|
def receive_response(bus, timeout=1.0):
|
||||||
"""Ожидание ответа от устройства"""
|
"""Ожидание ответа от устройства"""
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1)
|
msg = bus.recv(timeout=0.1)
|
||||||
if msg:
|
if msg:
|
||||||
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
return msg
|
return msg
|
||||||
print("[Ошибка] Таймаут")
|
print("[Ошибка] Таймаут")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def send_target_angle(bus):
|
def send_target_angle(bus):
|
||||||
# ID and cmd
|
# ID and cmd
|
||||||
arbitration_id = (DEVICE_ID << 4) | REG_WRITE
|
arbitration_id = (DEVICE_ID << 4) | REG_WRITE
|
||||||
id_bytes = list(arbitration_id.to_bytes(2, byteorder='little'))
|
id_bytes = list(arbitration_id.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# cmd + parametrs
|
# cmd + parametrs
|
||||||
data_write = [REG_POS]
|
data_write = [REG_POS]
|
||||||
|
|
||||||
|
|
||||||
full_data_for_crc = id_bytes + data_write
|
full_data_for_crc = id_bytes + data_write
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Full packet
|
# Full packet
|
||||||
packet = data_write + crc_bytes
|
packet = data_write + crc_bytes
|
||||||
|
|
||||||
|
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=arbitration_id,
|
arbitration_id=arbitration_id,
|
||||||
is_extended_id=False,
|
is_extended_id=False,
|
||||||
data=packet
|
data=packet
|
||||||
)
|
)
|
||||||
|
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
response = receive_response(bus)
|
response = receive_response(bus)
|
||||||
|
|
||||||
|
|
||||||
if response:
|
if response:
|
||||||
data = response.data
|
data = response.data
|
||||||
|
|
||||||
if len(data) < 4:
|
if len(data) < 4:
|
||||||
print("Слишком короткий ответ")
|
print("Слишком короткий ответ")
|
||||||
|
|
||||||
# Проверяем минимальную длину ответа (данные + CRC)
|
# Проверяем минимальную длину ответа (данные + CRC)
|
||||||
else:
|
else:
|
||||||
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
||||||
#buff with id and data without CRC
|
#buff with id and data without CRC
|
||||||
full_data = list(id_bytes) + list(data[:-2])
|
full_data = list(id_bytes) + list(data[:-2])
|
||||||
print(f"Received full_data: {list(full_data)}")
|
print(f"Received full_data: {list(full_data)}")
|
||||||
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
||||||
#calc CRC
|
#calc CRC
|
||||||
calc_crc = validate_crc16(full_data)
|
calc_crc = validate_crc16(full_data)
|
||||||
|
|
||||||
print(f"Расчитанный CRC PYTHON : 0x{calc_crc:02X}")
|
print(f"Расчитанный CRC PYTHON : 0x{calc_crc:02X}")
|
||||||
if received_crc == calc_crc:
|
if received_crc == calc_crc:
|
||||||
# Если CRC совпадает, проверяем структуру ответа:
|
# Если CRC совпадает, проверяем структуру ответа:
|
||||||
velocity = struct.unpack('<f', bytes(data[1:5]))[0]
|
velocity = struct.unpack('<f', bytes(data[1:5]))[0]
|
||||||
print(f"Угол: {velocity}")
|
print(f"Угол: {velocity}")
|
||||||
else:
|
else:
|
||||||
print("Ошибка: CRC не совпадает")
|
print("Ошибка: CRC не совпадает")
|
||||||
else:
|
else:
|
||||||
print("Устройство не ответило")
|
print("Устройство не ответило")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Инициализация CAN
|
# Инициализация CAN
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
print("CAN шина инициализирована.")
|
print("CAN шина инициализирована.")
|
||||||
|
|
||||||
send_target_angle(bus)
|
send_target_angle(bus)
|
||||||
|
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,108 +1,146 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
# Конфигурация
|
|
||||||
CAN_INTERFACE = 'can0'
|
# Конфигурация
|
||||||
OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства (по умолчанию)
|
CAN_INTERFACE = 'can0'
|
||||||
REG_READ = 0x7 # Код команды чтения
|
OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства
|
||||||
REG_ID = 0x01 # Адрес регистра с ID устройства
|
REG_READ = 0x7 # Код команды чтения
|
||||||
|
REG_ID = 0x01 # Адрес регистра с ID устройства
|
||||||
def send_can_message(bus, can_id, data):
|
|
||||||
"""Отправка CAN-сообщения"""
|
def flush_can_buffer(bus, duration=0.3):
|
||||||
try:
|
"""Очистка входного буфера CAN"""
|
||||||
msg = can.Message(
|
start_time = time.time()
|
||||||
arbitration_id=can_id,
|
flushed_count = 0
|
||||||
data=data,
|
while time.time() - start_time < duration:
|
||||||
is_extended_id=False
|
msg = bus.recv(timeout=0)
|
||||||
)
|
if msg:
|
||||||
bus.send(msg)
|
flushed_count += 1
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"Очищено сообщений из буфера: {flushed_count}")
|
||||||
return True
|
|
||||||
except can.CanError as e:
|
def send_can_message(bus, can_id, data):
|
||||||
print(f"Ошибка CAN: {e}")
|
"""Отправка CAN-сообщения"""
|
||||||
return False
|
try:
|
||||||
|
msg = can.Message(
|
||||||
def receive_response(bus, timeout=1.0):
|
arbitration_id=can_id,
|
||||||
"""Ожидание ответа от устройства"""
|
data=data,
|
||||||
start_time = time.time()
|
is_extended_id=False
|
||||||
while time.time() - start_time < timeout:
|
)
|
||||||
msg = bus.recv(timeout=0.1)
|
bus.send(msg)
|
||||||
if msg:
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
return True
|
||||||
return msg
|
except can.CanError as e:
|
||||||
print("[Ошибка] Таймаут")
|
print(f"Ошибка CAN: {e}")
|
||||||
return None
|
return False
|
||||||
|
|
||||||
def validate_crc16(data):
|
def receive_response(bus, timeout=1.0):
|
||||||
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
"""Ожидание ответа от устройства (сохраняем вашу оригинальную логику)"""
|
||||||
crc = 0xFFFF
|
start_time = time.time()
|
||||||
for byte in data:
|
while time.time() - start_time < timeout:
|
||||||
crc ^= byte
|
msg = bus.recv(timeout=0.1)
|
||||||
for _ in range(8):
|
if msg:
|
||||||
if crc & 0x0001:
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
crc = (crc >> 1) ^ 0xA001
|
return msg
|
||||||
else:
|
print("[Ошибка] Таймаут приема")
|
||||||
crc >>= 1
|
return None
|
||||||
return crc
|
|
||||||
|
def validate_crc16(data):
|
||||||
# Инициализация CAN-интерфейса
|
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
crc = 0xFFFF
|
||||||
|
for byte in data:
|
||||||
# ======= 1. Запрос текущего ID устройства =======
|
crc ^= byte
|
||||||
|
for _ in range(8):
|
||||||
# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ
|
if crc & 0x0001:
|
||||||
can_id_read = (OLD_DEVICE_ID << 4) | REG_READ
|
crc = (crc >> 1) ^ 0xA001
|
||||||
|
else:
|
||||||
# Данные для запроса: [регистр, резервный байт]
|
crc >>= 1
|
||||||
data_read = [REG_ID, 0x00]
|
return crc
|
||||||
|
|
||||||
# Формируем полные данные для расчета CRC:
|
def main():
|
||||||
# - CAN ID разбивается на 2 байта (little-endian)
|
# Инициализация CAN-интерфейса
|
||||||
# - Добавляем данные запроса
|
try:
|
||||||
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
bus = can.interface.Bus(
|
||||||
|
channel=CAN_INTERFACE,
|
||||||
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
bustype='socketcan',
|
||||||
crc = validate_crc16(full_data_for_crc)
|
bitrate=1000000 # Совпадает с устройством
|
||||||
crc_bytes = list(crc.to_bytes(2, 'little'))
|
)
|
||||||
|
except Exception as e:
|
||||||
# Собираем итоговый пакет: данные + CRC
|
print(f"Ошибка инициализации CAN: {e}")
|
||||||
packet_read = data_read + crc_bytes
|
sys.exit(1)
|
||||||
|
|
||||||
print("Запрос на чтение ID:", packet_read)
|
# ======= 1. Подготовка запроса =======
|
||||||
send_can_message(bus, can_id_read, packet_read)
|
can_id_read = (OLD_DEVICE_ID << 4) | REG_READ
|
||||||
|
data_read = [REG_ID, 0x00]
|
||||||
# ======= 2. Получение и проверка ответа =======
|
|
||||||
response = receive_response(bus)
|
# Формируем полные данные для расчета CRC:
|
||||||
if response:
|
full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read
|
||||||
data = response.data
|
|
||||||
|
# Рассчитываем CRC
|
||||||
if len(data) < 4:
|
crc = validate_crc16(full_data_for_crc)
|
||||||
print("Слишком короткий ответ")
|
crc_bytes = list(crc.to_bytes(2, 'little'))
|
||||||
|
|
||||||
# Проверяем минимальную длину ответа (данные + CRC)
|
# Собираем итоговый пакет
|
||||||
else:
|
packet_read = data_read + crc_bytes
|
||||||
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
|
||||||
#buff with id and data without CRC
|
# ======= 2. Отправка запроса с повторами =======
|
||||||
full_data = list(id_bytes) + list(data[:-2])
|
max_retries = 3
|
||||||
print(f"Received full_data: {list(full_data)}")
|
response = None
|
||||||
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
|
||||||
#calc CRC
|
for attempt in range(max_retries):
|
||||||
calc_crc = validate_crc16(full_data)
|
print(f"\nПопытка {attempt+1}/{max_retries}")
|
||||||
|
|
||||||
print(f"Расчитанный CRC PYTHON : 0x{calc_crc:02X}")
|
# Очистка буфера перед отправкой
|
||||||
if received_crc == calc_crc:
|
flush_can_buffer(bus, 0.3)
|
||||||
# Если CRC совпадает, проверяем структуру ответа:
|
|
||||||
print(f"Текущий ID устройства: 0x{data[1]:02X}")
|
# Отправка запроса
|
||||||
else:
|
print(f"Отправка запроса на чтение ID: {packet_read}")
|
||||||
print("Ошибка: CRC не совпадает")
|
if not send_can_message(bus, can_id_read, packet_read):
|
||||||
else:
|
print("Ошибка отправки, повтор...")
|
||||||
print("Устройство не ответило")
|
time.sleep(0.2)
|
||||||
|
continue
|
||||||
# Завершаем работу с шиной
|
|
||||||
bus.shutdown()
|
# Ожидание ответа
|
||||||
|
response = receive_response(bus, timeout=0.5)
|
||||||
if __name__ == "__main__":
|
if response:
|
||||||
import sys
|
break
|
||||||
if len(sys.argv) != 2:
|
|
||||||
print("Использование: python3 can_flasher.py address")
|
print("Ответ не получен, повтор...")
|
||||||
sys.exit(1)
|
time.sleep(0.2)
|
||||||
|
|
||||||
|
# ======= 3. Обработка ответа =======
|
||||||
|
if not response:
|
||||||
|
print("Устройство не ответило после всех попыток")
|
||||||
|
bus.shutdown()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
data = response.data
|
||||||
|
if len(data) < 4:
|
||||||
|
print("Слишком короткий ответ")
|
||||||
|
bus.shutdown()
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Проверяем минимальную длину ответа (данные + CRC)
|
||||||
|
id_bytes = response.arbitration_id.to_bytes(1, byteorder='little')
|
||||||
|
full_data = list(id_bytes) + list(data[:-2])
|
||||||
|
print(f"Полные данные для CRC: {full_data}")
|
||||||
|
|
||||||
|
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
||||||
|
calc_crc = validate_crc16(full_data)
|
||||||
|
|
||||||
|
print(f"Расчитанный CRC: 0x{calc_crc:04X}, Полученный CRC: 0x{received_crc:04X}")
|
||||||
|
|
||||||
|
if received_crc == calc_crc:
|
||||||
|
print(f"Текущий ID устройства: 0x{data[1]:02X}")
|
||||||
|
else:
|
||||||
|
print("Ошибка: CRC не совпадает")
|
||||||
|
|
||||||
|
# Завершаем работу с шиной
|
||||||
|
bus.shutdown()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) != 2:
|
||||||
|
print("Использование: python3 can_flasher.py <адрес_устройства>")
|
||||||
|
print("Пример: python3 can_flasher.py 1")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
main()
|
|
@ -1,67 +1,67 @@
|
||||||
from can.interface import Bus
|
from can.interface import Bus
|
||||||
import can
|
import can
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
import argparse
|
import argparse
|
||||||
|
|
||||||
# Константы
|
# Константы
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
DEVICE_ID = 0x27 # ID ADDR for servo
|
DEVICE_ID = 0x27 # ID ADDR for servo
|
||||||
REG_WRITE = 0x8
|
REG_WRITE = 0x8
|
||||||
REG_POS = 0x72 # MOTOR+ANGLE = 0x72
|
REG_POS = 0x72 # MOTOR+ANGLE = 0x72
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
# Calculate CRC16
|
# Calculate CRC16
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
def send_target_angle(bus, target_angle):
|
def send_target_angle(bus, target_angle):
|
||||||
# ID and cmd
|
# ID and cmd
|
||||||
arbitration_id = (DEVICE_ID << 4) | REG_WRITE
|
arbitration_id = (DEVICE_ID << 4) | REG_WRITE
|
||||||
id_bytes = list(arbitration_id.to_bytes(2, byteorder='little'))
|
id_bytes = list(arbitration_id.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# cmd + parametrs
|
# cmd + parametrs
|
||||||
data_write = [REG_POS] + list(struct.pack('<f', target_angle))
|
data_write = [REG_POS] + list(struct.pack('<f', target_angle))
|
||||||
|
|
||||||
|
|
||||||
full_data_for_crc = id_bytes + data_write
|
full_data_for_crc = id_bytes + data_write
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Full packet
|
# Full packet
|
||||||
packet = data_write + crc_bytes
|
packet = data_write + crc_bytes
|
||||||
|
|
||||||
|
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=arbitration_id,
|
arbitration_id=arbitration_id,
|
||||||
is_extended_id=False,
|
is_extended_id=False,
|
||||||
data=packet
|
data=packet
|
||||||
)
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{arbitration_id:03X}, Угол: {target_angle} rad, Данные: {list(msg.data)}")
|
print(f"[Отправка] CAN ID: 0x{arbitration_id:03X}, Угол: {target_angle} rad, Данные: {list(msg.data)}")
|
||||||
except can.CanError:
|
except can.CanError:
|
||||||
print("Ошибка отправки сообщения")
|
print("Ошибка отправки сообщения")
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(description="Отправка угла позиции по CAN.")
|
parser = argparse.ArgumentParser(description="Отправка угла позиции по CAN.")
|
||||||
parser.add_argument("--angle", type=float, required=True, help="Угол (в градусах)")
|
parser.add_argument("--angle", type=float, required=True, help="Угол (в градусах)")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Инициализация CAN
|
# Инициализация CAN
|
||||||
bus = Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
print("CAN шина инициализирована.")
|
print("CAN шина инициализирована.")
|
||||||
|
|
||||||
send_target_angle(bus, args.angle)
|
send_target_angle(bus, args.angle)
|
||||||
|
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,76 +1,76 @@
|
||||||
import can
|
import can
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
# Function to send the target speed
|
# Function to send the target speed
|
||||||
def send_target_speed(bus, target_speed):
|
def send_target_speed(bus, target_speed):
|
||||||
msg = can.Message()
|
msg = can.Message()
|
||||||
msg.arbitration_id = 1 # Message ID
|
msg.arbitration_id = 1 # Message ID
|
||||||
msg.is_extended_id = False
|
msg.is_extended_id = False
|
||||||
msg.dlc = 5 # Message length
|
msg.dlc = 5 # Message length
|
||||||
msg.data = bytearray([ord('V')] + list(struct.pack('<f', target_speed))) # 'V' for the command identifier, followed by the speed in float format
|
msg.data = bytearray([ord('V')] + list(struct.pack('<f', target_speed))) # 'V' for the command identifier, followed by the speed in float format
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"Sent message with target speed: {target_speed} rad/s")
|
print(f"Sent message with target speed: {target_speed} rad/s")
|
||||||
except can.CanError:
|
except can.CanError:
|
||||||
print("Message failed to send")
|
print("Message failed to send")
|
||||||
|
|
||||||
# Function to send the motor enable/disable command
|
# Function to send the motor enable/disable command
|
||||||
def send_motor_enable(bus, enable):
|
def send_motor_enable(bus, enable):
|
||||||
"""
|
"""
|
||||||
Sends a command to enable or disable the motor.
|
Sends a command to enable or disable the motor.
|
||||||
|
|
||||||
:param bus: The CAN bus
|
:param bus: The CAN bus
|
||||||
:param enable: 1 to enable the motor, 0 to disable it
|
:param enable: 1 to enable the motor, 0 to disable it
|
||||||
"""
|
"""
|
||||||
msg = can.Message()
|
msg = can.Message()
|
||||||
msg.arbitration_id = 1 # Message ID
|
msg.arbitration_id = 1 # Message ID
|
||||||
msg.is_extended_id = False
|
msg.is_extended_id = False
|
||||||
msg.dlc = 2 # Message length (flag + 1 byte of data)
|
msg.dlc = 2 # Message length (flag + 1 byte of data)
|
||||||
msg.data = bytearray([ord('E'), enable]) # 'E' for the command, followed by 0 or 1
|
msg.data = bytearray([ord('E'), enable]) # 'E' for the command, followed by 0 or 1
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
state = "enabled" if enable else "disabled"
|
state = "enabled" if enable else "disabled"
|
||||||
print(f"Sent message to {state} motor")
|
print(f"Sent message to {state} motor")
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Message failed to send: {e}")
|
print(f"Message failed to send: {e}")
|
||||||
sys.exit(1) # Exit the program on failure
|
sys.exit(1) # Exit the program on failure
|
||||||
|
|
||||||
send_target_speed(bus,0.0)
|
send_target_speed(bus,0.0)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# CAN interface setup
|
# CAN interface setup
|
||||||
bus = None # Define outside the try block for proper shutdown
|
bus = None # Define outside the try block for proper shutdown
|
||||||
try:
|
try:
|
||||||
bus = can.interface.Bus(channel='COM4', bustype='slcan', bitrate=1000000) # Ensure the bitrate matches the microcontroller settings
|
bus = can.interface.Bus(channel='COM4', bustype='slcan', bitrate=1000000) # Ensure the bitrate matches the microcontroller settings
|
||||||
print("CAN bus initialized.")
|
print("CAN bus initialized.")
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
user_input = input("Enter target speed: ")
|
user_input = input("Enter target speed: ")
|
||||||
if user_input.lower() == 'exit':
|
if user_input.lower() == 'exit':
|
||||||
print("Exiting...")
|
print("Exiting...")
|
||||||
break
|
break
|
||||||
try:
|
try:
|
||||||
target_speed = float(user_input)
|
target_speed = float(user_input)
|
||||||
send_target_speed(bus, target_speed)
|
send_target_speed(bus, target_speed)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Invalid input. Please enter a valid number.")
|
print("Invalid input. Please enter a valid number.")
|
||||||
|
|
||||||
# Disable motor before exiting
|
# Disable motor before exiting
|
||||||
send_motor_enable(bus, 0)
|
send_motor_enable(bus, 0)
|
||||||
print("Motor disabled.")
|
print("Motor disabled.")
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error initializing1 CAN bus: {e}")
|
print(f"Error initializing1 CAN bus: {e}")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
if bus is not None:
|
if bus is not None:
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
print("CAN bus shut down.")
|
print("CAN bus shut down.")
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
import can
|
import can
|
||||||
import struct
|
import struct
|
||||||
import time
|
import time
|
||||||
|
|
||||||
# Function to send the target speed
|
# Function to send the target speed
|
||||||
def send_target_speed(bus, target_speed):
|
def send_target_speed(bus, target_speed):
|
||||||
msg = can.Message()
|
msg = can.Message()
|
||||||
msg.arbitration_id = 1 # Message ID
|
msg.arbitration_id = 1 # Message ID
|
||||||
msg.is_extended_id = False
|
msg.is_extended_id = False
|
||||||
msg.dlc = 5 # Message length
|
msg.dlc = 5 # Message length
|
||||||
msg.data = [ord('V')] + list(struct.pack('<f', target_speed)) # 'V' for the command identifier, followed by the speed in float format
|
msg.data = [ord('V')] + list(struct.pack('<f', target_speed)) # 'V' for the command identifier, followed by the speed in float format
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"Sent message with target speed: {target_speed} m/s")
|
print(f"Sent message with target speed: {target_speed} m/s")
|
||||||
print(f"Message data: {msg.data}")
|
print(f"Message data: {msg.data}")
|
||||||
except can.CanError:
|
except can.CanError:
|
||||||
print("Message failed to send")
|
print("Message failed to send")
|
||||||
|
|
||||||
# Main function
|
# Main function
|
||||||
def main():
|
def main():
|
||||||
# CAN interface setup
|
# CAN interface setup
|
||||||
bus = can.interface.Bus(channel='can0', bustype='socketcan', bitrate=1000000) # Ensure the bitrate matches the microcontroller settings
|
bus = can.interface.Bus(channel='can0', bustype='socketcan', bitrate=1000000) # Ensure the bitrate matches the microcontroller settings
|
||||||
print("CAN bus initialized, sending target speed impulses...")
|
print("CAN bus initialized, sending target speed impulses...")
|
||||||
|
|
||||||
# Send impulses of target speed from -2 to 2 m/s
|
# Send impulses of target speed from -2 to 2 m/s
|
||||||
target_speeds = [-1, 1]
|
target_speeds = [-1, 1]
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
for speed in target_speeds:
|
for speed in target_speeds:
|
||||||
send_target_speed(bus, speed)
|
send_target_speed(bus, speed)
|
||||||
time.sleep(1) # 1-second delay between messages
|
time.sleep(1) # 1-second delay between messages
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,124 +1,124 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
OLD_DEVICE_ID = int(sys.argv[1])
|
OLD_DEVICE_ID = int(sys.argv[1])
|
||||||
NEW_DEVICE_ID = int(sys.argv[2])
|
NEW_DEVICE_ID = int(sys.argv[2])
|
||||||
REG_WRITE = 0x8
|
REG_WRITE = 0x8
|
||||||
REG_READ = 0x7
|
REG_READ = 0x7
|
||||||
REG_ID = 0x1
|
REG_ID = 0x1
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def receive_response(bus, timeout=1.0):
|
def receive_response(bus, timeout=1.0):
|
||||||
"""Ожидание ответа"""
|
"""Ожидание ответа"""
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1)
|
msg = bus.recv(timeout=0.1)
|
||||||
if msg:
|
if msg:
|
||||||
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
return msg
|
return msg
|
||||||
print("[Ошибка] Таймаут")
|
print("[Ошибка] Таймаут")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Функция расчета CRC16 (MODBUS)"""
|
"""Функция расчета CRC16 (MODBUS)"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
# Инициализация
|
# Инициализация
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
# ======= 1. Отправляем команду изменить ID =======
|
# ======= 1. Отправляем команду изменить ID =======
|
||||||
|
|
||||||
# Весь буфер: id + команда + параметры
|
# Весь буфер: id + команда + параметры
|
||||||
OLD_WITH_REG = (OLD_DEVICE_ID << 4) | REG_WRITE
|
OLD_WITH_REG = (OLD_DEVICE_ID << 4) | REG_WRITE
|
||||||
id_bytes = list(OLD_WITH_REG.to_bytes(2, byteorder='little'))
|
id_bytes = list(OLD_WITH_REG.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Важные части сообщения: address (id), команда, параметры
|
# Важные части сообщения: address (id), команда, параметры
|
||||||
data_write = [REG_ID, NEW_DEVICE_ID] # команда изменить ID
|
data_write = [REG_ID, NEW_DEVICE_ID] # команда изменить ID
|
||||||
|
|
||||||
# Полностью собираем массив для CRC (включая id и команду)
|
# Полностью собираем массив для CRC (включая id и команду)
|
||||||
full_data_for_crc = id_bytes + data_write
|
full_data_for_crc = id_bytes + data_write
|
||||||
|
|
||||||
# Расчет CRC по всему пакету
|
# Расчет CRC по всему пакету
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Итоговый пакет: команда + параметры + CRC
|
# Итоговый пакет: команда + параметры + CRC
|
||||||
packet_write = data_write + crc_bytes
|
packet_write = data_write + crc_bytes
|
||||||
|
|
||||||
print("Отправляем: команда изменить ID + CRC:", packet_write)
|
print("Отправляем: команда изменить ID + CRC:", packet_write)
|
||||||
# Отправляем с `OLD_DEVICE_ID` в качестве адреса
|
# Отправляем с `OLD_DEVICE_ID` в качестве адреса
|
||||||
send_can_message(bus, (OLD_DEVICE_ID << 4) | REG_WRITE, packet_write)
|
send_can_message(bus, (OLD_DEVICE_ID << 4) | REG_WRITE, packet_write)
|
||||||
|
|
||||||
time.sleep(1.0)
|
time.sleep(1.0)
|
||||||
|
|
||||||
# ======= 2. Запрашиваем текущий ID (используем новый адрес) =======
|
# ======= 2. Запрашиваем текущий ID (используем новый адрес) =======
|
||||||
|
|
||||||
# Теперь для запроса используем **уже новый id**
|
# Теперь для запроса используем **уже новый id**
|
||||||
NEW_WITH_REG = (NEW_DEVICE_ID << 4) | REG_READ
|
NEW_WITH_REG = (NEW_DEVICE_ID << 4) | REG_READ
|
||||||
current_id_bytes = list(NEW_WITH_REG.to_bytes(2, byteorder='little'))
|
current_id_bytes = list(NEW_WITH_REG.to_bytes(2, byteorder='little'))
|
||||||
data_read = [REG_ID, 0x00]
|
data_read = [REG_ID, 0x00]
|
||||||
|
|
||||||
full_data_for_crc = current_id_bytes + data_read
|
full_data_for_crc = current_id_bytes + data_read
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
packet_read = data_read + crc_bytes
|
packet_read = data_read + crc_bytes
|
||||||
|
|
||||||
print("Запрос на чтение ID + CRC (после смены):", packet_read)
|
print("Запрос на чтение ID + CRC (после смены):", packet_read)
|
||||||
send_can_message(bus, (NEW_DEVICE_ID << 4) | REG_READ, packet_read)
|
send_can_message(bus, (NEW_DEVICE_ID << 4) | REG_READ, packet_read)
|
||||||
|
|
||||||
# ======= 3. Получение и проверка ответа =======
|
# ======= 3. Получение и проверка ответа =======
|
||||||
|
|
||||||
response = receive_response(bus)
|
response = receive_response(bus)
|
||||||
if response:
|
if response:
|
||||||
data = response.data
|
data = response.data
|
||||||
if len(data) < 4:
|
if len(data) < 4:
|
||||||
print("Ответ слишком короткий")
|
print("Ответ слишком короткий")
|
||||||
else:
|
else:
|
||||||
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
||||||
#buff with id and data without CRC
|
#buff with id and data without CRC
|
||||||
full_data = list(id_bytes) + list(data[:-2])
|
full_data = list(id_bytes) + list(data[:-2])
|
||||||
print(f"Received full_data: {list(full_data)}")
|
print(f"Received full_data: {list(full_data)}")
|
||||||
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
||||||
#calc CRC
|
#calc CRC
|
||||||
calc_crc = validate_crc16(full_data)
|
calc_crc = validate_crc16(full_data)
|
||||||
if received_crc == calc_crc:
|
if received_crc == calc_crc:
|
||||||
if data[0] == ord('I') and data[1] == NEW_DEVICE_ID:
|
if data[0] == ord('I') and data[1] == NEW_DEVICE_ID:
|
||||||
print(f"\nУСПЕХ! ID устройства изменен на 0x{NEW_DEVICE_ID:02X}")
|
print(f"\nУСПЕХ! ID устройства изменен на 0x{NEW_DEVICE_ID:02X}")
|
||||||
else:
|
else:
|
||||||
print(f"Некорректный ответ: {list(data)}")
|
print(f"Некорректный ответ: {list(data)}")
|
||||||
else:
|
else:
|
||||||
print("CRC не совпадает, данные повреждены.")
|
print("CRC не совпадает, данные повреждены.")
|
||||||
else:
|
else:
|
||||||
print("Нет ответа от устройства.")
|
print("Нет ответа от устройства.")
|
||||||
|
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print("Использование: python3 can_flasher.py old_addr new addr")
|
print("Использование: python3 can_flasher.py old_addr new addr")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -1,78 +1,78 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
def flash_hex_with_stlink(hex_file_path):
|
def flash_hex_with_stlink(hex_file_path):
|
||||||
if not os.path.isfile(hex_file_path):
|
if not os.path.isfile(hex_file_path):
|
||||||
print(f"❌ Файл не найден: {hex_file_path}")
|
print(f"❌ Файл не найден: {hex_file_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
command = [
|
command = [
|
||||||
"st-flash",
|
"st-flash",
|
||||||
"--format", "ihex",
|
"--format", "ihex",
|
||||||
"write",
|
"write",
|
||||||
hex_file_path
|
hex_file_path
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(f"⚡️ Прошиваем {hex_file_path} через ST-Link...")
|
print(f"⚡️ Прошиваем {hex_file_path} через ST-Link...")
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
command,
|
command,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=30
|
timeout=30
|
||||||
)
|
)
|
||||||
|
|
||||||
print("▬▬▬ STDOUT ▬▬▬")
|
print("▬▬▬ STDOUT ▬▬▬")
|
||||||
print(result.stdout)
|
print(result.stdout)
|
||||||
|
|
||||||
print("▬▬▬ STDERR ▬▬▬")
|
print("▬▬▬ STDERR ▬▬▬")
|
||||||
print(result.stderr)
|
print(result.stderr)
|
||||||
|
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print("✅ Прошивка успешно завершена!")
|
print("✅ Прошивка успешно завершена!")
|
||||||
|
|
||||||
# Добавленный блок сброса
|
# Добавленный блок сброса
|
||||||
try:
|
try:
|
||||||
print("🔄 Выполняем сброс устройства...")
|
print("🔄 Выполняем сброс устройства...")
|
||||||
reset_result = subprocess.run(
|
reset_result = subprocess.run(
|
||||||
["st-info", "--reset"],
|
["st-info", "--reset"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
if reset_result.returncode == 0:
|
if reset_result.returncode == 0:
|
||||||
print("♻️ Устройство успешно сброшено!")
|
print("♻️ Устройство успешно сброшено!")
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ Ошибка (код: {reset_result.returncode})")
|
print(f"⚠️ Ошибка (код: {reset_result.returncode})")
|
||||||
print("▬▬▬ STDERR сброса ▬▬▬")
|
print("▬▬▬ STDERR сброса ▬▬▬")
|
||||||
print(reset_result.stderr)
|
print(reset_result.stderr)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"❌ Ошибка прошивки (код: {result.returncode})")
|
print(f"❌ Ошибка прошивки (код: {result.returncode})")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("❌ st-flash не найден! Установите stlink-tools.")
|
print("❌ st-flash не найден! Установите stlink-tools.")
|
||||||
return False
|
return False
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
print("❌ Таймаут операции! Проверьте подключение ST-Link.")
|
print("❌ Таймаут операции! Проверьте подключение ST-Link.")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Неизвестная ошибка: {str(e)}")
|
print(f"❌ Неизвестная ошибка: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Использование: python stlink_flash.py <firmware.hex>")
|
print("Использование: python stlink_flash.py <firmware.hex>")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
if flash_hex_with_stlink(sys.argv[1]):
|
if flash_hex_with_stlink(sys.argv[1]):
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
else:
|
else:
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
|
@ -1,100 +1,100 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
def flash_hex_with_stlink(hex_file_path, component_name):
|
def flash_hex_with_stlink(hex_file_path, component_name):
|
||||||
if not os.path.isfile(hex_file_path):
|
if not os.path.isfile(hex_file_path):
|
||||||
print(f"❌ Файл {component_name} не найден: {hex_file_path}")
|
print(f"❌ Файл {component_name} не найден: {hex_file_path}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
command = [
|
command = [
|
||||||
"st-flash",
|
"st-flash",
|
||||||
"--format", "ihex",
|
"--format", "ihex",
|
||||||
"write",
|
"write",
|
||||||
hex_file_path
|
hex_file_path
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
print(f"⚡️ Прошиваем {component_name} ({hex_file_path}) через ST-Link...")
|
print(f"⚡️ Прошиваем {component_name} ({hex_file_path}) через ST-Link...")
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
command,
|
command,
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=30
|
timeout=30
|
||||||
)
|
)
|
||||||
|
|
||||||
print("▬▬▬ STDOUT ▬▬▬")
|
print("▬▬▬ STDOUT ▬▬▬")
|
||||||
print(result.stdout)
|
print(result.stdout)
|
||||||
|
|
||||||
print("▬▬▬ STDERR ▬▬▬")
|
print("▬▬▬ STDERR ▬▬▬")
|
||||||
print(result.stderr)
|
print(result.stderr)
|
||||||
|
|
||||||
if result.returncode == 0:
|
if result.returncode == 0:
|
||||||
print(f"✅ {component_name} успешно прошит!")
|
print(f"✅ {component_name} успешно прошит!")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"❌ Ошибка прошивки {component_name} (код: {result.returncode})")
|
print(f"❌ Ошибка прошивки {component_name} (код: {result.returncode})")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except FileNotFoundError:
|
except FileNotFoundError:
|
||||||
print("❌ st-flash не найден! Установите stlink-tools.")
|
print("❌ st-flash не найден! Установите stlink-tools.")
|
||||||
return False
|
return False
|
||||||
except subprocess.TimeoutExpired:
|
except subprocess.TimeoutExpired:
|
||||||
print(f"❌ Таймаут операции при прошивке {component_name}! Проверьте подключение ST-Link.")
|
print(f"❌ Таймаут операции при прошивке {component_name}! Проверьте подключение ST-Link.")
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"❌ Неизвестная ошибка при прошивке {component_name}: {str(e)}")
|
print(f"❌ Неизвестная ошибка при прошивке {component_name}: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def reset_device():
|
def reset_device():
|
||||||
try:
|
try:
|
||||||
print("🔄 Выполняем сброс(перезагрузку) устройства...")
|
print("🔄 Выполняем сброс(перезагрузку) устройства...")
|
||||||
reset_result = subprocess.run(
|
reset_result = subprocess.run(
|
||||||
["st-info", "--reset"],
|
["st-info", "--reset"],
|
||||||
stdout=subprocess.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
stderr=subprocess.PIPE,
|
stderr=subprocess.PIPE,
|
||||||
universal_newlines=True,
|
universal_newlines=True,
|
||||||
timeout=10
|
timeout=10
|
||||||
)
|
)
|
||||||
if reset_result.returncode == 0:
|
if reset_result.returncode == 0:
|
||||||
print("♻️ Устройство успешно сброшено!")
|
print("♻️ Устройство успешно сброшено!")
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
print(f"⚠️ Ошибка при сбросе (код: {reset_result.returncode})")
|
print(f"⚠️ Ошибка при сбросе (код: {reset_result.returncode})")
|
||||||
print("▬▬▬ STDERR сброса ▬▬▬")
|
print("▬▬▬ STDERR сброса ▬▬▬")
|
||||||
print(reset_result.stderr)
|
print(reset_result.stderr)
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
print(f"⚠️ Ошибка при сбросе: {str(e)}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 3:
|
if len(sys.argv) != 3:
|
||||||
print("Использование: python stlink_flash.py <bootloader.hex> <application.hex>")
|
print("Использование: python stlink_flash.py <bootloader.hex> <application.hex>")
|
||||||
print("Пример: python stlink_flash.py bootloader.hex firmware.hex")
|
print("Пример: python stlink_flash.py bootloader.hex firmware.hex")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
bootloader_path = sys.argv[1]
|
bootloader_path = sys.argv[1]
|
||||||
app_path = sys.argv[2]
|
app_path = sys.argv[2]
|
||||||
|
|
||||||
# Прошиваем сначала бутлоадер
|
# Прошиваем сначала бутлоадер
|
||||||
if not flash_hex_with_stlink(bootloader_path, "Bootloader"):
|
if not flash_hex_with_stlink(bootloader_path, "Bootloader"):
|
||||||
print("\n💥 Ошибка прошивки бутлоадера!")
|
print("\n💥 Ошибка прошивки бутлоадера!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Сбрасываем устройство после прошивки бутлоадера
|
# Сбрасываем устройство после прошивки бутлоадера
|
||||||
reset_device()
|
reset_device()
|
||||||
time.sleep(1) # Короткая пауза
|
time.sleep(1) # Короткая пауза
|
||||||
|
|
||||||
# Прошиваем основное приложение
|
# Прошиваем основное приложение
|
||||||
if not flash_hex_with_stlink(app_path, "Application"):
|
if not flash_hex_with_stlink(app_path, "Application"):
|
||||||
print("\n💥 Ошибка прошивки основного приложения!")
|
print("\n💥 Ошибка прошивки основного приложения!")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Финальный сброс устройства
|
# Финальный сброс устройства
|
||||||
reset_device()
|
reset_device()
|
||||||
|
|
||||||
print("\n🎉 Все компоненты успешно прошиты!")
|
print("\n🎉 Все компоненты успешно прошиты!")
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
96
controller/fw/embed/test/test_simpleFOC.py
Normal file
96
controller/fw/embed/test/test_simpleFOC.py
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import can
|
||||||
|
import time
|
||||||
|
import sys
|
||||||
|
import struct
|
||||||
|
|
||||||
|
# Конфигурация
|
||||||
|
CAN_INTERFACE = 'can0'
|
||||||
|
DEVICE_ID = 0x69 # Текущий ID устройства
|
||||||
|
REG_READ = 0x7
|
||||||
|
REG_WRITE = 0x8
|
||||||
|
DATA_TYPE_ANGLE = 0x03
|
||||||
|
DATA_TYPE_VELOCITY = 0x04
|
||||||
|
DATA_TYPE_TORQUE = 0x05
|
||||||
|
|
||||||
|
# CRC функция (аналогичная устройству)
|
||||||
|
def validate_crc16(data):
|
||||||
|
crc = 0xFFFF
|
||||||
|
for byte in data:
|
||||||
|
crc ^= byte
|
||||||
|
for _ in range(8):
|
||||||
|
if crc & 0x0001:
|
||||||
|
crc = (crc >> 1) ^ 0xA001
|
||||||
|
else:
|
||||||
|
crc >>= 1
|
||||||
|
return crc
|
||||||
|
|
||||||
|
def send_can_message(bus, can_id, data):
|
||||||
|
try:
|
||||||
|
msg = can.Message(
|
||||||
|
arbitration_id=can_id,
|
||||||
|
data=data,
|
||||||
|
is_extended_id=False
|
||||||
|
)
|
||||||
|
bus.send(msg)
|
||||||
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
|
return True
|
||||||
|
except can.CanError as e:
|
||||||
|
print(f"Ошибка CAN: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
def receive_response(bus, timeout=1.0):
|
||||||
|
start_time = time.time()
|
||||||
|
while time.time() - start_time < timeout:
|
||||||
|
msg = bus.recv(timeout=0.1)
|
||||||
|
if msg:
|
||||||
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
|
return msg
|
||||||
|
print("[Ошибка] Таймаут")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def test_simplefoc_else_block():
|
||||||
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
|
# 1. Установка типа данных (DATA_TYPE_ANGLE)
|
||||||
|
can_id_write = (DEVICE_ID << 4) | REG_WRITE
|
||||||
|
data_set_type = [DATA_TYPE_ANGLE, 0x00]
|
||||||
|
full_data = list(can_id_write.to_bytes(2, 'little')) + data_set_type
|
||||||
|
crc = validate_crc16(full_data)
|
||||||
|
crc_bytes = list(crc.to_bytes(2, 'little'))
|
||||||
|
packet = data_set_type + crc_bytes
|
||||||
|
send_can_message(bus, can_id_write, packet)
|
||||||
|
time.sleep(0.1) # Ожидание обработки
|
||||||
|
|
||||||
|
# 2. Отправка SimpleFOC сообщения (угол)
|
||||||
|
target_angle = 45.0
|
||||||
|
angle_bytes = struct.pack('<f', target_angle)
|
||||||
|
can_id_simplefoc = (DEVICE_ID << 4) | 0x01 # Не REG_READ/REG_WRITE
|
||||||
|
payload = [0x00] + list(angle_bytes) + [0x00] # [type placeholder, angle, padding]
|
||||||
|
|
||||||
|
# Расчет CRC
|
||||||
|
full_data_sf = list(can_id_simplefoc.to_bytes(2, 'little')) + payload
|
||||||
|
crc_sf = validate_crc16(full_data_sf)
|
||||||
|
payload += list(crc_sf.to_bytes(2, 'little'))
|
||||||
|
|
||||||
|
# Отправка
|
||||||
|
print("\nТест SimpleFOC (блок else):")
|
||||||
|
send_can_message(bus, can_id_simplefoc, payload)
|
||||||
|
|
||||||
|
# 3. Проверка ответа (отправка угла + установка нового угла)
|
||||||
|
response = receive_response(bus)
|
||||||
|
if response:
|
||||||
|
# Проверка структуры ответа
|
||||||
|
if response.data[0] == ord('A'):
|
||||||
|
print("Успех: Отправлен текущий угол")
|
||||||
|
else:
|
||||||
|
print("Ошибка: Неверный тип ответа")
|
||||||
|
else:
|
||||||
|
print("Ошибка: Нет ответа от устройства")
|
||||||
|
|
||||||
|
# 4. Проверка установки нового угла (интеграционно)
|
||||||
|
# ... (может требовать дополнительной проверки на устройстве)
|
||||||
|
|
||||||
|
bus.shutdown()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
test_simplefoc_else_block()
|
|
@ -1,95 +1,95 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
DEVICE_ID = int(sys.argv[1]) # ID ADDR for servo
|
DEVICE_ID = int(sys.argv[1]) # ID ADDR for servo
|
||||||
REG_WRITE = 0x8 # Код команды записи
|
REG_WRITE = 0x8 # Код команды записи
|
||||||
REG_MOTOR_POSPID_Kp = 0x30
|
REG_MOTOR_POSPID_Kp = 0x30
|
||||||
REG_MOTOR_POSPID_Ki = 0x31
|
REG_MOTOR_POSPID_Ki = 0x31
|
||||||
REG_MOTOR_POSPID_Kd = 0x32
|
REG_MOTOR_POSPID_Kd = 0x32
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
"""Расчет CRC16 (MODBUS) для проверки целостности данных"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
def send_pid_value(bus, device_id, reg, value):
|
def send_pid_value(bus, device_id, reg, value):
|
||||||
"""Отправка коэффициента PID на устройство"""
|
"""Отправка коэффициента PID на устройство"""
|
||||||
# Формируем CAN ID для записи: (device_id << 4) | REG_WRITE
|
# Формируем CAN ID для записи: (device_id << 4) | REG_WRITE
|
||||||
can_id_write = (device_id << 4) | REG_WRITE
|
can_id_write = (device_id << 4) | REG_WRITE
|
||||||
|
|
||||||
# Упаковываем значение в байты (little-endian)
|
# Упаковываем значение в байты (little-endian)
|
||||||
float_bytes = struct.pack('<f', value)
|
float_bytes = struct.pack('<f', value)
|
||||||
|
|
||||||
# Формируем часть данных (регистр + значение)
|
# Формируем часть данных (регистр + значение)
|
||||||
data_part = [reg] + list(float_bytes)
|
data_part = [reg] + list(float_bytes)
|
||||||
|
|
||||||
# Полные данные для расчета CRC: CAN ID + данные
|
# Полные данные для расчета CRC: CAN ID + данные
|
||||||
full_data_for_crc = list(can_id_write.to_bytes(2, 'little')) + data_part
|
full_data_for_crc = list(can_id_write.to_bytes(2, 'little')) + data_part
|
||||||
|
|
||||||
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
# Рассчитываем CRC и разбиваем на байты (little-endian)
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, 'little'))
|
crc_bytes = list(crc.to_bytes(2, 'little'))
|
||||||
|
|
||||||
# Собираем итоговый пакет данных
|
# Собираем итоговый пакет данных
|
||||||
can_data = data_part + crc_bytes
|
can_data = data_part + crc_bytes
|
||||||
|
|
||||||
# Отправляем сообщение
|
# Отправляем сообщение
|
||||||
send_can_message(bus, can_id_write, can_data)
|
send_can_message(bus, can_id_write, can_data)
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Запрос коэффициентов у пользователя
|
# Запрос коэффициентов у пользователя
|
||||||
try:
|
try:
|
||||||
p = float(input("Введите коэффициент P: "))
|
p = float(input("Введите коэффициент P: "))
|
||||||
i = float(input("Введите коэффициент I: "))
|
i = float(input("Введите коэффициент I: "))
|
||||||
d = float(input("Введите коэффициент D: "))
|
d = float(input("Введите коэффициент D: "))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print("Ошибка: Введите числовые значения.")
|
print("Ошибка: Введите числовые значения.")
|
||||||
return
|
return
|
||||||
|
|
||||||
# Инициализация CAN-интерфейса
|
# Инициализация CAN-интерфейса
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Отправка коэффициентов с задержкой
|
# Отправка коэффициентов с задержкой
|
||||||
send_pid_value(bus, DEVICE_ID, REG_MOTOR_POSPID_Kp, p)
|
send_pid_value(bus, DEVICE_ID, REG_MOTOR_POSPID_Kp, p)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
send_pid_value(bus, DEVICE_ID, REG_MOTOR_POSPID_Ki, i)
|
send_pid_value(bus, DEVICE_ID, REG_MOTOR_POSPID_Ki, i)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
send_pid_value(bus, DEVICE_ID, REG_MOTOR_POSPID_Kd, d)
|
send_pid_value(bus, DEVICE_ID, REG_MOTOR_POSPID_Kd, d)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
# Завершение работы с шиной
|
# Завершение работы с шиной
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Используйте python3 pid_set.py addr")
|
print("Используйте python3 pid_set.py addr")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,122 +1,122 @@
|
||||||
import can
|
import can
|
||||||
import time
|
import time
|
||||||
import struct
|
import struct
|
||||||
# Конфигурация
|
# Конфигурация
|
||||||
CAN_INTERFACE = 'can0'
|
CAN_INTERFACE = 'can0'
|
||||||
DEVICE_ID = 0x00
|
DEVICE_ID = 0x00
|
||||||
SET_PID_P = 3.6
|
SET_PID_P = 3.6
|
||||||
REG_WRITE = 0x8
|
REG_WRITE = 0x8
|
||||||
REG_READ = 0x7
|
REG_READ = 0x7
|
||||||
REG_ID = 0x30 #REG_MOTOR_POSPID_Kp
|
REG_ID = 0x30 #REG_MOTOR_POSPID_Kp
|
||||||
PID_P = 0x01
|
PID_P = 0x01
|
||||||
|
|
||||||
def send_can_message(bus, can_id, data):
|
def send_can_message(bus, can_id, data):
|
||||||
"""Отправка CAN-сообщения"""
|
"""Отправка CAN-сообщения"""
|
||||||
try:
|
try:
|
||||||
msg = can.Message(
|
msg = can.Message(
|
||||||
arbitration_id=can_id,
|
arbitration_id=can_id,
|
||||||
data=data,
|
data=data,
|
||||||
is_extended_id=False
|
is_extended_id=False
|
||||||
)
|
)
|
||||||
bus.send(msg)
|
bus.send(msg)
|
||||||
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}")
|
||||||
return True
|
return True
|
||||||
except can.CanError as e:
|
except can.CanError as e:
|
||||||
print(f"Ошибка CAN: {e}")
|
print(f"Ошибка CAN: {e}")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def receive_response(bus, timeout=1.0):
|
def receive_response(bus, timeout=1.0):
|
||||||
print("Ожидание ответа")
|
print("Ожидание ответа")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
while time.time() - start_time < timeout:
|
while time.time() - start_time < timeout:
|
||||||
msg = bus.recv(timeout=0.1)
|
msg = bus.recv(timeout=0.1)
|
||||||
if msg:
|
if msg:
|
||||||
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}")
|
||||||
return msg
|
return msg
|
||||||
print("[Ошибка] Таймаут")
|
print("[Ошибка] Таймаут")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def validate_crc16(data):
|
def validate_crc16(data):
|
||||||
"""Функция расчета CRC16 (MODBUS)"""
|
"""Функция расчета CRC16 (MODBUS)"""
|
||||||
crc = 0xFFFF
|
crc = 0xFFFF
|
||||||
for byte in data:
|
for byte in data:
|
||||||
crc ^= byte
|
crc ^= byte
|
||||||
for _ in range(8):
|
for _ in range(8):
|
||||||
if crc & 0x0001:
|
if crc & 0x0001:
|
||||||
crc = (crc >> 1) ^ 0xA001
|
crc = (crc >> 1) ^ 0xA001
|
||||||
else:
|
else:
|
||||||
crc >>= 1
|
crc >>= 1
|
||||||
return crc
|
return crc
|
||||||
|
|
||||||
# Инициализация
|
# Инициализация
|
||||||
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
|
||||||
# Перевод float -> hex -> int
|
# Перевод float -> hex -> int
|
||||||
result = (struct.unpack('<I',struct.pack('<f', float(SET_PID_P)))[0])
|
result = (struct.unpack('<I',struct.pack('<f', float(SET_PID_P)))[0])
|
||||||
result_bytes = result.to_bytes(4, byteorder='little')
|
result_bytes = result.to_bytes(4, byteorder='little')
|
||||||
# ======= 1. Отправляем команду изменить ID =======
|
# ======= 1. Отправляем команду изменить ID =======
|
||||||
|
|
||||||
# Весь буфер: id + команда + параметры
|
# Весь буфер: id + команда + параметры
|
||||||
OLD_WITH_REG = (DEVICE_ID << 4) | REG_WRITE
|
OLD_WITH_REG = (DEVICE_ID << 4) | REG_WRITE
|
||||||
id_bytes = list(OLD_WITH_REG.to_bytes(2, byteorder='little'))
|
id_bytes = list(OLD_WITH_REG.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Важные части сообщения: address (id), команда, параметры
|
# Важные части сообщения: address (id), команда, параметры
|
||||||
data_write = [REG_ID] + list(result_bytes) # команда изменить PID_P
|
data_write = [REG_ID] + list(result_bytes) # команда изменить PID_P
|
||||||
|
|
||||||
# Полностью собираем массив для CRC (включая id и команду)
|
# Полностью собираем массив для CRC (включая id и команду)
|
||||||
full_data_for_crc = id_bytes + data_write
|
full_data_for_crc = id_bytes + data_write
|
||||||
|
|
||||||
# Расчет CRC по всему пакету
|
# Расчет CRC по всему пакету
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
|
|
||||||
# Итоговый пакет: команда + параметры + CRC
|
# Итоговый пакет: команда + параметры + CRC
|
||||||
packet_write = data_write + crc_bytes
|
packet_write = data_write + crc_bytes
|
||||||
|
|
||||||
print("Отправляем: команда изменить PID_p + CRC:", packet_write)
|
print("Отправляем: команда изменить PID_p + CRC:", packet_write)
|
||||||
# Отправляем с `OLD_DEVICE_ID` в качестве адреса
|
# Отправляем с `OLD_DEVICE_ID` в качестве адреса
|
||||||
send_can_message(bus, (DEVICE_ID << 4) | REG_WRITE, packet_write)
|
send_can_message(bus, (DEVICE_ID << 4) | REG_WRITE, packet_write)
|
||||||
|
|
||||||
time.sleep(1.0)
|
time.sleep(1.0)
|
||||||
|
|
||||||
# ======= 2. Запрашиваем текущий ID (используем новый адрес) =======
|
# ======= 2. Запрашиваем текущий ID (используем новый адрес) =======
|
||||||
|
|
||||||
# Теперь для запроса используем **уже новый id**
|
# Теперь для запроса используем **уже новый id**
|
||||||
NEW_WITH_REG = (DEVICE_ID << 4) | REG_READ
|
NEW_WITH_REG = (DEVICE_ID << 4) | REG_READ
|
||||||
current_id_bytes = list(NEW_WITH_REG.to_bytes(2, byteorder='little'))
|
current_id_bytes = list(NEW_WITH_REG.to_bytes(2, byteorder='little'))
|
||||||
data_read = [REG_ID, 0x00]
|
data_read = [REG_ID, 0x00]
|
||||||
|
|
||||||
full_data_for_crc = current_id_bytes + data_read
|
full_data_for_crc = current_id_bytes + data_read
|
||||||
crc = validate_crc16(full_data_for_crc)
|
crc = validate_crc16(full_data_for_crc)
|
||||||
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
crc_bytes = list(crc.to_bytes(2, byteorder='little'))
|
||||||
packet_read = data_read + crc_bytes
|
packet_read = data_read + crc_bytes
|
||||||
|
|
||||||
print("Запрос на чтение ID + CRC (после смены):", packet_read)
|
print("Запрос на чтение ID + CRC (после смены):", packet_read)
|
||||||
send_can_message(bus, (DEVICE_ID << 4) | REG_READ, packet_read)
|
send_can_message(bus, (DEVICE_ID << 4) | REG_READ, packet_read)
|
||||||
|
|
||||||
# ======= 3. Получение и проверка ответа =======
|
# ======= 3. Получение и проверка ответа =======
|
||||||
|
|
||||||
response = receive_response(bus)
|
response = receive_response(bus)
|
||||||
if response:
|
if response:
|
||||||
data = response.data
|
data = response.data
|
||||||
if len(data) < 4:
|
if len(data) < 4:
|
||||||
print("Ответ слишком короткий")
|
print("Ответ слишком короткий")
|
||||||
else:
|
else:
|
||||||
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
id_bytes = response.arbitration_id.to_bytes(1,byteorder='little')
|
||||||
#buff with id and data without CRC
|
#buff with id and data without CRC
|
||||||
full_data = list(id_bytes) + list(data[:-2])
|
full_data = list(id_bytes) + list(data[:-2])
|
||||||
print(f"Received full_data: {list(full_data)}")
|
print(f"Received full_data: {list(full_data)}")
|
||||||
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
received_crc = int.from_bytes(data[-2:], byteorder='little')
|
||||||
#calc CRC
|
#calc CRC
|
||||||
calc_crc = validate_crc16(full_data)
|
calc_crc = validate_crc16(full_data)
|
||||||
if received_crc == calc_crc:
|
if received_crc == calc_crc:
|
||||||
if data[0] == int(REG_ID):
|
if data[0] == int(REG_ID):
|
||||||
kp_val = struct.unpack('<f', bytes(data[1:5]))[0]
|
kp_val = struct.unpack('<f', bytes(data[1:5]))[0]
|
||||||
print(f"\nУСПЕХ! PID_P = {kp_val:.3f}")
|
print(f"\nУСПЕХ! PID_P = {kp_val:.3f}")
|
||||||
else:
|
else:
|
||||||
print(f"Некорректный ответ: {list(data)}")
|
print(f"Некорректный ответ: {list(data)}")
|
||||||
else:
|
else:
|
||||||
print("CRC не совпадает, данные повреждены.")
|
print("CRC не совпадает, данные повреждены.")
|
||||||
else:
|
else:
|
||||||
print("Нет ответа от устройства.")
|
print("Нет ответа от устройства.")
|
||||||
|
|
||||||
bus.shutdown()
|
bus.shutdown()
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
ip link set can0 type can bitrate 1000000
|
ip link set can0 type can bitrate 1000000
|
||||||
ip link set up can0
|
ip link set up can0
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Read 8 byte ascii from $1 and send it to CAN bus
|
# Read 8 byte ascii from $1 and send it to CAN bus
|
||||||
|
|
||||||
# <can_id>:
|
# <can_id>:
|
||||||
# 3 (SFF) or 8 (EFF) hex chars
|
# 3 (SFF) or 8 (EFF) hex chars
|
||||||
# {data}:
|
# {data}:
|
||||||
# 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.')
|
# 0..8 (0..64 CAN FD) ASCII hex-values (optionally separated by '.')
|
||||||
# {len}:
|
# {len}:
|
||||||
# an optional 0..8 value as RTR frames can contain a valid dlc field
|
# an optional 0..8 value as RTR frames can contain a valid dlc field
|
||||||
# <flags>:
|
# <flags>:
|
||||||
# a single ASCII Hex value (0 .. F) which defines canfd_frame.flags
|
# a single ASCII Hex value (0 .. F) which defines canfd_frame.flags
|
||||||
|
|
||||||
can_id=$1
|
can_id=$1
|
||||||
input=$2
|
input=$2
|
||||||
|
|
||||||
if [[ ${#input} -gt 8 ]]; then
|
if [[ ${#input} -gt 8 ]]; then
|
||||||
echo "Error: Input string must be no longer than 8 characters."
|
echo "Error: Input string must be no longer than 8 characters."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
hex_output=""
|
hex_output=""
|
||||||
for (( i=0; i<${#input}; i++ )); do
|
for (( i=0; i<${#input}; i++ )); do
|
||||||
hex_char=$(printf "%02x" "'${input:$i:1}")
|
hex_char=$(printf "%02x" "'${input:$i:1}")
|
||||||
hex_output+="${hex_char}"
|
hex_output+="${hex_char}"
|
||||||
done
|
done
|
||||||
|
|
||||||
hex_output=$(printf "%-16s" "$hex_output")
|
hex_output=$(printf "%-16s" "$hex_output")
|
||||||
hex_output=${hex_output// /0}
|
hex_output=${hex_output// /0}
|
||||||
|
|
||||||
can_id=$(printf "%03X" $can_id)
|
can_id=$(printf "%03X" $can_id)
|
||||||
|
|
||||||
cansend can0 $can_id#$hex_output
|
cansend can0 $can_id#$hex_output
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
|
|
||||||
/bin/bash $(pwd)/send_can.sh 1 E0
|
/bin/bash $(pwd)/send_can.sh 1 E0
|
||||||
|
|
||||||
/bin/bash $(pwd)/send_can.sh 1 E1
|
/bin/bash $(pwd)/send_can.sh 1 E1
|
||||||
|
|
||||||
/bin/bash $(pwd)/send_can.sh 1 C2
|
/bin/bash $(pwd)/send_can.sh 1 C2
|
||||||
|
|
||||||
/bin/bash $(pwd)/send_can.sh 1 1
|
/bin/bash $(pwd)/send_can.sh 1 1
|
||||||
sleep 1
|
sleep 1
|
||||||
/bin/bash $(pwd)/send_can.sh 1 -1
|
/bin/bash $(pwd)/send_can.sh 1 -1
|
||||||
sleep 1
|
sleep 1
|
||||||
/bin/bash $(pwd)/send_can.sh 1 -1
|
/bin/bash $(pwd)/send_can.sh 1 -1
|
||||||
sleep 1
|
sleep 1
|
||||||
/bin/bash $(pwd)/send_can.sh 1 2
|
/bin/bash $(pwd)/send_can.sh 1 2
|
||||||
sleep 1
|
sleep 1
|
||||||
/bin/bash $(pwd)/send_can.sh 1 C1
|
/bin/bash $(pwd)/send_can.sh 1 C1
|
||||||
sleep 1
|
sleep 1
|
||||||
/bin/bash $(pwd)/send_can.sh 1 0.5
|
/bin/bash $(pwd)/send_can.sh 1 0.5
|
||||||
sleep 5
|
sleep 5
|
||||||
/bin/bash $(pwd)/send_can.sh 1 2
|
/bin/bash $(pwd)/send_can.sh 1 2
|
||||||
sleep 5
|
sleep 5
|
||||||
/bin/bash $(pwd)/send_can.sh 1 5
|
/bin/bash $(pwd)/send_can.sh 1 5
|
||||||
sleep 5
|
sleep 5
|
||||||
/bin/bash $(pwd)/send_can.sh 1 -5
|
/bin/bash $(pwd)/send_can.sh 1 -5
|
||||||
sleep 5
|
sleep 5
|
||||||
/bin/bash $(pwd)/send_can.sh 1 20
|
/bin/bash $(pwd)/send_can.sh 1 20
|
||||||
sleep 5
|
sleep 5
|
||||||
/bin/bash $(pwd)/send_can.sh 1 E0
|
/bin/bash $(pwd)/send_can.sh 1 E0
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,86 +1,86 @@
|
||||||
{
|
{
|
||||||
"board": {
|
"board": {
|
||||||
"active_layer": 36,
|
"active_layer": 36,
|
||||||
"active_layer_preset": "",
|
"active_layer_preset": "",
|
||||||
"auto_track_width": true,
|
"auto_track_width": true,
|
||||||
"hidden_netclasses": [],
|
"hidden_netclasses": [],
|
||||||
"hidden_nets": [],
|
"hidden_nets": [],
|
||||||
"high_contrast_mode": 0,
|
"high_contrast_mode": 0,
|
||||||
"net_color_mode": 1,
|
"net_color_mode": 1,
|
||||||
"opacity": {
|
"opacity": {
|
||||||
"images": 0.6,
|
"images": 0.6,
|
||||||
"pads": 1.0,
|
"pads": 1.0,
|
||||||
"tracks": 1.0,
|
"tracks": 1.0,
|
||||||
"vias": 1.0,
|
"vias": 1.0,
|
||||||
"zones": 0.6
|
"zones": 0.6
|
||||||
},
|
},
|
||||||
"selection_filter": {
|
"selection_filter": {
|
||||||
"dimensions": true,
|
"dimensions": true,
|
||||||
"footprints": true,
|
"footprints": true,
|
||||||
"graphics": true,
|
"graphics": true,
|
||||||
"keepouts": true,
|
"keepouts": true,
|
||||||
"lockedItems": false,
|
"lockedItems": false,
|
||||||
"otherItems": true,
|
"otherItems": true,
|
||||||
"pads": true,
|
"pads": true,
|
||||||
"text": true,
|
"text": true,
|
||||||
"tracks": true,
|
"tracks": true,
|
||||||
"vias": true,
|
"vias": true,
|
||||||
"zones": true
|
"zones": true
|
||||||
},
|
},
|
||||||
"visible_items": [
|
"visible_items": [
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
2,
|
2,
|
||||||
3,
|
3,
|
||||||
4,
|
4,
|
||||||
5,
|
5,
|
||||||
6,
|
6,
|
||||||
7,
|
7,
|
||||||
8,
|
8,
|
||||||
9,
|
9,
|
||||||
10,
|
10,
|
||||||
11,
|
11,
|
||||||
12,
|
12,
|
||||||
13,
|
13,
|
||||||
14,
|
14,
|
||||||
15,
|
15,
|
||||||
16,
|
16,
|
||||||
17,
|
17,
|
||||||
18,
|
18,
|
||||||
19,
|
19,
|
||||||
20,
|
20,
|
||||||
21,
|
21,
|
||||||
22,
|
22,
|
||||||
23,
|
23,
|
||||||
24,
|
24,
|
||||||
25,
|
25,
|
||||||
26,
|
26,
|
||||||
27,
|
27,
|
||||||
28,
|
28,
|
||||||
29,
|
29,
|
||||||
30,
|
30,
|
||||||
32,
|
32,
|
||||||
33,
|
33,
|
||||||
34,
|
34,
|
||||||
35,
|
35,
|
||||||
36,
|
36,
|
||||||
39,
|
39,
|
||||||
40
|
40
|
||||||
],
|
],
|
||||||
"visible_layers": "0001010_00000001",
|
"visible_layers": "0001010_00000001",
|
||||||
"zone_display_mode": 0
|
"zone_display_mode": 0
|
||||||
},
|
},
|
||||||
"git": {
|
"git": {
|
||||||
"repo_password": "",
|
"repo_password": "",
|
||||||
"repo_type": "",
|
"repo_type": "",
|
||||||
"repo_username": "",
|
"repo_username": "",
|
||||||
"ssh_key": ""
|
"ssh_key": ""
|
||||||
},
|
},
|
||||||
"meta": {
|
"meta": {
|
||||||
"filename": "motor_controller_50mm.kicad_prl",
|
"filename": "motor_controller_50mm.kicad_prl",
|
||||||
"version": 3
|
"version": 3
|
||||||
},
|
},
|
||||||
"project": {
|
"project": {
|
||||||
"files": []
|
"files": []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,4 @@
|
||||||
(sym_lib_table
|
(sym_lib_table
|
||||||
(version 7)
|
(version 7)
|
||||||
(lib (name "motor_controller_50mm-rescue")(type "KiCad")(uri "${KIPRJMOD}/motor_controller_50mm-rescue.kicad_sym")(options "")(descr ""))
|
(lib (name "motor_controller_50mm-rescue")(type "KiCad")(uri "${KIPRJMOD}/motor_controller_50mm-rescue.kicad_sym")(options "")(descr ""))
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,286 +1,286 @@
|
||||||
# Example Kibot config file
|
# Example Kibot config file
|
||||||
kibot:
|
kibot:
|
||||||
version: 1
|
version: 1
|
||||||
|
|
||||||
preflight:
|
preflight:
|
||||||
run_erc: true
|
run_erc: true
|
||||||
update_xml: true
|
update_xml: true
|
||||||
run_drc: true
|
run_drc: true
|
||||||
check_zone_fills: false
|
check_zone_fills: false
|
||||||
ignore_unconnected: true
|
ignore_unconnected: true
|
||||||
|
|
||||||
global:
|
global:
|
||||||
# We want the revision added to the names for this project
|
# We want the revision added to the names for this project
|
||||||
output: '%f-%i_%r.%x'
|
output: '%f-%i_%r.%x'
|
||||||
hide_excluded: true
|
hide_excluded: true
|
||||||
|
|
||||||
# kiauto_wait_start: 60
|
# kiauto_wait_start: 60
|
||||||
# kiauto_time_out_scale: 2
|
# kiauto_time_out_scale: 2
|
||||||
|
|
||||||
outputs:
|
outputs:
|
||||||
- name: 'print_sch'
|
- name: 'print_sch'
|
||||||
comment: "Print schematic (PDF)"
|
comment: "Print schematic (PDF)"
|
||||||
type: pdf_sch_print
|
type: pdf_sch_print
|
||||||
dir: .
|
dir: .
|
||||||
options:
|
options:
|
||||||
output: Schematic.pdf
|
output: Schematic.pdf
|
||||||
|
|
||||||
- name: 'print_front'
|
- name: 'print_front'
|
||||||
comment: "Print F.Cu+Dwgs.User"
|
comment: "Print F.Cu+Dwgs.User"
|
||||||
type: pdf_pcb_print
|
type: pdf_pcb_print
|
||||||
dir: .
|
dir: .
|
||||||
options:
|
options:
|
||||||
output_name: PCB_Top.pdf
|
output_name: PCB_Top.pdf
|
||||||
layers:
|
layers:
|
||||||
- layer: B.Cu
|
- layer: B.Cu
|
||||||
- layer: F.SilkS
|
- layer: F.SilkS
|
||||||
|
|
||||||
- name: 'print_bottom'
|
- name: 'print_bottom'
|
||||||
comment: "Print B.Cu+Dwgs.User"
|
comment: "Print B.Cu+Dwgs.User"
|
||||||
type: pdf_pcb_print
|
type: pdf_pcb_print
|
||||||
dir: .
|
dir: .
|
||||||
layers:
|
layers:
|
||||||
- layer: B.Cu
|
- layer: B.Cu
|
||||||
- layer: Dwgs.User
|
- layer: Dwgs.User
|
||||||
|
|
||||||
- name: 'gerbers'
|
- name: 'gerbers'
|
||||||
comment: "Gerbers for the board house"
|
comment: "Gerbers for the board house"
|
||||||
type: gerber
|
type: gerber
|
||||||
dir: Gerbers
|
dir: Gerbers
|
||||||
options:
|
options:
|
||||||
# generic layer options
|
# generic layer options
|
||||||
exclude_edge_layer: true
|
exclude_edge_layer: true
|
||||||
exclude_pads_from_silkscreen: false
|
exclude_pads_from_silkscreen: false
|
||||||
use_aux_axis_as_origin: false
|
use_aux_axis_as_origin: false
|
||||||
plot_sheet_reference: false
|
plot_sheet_reference: false
|
||||||
plot_footprint_refs: true
|
plot_footprint_refs: true
|
||||||
plot_footprint_values: true
|
plot_footprint_values: true
|
||||||
force_plot_invisible_refs_vals: false
|
force_plot_invisible_refs_vals: false
|
||||||
tent_vias: true
|
tent_vias: true
|
||||||
|
|
||||||
# gerber options
|
# gerber options
|
||||||
line_width: 0.1
|
line_width: 0.1
|
||||||
subtract_mask_from_silk: false
|
subtract_mask_from_silk: false
|
||||||
use_protel_extensions: false
|
use_protel_extensions: false
|
||||||
gerber_precision: 4.6
|
gerber_precision: 4.6
|
||||||
create_gerber_job_file: true
|
create_gerber_job_file: true
|
||||||
use_gerber_x2_attributes: true
|
use_gerber_x2_attributes: true
|
||||||
use_gerber_net_attributes: true
|
use_gerber_net_attributes: true
|
||||||
|
|
||||||
layers:
|
layers:
|
||||||
- 'selected'
|
- 'selected'
|
||||||
# - layer: B.Cu
|
# - layer: B.Cu
|
||||||
# suffix: B_Cu
|
# suffix: B_Cu
|
||||||
# - layer: F.SilkS
|
# - layer: F.SilkS
|
||||||
# suffix: F_SilkS
|
# suffix: F_SilkS
|
||||||
# - layer: Edge.Cuts
|
# - layer: Edge.Cuts
|
||||||
# suffix: Edge_Cuts
|
# suffix: Edge_Cuts
|
||||||
|
|
||||||
- name: 'interactive_bom'
|
- name: 'interactive_bom'
|
||||||
comment: "Interactive Bill of Materials (HTML)"
|
comment: "Interactive Bill of Materials (HTML)"
|
||||||
type: ibom
|
type: ibom
|
||||||
dir: BoM
|
dir: BoM
|
||||||
options:
|
options:
|
||||||
hide_excluded: true
|
hide_excluded: true
|
||||||
blacklist: 'DNF*'
|
blacklist: 'DNF*'
|
||||||
name_format: '%f_%r_iBoM'
|
name_format: '%f_%r_iBoM'
|
||||||
|
|
||||||
- name: 'bom_html'
|
- name: 'bom_html'
|
||||||
comment: "Bill of Materials in HTML format"
|
comment: "Bill of Materials in HTML format"
|
||||||
type: bom
|
type: bom
|
||||||
dir: BoM
|
dir: BoM
|
||||||
options:
|
options:
|
||||||
format: HTML # HTML or CSV
|
format: HTML # HTML or CSV
|
||||||
|
|
||||||
- name: 'bom_csv'
|
- name: 'bom_csv'
|
||||||
comment: "Bill of Materials in CSV format"
|
comment: "Bill of Materials in CSV format"
|
||||||
type: bom
|
type: bom
|
||||||
dir: BoM
|
dir: BoM
|
||||||
options:
|
options:
|
||||||
format: CSV # HTML or CSV
|
format: CSV # HTML or CSV
|
||||||
ref_separator: ','
|
ref_separator: ','
|
||||||
normalize_values: true
|
normalize_values: true
|
||||||
normalize_locale: true
|
normalize_locale: true
|
||||||
csv: # Hide Project Info & Statistics for PCB manufacturer file processing
|
csv: # Hide Project Info & Statistics for PCB manufacturer file processing
|
||||||
hide_pcb_info: true
|
hide_pcb_info: true
|
||||||
hide_stats_info: true
|
hide_stats_info: true
|
||||||
columns:
|
columns:
|
||||||
- Row
|
- Row
|
||||||
- field: manf#
|
- field: manf#
|
||||||
name: Manufacturer Part Number
|
name: Manufacturer Part Number
|
||||||
- field: 'Quantity Per PCB'
|
- field: 'Quantity Per PCB'
|
||||||
name: Qty
|
name: Qty
|
||||||
- field: References
|
- field: References
|
||||||
name: Designator
|
name: Designator
|
||||||
- Part
|
- Part
|
||||||
- Value
|
- Value
|
||||||
- Footprint
|
- Footprint
|
||||||
- Description
|
- Description
|
||||||
- Datasheet
|
- Datasheet
|
||||||
|
|
||||||
- name: 'bom_xlsx'
|
- name: 'bom_xlsx'
|
||||||
comment: "Bill of Materials in XLSX format"
|
comment: "Bill of Materials in XLSX format"
|
||||||
type: bom
|
type: bom
|
||||||
dir: BoM
|
dir: BoM
|
||||||
options:
|
options:
|
||||||
format: XLSX
|
format: XLSX
|
||||||
|
|
||||||
- name: excellon_drill
|
- name: excellon_drill
|
||||||
comment: "Excellon drill files"
|
comment: "Excellon drill files"
|
||||||
type: excellon
|
type: excellon
|
||||||
dir: Drill
|
dir: Drill
|
||||||
options:
|
options:
|
||||||
metric_units: false
|
metric_units: false
|
||||||
pth_and_npth_single_file: false
|
pth_and_npth_single_file: false
|
||||||
use_aux_axis_as_origin: false
|
use_aux_axis_as_origin: false
|
||||||
minimal_header: false
|
minimal_header: false
|
||||||
mirror_y_axis: false
|
mirror_y_axis: false
|
||||||
report:
|
report:
|
||||||
filename: 'spora-drl.rpt'
|
filename: 'spora-drl.rpt'
|
||||||
map:
|
map:
|
||||||
type: 'pdf'
|
type: 'pdf'
|
||||||
|
|
||||||
- name: gerber_drills
|
- name: gerber_drills
|
||||||
comment: "Gerber drill files"
|
comment: "Gerber drill files"
|
||||||
type: gerb_drill
|
type: gerb_drill
|
||||||
dir: Drill
|
dir: Drill
|
||||||
options:
|
options:
|
||||||
use_aux_axis_as_origin: false
|
use_aux_axis_as_origin: false
|
||||||
|
|
||||||
- name: 'position'
|
- name: 'position'
|
||||||
comment: "Pick and place file"
|
comment: "Pick and place file"
|
||||||
type: position
|
type: position
|
||||||
dir: Position
|
dir: Position
|
||||||
options:
|
options:
|
||||||
format: ASCII # CSV or ASCII format
|
format: ASCII # CSV or ASCII format
|
||||||
units: millimeters # millimeters or inches
|
units: millimeters # millimeters or inches
|
||||||
separate_files_for_front_and_back: true
|
separate_files_for_front_and_back: true
|
||||||
only_smd: true
|
only_smd: true
|
||||||
|
|
||||||
- name: pcb_top_g
|
- name: pcb_top_g
|
||||||
comment: "PCB render top green"
|
comment: "PCB render top green"
|
||||||
type: pcbdraw
|
type: pcbdraw
|
||||||
dir: PCB/green
|
dir: PCB/green
|
||||||
options:
|
options:
|
||||||
format: jpg
|
format: jpg
|
||||||
show_components: none
|
show_components: none
|
||||||
dpi: 600
|
dpi: 600
|
||||||
|
|
||||||
- name: pcb_bot_g
|
- name: pcb_bot_g
|
||||||
comment: "PCB render bottom green"
|
comment: "PCB render bottom green"
|
||||||
type: pcbdraw
|
type: pcbdraw
|
||||||
dir: PCB/green
|
dir: PCB/green
|
||||||
options:
|
options:
|
||||||
format: jpg
|
format: jpg
|
||||||
bottom: True
|
bottom: True
|
||||||
show_components: none
|
show_components: none
|
||||||
dpi: 600
|
dpi: 600
|
||||||
|
|
||||||
- name: pcb_top_b
|
- name: pcb_top_b
|
||||||
comment: "PCB render top blue"
|
comment: "PCB render top blue"
|
||||||
type: pcbdraw
|
type: pcbdraw
|
||||||
dir: PCB/blue
|
dir: PCB/blue
|
||||||
options:
|
options:
|
||||||
format: jpg
|
format: jpg
|
||||||
style: set-blue-enig
|
style: set-blue-enig
|
||||||
show_components: none
|
show_components: none
|
||||||
dpi: 600
|
dpi: 600
|
||||||
|
|
||||||
- name: pcb_bot_b
|
- name: pcb_bot_b
|
||||||
comment: "PCB render bottom blue"
|
comment: "PCB render bottom blue"
|
||||||
type: pcbdraw
|
type: pcbdraw
|
||||||
dir: PCB/blue
|
dir: PCB/blue
|
||||||
options:
|
options:
|
||||||
format: jpg
|
format: jpg
|
||||||
style: set-blue-enig
|
style: set-blue-enig
|
||||||
bottom: True
|
bottom: True
|
||||||
show_components: none
|
show_components: none
|
||||||
dpi: 600
|
dpi: 600
|
||||||
|
|
||||||
- name: pcb_top_r
|
- name: pcb_top_r
|
||||||
comment: "PCB render top red"
|
comment: "PCB render top red"
|
||||||
type: pcbdraw
|
type: pcbdraw
|
||||||
dir: PCB/red
|
dir: PCB/red
|
||||||
options:
|
options:
|
||||||
format: jpg
|
format: jpg
|
||||||
style: set-red-enig
|
style: set-red-enig
|
||||||
show_components: none
|
show_components: none
|
||||||
dpi: 600
|
dpi: 600
|
||||||
|
|
||||||
- name: pcb_bot_r
|
- name: pcb_bot_r
|
||||||
comment: "PCB render bottom red"
|
comment: "PCB render bottom red"
|
||||||
type: pcbdraw
|
type: pcbdraw
|
||||||
dir: PCB/red
|
dir: PCB/red
|
||||||
options:
|
options:
|
||||||
format: jpg
|
format: jpg
|
||||||
style: set-red-enig
|
style: set-red-enig
|
||||||
bottom: True
|
bottom: True
|
||||||
show_components: none
|
show_components: none
|
||||||
dpi: 600
|
dpi: 600
|
||||||
|
|
||||||
- name: step
|
- name: step
|
||||||
comment: "Generate 3D model (STEP)"
|
comment: "Generate 3D model (STEP)"
|
||||||
type: step
|
type: step
|
||||||
dir: 3D
|
dir: 3D
|
||||||
options:
|
options:
|
||||||
metric_units: true
|
metric_units: true
|
||||||
origin: 85,66.2
|
origin: 85,66.2
|
||||||
|
|
||||||
# Gerber and drill files for PCBWay, with stencil (solder paste)
|
# Gerber and drill files for PCBWay, with stencil (solder paste)
|
||||||
# URL: https://www.pcbway.com
|
# URL: https://www.pcbway.com
|
||||||
# Based on setting used by Gerber Zipper (https://github.com/g200kg/kicad-gerberzipper)
|
# Based on setting used by Gerber Zipper (https://github.com/g200kg/kicad-gerberzipper)
|
||||||
- name: PCBWay_gerbers
|
- name: PCBWay_gerbers
|
||||||
comment: Gerbers compatible with PCBWay
|
comment: Gerbers compatible with PCBWay
|
||||||
type: gerber
|
type: gerber
|
||||||
dir: PCBWay
|
dir: PCBWay
|
||||||
options: &gerber_options
|
options: &gerber_options
|
||||||
exclude_edge_layer: true
|
exclude_edge_layer: true
|
||||||
exclude_pads_from_silkscreen: true
|
exclude_pads_from_silkscreen: true
|
||||||
plot_sheet_reference: false
|
plot_sheet_reference: false
|
||||||
plot_footprint_refs: true
|
plot_footprint_refs: true
|
||||||
plot_footprint_values: true
|
plot_footprint_values: true
|
||||||
force_plot_invisible_refs_vals: false
|
force_plot_invisible_refs_vals: false
|
||||||
tent_vias: true
|
tent_vias: true
|
||||||
use_protel_extensions: true
|
use_protel_extensions: true
|
||||||
create_gerber_job_file: false
|
create_gerber_job_file: false
|
||||||
output: "%f.%x"
|
output: "%f.%x"
|
||||||
gerber_precision: 4.6
|
gerber_precision: 4.6
|
||||||
use_gerber_x2_attributes: false
|
use_gerber_x2_attributes: false
|
||||||
use_gerber_net_attributes: false
|
use_gerber_net_attributes: false
|
||||||
disable_aperture_macros: true
|
disable_aperture_macros: true
|
||||||
line_width: 0.1
|
line_width: 0.1
|
||||||
subtract_mask_from_silk: false
|
subtract_mask_from_silk: false
|
||||||
inner_extension_pattern: '.gl%N'
|
inner_extension_pattern: '.gl%N'
|
||||||
layers:
|
layers:
|
||||||
- 'selected'
|
- 'selected'
|
||||||
|
|
||||||
- name: PCBWay_drill
|
- name: PCBWay_drill
|
||||||
comment: Drill files compatible with PCBWay
|
comment: Drill files compatible with PCBWay
|
||||||
type: excellon
|
type: excellon
|
||||||
dir: PCBWay
|
dir: PCBWay
|
||||||
options:
|
options:
|
||||||
metric_units: false
|
metric_units: false
|
||||||
minimal_header: true
|
minimal_header: true
|
||||||
zeros_format: SUPPRESS_LEADING
|
zeros_format: SUPPRESS_LEADING
|
||||||
# left_digits: 3
|
# left_digits: 3
|
||||||
# right_digits: 3
|
# right_digits: 3
|
||||||
# See https://github.com/INTI-CMNB/kicad-ci-test-spora/issues/1
|
# See https://github.com/INTI-CMNB/kicad-ci-test-spora/issues/1
|
||||||
# and https://docs.oshpark.com/design-tools/gerbv/fix-drill-format/
|
# and https://docs.oshpark.com/design-tools/gerbv/fix-drill-format/
|
||||||
left_digits: 2
|
left_digits: 2
|
||||||
right_digits: 4
|
right_digits: 4
|
||||||
pth_and_npth_single_file: false
|
pth_and_npth_single_file: false
|
||||||
pth_id: ''
|
pth_id: ''
|
||||||
npth_id: '-NPTH'
|
npth_id: '-NPTH'
|
||||||
output: "%f%i.drl"
|
output: "%f%i.drl"
|
||||||
|
|
||||||
- name: PCBWay
|
- name: PCBWay
|
||||||
comment: ZIP file for PCBWay
|
comment: ZIP file for PCBWay
|
||||||
type: compress
|
type: compress
|
||||||
dir: PCBWay
|
dir: PCBWay
|
||||||
options:
|
options:
|
||||||
format: ZIP
|
format: ZIP
|
||||||
files:
|
files:
|
||||||
- from_output: PCBWay_gerbers
|
- from_output: PCBWay_gerbers
|
||||||
dest: /
|
dest: /
|
||||||
- from_output: PCBWay_drill
|
- from_output: PCBWay_drill
|
||||||
dest: /
|
dest: /
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
## Описание директорий и файлов
|
## Описание директорий и файлов
|
||||||
|
|
||||||
```[motor]
|
```[motor]
|
||||||
├── parts/ # Детали моторов
|
├── parts/ # Детали моторов
|
||||||
│ ├── 53mm/ # Детали для 53мм мотора с пластиковым ротором
|
│ ├── 53mm/ # Детали для 53мм мотора с пластиковым ротором
|
||||||
│ ├── 53mm_metal/ # Детали для 53мм мотора с металлическим ротором
|
│ ├── 53mm_metal/ # Детали для 53мм мотора с металлическим ротором
|
||||||
│ ├── 72mm/ # Детали для 72мм мотора с пластиковым ротором
|
│ ├── 72mm/ # Детали для 72мм мотора с пластиковым ротором
|
||||||
│ ├── 72mm_metal/ # Детали для 72мм мотора с металлическим ротором
|
│ ├── 72mm_metal/ # Детали для 72мм мотора с металлическим ротором
|
||||||
│ ├── magnetic_parts_dxf/ # Файлы для лазерной резки деталей металлических статоров
|
│ ├── magnetic_parts_dxf/ # Файлы для лазерной резки деталей металлических статоров
|
||||||
│ └── сommon_parts/ # Детали общие для разных моторов
|
│ └── сommon_parts/ # Детали общие для разных моторов
|
||||||
├── _asm_53mm_metall_motor.SLDASM # Сборка мотора 53мм с металлическим ротором
|
├── _asm_53mm_metall_motor.SLDASM # Сборка мотора 53мм с металлическим ротором
|
||||||
├── _asm_53mm_motor.SLDASM # Сборка мотора 53мм с пластиковым ротором
|
├── _asm_53mm_motor.SLDASM # Сборка мотора 53мм с пластиковым ротором
|
||||||
├── _asm_72mm_metall_motor.SLDASM # Сборка мотора 72мм с металлическим ротором
|
├── _asm_72mm_metall_motor.SLDASM # Сборка мотора 72мм с металлическим ротором
|
||||||
└── _asm_72mm_motor.SLDASM # Сборка мотора 72мм с пластиковым ротором
|
└── _asm_72mm_motor.SLDASM # Сборка мотора 72мм с пластиковым ротором
|
||||||
```
|
```
|
||||||
|
|
||||||
Важно, что каждая сборка использует файлы из разных папок.
|
Важно, что каждая сборка использует файлы из разных папок.
|
||||||
Поэтому, для открытия, необходимо скачать все папки.
|
Поэтому, для открытия, необходимо скачать все папки.
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
||||||
# Модели редукторов для двигателя
|
# Модели редукторов для двигателя
|
||||||
|
|
||||||
```[reducer]
|
```[reducer]
|
||||||
├── PREC/ # Прецессирующий редуктор
|
├── PREC/ # Прецессирующий редуктор
|
||||||
└── WAVE/ # Волновой редуктор с телами промежуточного качения
|
└── WAVE/ # Волновой редуктор с телами промежуточного качения
|
||||||
```
|
```
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -1,342 +1,342 @@
|
||||||
ISO-10303-21;
|
ISO-10303-21;
|
||||||
HEADER;
|
HEADER;
|
||||||
FILE_DESCRIPTION (( 'STEP AP203' ),
|
FILE_DESCRIPTION (( 'STEP AP203' ),
|
||||||
'1' );
|
'1' );
|
||||||
FILE_NAME ('spacer_241007.STEP',
|
FILE_NAME ('spacer_241007.STEP',
|
||||||
'2024-12-12T07:56:01',
|
'2024-12-12T07:56:01',
|
||||||
( '' ),
|
( '' ),
|
||||||
( '' ),
|
( '' ),
|
||||||
'SwSTEP 2.0',
|
'SwSTEP 2.0',
|
||||||
'SolidWorks 2022',
|
'SolidWorks 2022',
|
||||||
'' );
|
'' );
|
||||||
FILE_SCHEMA (( 'CONFIG_CONTROL_DESIGN' ));
|
FILE_SCHEMA (( 'CONFIG_CONTROL_DESIGN' ));
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
|
|
||||||
DATA;
|
DATA;
|
||||||
#1 = CARTESIAN_POINT ( 'NONE', ( -8.500000000000000000, 7.000000000000000000, -13.50000000000000178 ) ) ;
|
#1 = CARTESIAN_POINT ( 'NONE', ( -8.500000000000000000, 7.000000000000000000, -13.50000000000000178 ) ) ;
|
||||||
#2 = EDGE_CURVE ( 'NONE', #23, #42, #141, .T. ) ;
|
#2 = EDGE_CURVE ( 'NONE', #23, #42, #141, .T. ) ;
|
||||||
#3 = MANIFOLD_SOLID_BREP ( '??????????1', #100 ) ;
|
#3 = MANIFOLD_SOLID_BREP ( '??????????1', #100 ) ;
|
||||||
#4 = CARTESIAN_POINT ( 'NONE', ( 1.004210375300829674E-15, 4.660000000000000142, -7.900000000000000355 ) ) ;
|
#4 = CARTESIAN_POINT ( 'NONE', ( 1.004210375300829674E-15, 4.660000000000000142, -7.900000000000000355 ) ) ;
|
||||||
#5 = DESIGN_CONTEXT ( 'detailed design', #287, 'design' ) ;
|
#5 = DESIGN_CONTEXT ( 'detailed design', #287, 'design' ) ;
|
||||||
#6 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#6 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#7 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #284 ) ;
|
#7 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #284 ) ;
|
||||||
#8 = LINE ( 'NONE', #192, #119 ) ;
|
#8 = LINE ( 'NONE', #192, #119 ) ;
|
||||||
#9 = FACE_OUTER_BOUND ( 'NONE', #134, .T. ) ;
|
#9 = FACE_OUTER_BOUND ( 'NONE', #134, .T. ) ;
|
||||||
#10 = MECHANICAL_CONTEXT ( 'NONE', #200, 'mechanical' ) ;
|
#10 = MECHANICAL_CONTEXT ( 'NONE', #200, 'mechanical' ) ;
|
||||||
#11 = EDGE_LOOP ( 'NONE', ( #247, #267, #38, #207 ) ) ;
|
#11 = EDGE_LOOP ( 'NONE', ( #247, #267, #38, #207 ) ) ;
|
||||||
#12 = CIRCLE ( 'NONE', #109, 8.500000000000000000 ) ;
|
#12 = CIRCLE ( 'NONE', #109, 8.500000000000000000 ) ;
|
||||||
#13 = APPLICATION_PROTOCOL_DEFINITION ( 'international standard', 'config_control_design', 1994, #200 ) ;
|
#13 = APPLICATION_PROTOCOL_DEFINITION ( 'international standard', 'config_control_design', 1994, #200 ) ;
|
||||||
#14 = ORIENTED_EDGE ( 'NONE', *, *, #133, .T. ) ;
|
#14 = ORIENTED_EDGE ( 'NONE', *, *, #133, .T. ) ;
|
||||||
#15 = DATE_AND_TIME ( #36, #7 ) ;
|
#15 = DATE_AND_TIME ( #36, #7 ) ;
|
||||||
#16 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, -8.500000000000000000 ) ) ;
|
#16 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, -8.500000000000000000 ) ) ;
|
||||||
#17 = SECURITY_CLASSIFICATION_LEVEL ( 'unclassified' ) ;
|
#17 = SECURITY_CLASSIFICATION_LEVEL ( 'unclassified' ) ;
|
||||||
#18 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, -4.549999999999999822 ) ) ;
|
#18 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, -4.549999999999999822 ) ) ;
|
||||||
#19 = EDGE_CURVE ( 'NONE', #266, #264, #294, .T. ) ;
|
#19 = EDGE_CURVE ( 'NONE', #266, #264, #294, .T. ) ;
|
||||||
#20 = APPROVAL_DATE_TIME ( #265, #49 ) ;
|
#20 = APPROVAL_DATE_TIME ( #265, #49 ) ;
|
||||||
#21 = ORIENTED_EDGE ( 'NONE', *, *, #108, .T. ) ;
|
#21 = ORIENTED_EDGE ( 'NONE', *, *, #108, .T. ) ;
|
||||||
#22 = APPROVAL_DATE_TIME ( #93, #112 ) ;
|
#22 = APPROVAL_DATE_TIME ( #93, #112 ) ;
|
||||||
#23 = VERTEX_POINT ( 'NONE', #244 ) ;
|
#23 = VERTEX_POINT ( 'NONE', #244 ) ;
|
||||||
#24 = ORIENTED_EDGE ( 'NONE', *, *, #19, .F. ) ;
|
#24 = ORIENTED_EDGE ( 'NONE', *, *, #19, .F. ) ;
|
||||||
#25 = CIRCLE ( 'NONE', #114, 7.900000000000000355 ) ;
|
#25 = CIRCLE ( 'NONE', #114, 7.900000000000000355 ) ;
|
||||||
#26 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
#26 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#27 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 6.256346360029705345, 4.549999999999999822 ) ) ;
|
#27 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 6.256346360029705345, 4.549999999999999822 ) ) ;
|
||||||
#28 = DIRECTION ( 'NONE', ( 1.000000000000000000, 0.000000000000000000, 1.224646799147353207E-16 ) ) ;
|
#28 = DIRECTION ( 'NONE', ( 1.000000000000000000, 0.000000000000000000, 1.224646799147353207E-16 ) ) ;
|
||||||
#29 = AXIS2_PLACEMENT_3D ( 'NONE', #230, #28, #184 ) ;
|
#29 = AXIS2_PLACEMENT_3D ( 'NONE', #230, #28, #184 ) ;
|
||||||
#30 = DIRECTION ( 'NONE', ( 0.9961946980917461003, -0.08715574274765133800, 0.000000000000000000 ) ) ;
|
#30 = DIRECTION ( 'NONE', ( 0.9961946980917461003, -0.08715574274765133800, 0.000000000000000000 ) ) ;
|
||||||
#31 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -4.549999999999999822 ) ) ;
|
#31 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -4.549999999999999822 ) ) ;
|
||||||
#32 = APPROVAL_ROLE ( '' ) ;
|
#32 = APPROVAL_ROLE ( '' ) ;
|
||||||
#33 = ORIENTED_EDGE ( 'NONE', *, *, #189, .T. ) ;
|
#33 = ORIENTED_EDGE ( 'NONE', *, *, #189, .T. ) ;
|
||||||
#34 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#34 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#35 =( NAMED_UNIT ( * ) SI_UNIT ( $, .STERADIAN. ) SOLID_ANGLE_UNIT ( ) );
|
#35 =( NAMED_UNIT ( * ) SI_UNIT ( $, .STERADIAN. ) SOLID_ANGLE_UNIT ( ) );
|
||||||
#36 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
#36 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
||||||
#37 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#37 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#38 = ORIENTED_EDGE ( 'NONE', *, *, #260, .F. ) ;
|
#38 = ORIENTED_EDGE ( 'NONE', *, *, #260, .F. ) ;
|
||||||
#39 = FACE_OUTER_BOUND ( 'NONE', #11, .T. ) ;
|
#39 = FACE_OUTER_BOUND ( 'NONE', #11, .T. ) ;
|
||||||
#40 = CIRCLE ( 'NONE', #253, 8.500000000000000000 ) ;
|
#40 = CIRCLE ( 'NONE', #253, 8.500000000000000000 ) ;
|
||||||
#41 = ORIENTED_EDGE ( 'NONE', *, *, #2, .F. ) ;
|
#41 = ORIENTED_EDGE ( 'NONE', *, *, #2, .F. ) ;
|
||||||
#42 = VERTEX_POINT ( 'NONE', #16 ) ;
|
#42 = VERTEX_POINT ( 'NONE', #16 ) ;
|
||||||
#43 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#43 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#44 = ADVANCED_FACE ( 'NONE', ( #39 ), #254, .T. ) ;
|
#44 = ADVANCED_FACE ( 'NONE', ( #39 ), #254, .T. ) ;
|
||||||
#45 = CARTESIAN_POINT ( 'NONE', ( 16.99999999999999645, 4.769039080089115146, 8.499999999999998224 ) ) ;
|
#45 = CARTESIAN_POINT ( 'NONE', ( 16.99999999999999645, 4.769039080089115146, 8.499999999999998224 ) ) ;
|
||||||
#46 = CC_DESIGN_APPROVAL ( #112, ( #238 ) ) ;
|
#46 = CC_DESIGN_APPROVAL ( #112, ( #238 ) ) ;
|
||||||
#47 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #211, #51, #167, #299 ),
|
#47 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #211, #51, #167, #299 ),
|
||||||
.UNSPECIFIED., .F., .T. )
|
.UNSPECIFIED., .F., .T. )
|
||||||
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
||||||
( 1.570796326794896558, 4.712388980384689674 ),
|
( 1.570796326794896558, 4.712388980384689674 ),
|
||||||
.UNSPECIFIED. )
|
.UNSPECIFIED. )
|
||||||
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
||||||
REPRESENTATION_ITEM ( '' ) );
|
REPRESENTATION_ITEM ( '' ) );
|
||||||
#48 = DIRECTION ( 'NONE', ( 0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#48 = DIRECTION ( 'NONE', ( 0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#49 = APPROVAL ( #179, 'UNSPECIFIED' ) ;
|
#49 = APPROVAL ( #179, 'UNSPECIFIED' ) ;
|
||||||
#50 = DIRECTION ( 'NONE', ( -0.08715574274765133800, -0.9961946980917461003, 0.000000000000000000 ) ) ;
|
#50 = DIRECTION ( 'NONE', ( -0.08715574274765133800, -0.9961946980917461003, 0.000000000000000000 ) ) ;
|
||||||
#51 = CARTESIAN_POINT ( 'NONE', ( -16.99999999999999645, 7.743653639970296432, 8.500000000000001776 ) ) ;
|
#51 = CARTESIAN_POINT ( 'NONE', ( -16.99999999999999645, 7.743653639970296432, 8.500000000000001776 ) ) ;
|
||||||
#52 = VECTOR ( 'NONE', #94, 1000.000000000000000 ) ;
|
#52 = VECTOR ( 'NONE', #94, 1000.000000000000000 ) ;
|
||||||
#53 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 7.900000000000000355 ) ) ;
|
#53 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 7.900000000000000355 ) ) ;
|
||||||
#54 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#54 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#55 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #135, #62, ( #238 ) ) ;
|
#55 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #135, #62, ( #238 ) ) ;
|
||||||
#56 = APPLICATION_PROTOCOL_DEFINITION ( 'international standard', 'config_control_design', 1994, #287 ) ;
|
#56 = APPLICATION_PROTOCOL_DEFINITION ( 'international standard', 'config_control_design', 1994, #287 ) ;
|
||||||
#57 = AXIS2_PLACEMENT_3D ( 'NONE', #97, #80, #169 ) ;
|
#57 = AXIS2_PLACEMENT_3D ( 'NONE', #97, #80, #169 ) ;
|
||||||
#58 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #210, #191, #273, #120 ),
|
#58 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #210, #191, #273, #120 ),
|
||||||
.UNSPECIFIED., .F., .T. )
|
.UNSPECIFIED., .F., .T. )
|
||||||
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
||||||
( 4.712388980384689674, 7.853981633974482790 ),
|
( 4.712388980384689674, 7.853981633974482790 ),
|
||||||
.UNSPECIFIED. )
|
.UNSPECIFIED. )
|
||||||
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
||||||
REPRESENTATION_ITEM ( '' ) );
|
REPRESENTATION_ITEM ( '' ) );
|
||||||
#59 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#59 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#60 = APPROVAL_DATE_TIME ( #214, #164 ) ;
|
#60 = APPROVAL_DATE_TIME ( #214, #164 ) ;
|
||||||
#61 = SECURITY_CLASSIFICATION ( '', '', #17 ) ;
|
#61 = SECURITY_CLASSIFICATION ( '', '', #17 ) ;
|
||||||
#62 = PERSON_AND_ORGANIZATION_ROLE ( 'design_supplier' ) ;
|
#62 = PERSON_AND_ORGANIZATION_ROLE ( 'design_supplier' ) ;
|
||||||
#63 = ORIENTED_EDGE ( 'NONE', *, *, #145, .T. ) ;
|
#63 = ORIENTED_EDGE ( 'NONE', *, *, #145, .T. ) ;
|
||||||
#64 = EDGE_LOOP ( 'NONE', ( #205, #158, #290, #67 ) ) ;
|
#64 = EDGE_LOOP ( 'NONE', ( #205, #158, #290, #67 ) ) ;
|
||||||
#65 = ADVANCED_FACE ( 'NONE', ( #182 ), #142, .F. ) ;
|
#65 = ADVANCED_FACE ( 'NONE', ( #182 ), #142, .F. ) ;
|
||||||
#66 = DATE_TIME_ROLE ( 'classification_date' ) ;
|
#66 = DATE_TIME_ROLE ( 'classification_date' ) ;
|
||||||
#67 = ORIENTED_EDGE ( 'NONE', *, *, #83, .F. ) ;
|
#67 = ORIENTED_EDGE ( 'NONE', *, *, #83, .F. ) ;
|
||||||
#68 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #242 ) ;
|
#68 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #242 ) ;
|
||||||
#69 = ORIENTED_EDGE ( 'NONE', *, *, #155, .T. ) ;
|
#69 = ORIENTED_EDGE ( 'NONE', *, *, #155, .T. ) ;
|
||||||
#70 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #252, #166, #45, #190 ),
|
#70 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #252, #166, #45, #190 ),
|
||||||
.UNSPECIFIED., .F., .T. )
|
.UNSPECIFIED., .F., .T. )
|
||||||
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
||||||
( 4.712388980384689674, 7.853981633974482790 ),
|
( 4.712388980384689674, 7.853981633974482790 ),
|
||||||
.UNSPECIFIED. )
|
.UNSPECIFIED. )
|
||||||
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
||||||
REPRESENTATION_ITEM ( '' ) );
|
REPRESENTATION_ITEM ( '' ) );
|
||||||
#71 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
#71 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
||||||
#72 = ORIENTED_EDGE ( 'NONE', *, *, #260, .T. ) ;
|
#72 = ORIENTED_EDGE ( 'NONE', *, *, #260, .T. ) ;
|
||||||
#73 = PRODUCT_DEFINITION ( 'UNKNOWN', '', #238, #5 ) ;
|
#73 = PRODUCT_DEFINITION ( 'UNKNOWN', '', #238, #5 ) ;
|
||||||
#74 = LINE ( 'NONE', #188, #105 ) ;
|
#74 = LINE ( 'NONE', #188, #105 ) ;
|
||||||
#75 = FACE_BOUND ( 'NONE', #218, .T. ) ;
|
#75 = FACE_BOUND ( 'NONE', #218, .T. ) ;
|
||||||
#76 = AXIS2_PLACEMENT_3D ( 'NONE', #124, #276, #168 ) ;
|
#76 = AXIS2_PLACEMENT_3D ( 'NONE', #124, #276, #168 ) ;
|
||||||
#77 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #6, #82, ( #229 ) ) ;
|
#77 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #6, #82, ( #229 ) ) ;
|
||||||
#78 = PLANE ( 'NONE', #152 ) ;
|
#78 = PLANE ( 'NONE', #152 ) ;
|
||||||
#79 = CYLINDRICAL_SURFACE ( 'NONE', #165, 8.500000000000000000 ) ;
|
#79 = CYLINDRICAL_SURFACE ( 'NONE', #165, 8.500000000000000000 ) ;
|
||||||
#80 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#80 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#81 = AXIS2_PLACEMENT_3D ( 'NONE', #53, #257, #297 ) ;
|
#81 = AXIS2_PLACEMENT_3D ( 'NONE', #53, #257, #297 ) ;
|
||||||
#82 = PERSON_AND_ORGANIZATION_ROLE ( 'design_owner' ) ;
|
#82 = PERSON_AND_ORGANIZATION_ROLE ( 'design_owner' ) ;
|
||||||
#83 = EDGE_CURVE ( 'NONE', #292, #264, #261, .T. ) ;
|
#83 = EDGE_CURVE ( 'NONE', #292, #264, #261, .T. ) ;
|
||||||
#84 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
#84 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#85 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
#85 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#86 = PERSON ( 'UNSPECIFIED', 'UNSPECIFIED', 'UNSPECIFIED', ('UNSPECIFIED'), ('UNSPECIFIED'), ('UNSPECIFIED') ) ;
|
#86 = PERSON ( 'UNSPECIFIED', 'UNSPECIFIED', 'UNSPECIFIED', ('UNSPECIFIED'), ('UNSPECIFIED'), ('UNSPECIFIED') ) ;
|
||||||
#87 = ORIENTED_EDGE ( 'NONE', *, *, #133, .F. ) ;
|
#87 = ORIENTED_EDGE ( 'NONE', *, *, #133, .F. ) ;
|
||||||
#88 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #291 ) ;
|
#88 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #291 ) ;
|
||||||
#89 = AXIS2_PLACEMENT_3D ( 'NONE', #150, #231, #212 ) ;
|
#89 = AXIS2_PLACEMENT_3D ( 'NONE', #150, #231, #212 ) ;
|
||||||
#90 = ORIENTED_EDGE ( 'NONE', *, *, #235, .F. ) ;
|
#90 = ORIENTED_EDGE ( 'NONE', *, *, #235, .F. ) ;
|
||||||
#91 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #194, #174, ( #73 ) ) ;
|
#91 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #194, #174, ( #73 ) ) ;
|
||||||
#92 = ORIENTED_EDGE ( 'NONE', *, *, #256, .T. ) ;
|
#92 = ORIENTED_EDGE ( 'NONE', *, *, #256, .T. ) ;
|
||||||
#93 = DATE_AND_TIME ( #157, #88 ) ;
|
#93 = DATE_AND_TIME ( #157, #88 ) ;
|
||||||
#94 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#94 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#95 = CC_DESIGN_APPROVAL ( #164, ( #73 ) ) ;
|
#95 = CC_DESIGN_APPROVAL ( #164, ( #73 ) ) ;
|
||||||
#96 = VERTEX_POINT ( 'NONE', #101 ) ;
|
#96 = VERTEX_POINT ( 'NONE', #101 ) ;
|
||||||
#97 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
#97 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#98 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#98 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#99 = FACE_OUTER_BOUND ( 'NONE', #178, .T. ) ;
|
#99 = FACE_OUTER_BOUND ( 'NONE', #178, .T. ) ;
|
||||||
#100 = CLOSED_SHELL ( 'NONE', ( #44, #123, #277, #65, #185, #250, #172, #285 ) ) ;
|
#100 = CLOSED_SHELL ( 'NONE', ( #44, #123, #277, #65, #185, #250, #172, #285 ) ) ;
|
||||||
#101 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 6.256346360029705345, 8.500000000000000000 ) ) ;
|
#101 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 6.256346360029705345, 8.500000000000000000 ) ) ;
|
||||||
#102 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#102 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#103 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
#103 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
||||||
#104 = UNCERTAINTY_MEASURE_WITH_UNIT (LENGTH_MEASURE( 1.000000000000000082E-05 ), #195, 'distance_accuracy_value', 'NONE');
|
#104 = UNCERTAINTY_MEASURE_WITH_UNIT (LENGTH_MEASURE( 1.000000000000000082E-05 ), #195, 'distance_accuracy_value', 'NONE');
|
||||||
#105 = VECTOR ( 'NONE', #233, 1000.000000000000000 ) ;
|
#105 = VECTOR ( 'NONE', #233, 1000.000000000000000 ) ;
|
||||||
#106 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 4.660000000000000142, 4.549999999999999822 ) ) ;
|
#106 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 4.660000000000000142, 4.549999999999999822 ) ) ;
|
||||||
#107 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
#107 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
||||||
#108 = EDGE_CURVE ( 'NONE', #264, #292, #208, .T. ) ;
|
#108 = EDGE_CURVE ( 'NONE', #264, #292, #208, .T. ) ;
|
||||||
#109 = AXIS2_PLACEMENT_3D ( 'NONE', #103, #85, #175 ) ;
|
#109 = AXIS2_PLACEMENT_3D ( 'NONE', #103, #85, #175 ) ;
|
||||||
#110 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
#110 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
||||||
#111 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#111 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#112 = APPROVAL ( #222, 'UNSPECIFIED' ) ;
|
#112 = APPROVAL ( #222, 'UNSPECIFIED' ) ;
|
||||||
#113 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
#113 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#114 = AXIS2_PLACEMENT_3D ( 'NONE', #234, #209, #228 ) ;
|
#114 = AXIS2_PLACEMENT_3D ( 'NONE', #234, #209, #228 ) ;
|
||||||
#115 = ORIENTED_EDGE ( 'NONE', *, *, #83, .T. ) ;
|
#115 = ORIENTED_EDGE ( 'NONE', *, *, #83, .T. ) ;
|
||||||
#116 = ORIENTED_EDGE ( 'NONE', *, *, #197, .F. ) ;
|
#116 = ORIENTED_EDGE ( 'NONE', *, *, #197, .F. ) ;
|
||||||
#117 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#117 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#118 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#118 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#119 = VECTOR ( 'NONE', #262, 1000.000000000000000 ) ;
|
#119 = VECTOR ( 'NONE', #262, 1000.000000000000000 ) ;
|
||||||
#120 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 6.256346360029705345, 4.549999999999999822 ) ) ;
|
#120 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 6.256346360029705345, 4.549999999999999822 ) ) ;
|
||||||
#121 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
#121 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
||||||
#122 = FACE_BOUND ( 'NONE', #215, .T. ) ;
|
#122 = FACE_BOUND ( 'NONE', #215, .T. ) ;
|
||||||
#123 = ADVANCED_FACE ( 'NONE', ( #144 ), #79, .T. ) ;
|
#123 = ADVANCED_FACE ( 'NONE', ( #144 ), #79, .T. ) ;
|
||||||
#124 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
#124 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
||||||
#125 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
#125 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
||||||
#126 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
#126 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#127 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
#127 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
||||||
#128 = AXIS2_PLACEMENT_3D ( 'NONE', #110, #126, #153 ) ;
|
#128 = AXIS2_PLACEMENT_3D ( 'NONE', #110, #126, #153 ) ;
|
||||||
#129 = CARTESIAN_POINT ( 'NONE', ( -9.099999999999997868, 7.052493198115552531, -4.549999999999998934 ) ) ;
|
#129 = CARTESIAN_POINT ( 'NONE', ( -9.099999999999997868, 7.052493198115552531, -4.549999999999998934 ) ) ;
|
||||||
#130 = FACE_OUTER_BOUND ( 'NONE', #138, .T. ) ;
|
#130 = FACE_OUTER_BOUND ( 'NONE', #138, .T. ) ;
|
||||||
#131 = APPROVAL_PERSON_ORGANIZATION ( #117, #49, #201 ) ;
|
#131 = APPROVAL_PERSON_ORGANIZATION ( #117, #49, #201 ) ;
|
||||||
#132 = EDGE_LOOP ( 'NONE', ( #202, #295, #72, #41 ) ) ;
|
#132 = EDGE_LOOP ( 'NONE', ( #202, #295, #72, #41 ) ) ;
|
||||||
#133 = EDGE_CURVE ( 'NONE', #96, #23, #47, .T. ) ;
|
#133 = EDGE_CURVE ( 'NONE', #96, #23, #47, .T. ) ;
|
||||||
#134 = EDGE_LOOP ( 'NONE', ( #286, #249, #159, #24 ) ) ;
|
#134 = EDGE_LOOP ( 'NONE', ( #286, #249, #159, #24 ) ) ;
|
||||||
#135 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#135 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#136 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
#136 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 5.259999999999999787, 0.000000000000000000 ) ) ;
|
||||||
#137 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
#137 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
||||||
#138 = EDGE_LOOP ( 'NONE', ( #116, #246, #69, #180 ) ) ;
|
#138 = EDGE_LOOP ( 'NONE', ( #116, #246, #69, #180 ) ) ;
|
||||||
#139 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #37, #161, ( #238 ) ) ;
|
#139 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #37, #161, ( #238 ) ) ;
|
||||||
#140 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#140 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#141 = LINE ( 'NONE', #251, #301 ) ;
|
#141 = LINE ( 'NONE', #251, #301 ) ;
|
||||||
#142 = CYLINDRICAL_SURFACE ( 'NONE', #232, 4.549999999999999822 ) ;
|
#142 = CYLINDRICAL_SURFACE ( 'NONE', #232, 4.549999999999999822 ) ;
|
||||||
#143 = TOROIDAL_SURFACE ( 'NONE', #128, 7.900000000000000355, 0.5999999999999999778 ) ;
|
#143 = TOROIDAL_SURFACE ( 'NONE', #128, 7.900000000000000355, 0.5999999999999999778 ) ;
|
||||||
#144 = FACE_OUTER_BOUND ( 'NONE', #132, .T. ) ;
|
#144 = FACE_OUTER_BOUND ( 'NONE', #132, .T. ) ;
|
||||||
#145 = EDGE_CURVE ( 'NONE', #266, #162, #58, .T. ) ;
|
#145 = EDGE_CURVE ( 'NONE', #266, #162, #58, .T. ) ;
|
||||||
#146 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#146 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#147 = PLANE ( 'NONE', #89 ) ;
|
#147 = PLANE ( 'NONE', #89 ) ;
|
||||||
#148 = AXIS2_PLACEMENT_3D ( 'NONE', #121, #296, #102 ) ;
|
#148 = AXIS2_PLACEMENT_3D ( 'NONE', #121, #296, #102 ) ;
|
||||||
#149 = CC_DESIGN_DATE_AND_TIME_ASSIGNMENT ( #270, #66, ( #61 ) ) ;
|
#149 = CC_DESIGN_DATE_AND_TIME_ASSIGNMENT ( #270, #66, ( #61 ) ) ;
|
||||||
#150 = CARTESIAN_POINT ( 'NONE', ( -8.500000000000000000, 4.660000000000000142, -13.50000000000000178 ) ) ;
|
#150 = CARTESIAN_POINT ( 'NONE', ( -8.500000000000000000, 4.660000000000000142, -13.50000000000000178 ) ) ;
|
||||||
#151 = DIRECTION ( 'NONE', ( 1.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
|
#151 = DIRECTION ( 'NONE', ( 1.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#152 = AXIS2_PLACEMENT_3D ( 'NONE', #1, #50, #30 ) ;
|
#152 = AXIS2_PLACEMENT_3D ( 'NONE', #1, #50, #30 ) ;
|
||||||
#153 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#153 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#154 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, -4.549999999999999822 ) ) ;
|
#154 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, -4.549999999999999822 ) ) ;
|
||||||
#155 = EDGE_CURVE ( 'NONE', #237, #268, #170, .T. ) ;
|
#155 = EDGE_CURVE ( 'NONE', #237, #268, #170, .T. ) ;
|
||||||
#156 = CC_DESIGN_SECURITY_CLASSIFICATION ( #61, ( #238 ) ) ;
|
#156 = CC_DESIGN_SECURITY_CLASSIFICATION ( #61, ( #238 ) ) ;
|
||||||
#157 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
#157 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
||||||
#158 = ORIENTED_EDGE ( 'NONE', *, *, #145, .F. ) ;
|
#158 = ORIENTED_EDGE ( 'NONE', *, *, #145, .F. ) ;
|
||||||
#159 = ORIENTED_EDGE ( 'NONE', *, *, #108, .F. ) ;
|
#159 = ORIENTED_EDGE ( 'NONE', *, *, #108, .F. ) ;
|
||||||
#160 = VERTEX_POINT ( 'NONE', #4 ) ;
|
#160 = VERTEX_POINT ( 'NONE', #4 ) ;
|
||||||
#161 = PERSON_AND_ORGANIZATION_ROLE ( 'creator' ) ;
|
#161 = PERSON_AND_ORGANIZATION_ROLE ( 'creator' ) ;
|
||||||
#162 = VERTEX_POINT ( 'NONE', #27 ) ;
|
#162 = VERTEX_POINT ( 'NONE', #27 ) ;
|
||||||
#163 = EDGE_LOOP ( 'NONE', ( #226, #33 ) ) ;
|
#163 = EDGE_LOOP ( 'NONE', ( #226, #33 ) ) ;
|
||||||
#164 = APPROVAL ( #283, 'UNSPECIFIED' ) ;
|
#164 = APPROVAL ( #283, 'UNSPECIFIED' ) ;
|
||||||
#165 = AXIS2_PLACEMENT_3D ( 'NONE', #26, #98, #272 ) ;
|
#165 = AXIS2_PLACEMENT_3D ( 'NONE', #26, #98, #272 ) ;
|
||||||
#166 = CARTESIAN_POINT ( 'NONE', ( 16.99999999999999645, 4.769039080089115146, -8.500000000000003553 ) ) ;
|
#166 = CARTESIAN_POINT ( 'NONE', ( 16.99999999999999645, 4.769039080089115146, -8.500000000000003553 ) ) ;
|
||||||
#167 = CARTESIAN_POINT ( 'NONE', ( -16.99999999999999645, 7.743653639970296432, -8.499999999999996447 ) ) ;
|
#167 = CARTESIAN_POINT ( 'NONE', ( -16.99999999999999645, 7.743653639970296432, -8.499999999999996447 ) ) ;
|
||||||
#168 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#168 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#169 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
#169 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
||||||
#170 = CIRCLE ( 'NONE', #81, 0.5999999999999998668 ) ;
|
#170 = CIRCLE ( 'NONE', #81, 0.5999999999999998668 ) ;
|
||||||
#171 = CARTESIAN_POINT ( 'NONE', ( -9.099999999999997868, 7.052493198115552531, 4.550000000000000711 ) ) ;
|
#171 = CARTESIAN_POINT ( 'NONE', ( -9.099999999999997868, 7.052493198115552531, 4.550000000000000711 ) ) ;
|
||||||
#172 = ADVANCED_FACE ( 'NONE', ( #278 ), #186, .T. ) ;
|
#172 = ADVANCED_FACE ( 'NONE', ( #278 ), #186, .T. ) ;
|
||||||
#173 = CIRCLE ( 'NONE', #29, 0.5999999999999998668 ) ;
|
#173 = CIRCLE ( 'NONE', #29, 0.5999999999999998668 ) ;
|
||||||
#174 = PERSON_AND_ORGANIZATION_ROLE ( 'creator' ) ;
|
#174 = PERSON_AND_ORGANIZATION_ROLE ( 'creator' ) ;
|
||||||
#175 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#175 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#176 = ORIENTED_EDGE ( 'NONE', *, *, #293, .T. ) ;
|
#176 = ORIENTED_EDGE ( 'NONE', *, *, #293, .T. ) ;
|
||||||
#177 = AXIS2_PLACEMENT_3D ( 'NONE', #198, #54, #151 ) ;
|
#177 = AXIS2_PLACEMENT_3D ( 'NONE', #198, #54, #151 ) ;
|
||||||
#178 = EDGE_LOOP ( 'NONE', ( #223, #87 ) ) ;
|
#178 = EDGE_LOOP ( 'NONE', ( #223, #87 ) ) ;
|
||||||
#179 = APPROVAL_STATUS ( 'not_yet_approved' ) ;
|
#179 = APPROVAL_STATUS ( 'not_yet_approved' ) ;
|
||||||
#180 = ORIENTED_EDGE ( 'NONE', *, *, #256, .F. ) ;
|
#180 = ORIENTED_EDGE ( 'NONE', *, *, #256, .F. ) ;
|
||||||
#181 = APPROVAL_ROLE ( '' ) ;
|
#181 = APPROVAL_ROLE ( '' ) ;
|
||||||
#182 = FACE_OUTER_BOUND ( 'NONE', #64, .T. ) ;
|
#182 = FACE_OUTER_BOUND ( 'NONE', #64, .T. ) ;
|
||||||
#183 = PRODUCT_DEFINITION_SHAPE ( 'NONE', 'NONE', #73 ) ;
|
#183 = PRODUCT_DEFINITION_SHAPE ( 'NONE', 'NONE', #73 ) ;
|
||||||
#184 = DIRECTION ( 'NONE', ( 1.224646799147353207E-16, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
#184 = DIRECTION ( 'NONE', ( 1.224646799147353207E-16, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
||||||
#185 = ADVANCED_FACE ( 'NONE', ( #259, #75 ), #147, .F. ) ;
|
#185 = ADVANCED_FACE ( 'NONE', ( #259, #75 ), #147, .F. ) ;
|
||||||
#186 = CYLINDRICAL_SURFACE ( 'NONE', #57, 8.500000000000000000 ) ;
|
#186 = CYLINDRICAL_SURFACE ( 'NONE', #57, 8.500000000000000000 ) ;
|
||||||
#187 = APPROVAL_PERSON_ORGANIZATION ( #236, #164, #32 ) ;
|
#187 = APPROVAL_PERSON_ORGANIZATION ( #236, #164, #32 ) ;
|
||||||
#188 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 7.000000000000000000, 8.500000000000000000 ) ) ;
|
#188 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 7.000000000000000000, 8.500000000000000000 ) ) ;
|
||||||
#189 = EDGE_CURVE ( 'NONE', #160, #237, #25, .T. ) ;
|
#189 = EDGE_CURVE ( 'NONE', #160, #237, #25, .T. ) ;
|
||||||
#190 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 6.256346360029705345, 8.500000000000000000 ) ) ;
|
#190 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 6.256346360029705345, 8.500000000000000000 ) ) ;
|
||||||
#191 = CARTESIAN_POINT ( 'NONE', ( 9.099999999999997868, 5.460199521943859047, -4.550000000000001599 ) ) ;
|
#191 = CARTESIAN_POINT ( 'NONE', ( 9.099999999999997868, 5.460199521943859047, -4.550000000000001599 ) ) ;
|
||||||
#192 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 7.000000000000000000, 4.549999999999999822 ) ) ;
|
#192 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 7.000000000000000000, 4.549999999999999822 ) ) ;
|
||||||
#193 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
#193 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
||||||
#194 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#194 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#195 =( LENGTH_UNIT ( ) NAMED_UNIT ( * ) SI_UNIT ( .MILLI., .METRE. ) );
|
#195 =( LENGTH_UNIT ( ) NAMED_UNIT ( * ) SI_UNIT ( .MILLI., .METRE. ) );
|
||||||
#196 = AXIS2_PLACEMENT_3D ( 'NONE', #84, #59, #193 ) ;
|
#196 = AXIS2_PLACEMENT_3D ( 'NONE', #84, #59, #193 ) ;
|
||||||
#197 = EDGE_CURVE ( 'NONE', #160, #42, #173, .T. ) ;
|
#197 = EDGE_CURVE ( 'NONE', #160, #42, #173, .T. ) ;
|
||||||
#198 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
|
#198 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#199 = EDGE_LOOP ( 'NONE', ( #90, #14, #271, #92 ) ) ;
|
#199 = EDGE_LOOP ( 'NONE', ( #90, #14, #271, #92 ) ) ;
|
||||||
#200 = APPLICATION_CONTEXT ( 'configuration controlled 3d designs of mechanical parts and assemblies' ) ;
|
#200 = APPLICATION_CONTEXT ( 'configuration controlled 3d designs of mechanical parts and assemblies' ) ;
|
||||||
#201 = APPROVAL_ROLE ( '' ) ;
|
#201 = APPROVAL_ROLE ( '' ) ;
|
||||||
#202 = ORIENTED_EDGE ( 'NONE', *, *, #219, .T. ) ;
|
#202 = ORIENTED_EDGE ( 'NONE', *, *, #219, .T. ) ;
|
||||||
#203 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
#203 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
||||||
#204 = PERSON_AND_ORGANIZATION_ROLE ( 'classification_officer' ) ;
|
#204 = PERSON_AND_ORGANIZATION_ROLE ( 'classification_officer' ) ;
|
||||||
#205 = ORIENTED_EDGE ( 'NONE', *, *, #274, .F. ) ;
|
#205 = ORIENTED_EDGE ( 'NONE', *, *, #274, .F. ) ;
|
||||||
#206 = SHAPE_DEFINITION_REPRESENTATION ( #183, #217 ) ;
|
#206 = SHAPE_DEFINITION_REPRESENTATION ( #183, #217 ) ;
|
||||||
#207 = ORIENTED_EDGE ( 'NONE', *, *, #155, .F. ) ;
|
#207 = ORIENTED_EDGE ( 'NONE', *, *, #155, .F. ) ;
|
||||||
#208 = CIRCLE ( 'NONE', #148, 4.549999999999999822 ) ;
|
#208 = CIRCLE ( 'NONE', #148, 4.549999999999999822 ) ;
|
||||||
#209 = DIRECTION ( 'NONE', ( 0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#209 = DIRECTION ( 'NONE', ( 0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#210 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -4.549999999999999822 ) ) ;
|
#210 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -4.549999999999999822 ) ) ;
|
||||||
#211 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 6.256346360029705345, 8.500000000000000000 ) ) ;
|
#211 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 6.256346360029705345, 8.500000000000000000 ) ) ;
|
||||||
#212 = DIRECTION ( 'NONE', ( 0.000000000000000000, -0.000000000000000000, 1.000000000000000000 ) ) ;
|
#212 = DIRECTION ( 'NONE', ( 0.000000000000000000, -0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#213 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
#213 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#214 = DATE_AND_TIME ( #127, #248 ) ;
|
#214 = DATE_AND_TIME ( #127, #248 ) ;
|
||||||
#215 = EDGE_LOOP ( 'NONE', ( #63, #176 ) ) ;
|
#215 = EDGE_LOOP ( 'NONE', ( #63, #176 ) ) ;
|
||||||
#216 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #140, #204, ( #61 ) ) ;
|
#216 = CC_DESIGN_PERSON_AND_ORGANIZATION_ASSIGNMENT ( #140, #204, ( #61 ) ) ;
|
||||||
#217 = ADVANCED_BREP_SHAPE_REPRESENTATION ( 'spacer_241007', ( #3, #177 ), #243 ) ;
|
#217 = ADVANCED_BREP_SHAPE_REPRESENTATION ( 'spacer_241007', ( #3, #177 ), #243 ) ;
|
||||||
#218 = EDGE_LOOP ( 'NONE', ( #21, #115 ) ) ;
|
#218 = EDGE_LOOP ( 'NONE', ( #21, #115 ) ) ;
|
||||||
#219 = EDGE_CURVE ( 'NONE', #23, #96, #70, .T. ) ;
|
#219 = EDGE_CURVE ( 'NONE', #23, #96, #70, .T. ) ;
|
||||||
#220 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#220 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#221 = AXIS2_PLACEMENT_3D ( 'NONE', #136, #225, #118 ) ;
|
#221 = AXIS2_PLACEMENT_3D ( 'NONE', #136, #225, #118 ) ;
|
||||||
#222 = APPROVAL_STATUS ( 'not_yet_approved' ) ;
|
#222 = APPROVAL_STATUS ( 'not_yet_approved' ) ;
|
||||||
#223 = ORIENTED_EDGE ( 'NONE', *, *, #219, .F. ) ;
|
#223 = ORIENTED_EDGE ( 'NONE', *, *, #219, .F. ) ;
|
||||||
#224 = DATE_TIME_ROLE ( 'creation_date' ) ;
|
#224 = DATE_TIME_ROLE ( 'creation_date' ) ;
|
||||||
#225 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
#225 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#226 = ORIENTED_EDGE ( 'NONE', *, *, #240, .T. ) ;
|
#226 = ORIENTED_EDGE ( 'NONE', *, *, #240, .T. ) ;
|
||||||
#227 = CIRCLE ( 'NONE', #258, 7.900000000000000355 ) ;
|
#227 = CIRCLE ( 'NONE', #258, 7.900000000000000355 ) ;
|
||||||
#228 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#228 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#229 = PRODUCT ( 'spacer_241007', 'spacer_241007', '', ( #10 ) ) ;
|
#229 = PRODUCT ( 'spacer_241007', 'spacer_241007', '', ( #10 ) ) ;
|
||||||
#230 = CARTESIAN_POINT ( 'NONE', ( 9.674709713264090115E-16, 5.259999999999999787, -7.900000000000000355 ) ) ;
|
#230 = CARTESIAN_POINT ( 'NONE', ( 9.674709713264090115E-16, 5.259999999999999787, -7.900000000000000355 ) ) ;
|
||||||
#231 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
#231 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#232 = AXIS2_PLACEMENT_3D ( 'NONE', #113, #220, #203 ) ;
|
#232 = AXIS2_PLACEMENT_3D ( 'NONE', #113, #220, #203 ) ;
|
||||||
#233 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#233 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#234 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
#234 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
||||||
#235 = EDGE_CURVE ( 'NONE', #96, #268, #74, .T. ) ;
|
#235 = EDGE_CURVE ( 'NONE', #96, #268, #74, .T. ) ;
|
||||||
#236 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
#236 = PERSON_AND_ORGANIZATION ( #86, #279 ) ;
|
||||||
#237 = VERTEX_POINT ( 'NONE', #275 ) ;
|
#237 = VERTEX_POINT ( 'NONE', #275 ) ;
|
||||||
#238 = PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE ( 'ANY', '', #229, .NOT_KNOWN. ) ;
|
#238 = PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE ( 'ANY', '', #229, .NOT_KNOWN. ) ;
|
||||||
#239 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -4.549999999999999822 ) ) ;
|
#239 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -4.549999999999999822 ) ) ;
|
||||||
#240 = EDGE_CURVE ( 'NONE', #237, #160, #227, .T. ) ;
|
#240 = EDGE_CURVE ( 'NONE', #237, #160, #227, .T. ) ;
|
||||||
#241 = CYLINDRICAL_SURFACE ( 'NONE', #196, 4.549999999999999822 ) ;
|
#241 = CYLINDRICAL_SURFACE ( 'NONE', #196, 4.549999999999999822 ) ;
|
||||||
#242 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
#242 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
||||||
#243 =( GEOMETRIC_REPRESENTATION_CONTEXT ( 3 ) GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT ( ( #104 ) ) GLOBAL_UNIT_ASSIGNED_CONTEXT ( ( #195, #280, #35 ) ) REPRESENTATION_CONTEXT ( 'NONE', 'WORKASPACE' ) );
|
#243 =( GEOMETRIC_REPRESENTATION_CONTEXT ( 3 ) GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT ( ( #104 ) ) GLOBAL_UNIT_ASSIGNED_CONTEXT ( ( #195, #280, #35 ) ) REPRESENTATION_CONTEXT ( 'NONE', 'WORKASPACE' ) );
|
||||||
#244 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -8.500000000000000000 ) ) ;
|
#244 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -8.500000000000000000 ) ) ;
|
||||||
#245 = PRODUCT_RELATED_PRODUCT_CATEGORY ( 'detail', '', ( #229 ) ) ;
|
#245 = PRODUCT_RELATED_PRODUCT_CATEGORY ( 'detail', '', ( #229 ) ) ;
|
||||||
#246 = ORIENTED_EDGE ( 'NONE', *, *, #240, .F. ) ;
|
#246 = ORIENTED_EDGE ( 'NONE', *, *, #240, .F. ) ;
|
||||||
#247 = ORIENTED_EDGE ( 'NONE', *, *, #189, .F. ) ;
|
#247 = ORIENTED_EDGE ( 'NONE', *, *, #189, .F. ) ;
|
||||||
#248 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #107 ) ;
|
#248 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #107 ) ;
|
||||||
#249 = ORIENTED_EDGE ( 'NONE', *, *, #274, .T. ) ;
|
#249 = ORIENTED_EDGE ( 'NONE', *, *, #274, .T. ) ;
|
||||||
#250 = ADVANCED_FACE ( 'NONE', ( #122, #99 ), #78, .F. ) ;
|
#250 = ADVANCED_FACE ( 'NONE', ( #122, #99 ), #78, .F. ) ;
|
||||||
#251 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, -8.500000000000000000 ) ) ;
|
#251 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 7.000000000000000000, -8.500000000000000000 ) ) ;
|
||||||
#252 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -8.500000000000000000 ) ) ;
|
#252 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -8.500000000000000000 ) ) ;
|
||||||
#253 = AXIS2_PLACEMENT_3D ( 'NONE', #125, #213, #34 ) ;
|
#253 = AXIS2_PLACEMENT_3D ( 'NONE', #125, #213, #34 ) ;
|
||||||
#254 = TOROIDAL_SURFACE ( 'NONE', #221, 7.900000000000000355, 0.5999999999999999778 ) ;
|
#254 = TOROIDAL_SURFACE ( 'NONE', #221, 7.900000000000000355, 0.5999999999999999778 ) ;
|
||||||
#255 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
#255 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 0.000000000000000000 ) ) ;
|
||||||
#256 = EDGE_CURVE ( 'NONE', #42, #268, #40, .T. ) ;
|
#256 = EDGE_CURVE ( 'NONE', #42, #268, #40, .T. ) ;
|
||||||
#257 = DIRECTION ( 'NONE', ( -1.000000000000000000, -0.000000000000000000, 0.000000000000000000 ) ) ;
|
#257 = DIRECTION ( 'NONE', ( -1.000000000000000000, -0.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#258 = AXIS2_PLACEMENT_3D ( 'NONE', #255, #48, #146 ) ;
|
#258 = AXIS2_PLACEMENT_3D ( 'NONE', #255, #48, #146 ) ;
|
||||||
#259 = FACE_OUTER_BOUND ( 'NONE', #163, .T. ) ;
|
#259 = FACE_OUTER_BOUND ( 'NONE', #163, .T. ) ;
|
||||||
#260 = EDGE_CURVE ( 'NONE', #268, #42, #12, .T. ) ;
|
#260 = EDGE_CURVE ( 'NONE', #268, #42, #12, .T. ) ;
|
||||||
#261 = CIRCLE ( 'NONE', #76, 4.549999999999999822 ) ;
|
#261 = CIRCLE ( 'NONE', #76, 4.549999999999999822 ) ;
|
||||||
#262 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
#262 = DIRECTION ( 'NONE', ( -0.000000000000000000, -1.000000000000000000, -0.000000000000000000 ) ) ;
|
||||||
#263 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 5.259999999999999787, 8.500000000000000000 ) ) ;
|
#263 = CARTESIAN_POINT ( 'NONE', ( 1.040949779275250140E-15, 5.259999999999999787, 8.500000000000000000 ) ) ;
|
||||||
#264 = VERTEX_POINT ( 'NONE', #154 ) ;
|
#264 = VERTEX_POINT ( 'NONE', #154 ) ;
|
||||||
#265 = DATE_AND_TIME ( #137, #68 ) ;
|
#265 = DATE_AND_TIME ( #137, #68 ) ;
|
||||||
#266 = VERTEX_POINT ( 'NONE', #31 ) ;
|
#266 = VERTEX_POINT ( 'NONE', #31 ) ;
|
||||||
#267 = ORIENTED_EDGE ( 'NONE', *, *, #197, .T. ) ;
|
#267 = ORIENTED_EDGE ( 'NONE', *, *, #197, .T. ) ;
|
||||||
#268 = VERTEX_POINT ( 'NONE', #263 ) ;
|
#268 = VERTEX_POINT ( 'NONE', #263 ) ;
|
||||||
#269 = CC_DESIGN_APPROVAL ( #49, ( #61 ) ) ;
|
#269 = CC_DESIGN_APPROVAL ( #49, ( #61 ) ) ;
|
||||||
#270 = DATE_AND_TIME ( #288, #282 ) ;
|
#270 = DATE_AND_TIME ( #288, #282 ) ;
|
||||||
#271 = ORIENTED_EDGE ( 'NONE', *, *, #2, .T. ) ;
|
#271 = ORIENTED_EDGE ( 'NONE', *, *, #2, .T. ) ;
|
||||||
#272 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
#272 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, -1.000000000000000000 ) ) ;
|
||||||
#273 = CARTESIAN_POINT ( 'NONE', ( 9.099999999999997868, 5.460199521943859047, 4.549999999999998934 ) ) ;
|
#273 = CARTESIAN_POINT ( 'NONE', ( 9.099999999999997868, 5.460199521943859047, 4.549999999999998934 ) ) ;
|
||||||
#274 = EDGE_CURVE ( 'NONE', #162, #292, #8, .T. ) ;
|
#274 = EDGE_CURVE ( 'NONE', #162, #292, #8, .T. ) ;
|
||||||
#275 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 7.900000000000000355 ) ) ;
|
#275 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 4.660000000000000142, 7.900000000000000355 ) ) ;
|
||||||
#276 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
#276 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#277 = ADVANCED_FACE ( 'NONE', ( #9 ), #241, .F. ) ;
|
#277 = ADVANCED_FACE ( 'NONE', ( #9 ), #241, .F. ) ;
|
||||||
#278 = FACE_OUTER_BOUND ( 'NONE', #199, .T. ) ;
|
#278 = FACE_OUTER_BOUND ( 'NONE', #199, .T. ) ;
|
||||||
#279 = ORGANIZATION ( 'UNSPECIFIED', 'UNSPECIFIED', '' ) ;
|
#279 = ORGANIZATION ( 'UNSPECIFIED', 'UNSPECIFIED', '' ) ;
|
||||||
#280 =( NAMED_UNIT ( * ) PLANE_ANGLE_UNIT ( ) SI_UNIT ( $, .RADIAN. ) );
|
#280 =( NAMED_UNIT ( * ) PLANE_ANGLE_UNIT ( ) SI_UNIT ( $, .RADIAN. ) );
|
||||||
#281 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 6.256346360029705345, 4.549999999999999822 ) ) ;
|
#281 = CARTESIAN_POINT ( 'NONE', ( 5.572142936120457327E-16, 6.256346360029705345, 4.549999999999999822 ) ) ;
|
||||||
#282 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #71 ) ;
|
#282 = LOCAL_TIME ( 15, 56, 1.000000000000000000, #71 ) ;
|
||||||
#283 = APPROVAL_STATUS ( 'not_yet_approved' ) ;
|
#283 = APPROVAL_STATUS ( 'not_yet_approved' ) ;
|
||||||
#284 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
#284 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
||||||
#285 = ADVANCED_FACE ( 'NONE', ( #130 ), #143, .T. ) ;
|
#285 = ADVANCED_FACE ( 'NONE', ( #130 ), #143, .T. ) ;
|
||||||
#286 = ORIENTED_EDGE ( 'NONE', *, *, #293, .F. ) ;
|
#286 = ORIENTED_EDGE ( 'NONE', *, *, #293, .F. ) ;
|
||||||
#287 = APPLICATION_CONTEXT ( 'configuration controlled 3d designs of mechanical parts and assemblies' ) ;
|
#287 = APPLICATION_CONTEXT ( 'configuration controlled 3d designs of mechanical parts and assemblies' ) ;
|
||||||
#288 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
#288 = CALENDAR_DATE ( 2024, 12, 12 ) ;
|
||||||
#289 = APPROVAL_PERSON_ORGANIZATION ( #111, #112, #181 ) ;
|
#289 = APPROVAL_PERSON_ORGANIZATION ( #111, #112, #181 ) ;
|
||||||
#290 = ORIENTED_EDGE ( 'NONE', *, *, #19, .T. ) ;
|
#290 = ORIENTED_EDGE ( 'NONE', *, *, #19, .T. ) ;
|
||||||
#291 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
#291 = COORDINATED_UNIVERSAL_TIME_OFFSET ( 8, 0, .AHEAD. ) ;
|
||||||
#292 = VERTEX_POINT ( 'NONE', #106 ) ;
|
#292 = VERTEX_POINT ( 'NONE', #106 ) ;
|
||||||
#293 = EDGE_CURVE ( 'NONE', #162, #266, #300, .T. ) ;
|
#293 = EDGE_CURVE ( 'NONE', #162, #266, #300, .T. ) ;
|
||||||
#294 = LINE ( 'NONE', #18, #52 ) ;
|
#294 = LINE ( 'NONE', #18, #52 ) ;
|
||||||
#295 = ORIENTED_EDGE ( 'NONE', *, *, #235, .T. ) ;
|
#295 = ORIENTED_EDGE ( 'NONE', *, *, #235, .T. ) ;
|
||||||
#296 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
#296 = DIRECTION ( 'NONE', ( -0.000000000000000000, 1.000000000000000000, 0.000000000000000000 ) ) ;
|
||||||
#297 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
#297 = DIRECTION ( 'NONE', ( 0.000000000000000000, 0.000000000000000000, 1.000000000000000000 ) ) ;
|
||||||
#298 = CC_DESIGN_DATE_AND_TIME_ASSIGNMENT ( #15, #224, ( #73 ) ) ;
|
#298 = CC_DESIGN_DATE_AND_TIME_ASSIGNMENT ( #15, #224, ( #73 ) ) ;
|
||||||
#299 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -8.500000000000000000 ) ) ;
|
#299 = CARTESIAN_POINT ( 'NONE', ( 0.000000000000000000, 6.256346360029705345, -8.500000000000000000 ) ) ;
|
||||||
#300 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #281, #171, #129, #239 ),
|
#300 =( BOUNDED_CURVE ( ) B_SPLINE_CURVE ( 3, ( #281, #171, #129, #239 ),
|
||||||
.UNSPECIFIED., .F., .T. )
|
.UNSPECIFIED., .F., .T. )
|
||||||
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
B_SPLINE_CURVE_WITH_KNOTS ( ( 4, 4 ),
|
||||||
( 1.570796326794896558, 4.712388980384689674 ),
|
( 1.570796326794896558, 4.712388980384689674 ),
|
||||||
.UNSPECIFIED. )
|
.UNSPECIFIED. )
|
||||||
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
CURVE ( ) GEOMETRIC_REPRESENTATION_ITEM ( ) RATIONAL_B_SPLINE_CURVE ( ( 1.000000000000000000, 0.3333333333333333703, 0.3333333333333333703, 1.000000000000000000 ) )
|
||||||
REPRESENTATION_ITEM ( '' ) );
|
REPRESENTATION_ITEM ( '' ) );
|
||||||
#301 = VECTOR ( 'NONE', #43, 1000.000000000000000 ) ;
|
#301 = VECTOR ( 'NONE', #43, 1000.000000000000000 ) ;
|
||||||
ENDSEC;
|
ENDSEC;
|
||||||
END-ISO-10303-21;
|
END-ISO-10303-21;
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue