Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 3dac443

Browse files
authored
Portenta Hat Carrier: User Manual Fan Control Section Minor Typo Patch (#1443)
* User manual fan control section minor typo patch * Minor content update * Content minor patch * Content minor patch * Content minor patch * Removed Docker Hello World Section * Linter patch
1 parent eac40be commit 3dac443

File tree

2 files changed

+27
-218
lines changed

2 files changed

+27
-218
lines changed
-2.02 KB
Binary file not shown.

‎content/hardware/04.pro/carriers/portenta-hat-carrier/tutorials/user-manual/content.md‎

Lines changed: 27 additions & 218 deletions
Original file line numberDiff line numberDiff line change
@@ -419,217 +419,6 @@ python3 hello_world_python.py
419419

420420
Portenta Hat Carrier's user programmable LED will start blinking whenever the script is running.
421421

422-
#### Hello World Using Linux and Docker
423-
<br></br>
424-
425-
We can use the Python® script and create a Docker image as well for containerized applications.
426-
427-
For you convenience, the example files can be downloaded [here](assets/hello_world_led.zip) and used as a template for containerizing further examples.
428-
429-
The example script to use will be the following sketch:
430-
431-
```python
432-
#!/usr/bin/env python3
433-
434-
import serial
435-
import logging
436-
437-
class GPIOController:
438-
def __init__(self, gpio_number):
439-
self.gpio_number = gpio_number
440-
self.gpio_path = f"/sys/class/gpio/gpio{gpio_number}/"
441-
442-
def export(self):
443-
with open("/sys/class/gpio/export", "w") as f:
444-
f.write(str(self.gpio_number))
445-
446-
def unexport(self):
447-
with open("/sys/class/gpio/unexport", "w") as f:
448-
f.write(str(self.gpio_number))
449-
450-
def set_direction(self, direction):
451-
with open(f"{self.gpio_path}direction", "w") as f:
452-
f.write(direction)
453-
454-
def read_direction(self):
455-
with open(f"{self.gpio_path}direction", "r") as f:
456-
return f.read().strip()
457-
458-
def set_value(self, value):
459-
with open(f"{self.gpio_path}value", "w") as f:
460-
f.write(str(value))
461-
462-
def read_value(self):
463-
with open(f"{self.gpio_path}value", "r") as f:
464-
return int(f.read().strip())
465-
466-
def main():
467-
468-
logging.info("============================================")
469-
logging.info("Hello World PHC!")
470-
logging.info("============================================")
471-
472-
ser = serial.Serial()
473-
ser.baudrate = 19200
474-
ser.port = '/dev/ttymxc3'
475-
ser.bytesize = 8
476-
ser.parity = 'N'
477-
ser.stopbits = 2
478-
ser.timeout = 1
479-
logging.debug("Configured serial port with:\n\r%s" % str(ser))
480-
logging.debug("Opening serial port")
481-
482-
gpio = GPIOController(163)
483-
484-
# Export GPIO
485-
gpio.export()
486-
487-
# Set as output
488-
gpio.set_direction("out")
489-
if gpio.read_direction() == "out":
490-
print("GPIO set as output.")
491-
492-
# Turn on (set to 1) and then off (set to 0)
493-
while True:
494-
gpio.set_value(1)
495-
time.sleep(1)
496-
gpio.set_value(0)
497-
time.sleep(1)
498-
499-
# Unexport
500-
# gpio.unexport()
501-
502-
if __name__ == "__main__":
503-
main()
504-
```
505-
506-
The provided Python® script begins with the import of required modules. The `serial` library, in particular, will help us to communicate over serial ports. This script then defines a `GPIOController` class that packages the functionalities we executed manually in the shell commands.
507-
508-
This abstraction makes it easier to manipulate the GPIO without having to rewrite shell commands for every operation. Functions like `export`, `unexport`, `set_direction`, and `set_value` are used to mirror the actions we took in our manual steps.
509-
510-
The decision to containerize the Python® script using Docker ensures that it runs in a consistent environment and is isolated from other processes. Docker provides a mechanism to create containerized applications that can be executed reliably across various platforms.
511-
512-
```bash
513-
# dockerfile
514-
515-
# Use an official Python runtime as the base image
516-
FROM python:3.9-slim
517-
518-
COPY requirements.txt ./
519-
520-
RUN set -ex \
521-
&& pip3 --disable-pip-version-check --no-cache-dir install \
522-
-r requirements.txt \
523-
&& rm ./requirements.txt
524-
525-
# Set the working directory
526-
WORKDIR /app
527-
528-
# Copy the local code to the container
529-
COPY ./src/hello_world_led.py ./
530-
531-
RUN chmod 755 -R .
532-
533-
# Run the Python script
534-
CMD ["python", "./hello_world_led.py"]
535-
```
536-
537-
The _dockerfile_ begins by selecting an official Python® runtime as the base image, which ensures Python® is set up and ready to run scripts. Following this, the _`requirements.txt`_ file, which lists the Python® libraries our script depends upon, is copied into the Docker image. The pip command is then used to install these dependencies.
538-
539-
The script depends on external libraries for functionality, specifically the `pyserial` library for this instance, which aids in serial communication. This library is defined in the _`requirements.txt`_ file.
540-
541-
You must manually create this text file and add the following line to it. In further applications, this file will contain any Python® library that is needed to support your script.
542-
543-
```
544-
pyserial==3.4
545-
```
546-
547-
Within the dockerfile, a working directory, `/app`, is defined inside the container. The Python® script is copied into this directory and granted execution permissions, ensuring that it can run without issues. The concluding action sets the default command for the Docker container to initiate the Python® script when the container starts.
548-
549-
```bash
550-
# docker-compose.yaml
551-
552-
version: '3.6'
553-
554-
services:
555-
hello_world_led:
556-
image: hello_world_led:latest
557-
container_name: 'hello_world_led'
558-
restart: unless-stopped
559-
environment:
560-
- PYTHONUNBUFFERED=1
561-
volumes:
562-
- '/var/run/secrets:/app/config/'
563-
- '/run/arduino_hw_info.env:/run/arduino_hw_info.env:ro'
564-
extra_hosts:
565-
- 'm4-proxy:host-gateway'
566-
devices:
567-
- '/dev/ttymxc3'
568-
tty: true
569-
user: "0"
570-
```
571-
572-
This file tree diagram illustrates how the directory should be structured, containing both the Python® script and the associated Docker components:
573-
574-
```
575-
└── hello_world_led
576-
├── src
577-
│ ├── hello_world_led.py
578-
├── Docker-build.conf
579-
├── docker-compose.yaml
580-
├── dockerfile
581-
└── requirements.txt
582-
```
583-
584-
For the Portenta X8, you will need to upload the Python® script along with the Docker elements. You can set up a directory (with a name of your choosing), in this case `hello_world_led`, within the container resources for dockerization to ease this transfer:
585-
586-
```
587-
adb push <local directory path> /home/fio
588-
```
589-
590-
Once the files are transferred, access the shell of the Portenta X8 with elevated privileges:
591-
592-
```
593-
adb shell
594-
sudo su -
595-
```
596-
597-
To execute the script, first build the Docker image. Navigate to the directory containing the previously mentioned files and run:
598-
599-
```bash
600-
sudo docker build . -t hello_world_led
601-
```
602-
603-
The commands provided outline the process of starting the container with the necessary permissions, ensuring access to the required components on the Portenta X8.
604-
605-
The following commands run the container and ensure that the script inside can interact with the GPIOs, even within the container's environment.
606-
607-
Following command uses the _docker-compose.yml_ configuration file to start the services defined within. It is a tool for defining and running multi-container Docker applications.
608-
609-
```bash
610-
docker compose up
611-
```
612-
613-
Then we have the next command allowing us to run the `hello_world_led` container with elevated privileges, giving it almost the same level of access to the host as processes running outside containers.
614-
615-
```bash
616-
docker run --privileged hello_world_led
617-
```
618-
619-
This is useful for certain operations like direct hardware access, which is likely necessary for GPIO interactions.
620-
621-
Subsequently, the following command mounts the host's `/sys` directory into the `hello_world_led` container, which is often used for interacting with device drivers and kernel features.
622-
623-
```bash
624-
docker run -v /sys:/sys hello_world_led
625-
```
626-
627-
This allows the container to have direct access to the host's GPIOs and other system attributes. Given its access capabilities, the container can be run; however, always ensure the configuration is set correctly.
628-
629-
The Python® scripts found later in the user manual can be used to containerize and leverage benefits of using Docker.
630-
631-
***To delve deeper into the use of Docker and custom containers on the Portenta X8, refer to this [tutorial](https://docs.arduino.cc/tutorials/portenta-x8/custom-container).***
632-
633422
Please check out the [Portenta X8 user manual](https://docs.arduino.cc/tutorials/portenta-x8/user-manual) to learn how the board operates, and maximize its potential when paired with the Portenta Hat Carrier. The Portenta Hat Carrier supports the Portenta X8 via High-Density connectors.
634423

635424
The Portenta X8 has the capability to operate in Linux environment, and it is based on Yocto Linux distribution. It is recommendable to read how the Portenta X8 works in terms of Linux environment [here](https://docs.arduino.cc/tutorials/portenta-x8/user-manual#linux-environment).
@@ -1443,7 +1232,7 @@ echo 50000 | sudo tee /sys/class/pwm/pwmchip0/pwm9/duty_cycle #50% duty
14431232
And activate the PWM channel:
14441233

14451234
```
1446-
echo | sudo tee /sys/class/pwm/pwmchip0/pwm9/enable
1235+
echo 1 | sudo tee /sys/class/pwm/pwmchip0/pwm9/enable
14471236
```
14481237

14491238
Consider the following Python® script if you would like to automate the command sequence:
@@ -1990,7 +1779,19 @@ Using the Portenta X8 in combination with the Hat Carrier allows you to evaluate
19901779

19911780
To use the _iperf3_ tool, we will set the Portenta X8 and Hat Carrier as the Server and the controlling computer as the Client. The commands will measure the bandwidth between the Portenta Hat Carrier with Portenta X8 and the computer. For a deeper understanding of _iperf3_, refer to its [official documentation](https://iperf.fr/iperf-doc.php).
19921781

1993-
Begin by setting up the Portenta Hat Carrier with Portenta X8 as the Server. For the configuration of the necessary files to establish _iperf3_ on the device, follow the steps for _Linux and Cygwin_ under _General Build Instructions_ available [here](https://github.com/userdocs/iperf3-static).
1782+
Begin by setting up the Portenta Hat Carrier with Portenta X8 as the Server. For the configuration of the necessary files to establish _iperf3_ on the device, follow the steps for _Linux and Cygwin_ under _General Build Instructions_ available [here](https://github.com/userdocs/iperf3-static). In this case, we need _aarch64 / arm64_ version, thus we need to execute following commands:
1783+
1784+
```bash
1785+
mkdir -p ~/bin && source ~/.profile
1786+
```
1787+
1788+
```bash
1789+
wget -qO ~/bin/iperf3 https://github.com/userdocs/iperf3-static/releases/latest/download/iperf3-arm64v8
1790+
```
1791+
1792+
```bash
1793+
chmod 700 ~/bin/iperf3
1794+
```
19941795

19951796
Once installed, _iperf3_ will be ready on your device. To ensure it operates without issues, run:
19961797

@@ -2004,16 +1805,24 @@ By following the provided instructions, the tool should be located in the Linux
20041805
# ~bin/
20051806
```
20061807

1808+
Check the tool's version using the following command:
1809+
1810+
```bash
1811+
./iperf3 -v
1812+
```
1813+
1814+
It should display the version information for the _iperf3_ tool.
1815+
20071816
Activate the Portenta Hat Carrier with Portenta X8 as a Server using the command:
20081817

20091818
```bash
2010-
iperf3 -s
1819+
./iperf3 -s
20111820
```
20121821

20131822
This will set the Server to wait for connections via its IP address. It listens on port `5201` by default. To use an alternative port, append `-p` and your chosen port number:
20141823

20151824
```bash
2016-
iperf3 -s -p <Port Number>
1825+
./iperf3 -s -p <Port Number>
20171826
```
20181827

20191828
To identify the IP address of the Portenta X8, you can use either of the following commands and search for `eth0` which provides the network information related to Ethernet connection:
@@ -2794,7 +2603,7 @@ It can interact with up to four relay ports on the board. Among its various feat
27942603
```python
27952604
from __future__ import print_function
27962605

2797-
import smbus2 import SMBus
2606+
from smbus2 import SMBus
27982607

27992608
# The number of relay ports on the relay board.
28002609
# This value should never change!
@@ -2807,7 +2616,7 @@ DEVICE_ADDRESS = 0x20 # 7 bit address (will be left shifted to add the read wri
28072616
DEVICE_REG_MODE1 = 0x06
28082617
DEVICE_REG_DATA = 0xff
28092618

2810-
bus = smbus.SMBus(3) # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)
2619+
bus = SMBus(3) # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)
28112620

28122621

28132622
def relay_on(relay_num):
@@ -3659,7 +3468,7 @@ def processData(data):
36593468
print("Received:", data) # For now, just print the data. Modify as needed.
36603469

36613470
# Set up the serial port
3662-
ser = serial.Serial('/dev/ttymxc1', 9600) # Use the appropriate port and baud rate for your device
3471+
ser = serial.Serial('/dev/ttymxc3', 9600) # Use the appropriate port and baud rate for your device
36633472

36643473
incoming = ""
36653474

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /