bluer-sbc 8.248.1__py3-none-any.whl → 9.36.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of bluer-sbc might be problematic. Click here for more details.
- bluer_sbc/.abcli/{blue_sbc.sh → bluer_sbc.sh} +2 -0
- bluer_sbc/.abcli/sbc/parts/adjust.sh +12 -0
- bluer_sbc/.abcli/sbc/parts/cd.sh +5 -0
- bluer_sbc/.abcli/sbc/parts.sh +15 -0
- bluer_sbc/.abcli/tests/help.sh +4 -0
- bluer_sbc/.abcli/tests/parts_adjust.sh +13 -0
- bluer_sbc/README/__init__.py +0 -28
- bluer_sbc/README/aliases.py +1 -0
- bluer_sbc/README/build.py +29 -0
- bluer_sbc/README/design.py +32 -0
- bluer_sbc/README/designs/__init__.py +38 -11
- bluer_sbc/README/designs/battery_bus.py +2 -2
- bluer_sbc/README/designs/shelter.py +2 -2
- bluer_sbc/README/designs/swallow_head.py +1 -1
- bluer_sbc/README/designs/x.py +2 -5
- bluer_sbc/README/parts.py +15 -0
- bluer_sbc/README/root.py +4 -0
- bluer_sbc/README/shortcuts.py +17 -0
- bluer_sbc/__init__.py +2 -2
- bluer_sbc/__main__.py +3 -2
- bluer_sbc/designs/__init__.py +0 -0
- bluer_sbc/designs/battery_bus/__init__.py +0 -0
- bluer_sbc/designs/battery_bus/parts.py +5 -0
- bluer_sbc/designs/swallow/__init__.py +0 -0
- bluer_sbc/designs/swallow/parts.py +3 -0
- bluer_sbc/designs/swallow_head/__init__.py +0 -0
- bluer_sbc/designs/swallow_head/parts.py +15 -0
- bluer_sbc/help/functions.py +2 -0
- bluer_sbc/help/parts.py +49 -0
- bluer_sbc/parts/__init__.py +0 -0
- bluer_sbc/parts/__main__.py +41 -0
- bluer_sbc/parts/classes/db.py +208 -0
- bluer_sbc/parts/classes/part.py +96 -0
- bluer_sbc/parts/db.py +381 -0
- {bluer_sbc-8.248.1.dist-info → bluer_sbc-9.36.1.dist-info}/METADATA +11 -3
- {bluer_sbc-8.248.1.dist-info → bluer_sbc-9.36.1.dist-info}/RECORD +39 -18
- {bluer_sbc-8.248.1.dist-info → bluer_sbc-9.36.1.dist-info}/WHEEL +0 -0
- {bluer_sbc-8.248.1.dist-info → bluer_sbc-9.36.1.dist-info}/licenses/LICENSE +0 -0
- {bluer_sbc-8.248.1.dist-info → bluer_sbc-9.36.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
from typing import Dict, List, Iterator, Tuple
|
|
2
|
+
import copy
|
|
3
|
+
import os
|
|
4
|
+
import numpy as np
|
|
5
|
+
import cv2
|
|
6
|
+
from functools import reduce
|
|
7
|
+
from tqdm import tqdm
|
|
8
|
+
|
|
9
|
+
from blueness import module
|
|
10
|
+
from bluer_options.logger import log_list
|
|
11
|
+
from bluer_objects import file
|
|
12
|
+
from bluer_objects import README
|
|
13
|
+
from bluer_objects.README.consts import assets_path, assets_url
|
|
14
|
+
|
|
15
|
+
from bluer_sbc import NAME
|
|
16
|
+
from bluer_sbc.parts.classes.part import Part
|
|
17
|
+
from bluer_sbc.logger import logger
|
|
18
|
+
|
|
19
|
+
NAME = module.name(__file__, NAME)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PartDB:
|
|
23
|
+
def __init__(self):
|
|
24
|
+
self._db: Dict[str, Part] = {}
|
|
25
|
+
|
|
26
|
+
suffix = "bluer-sbc/parts"
|
|
27
|
+
self.url_prefix = assets_url(
|
|
28
|
+
suffix=suffix,
|
|
29
|
+
volume=2,
|
|
30
|
+
)
|
|
31
|
+
self.path = assets_path(
|
|
32
|
+
suffix=suffix,
|
|
33
|
+
volume=2,
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
def __iter__(self):
|
|
37
|
+
return iter(self._db.values())
|
|
38
|
+
|
|
39
|
+
def __setitem__(
|
|
40
|
+
self,
|
|
41
|
+
name: str,
|
|
42
|
+
part: Part,
|
|
43
|
+
):
|
|
44
|
+
assert isinstance(part, Part)
|
|
45
|
+
|
|
46
|
+
self._db[name] = copy.deepcopy(part)
|
|
47
|
+
self._db[name].name = name
|
|
48
|
+
|
|
49
|
+
def __getitem__(self, name: str) -> Part:
|
|
50
|
+
return self._db[name]
|
|
51
|
+
|
|
52
|
+
def items(self) -> Iterator[Tuple[str, Part]]:
|
|
53
|
+
return self._db.items()
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def README(self) -> List[str]:
|
|
57
|
+
return sorted(
|
|
58
|
+
[
|
|
59
|
+
"- [{}](./{}.md).".format(
|
|
60
|
+
part.info[0],
|
|
61
|
+
part.name,
|
|
62
|
+
)
|
|
63
|
+
for part in self
|
|
64
|
+
]
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def adjust(
|
|
68
|
+
self,
|
|
69
|
+
dryrun: bool = True,
|
|
70
|
+
verbose: bool = False,
|
|
71
|
+
) -> bool:
|
|
72
|
+
logger.info(
|
|
73
|
+
"{}.adjust{}".format(
|
|
74
|
+
NAME,
|
|
75
|
+
" [dryrun]" if dryrun else "",
|
|
76
|
+
)
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
list_of_filenames = reduce(
|
|
80
|
+
lambda x, y: x + y,
|
|
81
|
+
[
|
|
82
|
+
[part.images[0]]
|
|
83
|
+
for part_name, part in self._db.items()
|
|
84
|
+
if part_name != "template" and part.images
|
|
85
|
+
],
|
|
86
|
+
[],
|
|
87
|
+
)
|
|
88
|
+
log_list(logger, "adjusting", list_of_filenames, "images")
|
|
89
|
+
|
|
90
|
+
max_width = 0
|
|
91
|
+
max_height = 0
|
|
92
|
+
for filename in tqdm(list_of_filenames):
|
|
93
|
+
success, image = file.load_image(
|
|
94
|
+
os.path.join(self.path, filename),
|
|
95
|
+
log=verbose,
|
|
96
|
+
)
|
|
97
|
+
if not success:
|
|
98
|
+
return success
|
|
99
|
+
|
|
100
|
+
max_height = max(max_height, image.shape[0])
|
|
101
|
+
max_width = max(max_width, image.shape[1])
|
|
102
|
+
|
|
103
|
+
logger.info(f"size: {max_height} x {max_width}")
|
|
104
|
+
|
|
105
|
+
for filename in tqdm(list_of_filenames):
|
|
106
|
+
success, image = file.load_image(
|
|
107
|
+
os.path.join(self.path, filename),
|
|
108
|
+
log=verbose,
|
|
109
|
+
)
|
|
110
|
+
if not success:
|
|
111
|
+
return success
|
|
112
|
+
|
|
113
|
+
if image.shape[0] == max_height and image.shape[1] == max_width:
|
|
114
|
+
logger.info("✅")
|
|
115
|
+
continue
|
|
116
|
+
|
|
117
|
+
image = image[:, :, :3]
|
|
118
|
+
|
|
119
|
+
scale = min(
|
|
120
|
+
max_height / image.shape[0],
|
|
121
|
+
max_width / image.shape[1],
|
|
122
|
+
)
|
|
123
|
+
image = cv2.resize(
|
|
124
|
+
image,
|
|
125
|
+
dsize=(
|
|
126
|
+
int(scale * image.shape[1]),
|
|
127
|
+
int(scale * image.shape[0]),
|
|
128
|
+
),
|
|
129
|
+
interpolation=cv2.INTER_LINEAR,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
padded_image = (
|
|
133
|
+
np.ones(
|
|
134
|
+
(max_height, max_width, 3),
|
|
135
|
+
dtype=np.uint8,
|
|
136
|
+
)
|
|
137
|
+
* 255
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
y_offset = (max_height - image.shape[0]) // 2
|
|
141
|
+
x_offset = (max_width - image.shape[1]) // 2
|
|
142
|
+
|
|
143
|
+
padded_image[
|
|
144
|
+
y_offset : y_offset + image.shape[0],
|
|
145
|
+
x_offset : x_offset + image.shape[1],
|
|
146
|
+
] = image
|
|
147
|
+
|
|
148
|
+
if not dryrun:
|
|
149
|
+
if not file.save_image(
|
|
150
|
+
os.path.join(self.path, filename),
|
|
151
|
+
padded_image,
|
|
152
|
+
log=verbose,
|
|
153
|
+
):
|
|
154
|
+
return False
|
|
155
|
+
|
|
156
|
+
return True
|
|
157
|
+
|
|
158
|
+
def as_images(
|
|
159
|
+
self,
|
|
160
|
+
dict_of_parts: Dict[str, str],
|
|
161
|
+
reference: str = "../../parts",
|
|
162
|
+
) -> List[str]:
|
|
163
|
+
return README.Items(
|
|
164
|
+
[
|
|
165
|
+
{
|
|
166
|
+
"name": self._db[part_name].info[0],
|
|
167
|
+
"marquee": self._db[part_name].image_url(
|
|
168
|
+
url_prefix=self.url_prefix
|
|
169
|
+
),
|
|
170
|
+
"description": description,
|
|
171
|
+
"url": f"{reference}/{part_name}.md",
|
|
172
|
+
}
|
|
173
|
+
for part_name, description in dict_of_parts.items()
|
|
174
|
+
],
|
|
175
|
+
sort=True,
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
def as_list(
|
|
179
|
+
self,
|
|
180
|
+
dict_of_parts: Dict[str, str],
|
|
181
|
+
reference: str = "../../parts",
|
|
182
|
+
log: bool = True,
|
|
183
|
+
) -> List[str]:
|
|
184
|
+
if log:
|
|
185
|
+
logger.info(
|
|
186
|
+
"{}.as_list: {}".format(
|
|
187
|
+
self.__class__.__name__,
|
|
188
|
+
", ".join(dict_of_parts.keys()),
|
|
189
|
+
)
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
for part_name in dict_of_parts:
|
|
193
|
+
if part_name not in self._db:
|
|
194
|
+
logger.error(f"{part_name}: part not found.")
|
|
195
|
+
assert False
|
|
196
|
+
|
|
197
|
+
return sorted(
|
|
198
|
+
[
|
|
199
|
+
(
|
|
200
|
+
"1. [{}{}]({}).".format(
|
|
201
|
+
self._db[part_name].info[0],
|
|
202
|
+
": {}".format(description) if description else "",
|
|
203
|
+
f"{reference}/{part_name}.md",
|
|
204
|
+
)
|
|
205
|
+
)
|
|
206
|
+
for part_name, description in dict_of_parts.items()
|
|
207
|
+
]
|
|
208
|
+
)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
from typing import List, Union
|
|
2
|
+
import copy
|
|
3
|
+
|
|
4
|
+
from bluer_objects import markdown
|
|
5
|
+
from bluer_objects import file
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Part:
|
|
9
|
+
def __init__(
|
|
10
|
+
self,
|
|
11
|
+
info: Union[List[str], str] = [],
|
|
12
|
+
name: str = "",
|
|
13
|
+
images: List[str] = [],
|
|
14
|
+
):
|
|
15
|
+
self.name = name
|
|
16
|
+
|
|
17
|
+
self.info = (
|
|
18
|
+
copy.deepcopy(info)
|
|
19
|
+
if isinstance(
|
|
20
|
+
info,
|
|
21
|
+
list,
|
|
22
|
+
)
|
|
23
|
+
else [info]
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
self.images = (
|
|
27
|
+
copy.deepcopy(images)
|
|
28
|
+
if isinstance(
|
|
29
|
+
images,
|
|
30
|
+
list,
|
|
31
|
+
)
|
|
32
|
+
else [images]
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
def filename(
|
|
36
|
+
self,
|
|
37
|
+
create: bool = False,
|
|
38
|
+
) -> str:
|
|
39
|
+
reference = file.path(__file__)
|
|
40
|
+
filename = file.absolute(
|
|
41
|
+
f"../../docs/parts/{self.name}.md",
|
|
42
|
+
reference,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
if not create or file.exists(filename):
|
|
46
|
+
return filename
|
|
47
|
+
|
|
48
|
+
template_filename = file.absolute(
|
|
49
|
+
"../../docs/parts/template-template.md",
|
|
50
|
+
reference,
|
|
51
|
+
)
|
|
52
|
+
assert file.copy(
|
|
53
|
+
template_filename,
|
|
54
|
+
file.add_suffix(filename, "template"),
|
|
55
|
+
log=True,
|
|
56
|
+
), template_filename
|
|
57
|
+
|
|
58
|
+
return filename
|
|
59
|
+
|
|
60
|
+
def image_url(
|
|
61
|
+
self,
|
|
62
|
+
url_prefix: str,
|
|
63
|
+
filename: str = "",
|
|
64
|
+
) -> str:
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
"{}/{}?raw=true".format(
|
|
68
|
+
url_prefix,
|
|
69
|
+
filename if filename else self.images[0],
|
|
70
|
+
)
|
|
71
|
+
if self.images
|
|
72
|
+
else ""
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
def README(
|
|
76
|
+
self,
|
|
77
|
+
url_prefix: str,
|
|
78
|
+
) -> List[str]:
|
|
79
|
+
return [f"- {info}" for info in self.info] + (
|
|
80
|
+
[""]
|
|
81
|
+
+ markdown.generate_table(
|
|
82
|
+
[
|
|
83
|
+
"".format(
|
|
84
|
+
self.image_url(
|
|
85
|
+
url_prefix,
|
|
86
|
+
filename,
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
for filename in self.images
|
|
90
|
+
],
|
|
91
|
+
cols=3,
|
|
92
|
+
log=False,
|
|
93
|
+
)
|
|
94
|
+
if self.images
|
|
95
|
+
else []
|
|
96
|
+
)
|
bluer_sbc/parts/db.py
ADDED
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
from bluer_sbc.parts.classes.part import Part
|
|
2
|
+
from bluer_sbc.parts.classes.db import PartDB
|
|
3
|
+
|
|
4
|
+
db_of_parts: PartDB = PartDB()
|
|
5
|
+
|
|
6
|
+
db_of_parts["resistor"] = Part(
|
|
7
|
+
info=[
|
|
8
|
+
"Resistor, 1/4 watt, 5% tolerance",
|
|
9
|
+
],
|
|
10
|
+
images=["resistor.png"],
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
db_of_parts["4-ch-transceiver"] = Part(
|
|
14
|
+
info=[
|
|
15
|
+
"4-channel transmitter and receiver",
|
|
16
|
+
"source: [digikala](https://www.digikala.com/product/dkp-11037586/%DA%AF%DB%8C%D8%B1%D9%86%D8%AF%D9%87-%D9%88-%D9%81%D8%B1%D8%B3%D8%AA%D9%86%D8%AF%D9%87-%D9%85%D8%A7%D8%B4%DB%8C%D9%86-%DA%A9%D9%86%D8%AA%D8%B1%D9%84%DB%8C-%D9%85%D8%AF%D9%84-4ch-led/)",
|
|
17
|
+
"voltages: receiver 6 VDC, transmitter 3 VDC",
|
|
18
|
+
],
|
|
19
|
+
images="4-channel-remote-control.png",
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
db_of_parts["470-mF"] = Part(
|
|
23
|
+
info=[
|
|
24
|
+
"capacitor, 470 μF to 1000 μF, 16 V or 25 V, Electrolytic, 105 °C rated if possible."
|
|
25
|
+
],
|
|
26
|
+
images=["capacitor.png"],
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
db_of_parts["BTS7960"] = Part(
|
|
30
|
+
info=[
|
|
31
|
+
"43 A, H-Bridge Motor Driver",
|
|
32
|
+
"specs: [BTS7960](https://www.handsontec.com/dataspecs/module/BTS7960%20Motor%20Driver.pdf)",
|
|
33
|
+
],
|
|
34
|
+
images="bts7960.jpg",
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
db_of_parts["dc-motor-12-VDC-45W"] = Part(
|
|
38
|
+
info=[
|
|
39
|
+
"12 VDC motor, 20-45 W",
|
|
40
|
+
"type 1: 9,000 RPM, output ~60 RPM",
|
|
41
|
+
"type 2: 10,000 RPM, output 72 RPM",
|
|
42
|
+
"https://parsbike.com/product/%D9%85%D9%88%D8%AA%D9%88%D8%B1-%DA%AF%DB%8C%D8%B1%D8%A8%DA%A9%D8%B3-%D9%85%D8%A7%D8%B4%DB%8C%D9%86-%D8%B4%D8%A7%D8%B1%DA%98%DB%8C-%D9%88-%D9%85%D9%88%D8%AA%D9%88%D8%B1-%D8%B4%D8%A7%D8%B1%DA%98%DB%8C/",
|
|
43
|
+
],
|
|
44
|
+
images=[
|
|
45
|
+
"gearbox1.jpg",
|
|
46
|
+
"gearbox2.jpg",
|
|
47
|
+
"gearbox3.jpg",
|
|
48
|
+
"gearbox4.jpg",
|
|
49
|
+
"gearbox5.jpg",
|
|
50
|
+
"gearbox6.jpg",
|
|
51
|
+
"gearbox7.jpg",
|
|
52
|
+
"gearbox8.jpg",
|
|
53
|
+
],
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
db_of_parts["LED"] = Part(
|
|
57
|
+
info=[
|
|
58
|
+
"LED, ~2 V forward voltage, 10-20 mA",
|
|
59
|
+
],
|
|
60
|
+
images=["led.png"],
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
db_of_parts["Polyfuse"] = Part(
|
|
64
|
+
info=[
|
|
65
|
+
"Polyfuse, 1.1 A hold, 2.2 A trip, 16 V, resettable, through-hole, e.g., MF-R110",
|
|
66
|
+
],
|
|
67
|
+
images=["polyfuse.png"],
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
db_of_parts["rpi3bp"] = Part(
|
|
71
|
+
info=[
|
|
72
|
+
"Raspberry Pi 3B+",
|
|
73
|
+
],
|
|
74
|
+
images=[
|
|
75
|
+
"rpi3bplus.png",
|
|
76
|
+
"gpio-pinout.png",
|
|
77
|
+
],
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
db_of_parts["SLA-Battery"] = Part(
|
|
81
|
+
info=[
|
|
82
|
+
"Rechargeable sealed lead acid battery, 12 V, 7 Ah",
|
|
83
|
+
],
|
|
84
|
+
images=[
|
|
85
|
+
"battery.png",
|
|
86
|
+
],
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
db_of_parts["TVS-diode"] = Part(
|
|
90
|
+
info=[
|
|
91
|
+
"TVS diode, unidirectional, 600 W, 6.8 V clamp, e.g. P6KE6.8A, DO-15 package",
|
|
92
|
+
],
|
|
93
|
+
images=[
|
|
94
|
+
"TVSdiode.png",
|
|
95
|
+
],
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
db_of_parts["XL4015"] = Part(
|
|
99
|
+
info=[
|
|
100
|
+
"XL4015: 12 VDC -> 5 VDC, 4A",
|
|
101
|
+
"specs: [XL4015](https://www.handsontec.com/dataspecs/module/XL4015-5A-PS.pdf)",
|
|
102
|
+
],
|
|
103
|
+
images=[
|
|
104
|
+
"XL4015.png",
|
|
105
|
+
],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
db_of_parts["rpi-camera"] = Part(
|
|
109
|
+
info=[
|
|
110
|
+
"Raspberry Pi Camera, V1.3"
|
|
111
|
+
"https://www.raspberrypi.com/documentation/accessories/camera.html",
|
|
112
|
+
],
|
|
113
|
+
images=[
|
|
114
|
+
"rpi-camera.jpg",
|
|
115
|
+
],
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
db_of_parts["DC-gearboxed-motor-12V-120RPM"] = Part(
|
|
119
|
+
info=[
|
|
120
|
+
"Gearboxed DC Motor, 12 V (3-24 V), 3A, 120 RPM, 1:91, 15 Kg cm",
|
|
121
|
+
"[GM6558](https://www.landaelectronic.com/product/%d9%85%d9%88%d8%aa%d9%88%d8%b1-dc-%da%af%db%8c%d8%b1%d8%a8%da%a9%d8%b3-%d8%ad%d9%84%d8%b2%d9%88%d9%86%db%8c-gm6558/)",
|
|
122
|
+
],
|
|
123
|
+
images=[
|
|
124
|
+
"GM6558/01.jpg",
|
|
125
|
+
"GM6558/02.jpg",
|
|
126
|
+
"GM6558/03.jpg",
|
|
127
|
+
"GM6558/04.jpg",
|
|
128
|
+
"GM6558/measurements.jpg",
|
|
129
|
+
"GM6558/specs.png",
|
|
130
|
+
],
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
db_of_parts["2xAA-battery-holder"] = Part(
|
|
134
|
+
info=[
|
|
135
|
+
"2 x AA battery holder",
|
|
136
|
+
],
|
|
137
|
+
images=[
|
|
138
|
+
"2xAA-battery-holder.jpg",
|
|
139
|
+
],
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
db_of_parts["4xAA-battery-holder"] = Part(
|
|
143
|
+
info=[
|
|
144
|
+
"4 x AA battery holder",
|
|
145
|
+
],
|
|
146
|
+
images=[
|
|
147
|
+
"4xAA-battery-holder.jpg",
|
|
148
|
+
],
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
db_of_parts["PCB-double-9x7"] = Part(
|
|
152
|
+
info=[
|
|
153
|
+
"double-sided PCB, 9 cm x 7 cm",
|
|
154
|
+
],
|
|
155
|
+
images=[
|
|
156
|
+
"PCB-double-9x7.jpeg",
|
|
157
|
+
],
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
db_of_parts["PCB-single-14x9_5"] = Part(
|
|
161
|
+
info=[
|
|
162
|
+
"single-sided PCB, 14 cm x 9.5 cm",
|
|
163
|
+
],
|
|
164
|
+
images=[
|
|
165
|
+
"pcb-14x9_5cm.jpg",
|
|
166
|
+
],
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
db_of_parts["pushbutton"] = Part(
|
|
170
|
+
info=[
|
|
171
|
+
"push button",
|
|
172
|
+
],
|
|
173
|
+
images=[
|
|
174
|
+
"pushbutton.png",
|
|
175
|
+
],
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
db_of_parts["yellow-gearbox-dc-motor"] = Part(
|
|
179
|
+
info=[
|
|
180
|
+
"gearboxed DC motor, 6V DC",
|
|
181
|
+
],
|
|
182
|
+
images=[
|
|
183
|
+
"yellow-gearbox-dc-motor.png",
|
|
184
|
+
],
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
db_of_parts["yellow-wheels"] = Part(
|
|
188
|
+
info=[
|
|
189
|
+
"wheels for gearboxed DC motor",
|
|
190
|
+
],
|
|
191
|
+
images=[
|
|
192
|
+
"yellow-wheels.jpg",
|
|
193
|
+
],
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
db_of_parts["36v-hub-motor"] = Part(
|
|
197
|
+
info=[
|
|
198
|
+
"36V DC hub motor, 350 W, front, no gearbox",
|
|
199
|
+
"[source](https://samamotor.ir/%D9%87%D8%A7%D8%A8-%D9%85%D9%88%D8%AA%D9%88%D8%B1/5105-%D9%87%D8%A7%D8%A8-%D9%85%D9%88%D8%AA%D9%88%D8%B1-350-%D9%88%D8%A7%D8%AA-36-%D9%88%D9%84%D8%AA-%D8%A8%D8%AF%D9%88%D9%86-%DA%AF%DB%8C%D8%B1%D8%A8%DA%A9%D8%B3-%D8%AF%D9%88%DA%86%D8%B1%D8%AE%D9%87-%D9%85%D8%AE%D8%B5%D9%88%D8%B5-%DA%86%D8%B1%D8%AE-%D8%AC%D9%84%D9%88-.html)",
|
|
200
|
+
],
|
|
201
|
+
images=[
|
|
202
|
+
"36v-hub-motor.jpg",
|
|
203
|
+
],
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
db_of_parts["brushless-350w-drive"] = Part(
|
|
207
|
+
info=[
|
|
208
|
+
"brushless drive, 36 - 48 V DC, 350 W, sine wave, silent",
|
|
209
|
+
"[source](https://samamotor.ir/%D8%AF%D8%B1%D8%A7%DB%8C%D9%88%D8%B1-%D9%85%D9%88%D8%AA%D9%88%D8%B1-%D8%A8%D8%B1%D8%A7%D8%B4%D9%84%D8%B3-bldc/4821-%D8%AF%D8%B1%D8%A7%DB%8C%D9%88%D8%B1-%D8%A8%D8%B1%D8%A7%D8%B4%D9%84%D8%B3-36-48-%D9%88%D9%84%D8%AA-350-%D9%88%D8%A7%D8%AA-sine-wave-silent.html)",
|
|
210
|
+
],
|
|
211
|
+
images=[
|
|
212
|
+
"brushless-350w-drive.jpg",
|
|
213
|
+
],
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
db_of_parts["LJ-6V-battery"] = Part(
|
|
217
|
+
info=[
|
|
218
|
+
"6V DC (4 cell) NICD battery",
|
|
219
|
+
"https://www.digikala.com/product/dkp-3213588/%C3%98/",
|
|
220
|
+
],
|
|
221
|
+
images=[
|
|
222
|
+
"LJ-6V-battery.jpg",
|
|
223
|
+
],
|
|
224
|
+
)
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
db_of_parts["USB-charger-NICD-6V"] = Part(
|
|
228
|
+
info=[
|
|
229
|
+
"6V DC charger for NICD batteries",
|
|
230
|
+
"https://www.digikala.com/product/dkp-5977954/%D8%B4%D8%A7%D8%B1%DA%98%D8%B1-%D8%A8%D8%A7%D8%AA%D8%B1%DB%8C-%D9%85%D8%A7%D8%B4%DB%8C%D9%86-%DA%A9%D9%86%D8%AA%D8%B1%D9%84%DB%8C-%D9%85%D8%AF%D9%84-6-%D9%88%D9%84%D8%AA-%DA%A9%D8%AF-6v-usb-sm-%D8%A8%D9%87-%D9%87%D9%85%D8%B1%D8%A7%D9%87-%D8%B3%D9%88%DA%A9%D8%AA-sm-%D8%AF%D9%88-%D9%BE%DB%8C%D9%86/",
|
|
231
|
+
],
|
|
232
|
+
images=[
|
|
233
|
+
"USB-charger-NICD-6V-1.jpg",
|
|
234
|
+
"USB-charger-NICD-6V-2.jpg",
|
|
235
|
+
],
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
db_of_parts["L-1x2"] = Part(
|
|
239
|
+
info=[
|
|
240
|
+
"L 1x2",
|
|
241
|
+
"https://robotexiran.com/product/%d8%a8%d8%b3%d8%aa-21-l/",
|
|
242
|
+
],
|
|
243
|
+
images=[
|
|
244
|
+
"L-1x2-1.jpg",
|
|
245
|
+
"L-1x2-2.jpg",
|
|
246
|
+
],
|
|
247
|
+
)
|
|
248
|
+
|
|
249
|
+
db_of_parts["shaft-10cm"] = Part(
|
|
250
|
+
info=[
|
|
251
|
+
"shaft, 10 cm",
|
|
252
|
+
"https://robotexiran.com/product/%d9%85%d8%ad%d9%88%d8%b1-10cm/",
|
|
253
|
+
],
|
|
254
|
+
images=[
|
|
255
|
+
"shaft-10cm.jpg",
|
|
256
|
+
],
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
db_of_parts["M3"] = Part(
|
|
260
|
+
info=[
|
|
261
|
+
"M3 nuts and bolts",
|
|
262
|
+
],
|
|
263
|
+
images=[
|
|
264
|
+
"M3.jpg",
|
|
265
|
+
],
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
db_of_parts["front-connector"] = Part(
|
|
269
|
+
info=[
|
|
270
|
+
"front connector",
|
|
271
|
+
],
|
|
272
|
+
images=[
|
|
273
|
+
"front-connector.jpg",
|
|
274
|
+
],
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
db_of_parts["front-wheels"] = Part(
|
|
278
|
+
info=[
|
|
279
|
+
"front wheels",
|
|
280
|
+
],
|
|
281
|
+
images=[
|
|
282
|
+
"front-wheels.jpg",
|
|
283
|
+
],
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
db_of_parts["wheel"] = Part(
|
|
287
|
+
info=[
|
|
288
|
+
"power wheel wheels",
|
|
289
|
+
"https://sarobatic.ir/product/%DA%86%D8%B1%D8%AE-%D8%A8%D8%B2%D8%B1%DA%AF-%D8%B9%D9%82%D8%A8-%D9%85%D8%A7%D8%B4%DB%8C%D9%86-%D8%B4%D8%A7%D8%B1%DA%98%DB%8C-%D8%A7%D8%B3%D8%AA%D9%88%DA%A9/",
|
|
290
|
+
"https://toys-repair.ir/product/2768/",
|
|
291
|
+
],
|
|
292
|
+
images=[
|
|
293
|
+
"wheel1.jpg",
|
|
294
|
+
"wheel4.jpg",
|
|
295
|
+
"wheel3.jpg",
|
|
296
|
+
],
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
db_of_parts["ultrasonic-sensor"] = Part(
|
|
300
|
+
info=[
|
|
301
|
+
"HC-SR04: ultrasonic-sensor",
|
|
302
|
+
"[datasheet](https://cdn.sparkfun.com/datasheets/Sensors/Proximity/HCSR04.pdf)",
|
|
303
|
+
"1m ~= 6ms",
|
|
304
|
+
"fov = 15 - 30 deg",
|
|
305
|
+
],
|
|
306
|
+
images=[
|
|
307
|
+
"HC-SR04.jpg",
|
|
308
|
+
],
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
db_of_parts["connector"] = Part(
|
|
312
|
+
info=[
|
|
313
|
+
"auto power connectors",
|
|
314
|
+
],
|
|
315
|
+
images=[
|
|
316
|
+
"connector.jpg",
|
|
317
|
+
],
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
db_of_parts["1N4148"] = Part(
|
|
321
|
+
info=[
|
|
322
|
+
"1N4148 diode",
|
|
323
|
+
],
|
|
324
|
+
images=[
|
|
325
|
+
"TVSdiode.png",
|
|
326
|
+
],
|
|
327
|
+
)
|
|
328
|
+
|
|
329
|
+
db_of_parts["40-inch-TV"] = Part(
|
|
330
|
+
info=[
|
|
331
|
+
"40 inch TV",
|
|
332
|
+
],
|
|
333
|
+
images=[
|
|
334
|
+
"40-inch-TV.jpg",
|
|
335
|
+
],
|
|
336
|
+
)
|
|
337
|
+
|
|
338
|
+
db_of_parts["power-station"] = Part(
|
|
339
|
+
info=[
|
|
340
|
+
"power station.",
|
|
341
|
+
],
|
|
342
|
+
images=[
|
|
343
|
+
"power-station.jpeg",
|
|
344
|
+
],
|
|
345
|
+
)
|
|
346
|
+
|
|
347
|
+
db_of_parts["TV-bracket"] = Part(
|
|
348
|
+
info=[
|
|
349
|
+
"TV bracket",
|
|
350
|
+
],
|
|
351
|
+
images=[
|
|
352
|
+
"tv-bracket.jpeg",
|
|
353
|
+
],
|
|
354
|
+
)
|
|
355
|
+
|
|
356
|
+
db_of_parts["on-off-switch"] = Part(
|
|
357
|
+
info=[
|
|
358
|
+
"on/off switch",
|
|
359
|
+
],
|
|
360
|
+
images=[
|
|
361
|
+
"on-off-switch.png",
|
|
362
|
+
],
|
|
363
|
+
)
|
|
364
|
+
|
|
365
|
+
db_of_parts["charging-port"] = Part(
|
|
366
|
+
info=[
|
|
367
|
+
"charging port",
|
|
368
|
+
],
|
|
369
|
+
images=[
|
|
370
|
+
"charging-port.jpg",
|
|
371
|
+
],
|
|
372
|
+
)
|
|
373
|
+
|
|
374
|
+
db_of_parts["template"] = Part(
|
|
375
|
+
info=[
|
|
376
|
+
"template",
|
|
377
|
+
],
|
|
378
|
+
images=[
|
|
379
|
+
"template.jpg",
|
|
380
|
+
],
|
|
381
|
+
)
|