Compare commits
443 Commits
master
..
1a4ba3b896
| Author | SHA1 | Date | |
|---|---|---|---|
| 1a4ba3b896 | |||
| cc56c9c0ef | |||
| 3292fd8a30 | |||
| 848a866491 | |||
| 465253434e | |||
| b420396896 | |||
| 9af5f221e7 | |||
| c7b13c1e66 | |||
| 26968a0cc2 | |||
| 3f6fc6b1e5 | |||
| 68ea437305 | |||
| b16a91f3d4 | |||
| 65370b01a8 | |||
| 46ab42e8c0 | |||
| aecc14dfc2 | |||
| 9f5b78f6ff | |||
| fd249860de | |||
| de05c6bcff | |||
| 615b8b3e89 | |||
| 52d9b0c9ef | |||
| fdc6706dc1 | |||
| 276e953c4b | |||
| 84fd7aa6f4 | |||
| f957cb8205 | |||
| 1c07896b2f | |||
| 13091317f3 | |||
| f16890d5d3 | |||
| 4313143f18 | |||
| 8d3347dc2f | |||
| 6f9043a8e4 | |||
| e5e0306ca4 | |||
| b32d04c529 | |||
| 6508a0c246 | |||
| 2b421c6f6b | |||
| a8c416eacc | |||
| 93bed7edc6 | |||
| e2ebf32698 | |||
| c74f9b1078 | |||
| 73e1d8825f | |||
| 708d8c5a71 | |||
| 36bd9ae674 | |||
| b682bb8e19 | |||
| d27a9d81a3 | |||
| 83c6621482 | |||
| e75a1c983d | |||
| aba81a02c1 | |||
| 12798c8588 | |||
| 22a375a2ee | |||
| 93757eeb2f | |||
| 1919e6291f | |||
| 5b076f81a8 | |||
| 0b0d9a837c | |||
| 16c746ad2d | |||
| 8830f7e2ef | |||
| fcfcfe4c7c | |||
| 5172a24509 | |||
| 0764e76ddb | |||
| cf470109e7 | |||
| 5cc6613a3e | |||
| 7a88ffbfa7 | |||
| 40fcbbf578 | |||
| 78f8edcecf | |||
| df93fcbdc0 | |||
| 75bfa63a22 | |||
| 7dd9b5a490 | |||
| 1b111e5547 | |||
| 92c2947c95 | |||
| af1032f8ca | |||
| ac3c6e1715 | |||
| d09aac119c | |||
| 38dfafc141 | |||
| 33a3bf1d68 | |||
| 3ced88ec84 | |||
| 499682c1f2 | |||
| 8bc2d51af0 | |||
| e200898015 | |||
| 78e95f3650 | |||
| 5d38bdccda | |||
| bc1deab1e9 | |||
| b3525a8185 | |||
| f55ad94ec6 | |||
| e14084b13f | |||
| 105c8911ac | |||
| 3a6473f278 | |||
| 3c95662453 | |||
| cd70b150b0 | |||
| 6fb91723bb | |||
| cdb0d7de26 | |||
| 0c59db3d1c | |||
| 54915d6dc6 | |||
| c8b632ea68 | |||
| 1e7bd49677 | |||
| 19264b0232 | |||
| efc02342e6 | |||
| 0e142f4e66 | |||
| ceffff46b8 | |||
| c2cec9b95d | |||
| 07a301bc84 | |||
| e1bc98509d | |||
| de5cf41385 | |||
| 763bae7791 | |||
| 6e2f471b5a | |||
| b04f2ad8e2 | |||
| 54a05bf06e | |||
| ce9329f20e | |||
| 2f22bd0316 | |||
| 227c1988f7 | |||
| edbb314ca6 | |||
| 55598ae10a | |||
| e7af22b776 | |||
| e2cfa3aa20 | |||
| 23764e4a36 | |||
| c64b4cfb43 | |||
| 316a067f56 | |||
| 47d918d633 | |||
| 621676c85e | |||
| 5d4d762b9b | |||
| c9e0eef4b8 | |||
| 9ef2705543 | |||
| 017199f318 | |||
| 7136a33f63 | |||
| 2c0db0169c | |||
| 14a63d584d | |||
| 52b93fd4da | |||
| af008e165c | |||
| eceac6ca6d | |||
| f7a3c0ec27 | |||
| 39a449d818 | |||
| e7bebcb07b | |||
| 4c4f7c8af4 | |||
| 8020d862e3 | |||
| 5046eb26dd | |||
| 7a64390310 | |||
| 4b7c4ff93f | |||
| ec7ac820cd | |||
| a7ada08b15 | |||
| 57a07815a2 | |||
| cda6ab93a0 | |||
| edeeb9463f | |||
| 3d04e90d37 | |||
| 96b8da01da | |||
| 894809401c | |||
| 8c368adf02 | |||
| d4dc5812a6 | |||
| 05671eb309 | |||
| ca27877268 | |||
| 781be047fa | |||
| bcc7aa2869 | |||
| 13026df615 | |||
| cba8a071bc | |||
| a4287d64a3 | |||
| e7e4a9950b | |||
| 60e8be3ba5 | |||
| 129e31b7a2 | |||
| 9c3dfbbbbf | |||
| 82e3148975 | |||
| d374248ca5 | |||
| 7bf1646d1e | |||
| a02d71eb93 | |||
| 810701ef1f | |||
| b2b64ca5c2 | |||
| bcd8cd35a5 | |||
| a7a1fb61b4 | |||
| ff5b584d9c | |||
| bfc1fedbde | |||
| af52445efa | |||
| 449873950c | |||
| 022d98be9c | |||
| 318088797d | |||
| 6c88f3a9cc | |||
| 3e1c20ba08 | |||
| 14defb2e10 | |||
| 91a8020659 | |||
| c474a182ea | |||
| 09ee7127dc | |||
| 8e2620dae0 | |||
| 1b360d8c89 | |||
| e4f6e8b2b8 | |||
| 8e392679c1 | |||
| 0e7d01edbd | |||
| 8f3e4250fe | |||
| db25d6553a | |||
| 86d63d4460 | |||
| 50518c5035 | |||
| d75a8bb2b2 | |||
| 927b11e2bf | |||
| 3f618711bd | |||
| 5c2d042211 | |||
| 1a9279e152 | |||
| a356870ac1 | |||
| 457983cff0 | |||
| 34622c5efe | |||
| 7f5d34a405 | |||
| 3fa3669f34 | |||
| 901c49017b | |||
| 17c73e06f3 | |||
| 2c1bb808fd | |||
| 34f1a2c15b | |||
| e8c53a6fed | |||
| 8589485e8f | |||
| ff77541f12 | |||
| 33e7a0b919 | |||
| 1d60de2ec8 | |||
| e892f998d4 | |||
| f9d3ecfbdc | |||
| 3603732b51 | |||
| 337338f5c8 | |||
| 894ef7f081 | |||
| c27fabee9b | |||
| b20b01d770 | |||
| 0348ba0da9 | |||
| 26d36c7dd8 | |||
| 0e84e0abe5 | |||
| 789eb7434b | |||
| 502a1996b4 | |||
| 0656f81f0b | |||
| 14cc8a79e4 | |||
| 88156ae02d | |||
| f2a8564cae | |||
| 57eac1e589 | |||
| be956d5d4f | |||
| 1a3d79334f | |||
| a02d2768f5 | |||
| 51a4bcb237 | |||
| 7193f5796e | |||
| a26271b4c9 | |||
| 3048518868 | |||
| a605bbafaf | |||
| f87cc98664 | |||
| 3d1e5e27fc | |||
| c360292302 | |||
| 3fd79a43ec | |||
| 58a928b4a1 | |||
| 3037f62d96 | |||
| 8a5e6179f4 | |||
| 5d3c948219 | |||
| 9812e9bcde | |||
| 4583d9c6b8 | |||
| 588b4b29f0 | |||
| 7662dabc77 | |||
| 561b5899d3 | |||
| 856eeacf6b | |||
| 9414bbf1d2 | |||
| 47d07157cd | |||
| dd4484d205 | |||
| 3454dd6e82 | |||
| ca92c0ca48 | |||
| 385844c14f | |||
| e7bcc797af | |||
| 1baf80741f | |||
| 93b35031e6 | |||
| 38188a1e45 | |||
| 88193364fa | |||
| df51b1c47b | |||
| 883b441ee1 | |||
| 541bdb52dc | |||
| d97bd08048 | |||
| 50e48f437a | |||
| c2bcd0d0ce | |||
| 305d6b9fae | |||
| d09d246467 | |||
| 8af65974f7 | |||
| 7bd64ec88e | |||
| 0c6d0cf2c5 | |||
| 6851b406c3 | |||
| 394849b642 | |||
| 5f217d62ee | |||
| 3744d262a4 | |||
| e5642e505f | |||
| a316b71311 | |||
| bab537caca | |||
| 11847a31d0 | |||
| 87b985ba95 | |||
| 77e00a61cd | |||
| b5351677fe | |||
| 49da5b8ef5 | |||
| 742ea6d617 | |||
| 22f39e6523 | |||
| a28eb8d69f | |||
| 5aa0faec1e | |||
| b29b03b5f5 | |||
| 09230ea09f | |||
| 93b3ad36e9 | |||
| d8534ee312 | |||
| 0112032a1e | |||
| cca6126d2c | |||
| ad0ac8ac90 | |||
| d481f98640 | |||
| 7cfd9f70f2 | |||
| c486309ff2 | |||
| b0a1756cc9 | |||
| 4a0fad6dee | |||
| 5668320faf | |||
| f1ab1a7118 | |||
| 6c0f1985ba | |||
| 17f700caee | |||
| 59d708acd7 | |||
| 999d73da21 | |||
| 27063979a3 | |||
| a71066166a | |||
| 7df142a508 | |||
| c3132a6aad | |||
| 4d6be4de65 | |||
| 8c3a1e8ccf | |||
| 3d604121fe | |||
| 83ca3b65f9 | |||
| 6269b56e06 | |||
| 92c210458a | |||
| d496697297 | |||
| 44aba9ba2a | |||
| 8e10d22da4 | |||
| 8258e663b6 | |||
| c3e81029e8 | |||
| 2c04933596 | |||
| 567641b3cf | |||
| 352a86eac1 | |||
| acc3c11151 | |||
| 801d49565c | |||
| 4bf4183e43 | |||
| c9ee7d8eb9 | |||
| 21079fdc85 | |||
| 553e431989 | |||
| 48ffc8c5f4 | |||
| 55bbdcacde | |||
| 2292603d6d | |||
| 788f1e460c | |||
| 0b825533c8 | |||
| 4467ebcd1b | |||
| e5f8657ed6 | |||
| 6763d5d29d | |||
| 60b64d988b | |||
| e6df3e487e | |||
| 9a37a0a0f0 | |||
| 5992430f1c | |||
| b407486fcc | |||
| 5858c62bb5 | |||
| e760e2f579 | |||
| 402f6a2b6a | |||
| 601b9cf0c2 | |||
| 1bdc4a03b1 | |||
| e87e5c1118 | |||
| 25a94a3b1a | |||
| 26050ae306 | |||
| a6188b8bdf | |||
| e1e63f7dde | |||
| d0a310b881 | |||
| 4ca00d7369 | |||
| aedd240b34 | |||
| f248f68e82 | |||
| 1d60c29789 | |||
| a9bae06334 | |||
| aca385f5b0 | |||
| f4f657c701 | |||
| 8a26705d7a | |||
| 766131ecfe | |||
| b1f5478eb9 | |||
| 78c7a9ef40 | |||
| 8457f3ac8f | |||
| 65c9d11296 | |||
| db3808bd09 | |||
| 4c32a4fcb4 | |||
| f82931da06 | |||
| c3dc17bca0 | |||
| c53d0ee4df | |||
| 299750d47e | |||
| 8375e95360 | |||
| 8625c80c71 | |||
| 5a4a6336cc | |||
| b12e6f33d9 | |||
| e0af5124a7 | |||
| b526fdcd60 | |||
| a7fef5ba7d | |||
| 58f9cec145 | |||
| e812db544c | |||
| 17d87ef422 | |||
| 246f7a22cd | |||
| 90fc510a21 | |||
| b03528530c | |||
| 21feba0141 | |||
| 937c23f2be | |||
| b53c68bb7a | |||
| f312acddc8 | |||
| 5012ad8ad7 | |||
| bee5b3a67d | |||
| 578b390b72 | |||
| 9640f03e2e | |||
| 536d3d731c | |||
| 93d0994725 | |||
| 118769b2c5 | |||
| 147356b1ae | |||
| e06c9c2979 | |||
| 9eed4f8a21 | |||
| 0a83d5e7fb | |||
| cf6fc30a19 | |||
| 7bc4e5acb8 | |||
| 836d80e9b6 | |||
| 1f8b6a7826 | |||
| 8f5b49859c | |||
| d79593d1da | |||
| b78fd06342 | |||
| 400c15dd7d | |||
| db64d2e2c0 | |||
| c5b4af9657 | |||
| 1514939a58 | |||
| f2e21205f0 | |||
| 0d49699b16 | |||
| 4795ec01e4 | |||
| ab96e2cf41 | |||
| 4da41acc2c | |||
| 788f06d011 | |||
| 94f7f78bba | |||
| f5331b9e47 | |||
| 79509ac6d4 | |||
| e76cd3c238 | |||
| 5e870a1760 | |||
| 458a13746d | |||
| 32d53914d9 | |||
| 4baedab71e | |||
| 0a63e9f9df | |||
| 0f4ee99f05 | |||
| ae849589eb | |||
| a5ecfe614b | |||
| 7ffc0536cb | |||
| 6fe2baa57a | |||
| 16cfe7aceb | |||
| 239692a729 | |||
| d920ea0690 | |||
| cd33393885 | |||
| 37321cc36d | |||
| 052f533912 | |||
| 52256e07da | |||
| 77d3f76e60 | |||
| 87d3ac8c82 | |||
| 8a95de44f9 | |||
| 4d4daa5180 | |||
| 3bd0b81836 | |||
| fd6701a0e6 | |||
| a0968f46bc | |||
| 2fcedb0223 | |||
| 84de8fb2a0 | |||
| 6370d24f99 | |||
| 790c0a2188 | |||
| d6f4f8cb54 |
@@ -0,0 +1,37 @@
|
|||||||
|
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||||
|
|
||||||
|
name: Build PC Client on Linux
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python 3.9
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.9
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install PySide6 psutil pyinstaller
|
||||||
|
- name: PyInstaller
|
||||||
|
run: |
|
||||||
|
cd ./software/pc
|
||||||
|
pyinstaller hexapod.spec
|
||||||
|
cp mainwindow.ui ./dist/hexapod/
|
||||||
|
- name: Archive built module
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: success()
|
||||||
|
with:
|
||||||
|
name: hexapod_linux
|
||||||
|
path: ./software/pc/dist/hexapod
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
|
||||||
|
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
|
||||||
|
|
||||||
|
name: Build PC Client on Windows
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ main ]
|
||||||
|
pull_request:
|
||||||
|
branches: [ main ]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: windows-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Set up Python 3.9
|
||||||
|
uses: actions/setup-python@v2
|
||||||
|
with:
|
||||||
|
python-version: 3.9
|
||||||
|
- name: Install dependencies
|
||||||
|
run: |
|
||||||
|
python -m pip install --upgrade pip
|
||||||
|
pip install PySide6 psutil pyinstaller
|
||||||
|
- name: PyInstaller
|
||||||
|
run: |
|
||||||
|
cd software\pc
|
||||||
|
pyinstaller hexapod.spec
|
||||||
|
copy mainwindow.ui .\dist\hexapod\
|
||||||
|
- name: Archive built module
|
||||||
|
uses: actions/upload-artifact@v2
|
||||||
|
if: success()
|
||||||
|
with:
|
||||||
|
name: hexapod_windows
|
||||||
|
path: .\software\pc\dist\hexapod
|
||||||
@@ -25,8 +25,6 @@ The table below shows the difference between this project and the original one.
|
|||||||
|
|
||||||
https://user-images.githubusercontent.com/471808/148647807-02e3e901-6181-4473-8ac4-3b5998fa8d17.mp4
|
https://user-images.githubusercontent.com/471808/148647807-02e3e901-6181-4473-8ac4-3b5998fa8d17.mp4
|
||||||
|
|
||||||
https://user-images.githubusercontent.com/471808/158099495-1caeb903-a2e6-4e8d-9f13-54728d7d255a.mp4
|
|
||||||
|
|
||||||
## Software
|
## Software
|
||||||
|
|
||||||
### Raspberry Pi
|
### Raspberry Pi
|
||||||
|
|||||||
Binary file not shown.
-123
@@ -1,123 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<code_scheme name="Project" version="173">
|
|
||||||
<JetCodeStyleSettings>
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</JetCodeStyleSettings>
|
|
||||||
<codeStyleSettings language="XML">
|
|
||||||
<option name="FORCE_REARRANGE_MODE" value="1" />
|
|
||||||
<indentOptions>
|
|
||||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
|
||||||
</indentOptions>
|
|
||||||
<arrangement>
|
|
||||||
<rules>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:android</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>xmlns:.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:id</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*:name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>name</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>style</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>^$</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>http://schemas.android.com/apk/res/android</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>ANDROID_ATTRIBUTE_ORDER</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<rule>
|
|
||||||
<match>
|
|
||||||
<AND>
|
|
||||||
<NAME>.*</NAME>
|
|
||||||
<XML_ATTRIBUTE />
|
|
||||||
<XML_NAMESPACE>.*</XML_NAMESPACE>
|
|
||||||
</AND>
|
|
||||||
</match>
|
|
||||||
<order>BY_NAME</order>
|
|
||||||
</rule>
|
|
||||||
</section>
|
|
||||||
</rules>
|
|
||||||
</arrangement>
|
|
||||||
</codeStyleSettings>
|
|
||||||
<codeStyleSettings language="kotlin">
|
|
||||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
|
||||||
</codeStyleSettings>
|
|
||||||
</code_scheme>
|
|
||||||
</component>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<component name="ProjectCodeStyleConfiguration">
|
|
||||||
<state>
|
|
||||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
|
||||||
</state>
|
|
||||||
</component>
|
|
||||||
Generated
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CompilerConfiguration">
|
<component name="CompilerConfiguration">
|
||||||
<bytecodeTargetLevel target="17" />
|
<bytecodeTargetLevel target="11" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+1
-1
@@ -7,13 +7,13 @@
|
|||||||
<option name="testRunner" value="GRADLE" />
|
<option name="testRunner" value="GRADLE" />
|
||||||
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
<option name="distributionType" value="DEFAULT_WRAPPED" />
|
||||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
<option name="gradleJvm" value="Embedded JDK" />
|
|
||||||
<option name="modules">
|
<option name="modules">
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|||||||
Generated
-6
@@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="KotlinJpsPluginSettings">
|
|
||||||
<option name="version" value="1.6.21" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
||||||
Generated
+1
-4
@@ -29,13 +29,10 @@
|
|||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectType">
|
<component name="ProjectType">
|
||||||
<option name="id" value="Android" />
|
<option name="id" value="Android" />
|
||||||
</component>
|
</component>
|
||||||
<component name="SuppressKotlinCodeStyleNotification">
|
|
||||||
<option name="disableForAll" value="true" />
|
|
||||||
</component>
|
|
||||||
</project>
|
</project>
|
||||||
@@ -4,12 +4,12 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdk 32
|
compileSdk 31
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "com.rookiedev.hexapod"
|
applicationId "com.rookiedev.hexapod"
|
||||||
minSdk 30
|
minSdk 30
|
||||||
targetSdk 32
|
targetSdk 31
|
||||||
versionCode 3
|
versionCode 3
|
||||||
versionName "1.2"
|
versionName "1.2"
|
||||||
|
|
||||||
@@ -29,14 +29,13 @@ android {
|
|||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
jvmTarget = '1.8'
|
jvmTarget = '1.8'
|
||||||
}
|
}
|
||||||
namespace 'com.rookiedev.hexapod'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
|
||||||
implementation 'androidx.core:core-ktx:1.7.0'
|
implementation 'androidx.core:core-ktx:1.7.0'
|
||||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
implementation 'com.google.android.material:material:1.6.0'
|
implementation 'com.google.android.material:material:1.5.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
testImplementation 'junit:junit:4.13.2'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.rookiedev.hexapod">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||||
|
|||||||
@@ -13,19 +13,18 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/black"
|
android:orientation="vertical"
|
||||||
android:orientation="vertical">
|
>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/title_paired_devices"
|
android:id="@+id/title_paired_devices"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/black"
|
|
||||||
android:padding="24dp"
|
android:padding="24dp"
|
||||||
android:text="Select a Device"
|
|
||||||
android:textAppearance="?attr/textAppearanceHeadline6"
|
android:textAppearance="?attr/textAppearanceHeadline6"
|
||||||
android:textColor="@color/white"
|
android:text="Select a Device"
|
||||||
android:visibility="visible" />
|
android:visibility="visible"
|
||||||
|
/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider"
|
android:id="@+id/divider"
|
||||||
@@ -37,9 +36,8 @@
|
|||||||
android:id="@+id/paired_devices"
|
android:id="@+id/paired_devices"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/black"
|
android:stackFromBottom="false"
|
||||||
android:listSelector="@color/grey_800"
|
/>
|
||||||
android:stackFromBottom="false" />
|
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/divider1"
|
android:id="@+id/divider1"
|
||||||
@@ -51,13 +49,14 @@
|
|||||||
android:id="@+id/cancel_picker"
|
android:id="@+id/cancel_picker"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/selectableItemBackground"
|
android:padding="24dp"
|
||||||
|
android:textAppearance="?attr/textAppearanceButton"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:gravity="center_horizontal"
|
android:background="?attr/selectableItemBackground"
|
||||||
android:padding="24dp"
|
|
||||||
android:text="Cancel"
|
android:text="Cancel"
|
||||||
android:textAppearance="?attr/textAppearanceButton"
|
android:visibility="visible"
|
||||||
android:visibility="visible" />
|
/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -18,12 +18,11 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
android:elevation="8dp"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:gravity="center_horizontal"
|
android:gravity="center_horizontal"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp">
|
android:paddingEnd="16dp"
|
||||||
|
android:elevation="8dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/hexapod_logo"
|
android:id="@+id/hexapod_logo"
|
||||||
@@ -51,16 +50,12 @@
|
|||||||
android:id="@+id/wifi_tab"
|
android:id="@+id/wifi_tab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/white"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:text="WiFi" />
|
android:text="WiFi" />
|
||||||
|
|
||||||
<com.google.android.material.tabs.TabItem
|
<com.google.android.material.tabs.TabItem
|
||||||
android:id="@+id/bluetooth_tab"
|
android:id="@+id/bluetooth_tab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/white"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:text="Bluetooth" />
|
android:text="Bluetooth" />
|
||||||
|
|
||||||
</com.google.android.material.tabs.TabLayout>
|
</com.google.android.material.tabs.TabLayout>
|
||||||
@@ -83,8 +78,6 @@
|
|||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
@@ -92,10 +85,9 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:errorEnabled="true"
|
app:errorEnabled="true"
|
||||||
app:layout_constraintBottom_toTopOf="@id/port_input_layout"
|
app:layout_constraintBottom_toTopOf="@id/port_input_layout"
|
||||||
@@ -107,23 +99,20 @@
|
|||||||
android:id="@+id/ip_input"
|
android:id="@+id/ip_input"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:digits="0123456789."
|
android:digits="0123456789."
|
||||||
android:forceDarkAllowed="false"
|
android:backgroundTint="@color/grey_100"
|
||||||
android:hint="IP"
|
android:hint="IP"
|
||||||
android:inputType="number|numberDecimal"
|
android:inputType="number|numberDecimal"
|
||||||
android:text="192.168.1.127"
|
android:text="192.168.1.127" />
|
||||||
android:textColor="@android:color/primary_text_light" />
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/port_input_layout"
|
android:id="@+id/port_input_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="4dp"
|
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
android:paddingEnd="16dp"
|
android:paddingEnd="16dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
app:errorEnabled="true"
|
app:errorEnabled="true"
|
||||||
app:layout_constraintBottom_toTopOf="@id/paired_devices"
|
app:layout_constraintBottom_toTopOf="@id/paired_devices"
|
||||||
@@ -135,12 +124,10 @@
|
|||||||
android:id="@+id/port_input"
|
android:id="@+id/port_input"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
android:backgroundTint="@color/grey_100"
|
||||||
android:forceDarkAllowed="false"
|
|
||||||
android:hint="Port"
|
android:hint="Port"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:text="1234"
|
android:text="1234" />
|
||||||
android:textColor="@android:color/primary_text_light" />
|
|
||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,9 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@color/grey_500"
|
|
||||||
android:clickable="true"
|
android:clickable="true"
|
||||||
android:focusable="true"
|
android:focusable="true"
|
||||||
android:forceDarkAllowed="false"
|
android:background="?android:attr/selectableItemBackground"
|
||||||
android:paddingTop="16dp"
|
android:paddingTop="16dp"
|
||||||
android:paddingBottom="16dp">
|
android:paddingBottom="16dp">
|
||||||
|
|
||||||
@@ -17,17 +16,17 @@
|
|||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
android:padding="16dp"
|
android:padding="16dp"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/textView_device_name"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/textView_device_name"
|
||||||
app:srcCompat="@drawable/ic_baseline_bluetooth_24" />
|
app:srcCompat="@drawable/ic_baseline_bluetooth_24" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView_device_name"
|
android:id="@+id/textView_device_name"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="TextView"
|
|
||||||
android:textAppearance="?attr/textAppearanceBody1"
|
android:textAppearance="?attr/textAppearanceBody1"
|
||||||
|
android:text="TextView"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/textView_device_mac"
|
app:layout_constraintBottom_toTopOf="@+id/textView_device_mac"
|
||||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
@@ -37,8 +36,8 @@
|
|||||||
android:id="@+id/textView_device_mac"
|
android:id="@+id/textView_device_mac"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="TextView"
|
|
||||||
android:textAppearance="?attr/textAppearanceCaption"
|
android:textAppearance="?attr/textAppearanceCaption"
|
||||||
|
android:text="TextView"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@+id/imageView"
|
app:layout_constraintStart_toEndOf="@+id/imageView"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/textView_device_name" />
|
app:layout_constraintTop_toBottomOf="@+id/textView_device_name" />
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ buildscript {
|
|||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#Wed Feb 09 11:03:31 EST 2022
|
#Wed Feb 09 11:03:31 EST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
## This file must *NOT* be checked into Version Control Systems,
|
## This file is automatically generated by Android Studio.
|
||||||
|
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||||
|
#
|
||||||
|
# This file should *NOT* be checked into Version Control Systems,
|
||||||
# as it contains information specific to your local configuration.
|
# as it contains information specific to your local configuration.
|
||||||
#
|
#
|
||||||
# Location of the SDK. This is only used by Gradle.
|
# Location of the SDK. This is only used by Gradle.
|
||||||
# For customization when using a Version Control System, please read the
|
# For customization when using a Version Control System, please read the
|
||||||
# header note.
|
# header note.
|
||||||
#Fri Oct 21 23:04:27 CDT 2022
|
sdk.dir=C\:\\Users\\rooki\\AppData\\Local\\Android\\Sdk
|
||||||
sdk.dir=/home/cole/Android/Sdk
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
# SPDX-FileCopyrightText: 2018 Kattni Rembor for Adafruit Industries
|
|
||||||
#
|
|
||||||
# SPDX-License-Identifier: MIT
|
|
||||||
#
|
|
||||||
# MODIFIED to use pololu motor drivers, but compatible with adafruit_servokit driver layout
|
|
||||||
# by Amelia Deck
|
|
||||||
# Based on adafruit_motor.py as well
|
|
||||||
|
|
||||||
"""
|
|
||||||
`adafruit_servokit`
|
|
||||||
====================================================
|
|
||||||
|
|
||||||
CircuitPython helper library for the PWM/Servo FeatherWing, Shield and Pi HAT and Bonnet kits.
|
|
||||||
|
|
||||||
* Author(s): Kattni Rembor
|
|
||||||
|
|
||||||
Implementation Notes
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
**Hardware:**
|
|
||||||
|
|
||||||
* `8-Channel PWM or Servo FeatherWing <https://www.adafruit.com/product/2928>`_
|
|
||||||
* `Adafruit 16-Channel 12-bit PWM/Servo Shield <https://www.adafruit.com/product/1411>`_
|
|
||||||
* `Adafruit 16-Channel PWM/Servo HAT for Raspberry Pi <https://www.adafruit.com/product/2327>`_
|
|
||||||
* `Adafruit 16-Channel PWM/Servo Bonnet for Raspberry Pi <https://www.adafruit.com/product/3416>`_
|
|
||||||
|
|
||||||
**Software and Dependencies:**
|
|
||||||
|
|
||||||
* Adafruit CircuitPython firmware for the supported boards:
|
|
||||||
https://github.com/adafruit/circuitpython/releases
|
|
||||||
|
|
||||||
* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
|
|
||||||
* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
|
|
||||||
* Adafruit's PCA9685 library: https://github.com/adafruit/Adafruit_CircuitPython_PCA9685
|
|
||||||
* Adafruit's Motor library: https://github.com/adafruit/Adafruit_CircuitPython_Motor
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
#import board
|
|
||||||
#from adafruit_pca9685 import PCA9685
|
|
||||||
|
|
||||||
try:
|
|
||||||
from typing import Optional
|
|
||||||
import maestro
|
|
||||||
import time
|
|
||||||
#from busio import I2C
|
|
||||||
#from adafruit_motor.servo import Servo, ContinuousServo
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
__version__ = "0.0.0+auto.0"
|
|
||||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ServoKit.git"
|
|
||||||
|
|
||||||
pca = None
|
|
||||||
|
|
||||||
class ServoKit:
|
|
||||||
"""Class representing an Adafruit PWM/Servo FeatherWing, Shield or Pi HAT and Bonnet kits.
|
|
||||||
|
|
||||||
Automatically uses the I2C bus on a Feather, Metro or Raspberry Pi.
|
|
||||||
|
|
||||||
Initialise the PCA9685 chip at ``address``.
|
|
||||||
|
|
||||||
The internal reference clock is 25MHz but may vary slightly with environmental conditions and
|
|
||||||
manufacturing variances. Providing a more precise ``reference_clock_speed`` can improve the
|
|
||||||
accuracy of the frequency and duty_cycle computations. See the ``calibration.py`` example in
|
|
||||||
the `PCA9685 GitHub repo <https://github.com/adafruit/Adafruit_CircuitPython_PCA9685>`_ for
|
|
||||||
how to derive this value by measuring the resulting pulse widths.
|
|
||||||
|
|
||||||
:param int channels: The number of servo channels available. Must be 8 or 16. The FeatherWing
|
|
||||||
has 8 channels. The Shield, HAT, and Bonnet have 16 channels.
|
|
||||||
:param ~I2C i2c: The I2C bus to use. If not provided, it will use generate the default I2C
|
|
||||||
bus singleton ``busio.I2C()`` and use that.
|
|
||||||
:param int address: The I2C address of the PCA9685. Default address is ``0x40``.
|
|
||||||
:param int reference_clock_speed: The frequency of the internal reference clock in Hertz.
|
|
||||||
Default reference clock speed is ``25000000``.
|
|
||||||
:param int frequency: The overall PWM frequency of the PCA9685 in Hertz.
|
|
||||||
Default frequency is ``50``.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
*,
|
|
||||||
channels: int,
|
|
||||||
#i2c: Optional[I2C] = None,
|
|
||||||
address: str = "/dev/ttyACM0",
|
|
||||||
reference_clock_speed: int = 25000000,
|
|
||||||
frequency: int = 50 # actually, device ID over serial pololu protocol. using existing var names for full compatibility!
|
|
||||||
) -> None:
|
|
||||||
if channels not in [6, 12, 18, 24]:
|
|
||||||
raise ValueError("servo_channels must be 6, 12, 18, 24!")
|
|
||||||
self._items = [None] * channels
|
|
||||||
self._channels = channels
|
|
||||||
#if i2c is None:
|
|
||||||
# i2c = board.I2C()
|
|
||||||
#self._pca = PCA9685(
|
|
||||||
# i2c, address=address, reference_clock_speed=reference_clock_speed
|
|
||||||
#)
|
|
||||||
#self._pca.frequency = frequency
|
|
||||||
global pca
|
|
||||||
self._pca = maestro.Controller(ttyStr=address,device=frequency)
|
|
||||||
pca = self._pca
|
|
||||||
self._servo = _Servo(self)
|
|
||||||
|
|
||||||
@property
|
|
||||||
def servo(self) -> "_Servo":
|
|
||||||
""":class:`~adafruit_motor.servo.Servo` controls for standard servos.
|
|
||||||
|
|
||||||
This FeatherWing example rotates a servo on channel ``0`` to ``180`` degrees for one second,
|
|
||||||
and then returns it to ``0`` degrees.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
import time
|
|
||||||
from adafruit_servokit import ServoKit
|
|
||||||
|
|
||||||
kit = ServoKit(channels=8)
|
|
||||||
|
|
||||||
kit.servo[0].angle = 180
|
|
||||||
time.sleep(1)
|
|
||||||
kit.servo[0].angle = 0
|
|
||||||
|
|
||||||
"""
|
|
||||||
return self._servo
|
|
||||||
|
|
||||||
|
|
||||||
class _Servo:
|
|
||||||
# pylint: disable=protected-access
|
|
||||||
def __init__(self, kit: ServoKit) -> None:
|
|
||||||
self.kit = kit
|
|
||||||
|
|
||||||
def __getitem__(self, servo_channel: int):
|
|
||||||
#import adafruit_motor.servo # pylint: disable=import-outside-toplevel
|
|
||||||
|
|
||||||
num_channels = self.kit._channels
|
|
||||||
if servo_channel >= num_channels or servo_channel < 0:
|
|
||||||
raise ValueError("servo must be 0-{}!".format(num_channels - 1))
|
|
||||||
servo = pololuservo(servo_channel)
|
|
||||||
|
|
||||||
return servo
|
|
||||||
raise ValueError("Channel {} is already in use.".format(servo_channel))
|
|
||||||
|
|
||||||
def __len__(self) -> int:
|
|
||||||
return len(self.kit._items)
|
|
||||||
|
|
||||||
class pololuservo:
|
|
||||||
def __init__(self, ch, actuation_range: int = 180, min_pulse: int = 1600, max_pulse: int = 9900):
|
|
||||||
self.ch = ch
|
|
||||||
self.actuation_range = actuation_range
|
|
||||||
self._min_duty = min_pulse
|
|
||||||
self._max_duty = max_pulse
|
|
||||||
self._duty_range = max_pulse - min_pulse
|
|
||||||
self.duty_cycle = 0
|
|
||||||
print("init servo", ch)
|
|
||||||
pca.setAccel(ch, 15)
|
|
||||||
pca.setTarget(ch, int((max_pulse-min_pulse)/2 + min_pulse)) # set midpoint
|
|
||||||
time.sleep(0.1)
|
|
||||||
pca.setAccel(ch, 0)
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
def angle(self) -> Optional[float]:
|
|
||||||
"""The servo angle in degrees. Must be in the range ``0`` to ``actuation_range``.
|
|
||||||
Is None when servo is disabled."""
|
|
||||||
if self.fraction is None: # special case for disabled servos
|
|
||||||
return None
|
|
||||||
return self.actuation_range * self.fraction
|
|
||||||
|
|
||||||
@angle.setter
|
|
||||||
def angle(self, new_angle: Optional[float]) -> None:
|
|
||||||
if new_angle is None: # disable the servo by sending 0 signal
|
|
||||||
self.fraction = None
|
|
||||||
return
|
|
||||||
if new_angle < 0 or new_angle > self.actuation_range:
|
|
||||||
raise ValueError("Angle out of range")
|
|
||||||
self.fraction = new_angle / self.actuation_range
|
|
||||||
|
|
||||||
@property
|
|
||||||
def fraction(self) -> Optional[float]:
|
|
||||||
"""Pulse width expressed as fraction between 0.0 (`min_pulse`) and 1.0 (`max_pulse`).
|
|
||||||
For conventional servos, corresponds to the servo position as a fraction
|
|
||||||
of the actuation range. Is None when servo is diabled (pulsewidth of 0ms).
|
|
||||||
"""
|
|
||||||
if self.duty_cycle == 0: # Special case for disabled servos
|
|
||||||
return None
|
|
||||||
return (self.duty_cycle - self._min_duty) / self._duty_range
|
|
||||||
|
|
||||||
@fraction.setter
|
|
||||||
def fraction(self, value: Optional[float]) -> None:
|
|
||||||
if value is None:
|
|
||||||
#self._pwm_out.duty_cycle = 0 # disable the motor
|
|
||||||
|
|
||||||
return
|
|
||||||
if not 0.0 <= value <= 1.0:
|
|
||||||
raise ValueError("Must be 0.0 to 1.0")
|
|
||||||
#if self.ch > 2 and self.ch < 6:
|
|
||||||
# valuetmp = 1.0 - value
|
|
||||||
# self.duty_cycle = self._min_duty + int(valuetmp * self._duty_range)
|
|
||||||
#else:
|
|
||||||
self.duty_cycle = self._min_duty + int(value * self._duty_range)
|
|
||||||
#print(self.ch)
|
|
||||||
#if self.ch == 0:
|
|
||||||
#print(value)
|
|
||||||
pca.setTarget(self.ch,int(self.duty_cycle))
|
|
||||||
time.sleep(0.002)
|
|
||||||
#self._pwm_out.duty_cycle = duty_cycle
|
|
||||||
@@ -49,9 +49,8 @@ class BluetoothServer(Thread):
|
|||||||
|
|
||||||
self.cmd_queue = out_cmd_queue
|
self.cmd_queue = out_cmd_queue
|
||||||
|
|
||||||
with open('config.json', 'r') as read_file:
|
with open('/home/pi/hexapod/software/raspberry pi/config.json', 'r') as read_file:
|
||||||
self.config = json.load(read_file)
|
self.config = json.load(read_file)
|
||||||
try:
|
|
||||||
|
|
||||||
stream = os.popen('hciconfig hci0')
|
stream = os.popen('hciconfig hci0')
|
||||||
output = stream.read()
|
output = stream.read()
|
||||||
@@ -65,16 +64,13 @@ class BluetoothServer(Thread):
|
|||||||
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
|
socket.AF_BLUETOOTH, socket.SOCK_STREAM, socket.BTPROTO_RFCOMM)
|
||||||
|
|
||||||
self.signal = self.SIG_NORMAL
|
self.signal = self.SIG_NORMAL
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
self.bt_socket.bind((self.mac, self.port))
|
self.bt_socket.bind((self.mac, self.port))
|
||||||
self.bt_socket.listen(1)
|
self.bt_socket.listen(1)
|
||||||
print('TCP listening')
|
print('TCP listening')
|
||||||
except: # OSError as err:
|
except OSError as err:
|
||||||
# print('emit tcp server error')
|
# print('emit tcp server error')
|
||||||
# self.status.emit(self.STOP, '')
|
# self.status.emit(self.STOP, '')
|
||||||
pass
|
pass
|
||||||
@@ -108,9 +104,6 @@ class BluetoothServer(Thread):
|
|||||||
break
|
break
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
try:
|
|
||||||
self.bt_socket.close()
|
self.bt_socket.close()
|
||||||
self.cmd_queue.put('standby:')
|
self.cmd_queue.put('standby:')
|
||||||
print('exit')
|
print('exit')
|
||||||
except:
|
|
||||||
pass
|
|
||||||
|
|||||||
@@ -38,39 +38,39 @@
|
|||||||
"movementInterval": 5,
|
"movementInterval": 5,
|
||||||
"movementSwitchDuration": 150,
|
"movementSwitchDuration": 150,
|
||||||
"leg0Offset": [
|
"leg0Offset": [
|
||||||
10,
|
4.0,
|
||||||
10,
|
6.0,
|
||||||
30
|
2
|
||||||
],
|
],
|
||||||
"leg0Scale": [
|
"leg0Scale": [
|
||||||
1,
|
1,
|
||||||
-1,
|
1,
|
||||||
-1
|
1
|
||||||
],
|
],
|
||||||
"leg1Offset": [
|
"leg1Offset": [
|
||||||
15,
|
-1.0,
|
||||||
-20,
|
8,
|
||||||
35
|
-6
|
||||||
],
|
],
|
||||||
"leg1Scale": [
|
"leg1Scale": [
|
||||||
1,
|
1,
|
||||||
-1,
|
1,
|
||||||
-1
|
1
|
||||||
],
|
],
|
||||||
"leg2Offset": [
|
"leg2Offset": [
|
||||||
-3,
|
1.0,
|
||||||
10,
|
12.0,
|
||||||
20
|
1.0
|
||||||
],
|
],
|
||||||
"leg2Scale": [
|
"leg2Scale": [
|
||||||
1,
|
1,
|
||||||
-1,
|
1,
|
||||||
-1
|
1
|
||||||
],
|
],
|
||||||
"leg3Offset": [
|
"leg3Offset": [
|
||||||
7,
|
-3,
|
||||||
15,
|
12.0,
|
||||||
-10
|
-6.0
|
||||||
],
|
],
|
||||||
"leg3Scale": [
|
"leg3Scale": [
|
||||||
1,
|
1,
|
||||||
@@ -78,9 +78,9 @@
|
|||||||
1
|
1
|
||||||
],
|
],
|
||||||
"leg4Offset": [
|
"leg4Offset": [
|
||||||
15,
|
-6,
|
||||||
10,
|
2,
|
||||||
5
|
-6.0
|
||||||
],
|
],
|
||||||
"leg4Scale": [
|
"leg4Scale": [
|
||||||
1,
|
1,
|
||||||
@@ -88,20 +88,13 @@
|
|||||||
1
|
1
|
||||||
],
|
],
|
||||||
"leg5Offset": [
|
"leg5Offset": [
|
||||||
-7,
|
0,
|
||||||
10,
|
4.0,
|
||||||
-30
|
-10
|
||||||
],
|
],
|
||||||
"leg5Scale": [
|
"leg5Scale": [
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
1
|
1
|
||||||
],
|
]
|
||||||
"leg0Laser": 17,
|
|
||||||
"leg1Laser": 27,
|
|
||||||
"leg2Laser": 22,
|
|
||||||
"leg3Laser": 10,
|
|
||||||
"leg4Laser": 9,
|
|
||||||
"leg5Laser": 11
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/python3
|
#!python
|
||||||
#
|
#
|
||||||
# 2021 - PRESENT Zhengyu Peng
|
# 2021 - PRESENT Zhengyu Peng
|
||||||
# Website: https://zpeng.me
|
# Website: https://zpeng.me
|
||||||
@@ -28,7 +28,6 @@
|
|||||||
# https://circuitpython.readthedocs.io/projects/servokit/en/latest/
|
# https://circuitpython.readthedocs.io/projects/servokit/en/latest/
|
||||||
from audioop import reverse
|
from audioop import reverse
|
||||||
from adafruit_servokit import ServoKit
|
from adafruit_servokit import ServoKit
|
||||||
import maestro
|
|
||||||
|
|
||||||
from leg import Leg
|
from leg import Leg
|
||||||
|
|
||||||
@@ -93,7 +92,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
self.calibration_mode = False
|
self.calibration_mode = False
|
||||||
|
|
||||||
with open('config.json', 'r') as read_file:
|
with open('/home/pi/hexapod/software/raspberry pi/config.json', 'r') as read_file:
|
||||||
self.config = json.load(read_file)
|
self.config = json.load(read_file)
|
||||||
|
|
||||||
# legs' coordinates
|
# legs' coordinates
|
||||||
@@ -116,40 +115,40 @@ class Hexapod(Thread):
|
|||||||
self.mount_position[:, 1] = self.mount_y
|
self.mount_position[:, 1] = self.mount_y
|
||||||
|
|
||||||
# Objects
|
# Objects
|
||||||
self.pca_right = ServoKit(channels=18, address="/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.4:1.0", frequency=0x0c)
|
self.pca_right = ServoKit(channels=16, address=0x40, frequency=120)
|
||||||
self.pca_left = ServoKit(channels=18, address="/dev/serial/by-path/platform-fd500000.pcie-pci-0000:01:00.0-usb-0:1.3:1.0", frequency=0x0d)
|
self.pca_left = ServoKit(channels=16, address=0x41, frequency=120)
|
||||||
#self.pca_left = self.pca_right
|
|
||||||
self.legs = [
|
self.legs = [
|
||||||
# front right
|
# front right
|
||||||
Leg(0,
|
Leg(0,
|
||||||
[self.pca_left.servo[0], self.pca_left.servo[1],
|
[self.pca_left.servo[15], self.pca_left.servo[14],
|
||||||
self.pca_left.servo[2]],
|
self.pca_left.servo[13]],
|
||||||
correction=self.config.get('leg0Offset', [0, 0, 0]), scale=self.config.get('leg0Scale', [1, 1, 1])),
|
correction=self.config.get('leg0Offset', [0, 0, 0])),
|
||||||
# center right
|
# center right
|
||||||
Leg(1,
|
Leg(1,
|
||||||
[self.pca_left.servo[3], self.pca_left.servo[4],
|
[self.pca_left.servo[8], self.pca_left.servo[4],
|
||||||
self.pca_left.servo[5]],
|
self.pca_left.servo[11]],
|
||||||
correction=self.config.get('leg1Offset', [0, 0, 0]), scale=self.config.get('leg1Scale', [1, 1, 1])),
|
correction=self.config.get('leg1Offset', [0, 0, 0])),
|
||||||
# rear right
|
# rear right
|
||||||
Leg(2,
|
Leg(2,
|
||||||
[self.pca_left.servo[6], self.pca_left.servo[7],
|
[self.pca_left.servo[0], self.pca_left.servo[1],
|
||||||
self.pca_left.servo[8]],
|
self.pca_left.servo[2]],
|
||||||
correction=self.config.get('leg2Offset', [0, 0, 0]), scale=self.config.get('leg2Scale', [1, 1, 1])),
|
correction=self.config.get('leg2Offset', [0, 0, 0])),
|
||||||
# rear left
|
# rear left
|
||||||
Leg(3,
|
Leg(3,
|
||||||
[self.pca_right.servo[6], self.pca_right.servo[7],
|
[self.pca_right.servo[15], self.pca_right.servo[14],
|
||||||
self.pca_right.servo[8]],
|
self.pca_right.servo[13]],
|
||||||
correction=self.config.get('leg3Offset', [0, 0, 0]), scale=self.config.get('leg3Scale', [1, 1, 1])),
|
correction=self.config.get('leg3Offset', [0, 0, 0])),
|
||||||
# center left
|
# center left
|
||||||
Leg(4,
|
Leg(4,
|
||||||
[self.pca_right.servo[3], self.pca_right.servo[4],
|
[self.pca_right.servo[7], self.pca_right.servo[11],
|
||||||
self.pca_right.servo[5]],
|
self.pca_right.servo[6]],
|
||||||
correction=self.config.get('leg4Offset', [0, 0, 0]), scale=self.config.get('leg4Scale', [1, 1, 1])),
|
correction=self.config.get('leg4Offset', [0, 0, 0])),
|
||||||
# front left
|
# front left
|
||||||
Leg(5,
|
Leg(5,
|
||||||
[self.pca_right.servo[0], self.pca_right.servo[1],
|
[self.pca_right.servo[0], self.pca_right.servo[2],
|
||||||
self.pca_right.servo[2]],
|
self.pca_right.servo[5]],
|
||||||
correction=self.config.get('leg5Offset', [0, 0, 0]), scale=self.config.get('leg5Scale', [1, 1, 1]))]
|
correction=self.config.get('leg5Offset', [0, 0, 0]))]
|
||||||
|
|
||||||
# self.leg_0.reset(True)
|
# self.leg_0.reset(True)
|
||||||
# self.leg_1.reset(True)
|
# self.leg_1.reset(True)
|
||||||
@@ -263,7 +262,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
cmd_string = self.cmd_queue.get(block=False)
|
cmd_string = self.cmd_queue.get(block=False)
|
||||||
print('interrupt')
|
print('interrput')
|
||||||
except Empty:
|
except Empty:
|
||||||
# time.sleep(self.interval)
|
# time.sleep(self.interval)
|
||||||
pass
|
pass
|
||||||
@@ -300,6 +299,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
angles[:, 1] = 90-((ar + a1) * 180 / np.pi)
|
angles[:, 1] = 90-((ar + a1) * 180 / np.pi)
|
||||||
angles[:, 2] = (90 - ((a1 + a2) * 180 / np.pi))+90
|
angles[:, 2] = (90 - ((a1 + a2) * 180 / np.pi))+90
|
||||||
|
|
||||||
return angles
|
return angles
|
||||||
|
|
||||||
def cmd_handler(self, cmd_string):
|
def cmd_handler(self, cmd_string):
|
||||||
@@ -350,8 +350,7 @@ class Hexapod(Thread):
|
|||||||
|
|
||||||
def save_config(self):
|
def save_config(self):
|
||||||
try:
|
try:
|
||||||
json.dump(self.config, open(
|
json.dump(self.config, open('/home/pi/hexapod/software/raspberry pi/config.json', 'w+'), indent=4)
|
||||||
'/home/amelia/hexapod/software/raspberry pi/config2.json', 'w+'), indent=4)
|
|
||||||
except PermissionError as err:
|
except PermissionError as err:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,6 @@ class Leg:
|
|||||||
self.junction_servos = junction_servos
|
self.junction_servos = junction_servos
|
||||||
self.correction = correction
|
self.correction = correction
|
||||||
self.constraint = constraint
|
self.constraint = constraint
|
||||||
self.scale = scale
|
|
||||||
|
|
||||||
def set_angle(self, junction, angle):
|
def set_angle(self, junction, angle):
|
||||||
set_angle = np.min(
|
set_angle = np.min(
|
||||||
@@ -51,19 +50,8 @@ class Leg:
|
|||||||
self.junction_servos[junction].angle = angle
|
self.junction_servos[junction].angle = angle
|
||||||
|
|
||||||
def move_junctions(self, angles):
|
def move_junctions(self, angles):
|
||||||
if self.scale[0] < 0:
|
|
||||||
self.set_angle(0, self.constraint[0][1] + self.constraint[0][0] - angles[0])
|
|
||||||
#print(self.scale, self.constraint[0][1] + self.constraint[0][0] - angles[0])
|
|
||||||
else:
|
|
||||||
self.set_angle(0, angles[0])
|
self.set_angle(0, angles[0])
|
||||||
#print(self.scale, angles[0])
|
|
||||||
if self.scale[1] < 0:
|
|
||||||
self.set_angle(1, self.constraint[1][1] + self.constraint[1][0] - angles[1])
|
|
||||||
else:
|
|
||||||
self.set_angle(1, angles[1])
|
self.set_angle(1, angles[1])
|
||||||
if self.scale[2] < 0:
|
|
||||||
self.set_angle(2, self.constraint[2][1] + self.constraint[2][0] - angles[2])
|
|
||||||
else:
|
|
||||||
self.set_angle(2, angles[2])
|
self.set_angle(2, angles[2])
|
||||||
|
|
||||||
def reset(self, calibrated=False):
|
def reset(self, calibrated=False):
|
||||||
|
|||||||
@@ -1,169 +0,0 @@
|
|||||||
import serial
|
|
||||||
from sys import version_info
|
|
||||||
|
|
||||||
PY2 = version_info[0] == 2 #Running Python 2.x?
|
|
||||||
|
|
||||||
#
|
|
||||||
#---------------------------
|
|
||||||
# Maestro Servo Controller
|
|
||||||
#---------------------------
|
|
||||||
#
|
|
||||||
# Support for the Pololu Maestro line of servo controllers
|
|
||||||
#
|
|
||||||
# Steven Jacobs -- Aug 2013
|
|
||||||
# https://github.com/FRC4564/Maestro/
|
|
||||||
#
|
|
||||||
# These functions provide access to many of the Maestro's capabilities using the
|
|
||||||
# Pololu serial protocol
|
|
||||||
#
|
|
||||||
class Controller:
|
|
||||||
# When connected via USB, the Maestro creates two virtual serial ports
|
|
||||||
# /dev/ttyACM0 for commands and /dev/ttyACM1 for communications.
|
|
||||||
# Be sure the Maestro is configured for "USB Dual Port" serial mode.
|
|
||||||
# "USB Chained Mode" may work as well, but hasn't been tested.
|
|
||||||
#
|
|
||||||
# Pololu protocol allows for multiple Maestros to be connected to a single
|
|
||||||
# serial port. Each connected device is then indexed by number.
|
|
||||||
# This device number defaults to 0x0C (or 12 in decimal), which this module
|
|
||||||
# assumes. If two or more controllers are connected to different serial
|
|
||||||
# ports, or you are using a Windows OS, you can provide the tty port. For
|
|
||||||
# example, '/dev/ttyACM2' or for Windows, something like 'COM3'.
|
|
||||||
def __init__(self,ttyStr='/dev/ttyACM0',device=0x0c):
|
|
||||||
# Open the command port
|
|
||||||
self.usb = serial.Serial(ttyStr)
|
|
||||||
# Command lead-in and device number are sent for each Pololu serial command.
|
|
||||||
self.PololuCmd = chr(0xaa) + chr(device)
|
|
||||||
# Track target position for each servo. The function isMoving() will
|
|
||||||
# use the Target vs Current servo position to determine if movement is
|
|
||||||
# occuring. Upto 24 servos on a Maestro, (0-23). Targets start at 0.
|
|
||||||
self.Targets = [0] * 24
|
|
||||||
# Servo minimum and maximum targets can be restricted to protect components.
|
|
||||||
self.Mins = [0] * 24
|
|
||||||
self.Maxs = [0] * 24
|
|
||||||
|
|
||||||
# Cleanup by closing USB serial port
|
|
||||||
def close(self):
|
|
||||||
self.usb.close()
|
|
||||||
|
|
||||||
# Send a Pololu command out the serial port
|
|
||||||
def sendCmd(self, cmd):
|
|
||||||
cmdStr = self.PololuCmd + cmd
|
|
||||||
if PY2:
|
|
||||||
self.usb.write(cmdStr)
|
|
||||||
else:
|
|
||||||
self.usb.write(bytes(cmdStr,'latin-1'))
|
|
||||||
|
|
||||||
# Set channels min and max value range. Use this as a safety to protect
|
|
||||||
# from accidentally moving outside known safe parameters. A setting of 0
|
|
||||||
# allows unrestricted movement.
|
|
||||||
#
|
|
||||||
# ***Note that the Maestro itself is configured to limit the range of servo travel
|
|
||||||
# which has precedence over these values. Use the Maestro Control Center to configure
|
|
||||||
# ranges that are saved to the controller. Use setRange for software controllable ranges.
|
|
||||||
def setRange(self, chan, min, max):
|
|
||||||
self.Mins[chan] = min
|
|
||||||
self.Maxs[chan] = max
|
|
||||||
|
|
||||||
# Return Minimum channel range value
|
|
||||||
def getMin(self, chan):
|
|
||||||
return self.Mins[chan]
|
|
||||||
|
|
||||||
# Return Maximum channel range value
|
|
||||||
def getMax(self, chan):
|
|
||||||
return self.Maxs[chan]
|
|
||||||
|
|
||||||
# Set channel to a specified target value. Servo will begin moving based
|
|
||||||
# on Speed and Acceleration parameters previously set.
|
|
||||||
# Target values will be constrained within Min and Max range, if set.
|
|
||||||
# For servos, target represents the pulse width in of quarter-microseconds
|
|
||||||
# Servo center is at 1500 microseconds, or 6000 quarter-microseconds
|
|
||||||
# Typcially valid servo range is 3000 to 9000 quarter-microseconds
|
|
||||||
# If channel is configured for digital output, values < 6000 = Low ouput
|
|
||||||
def setTarget(self, chan, target):
|
|
||||||
# if Min is defined and Target is below, force to Min
|
|
||||||
if self.Mins[chan] > 0 and target < self.Mins[chan]:
|
|
||||||
target = self.Mins[chan]
|
|
||||||
# if Max is defined and Target is above, force to Max
|
|
||||||
if self.Maxs[chan] > 0 and target > self.Maxs[chan]:
|
|
||||||
target = self.Maxs[chan]
|
|
||||||
#
|
|
||||||
lsb = target & 0x7f #7 bits for least significant byte
|
|
||||||
msb = (target >> 7) & 0x7f #shift 7 and take next 7 bits for msb
|
|
||||||
cmd = chr(0x04) + chr(chan) + chr(lsb) + chr(msb)
|
|
||||||
self.sendCmd(cmd)
|
|
||||||
# Record Target value
|
|
||||||
self.Targets[chan] = target
|
|
||||||
|
|
||||||
# Set speed of channel
|
|
||||||
# Speed is measured as 0.25microseconds/10milliseconds
|
|
||||||
# For the standard 1ms pulse width change to move a servo between extremes, a speed
|
|
||||||
# of 1 will take 1 minute, and a speed of 60 would take 1 second.
|
|
||||||
# Speed of 0 is unrestricted.
|
|
||||||
def setSpeed(self, chan, speed):
|
|
||||||
lsb = speed & 0x7f #7 bits for least significant byte
|
|
||||||
msb = (speed >> 7) & 0x7f #shift 7 and take next 7 bits for msb
|
|
||||||
cmd = chr(0x07) + chr(chan) + chr(lsb) + chr(msb)
|
|
||||||
self.sendCmd(cmd)
|
|
||||||
|
|
||||||
# Set acceleration of channel
|
|
||||||
# This provide soft starts and finishes when servo moves to target position.
|
|
||||||
# Valid values are from 0 to 255. 0=unrestricted, 1 is slowest start.
|
|
||||||
# A value of 1 will take the servo about 3s to move between 1ms to 2ms range.
|
|
||||||
def setAccel(self, chan, accel):
|
|
||||||
lsb = accel & 0x7f #7 bits for least significant byte
|
|
||||||
msb = (accel >> 7) & 0x7f #shift 7 and take next 7 bits for msb
|
|
||||||
cmd = chr(0x09) + chr(chan) + chr(lsb) + chr(msb)
|
|
||||||
self.sendCmd(cmd)
|
|
||||||
|
|
||||||
# Get the current position of the device on the specified channel
|
|
||||||
# The result is returned in a measure of quarter-microseconds, which mirrors
|
|
||||||
# the Target parameter of setTarget.
|
|
||||||
# This is not reading the true servo position, but the last target position sent
|
|
||||||
# to the servo. If the Speed is set to below the top speed of the servo, then
|
|
||||||
# the position result will align well with the acutal servo position, assuming
|
|
||||||
# it is not stalled or slowed.
|
|
||||||
def getPosition(self, chan):
|
|
||||||
cmd = chr(0x10) + chr(chan)
|
|
||||||
self.sendCmd(cmd)
|
|
||||||
lsb = ord(self.usb.read())
|
|
||||||
msb = ord(self.usb.read())
|
|
||||||
return (msb << 8) + lsb
|
|
||||||
|
|
||||||
# Test to see if a servo has reached the set target position. This only provides
|
|
||||||
# useful results if the Speed parameter is set slower than the maximum speed of
|
|
||||||
# the servo. Servo range must be defined first using setRange. See setRange comment.
|
|
||||||
#
|
|
||||||
# ***Note if target position goes outside of Maestro's allowable range for the
|
|
||||||
# channel, then the target can never be reached, so it will appear to always be
|
|
||||||
# moving to the target.
|
|
||||||
def isMoving(self, chan):
|
|
||||||
if self.Targets[chan] > 0:
|
|
||||||
if self.getPosition(chan) != self.Targets[chan]:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
# Have all servo outputs reached their targets? This is useful only if Speed and/or
|
|
||||||
# Acceleration have been set on one or more of the channels. Returns True or False.
|
|
||||||
# Not available with Micro Maestro.
|
|
||||||
def getMovingState(self):
|
|
||||||
cmd = chr(0x13)
|
|
||||||
self.sendCmd(cmd)
|
|
||||||
if self.usb.read() == chr(0):
|
|
||||||
return False
|
|
||||||
else:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# Run a Maestro Script subroutine in the currently active script. Scripts can
|
|
||||||
# have multiple subroutines, which get numbered sequentially from 0 on up. Code your
|
|
||||||
# Maestro subroutine to either infinitely loop, or just end (return is not valid).
|
|
||||||
def runScriptSub(self, subNumber):
|
|
||||||
cmd = chr(0x27) + chr(subNumber)
|
|
||||||
# can pass a param with command 0x28
|
|
||||||
# cmd = chr(0x28) + chr(subNumber) + chr(lsb) + chr(msb)
|
|
||||||
self.sendCmd(cmd)
|
|
||||||
|
|
||||||
# Stop the current Maestro Script
|
|
||||||
def stopScript(self):
|
|
||||||
cmd = chr(0x24)
|
|
||||||
self.sendCmd(cmd)
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
pyserial
|
|
||||||
numpy
|
|
||||||
@@ -47,10 +47,10 @@ class TCPServer(Thread):
|
|||||||
|
|
||||||
self.cmd_queue = out_cmd_queue
|
self.cmd_queue = out_cmd_queue
|
||||||
|
|
||||||
with open('config.json', 'r') as read_file:
|
with open('/home/pi/hexapod/software/raspberry pi/config.json', 'r') as read_file:
|
||||||
self.config = json.load(read_file)
|
self.config = json.load(read_file)
|
||||||
|
|
||||||
self.ip = '0.0.0.0'
|
self.ip = '192.168.1.127'
|
||||||
self.port = 1234
|
self.port = 1234
|
||||||
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
self.tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import maestro
|
|
||||||
servo = maestro.Controller()
|
|
||||||
import time
|
|
||||||
print("1")
|
|
||||||
for i in range(18):
|
|
||||||
|
|
||||||
servo.setAccel(i,10) #set servo 0 acceleration to 4
|
|
||||||
servo.setSpeed(i,50) #set speed of servo 1
|
|
||||||
servo.setTarget(i,6000) #set servo to move to center position
|
|
||||||
|
|
||||||
time.sleep(1)
|
|
||||||
#servo.setTarget(0,6000)
|
|
||||||
#x = servo.getPosition(1) #get the current position of servo 1
|
|
||||||
print("5")
|
|
||||||
#servo.close()
|
|
||||||
print("6")
|
|
||||||
Reference in New Issue
Block a user