Skip to content

Commit 5108952

Browse files
authored
Merge pull request #507 from luxonis/standalone_mode
Added standalone mode docs
2 parents 5fc698f + 1abdcf9 commit 5108952

File tree

3 files changed

+164
-47
lines changed

3 files changed

+164
-47
lines changed

docs/source/components/bootloader.rst

Lines changed: 6 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,14 @@ Bootloader
55

66
Depthai bootloader is a small program which aids in booting and updating bootloader or depthai application packages.
77

8-
To be able to run hostless, the Depthai bootloader must be first flashed to the devices flash.
9-
This step is required only once.
8+
To be able to run standalone (:ref:`documentation here <Standalone mode>`), the Depthai bootloader must be first
9+
flashed to the devices flash. This step is required only once.
1010

11-
Plug USB to the board
12-
Flash bootloader using DeviceBootloader::flashBootloader (Check Example at the bottom)
13-
Disconnect the board and switch the boot mode GPIO to the following settings: BOOT[4:0] : 01000 (see attached images for reference)
14-
Reassemble the board
11+
Once the device has the bootloader flashed, it will perform the same as before. Running pipelines with a host
12+
connected doesn’t require any changes.
1513

16-
Once the device has the bootloader flashed, it will perform the same as before. Running pipelines with a host connected doesn’t require any changes.
17-
18-
Suggested workflow is to perform as much of development as possible with the host connected as the iteration cycle is greatly improved.
14+
Suggested workflow is to perform as much of development as possible with the host connected as the
15+
iteration cycle is greatly improved.
1916

2017
Once desired pipeline is created, use the following function to flash: :code:`DeviceBootloader::flash`
2118

@@ -54,42 +51,4 @@ Depthai application package (**.dap**) consists of:
5451
- Assets structure (section “assets”)
5552
- Asset storage (section “asset_storage”)
5653

57-
Example
58-
#######
59-
60-
Following section will show an example of: Flashing bootloader (needed only once) and flashing a created Pipeline “myExamplePipeline” to the device
61-
(The example is written in Python, similar steps apply to C++)
62-
63-
#. **Flashing bootloader**
64-
65-
.. code-block:: python
66-
67-
import depthai as dai
68-
(f, bl) = dai.DeviceBootloader.getFirstAvailableDevice()
69-
bootloader = dai.DeviceBootloader(bl)
70-
progress = lambda p : print(f'Flashing progress: {p*100:.1f}%')
71-
bootloader.flashBootloader(progress)
72-
73-
.. note::
74-
Make sure to switch GPIO BOOT mode settings (See image below for more details)
75-
76-
#. **Flashing created pipeline**
77-
78-
.. code-block:: python
79-
80-
import depthai as dai
81-
# ...
82-
# Create Pipeline 'myExamplePipeline'
83-
# ...
84-
(f, bl) = dai.DeviceBootloader.getFirstAvailableDevice()
85-
bootloader = dai.DeviceBootloader(bl)
86-
progress = lambda p : print(f'Flashing progress: {p*100:.1f}%')
87-
bootloader.flash(progress, myExamplePipeline)
88-
89-
90-
GPIO boot settings. Boot settings must be set as following: BOOT[4:0] : 01000 and GPIO58 (WAKEUP): 0
91-
92-
.. image:: /_static/images/components/boot-depthai.jpeg
93-
:alt: boot-depthai
94-
9554
.. include:: ../includes/footer-short.rst

docs/source/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ node functionalities are presented with code.
6565
:caption: Tutorials:
6666

