Skip to content

Commit a7bdf0b

Browse files
committed
update docs
1 parent 35fcd5a commit a7bdf0b

File tree

15 files changed

+540
-236
lines changed

15 files changed

+540
-236
lines changed

docs/doc/en/basic/python_pkgs.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,14 @@ os.system("pip install --upgrade package_name")
2929
### Method 2: Installing Using the Terminal and pip Command
3030

3131
Follow the terminal usage method introduced in [Linux Basics](./linux_basic.md) and use `pip install package_name` to install the package you need.
32+
33+
34+
## Packages That Cannot Be Installed Directly with pip
35+
36+
pip on the device can install programs written in pure Python. However, for libraries that use other languages like C++ at the lower level, there are generally no precompiled packages available due to the unique nature of MaixCAM RISC-V.
37+
38+
Solutions:
39+
* **Method 1:** Find the source code of the corresponding package, cross-compile it into a `.whl` installation package on your computer, and then copy it to the device and use `pip install xxxx.whl` to install it. The toolchain used for compilation is the same as the one used by [MaixCDK](https://github.com/sipeed/MaixCDK/blob/main/platforms/maixcam.yaml).
40+
* **Method 2:** According to the [compilation system](../pro/compile_os.md), before compiling, you can execute `make menuconfig` in the `buildroot` directory to check if the Python interpreter's extra packages contain the software you need. After selecting it, you can recompile the system image to include the package.
41+
> If you successfully compile and test a package using Method 2 and find it necessary to integrate into the system, feel free to provide feedback through [issues](https://github.com/sipeed/maixpy/issues).
42+

docs/doc/en/comm/maix_protocol.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
---
2+
title: MaixCAM MaixPy Maix Application Communication Protocol
3+
---
4+
5+
6+
## Communication Protocol Overview
7+
8+
In order for two devices to communicate stably, there are typically several layers, starting from the bottom:
9+
10+
* **Hardware Layer**: For example, `UART` uses three wires: `TX`, `RX`, and `GND`. It can also be wireless, such as with WiFi.
11+
* **Transport Layer**: Uses transmission control protocols to ensure stable data transmission, such as the `UART` protocol, which specifies baud rate, stop bits, and parity bits to ensure correct data transmission. The `TCP` protocol works similarly.
12+
* **Application Layer**: The data obtained from the transport layer is stream data (simply put, a long string of data without punctuation). To help the application understand what the data means, the application typically defines its own communication protocol for the application layer to structure the transmitted content (you can think of this as adding punctuation to the stream of data to make it easier for the receiver to understand the sentence structure).
13+
14+
For example:
15+
The application layer protocol specifies that a data packet begins with a `$` symbol.
16+
A sends two data packets to B: `$12345$67890`. After receiving it, B knows that A has sent two packets, `12345` and `67890`. Without this protocol, if A sends `12345` followed by `67890`, since the data is transmitted as a stream, B might receive `1234567890`, making it unclear whether one or two packets were sent.
17+
18+
## Character Protocol vs. Binary Protocol
19+
20+
**Character Protocol**:
21+
In the previous example, we used `$` to mark the beginning of each packet. If we want to send the number `123`, we simply send the string `$123`, which is human-readable. The receiver needs to convert the string `123` to an `int` type. For example, in C language:
22+
```c
23+
int value;
24+
sscanf(buff, "$%d", &value);
25+
```
26+
27+
**Binary Protocol**:
28+
In a character protocol, sending the number `123` takes 4 bytes, and the receiver has to parse the string to convert it into an integer type. In a binary protocol, we can reduce the number of bytes transmitted and make it easier for the receiver to handle. We can simply send `0x24 0x7B`. `0x24` is the hexadecimal representation of the `$` symbol (refer to the ASCII table), and `0x7B` is the hexadecimal representation of the decimal number `123`. This uses only two bytes to transmit the same information that required 4 bytes in the character protocol. The receiver can directly read the second byte `0x7B` and use its value, such as in C language:
29+
```c
30+
uint8_t value = buff[1];
31+
```
32+
33+
This is just a simple explanation to help you understand the two protocols. In practice, each has its advantages depending on the specific use case, and other factors, such as checksum values, may also be considered. You can explore more and learn about it in the Maix Communication Protocol Practice section below.
34+
35+
## Maix Application Communication Protocol
36+
37+
The Maix Application Communication Protocol is an application layer protocol that uses UART or TCP as the transport layer.
38+
39+
It defines how the two parties communicate and the format in which data is transmitted, making it easier to parse and identify information. It is a binary protocol that includes frame headers, data content, checksums, etc.
40+
41+
The complete protocol definition is available in the [Maix Application Communication Protocol Standard](https://wiki.sipeed.com/maixcdk/doc/convention/protocol.html) (included in the MaixCDK documentation because MaixCDK also uses this protocol).
42+
43+
If you have no prior experience with communication protocols, it might seem a bit difficult, but by reviewing the examples below a few times, you should be able to understand it. In `MaixPy`, the API is already encapsulated, making it very simple to use. For other microcontrollers or chips, you may need to implement this protocol yourself, and you can refer to the appendix of the [Maix Application Communication Protocol Standard](https://wiki.sipeed.com/maixcdk/doc/convention/protocol.html) to check for any corresponding implementations.
44+
45+
For example, if we are performing object detection and want to send the detected object information (such as type and coordinates) via UART to another device (e.g., STM32 or Arduino microcontroller), here’s how it can be done.
46+
47+
Full Example: [MaixPy/examples/protocol/comm_protocol_yolov5.py](https://github.com/sipeed/MaixPy/tree/main/examples/protocol/comm_protocol_yolov5.py)
48+
49+
First, we need to detect the objects, based on the `yolov5` detection example. Here, we’ll skip other details and focus on how the detection results look:
50+
```python
51+
while not app.need_exit():
52+
img = cam.read()
53+
objs = detector.detect(img, conf_th = 0.5, iou_th = 0.45)
54+
for obj in objs:
55+
img.draw_rect(obj.x, obj.y, obj.w, obj.h, color = image.COLOR_RED)
56+
msg = f'{detector.labels[obj.class_id]}: {obj.score:.2f}'
57+
img.draw_string(obj.x, obj.y, msg, color = image.COLOR_RED)
58+
dis.show(img)
59+
```
60+
You can see that `objs` is a list of detection results. Here, we draw bounding boxes on the screen, but we can also send these results via UART.
61+
62+
We don't need to manually initialize the UART; we can directly use the built-in `maix.comm, maix.protocol` modules. By calling `comm.CommProtocol`, the UART is automatically initialized, with a default baud rate of `115200`. Communication protocol settings can be configured in the device's `System Settings -> Communication Protocol`. There might also be other communication methods, such as `TCP`, with the default set to `UART`. You can check the current setting by using `maix.app.get_sys_config_kv("comm", "method")`.
63+
64+
```python
65+
from maix import comm, protocol, app
66+
from maix.err import Err
67+
import struct
68+
69+
def encode_objs(objs):
70+
'''
71+
Encode objects info to bytes body for protocol
72+
2B x(LE) + 2B y(LE) + 2B w(LE) + 2B h(LE) + 2B idx ...
73+
'''
74+
body = b""
75+
for obj in objs:
76+
body += struct.pack("<hhHHH", obj.x, obj.y, obj.w, obj.h, obj.class_id)
77+
return body
78+
79+
APP_CMD_ECHO = 0x01 # Custom command 1, for testing, not used here, just reserved
80+
APP_CMD_DETECT_RES = 0x02 # Custom command 2, send detected object information
81+
# You can define more custom commands for your application
82+
83+
p = comm.CommProtocol(buff_size = 1024)
84+
85+
while not app.need_exit():
86+
# ...
87+
objs = detector.detect(img, conf_th = 0.5, iou_th = 0.45)
88+
if len(objs) > 0:
89+
body = encode_objs(objs)
90+
p.report(APP_CMD_DETECT_RES, body)
91+
# ...
92+
```
93+
94+
In the `encode_objs` function, we pack the detected object information into a `bytes` type data. Then, using the `p.report` function, we send the result.
95+
96+
The `body` content is simply defined as `2B x(LE) + 2B y(LE) + 2B w(LE) + 2B h(LE) + 2B idx ...`, where:
97+
98+
* For each object, we send 10 bytes (2 bytes for each of the `x`, `y`, `w`, `h`, and `class_id` coordinates). The `x` coordinate is represented as a short integer, encoded in little-endian (LE) format.
99+
* The loop encodes all objects and concatenates them into one byte array (`bytes`).
100+
101+
When calling the `report` function, the protocol header, checksum, and other details are automatically added at the lower level, resulting in a complete data frame ready to be received.
102+
103+
On the receiving end, you can decode the data according to the protocol. If the receiver is also using MaixPy, you can directly use:
104+
```python
105+
while not app.need_exit():
106+
msg = p.get_msg()
107+
if msg and msg.is_report and msg.cmd == APP_CMD_DETECT_RES:
108+
print("Received objects:", decode_objs(msg.get_body()))
109+
p.resp_ok(msg.cmd, b'1')
110+
```
111+
112+
If the device is something like an STM32 or Arduino, you can refer to the C language functions in the appendix of the [Maix Application Communication Protocol Standard](https://wiki.sipeed.com/maixcdk/doc/convention/protocol.html) for encoding and decoding.

0 commit comments

Comments
 (0)