6767
tutorials/hello_world.rst
68+
tutorials/standalone_mode.rst
6869
tutorials/multiple.rst
6970
tutorials/maximize_fov.rst
7071
tutorials/debugging.rst
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
Standalone mode
2+
===============
3+
4+
**Standalone / Hostless / On-The-Edge mode** means that the OAK camera isn't connected to a host computer. This can
5+
be achieved by first :ref:`flashing the bootloader <Flash bootloader>` and then :ref:`flashing the pipeline <Flash pipeline>`
6+
and assets (NN models) to the OAK's flash memory.
7+
8+
Standalone mode is **only possible on OAKs that have on-board flash** memory, which are currently `OAK IOT <https://docs.luxonis.com/projects/hardware/en/latest/#iot-designs>`__
9+
and `OAK POE <https://docs.luxonis.com/projects/hardware/en/latest/#poe-designs>`__ camera models.
10+
11+
Converting a demo to standalone mode
12+
####################################
13+
14+
Since there won't be any communication between the host and the device, you first need to remove all
15+
:ref:`XLinkOut` and :ref:`XLinkIn` nodes. This means that the device will only communicate with the "outside world"
16+
via either SPI (:ref:`SPIOut`/:ref:`SPIIn`) or :ref:`Script` node (GPIO/UART or network protocols if you have
17+
OAK POE mode; HTTP/TCP/UDP...).
18+
19+
Next thing you can also remove the host-side code, which usually looks something like this:
20+
21+
.. code-block:: python
22+
23+
with dai.Device(pipeline) as device:
24+
videoQ = device.getOutputQueue("video")
25+
faceDetQ = device.getOutputQueue("face_det")
26+
nnQ = device.getOutputQueue("nn")
27+
28+
while True:
29+
frame = videoQ.get().getCvFrame()
30+
# ...
31+
32+
33+
After you remove all host-side code, you would only be left with the :ref:`Pipeline` definition (with nodes/links).
34+
Since device no longer communicates with the host, you need to "route" your program's output through either SPI
35+
or script node, as mentioned above.
36+
37+
Flash bootloader
38+
################
39+
40+
Execute the code below to flash the :ref:`Bootloader` to the device. The bootloader is packaged together with the
41+
depthai, so if you have the latest depthai version, you will flash the latest bootloader version. This step
42+
is required only once.
43+
44+
.. code-block:: python
45+
46+
import depthai as dai
47+
(f, bl) = dai.DeviceBootloader.getFirstAvailableDevice()
48+
bootloader = dai.DeviceBootloader(bl)
49+
progress = lambda p : print(f'Flashing progress: {p*100:.1f}%')
50+
bootloader.flashBootloader(progress)
51+
52+
Flash pipeline
53+
##############
54+
55+
After you have standalone :ref:`Pipeline` definition and :ref:`Bootloader` already flashed on the device, you
56+
can start with flashing the pipeline. You can flash the pipeline with the following snippet:
57+
58+
.. code-block:: python
59+
60+
import depthai as dai
61+
62+
pipeline = dai.Pipeline()
63+
64+
# Define standalone pipeline; add nodes and link them
65+
# cam = pipeline.create(dai.node.ColorCamera)
66+
# script = pipeline.create(dai.node.Script)
67+
# ...
68+
69+
# Flash the pipeline
70+
(f, bl) = dai.DeviceBootloader.getFirstAvailableDevice()
71+
bootloader = dai.DeviceBootloader(bl)
72+
progress = lambda p : print(f'Flashing progress: {p*100:.1f}%')
73+
bootloader.flash(progress, pipeline)
74+
75+
After successfully flashing the pipeline, it will get started automatically when you power up the device.
76+
If you would like to change the flashed pipeline, simply re-flash it again.
77+
78+
Clear flash
79+
###########
80+
81+
Since pipeline will start when powering the device, this can lead to unnecesary heating. If you would like to clear
82+
the flashed pipeline, use the code snippet below.
83+
84+
.. warning::
85+
Code below doesn't work yet. We will be adding "flashClear" helper function to the library.
86+
87+
.. code-block:: python
88+
89+
import depthai as dai
90+
(f, bl) = dai.DeviceBootloader.getFirstAvailableDevice()
91+
if not f:
92+
print('No devices found, exiting...')
93+
exit(-1)
94+
95+
with dai.DeviceBootloader(bl) as bootloader:
96+
bootloader.flashClear()
97+
98+
Factory reset
99+
#############
100+
101+
In case you have soft-bricked your device, or just want to clear everything (flashed pipeline/assets and bootloader config),
102+
we recommend running the factory reset script below. It will also flash the latest bootloader version.
103+
104+
.. code-block:: python
105+
106+
import depthai as dai
107+
import tempfile
108+
109+
blBinary = dai.DeviceBootloader.getEmbeddedBootloaderBinary(dai.DeviceBootloader.Type.NETWORK)
110+
blBinary = blBinary + ([0xFF] * ((8 * 1024 * 1024 + 512) - len(blBinary)))
111+
112+
with tempfile.NamedTemporaryFile() as tmpBlFw:
113+
tmpBlFw.write(bytes(blBinary))
114+
115+
(f, device_info) = dai.DeviceBootloader.getFirstAvailableDevice()
116+
if not f:
117+
print('No devices found, exiting...')
118+
exit(-1)
119+
120+
with dai.DeviceBootloader(device_info, allowFlashingBootloader=True) as bootloader:
121+
progress = lambda p : print(f'Factory reset progress: {p*100:.1f}%')
122+
# Override SBR table, to prevent booting flashed application
123+
[success, msg] = bootloader.flashBootloader(progress, tmpBlFw.name)
124+
if success:
125+
print('Successfully overwritten SBR table. Device should now be reacheable through PoE')
126+
else:
127+
print(f"Couldn't overwrite SBR table to unbrick the device. Error: {msg}")
128+
129+
You can also **factory reset OAK POE at specific IP** if it's not reachable (not in same LAN).
130+
131+
.. code-block:: python
132+
133+
import depthai as dai
134+
import tempfile
135+
136+
blBinary = dai.DeviceBootloader.getEmbeddedBootloaderBinary(dai.DeviceBootloader.Type.NETWORK)
137+
blBinary = blBinary + ([0xFF] * ((8 * 1024 * 1024 + 512) - len(blBinary)))
138+
139+
with tempfile.NamedTemporaryFile() as tmpBlFw:
140+
tmpBlFw.write(bytes(blBinary))
141+
142+
device_info = dai.DeviceInfo()
143+
device_info.state = dai.XLinkDeviceState.X_LINK_BOOTLOADER
144+
device_info.desc.protocol = dai.XLinkProtocol.X_LINK_TCP_IP
145+
device_info.desc.name = "192.168.34.110" # Set IP here
146+
147+
with dai.DeviceBootloader(device_info, allowFlashingBootloader=True) as bootloader:
148+
progress = lambda p : print(f'Factory reset progress: {p*100:.1f}%')
149+
# Override SBR table, to prevent booting flashed application
150+
[success, msg] = bootloader.flashBootloader(progress, tmpBlFw.name)
151+
if success:
152+
print('Successfully overwritten SBR table. Device should now be reacheable through PoE')
153+
else:
154+
print(f"Couldn't overwrite SBR table to unbrick the device. Error: {msg}")
155+
156+
157+
.. include:: ../includes/footer-short.rst

0 commit comments

Comments
 (0)