Add LED strip support layer (#168)

Co-authored-by: sfalexrog <sfalexrog@gmail.com>
This commit is contained in:
Oleg Kalachev
2019-08-29 22:17:49 +03:00
committed by GitHub
parent 1773a1ccae
commit f9b1a82b5e
18 changed files with 877 additions and 175 deletions

View File

@@ -71,6 +71,7 @@
* [Модуль ESP8266](esp8266_bridge.md)
* [Сборка и модификация образа Клевера](image_building.md)
* [Подключение регулятора 4 в 1](4in1.md)
* [Светодиодная лента (legacy)](leds_old.md)
* [Вклад в Клевер](contributing.md)
* Мероприятия
* [Олимпиада НТИ 2019](nti2019.md)

View File

@@ -250,7 +250,7 @@
## Подключение светодиодной ленты к Raspberry Pi
1. Питание для ленты берется от второго BEC. Подключите контакты *«-»* и *«+»* к *Ground* и *5v* на ленте соответственно.
2. Контакт *D* можно подключить к любому свободному пину "GPIO" на Raspberry.
2. Подключите контакт *D* к GPIO-пину на Raspberry. Рекомендуется использовать пин GPIO21.
<img src="../assets/4/31_1.png" width=300 class="zoom center border">

View File

@@ -1,125 +1,154 @@
# Работа со светодиодной лентой на Raspberry 3
# Работа со светодиодной лентой
## Подключение и определение типа ленты
> **Note** Документация для версии образа, начиная с 0.18. Для более ранних версий см. [предыдущую версию статьи](leds_old.md).
> **Note** Документация для версии образа, начиная с 0.14. Для более ранних версий см. [документацию для версий 0.13](https://github.com/CopterExpress/clever/blob/v0.13/docs/leds.md)
Адресуемая RGB-светодиодная лента типа *ws281x*, которая входит в наборы "Клевер", позволяет выставлять произвольные 24-битные цвета на каждый из отдельных светодиодов. Это позволяет сделать полет Клевера более ярким, а также визуально получать информацию о полетных режимах, этапе выполнения пользовательской программы и других событиях.
Подключите светодиодную ленту к питанию +5v - 5v, земле GND - GND и сигнальному порту DIN - GPIO30, GPIO21, GPIO18.
<img src="../assets/clever-led.png" class="center" width=600>
<img src="../assets/led_connection.png" height="400px" alt="leds">
На образе [для RPi](image.md) предустановлены необходимые модули для работы с лентой. Они позволяют:
> **Caution** Обратите внимание, что светодиодную ленту нужно питать от стабильного источника энергии. Если вы подключите питание напрямую к Raspberry, то это создаст слишком большую нагрузку на ваш микрокомпьютер. Для снятия нагрузки с Raspberry можно подключить питание к преобразователю `BEC`.
* управлять эффектами/анимациями на ленте;
* управлять лентой на низком уровне (переключением цветов отдельных светодиодов);
* настраивать реакцию ленты на полетные события.
<!-- -->
> **Caution** Обратите внимание, что светодиодную ленту нужно питать от стабильного источника энергии. Если вы подключите питание напрямую к Raspberry, то это создаст слишком большую нагрузку на ваш микрокомпьютер. Для снятия нагрузки с Raspberry можно подключить питание к преобразователю BEC.
> **Note** При работе с [GPIO](gpio.md) следует подключать ленту к пину GPIO21. В противном случае управление LED-лентой будет работать некорректно.
## Высокоуровневое управление лентой
## Совместимость с ROS и Python
1. Для работы с лентой подключите ее к питанию +5v 5v, земле GND GND и сигнальному порту DIN GPIO21. Обратитесь [к инструкции по сборке](assemble_4.md#Подключение-светодиодной-ленты-к-Raspberry-Pi) для подробностей.
2. Включите поддержку LED-ленты в файле `~/catkin_ws/src/clever/clever/launch/clever.launch`:
Чтобы корректно работать со светодиодной лентой вам нужно добавить в окружение необходимые пути к библиотекам Python и пакетам ROS, для этого необходимо добавить в файл `/etc/sudoers` следующие строки:
```xml
<arg name="led" default="true"/>
```
```
Defaults env_keep += "PYTHONPATH"
Defaults env_keep += "PATH"
Defaults env_keep += "ROS_ROOT"
Defaults env_keep += "ROS_MASTER_URI"
Defaults env_keep += "ROS_PACKAGE_PATH"
Defaults env_keep += "ROS_LOCATIONS"
Defaults env_keep += "ROS_HOME"
Defaults env_keep += "ROS_LOG_DIR"
```
3. Настройте параметры подключения ленты *ws281x* в файле `~/catkin_ws/src/clever/clever/launch/led.launch`. Необходимо ввести верное количество светодиодов в ленте и GPIO-пин, использованный для подключения (если он отличается от *GPIO21*):
## Пример программы для светодиодной ленты на RPI3
```xml
<param name="led_count" value="30"/> <!-- количество светодиодов в ленте -->
<param name="gpio_pin" value="21"/> <!-- GPIO-пин для подключения -->
```
Для проверки работоспособности ленты можете использовать приведенный ниже код, данный код поочередно зажжет первые 10 диодов 3 цветами и в конце их погасит.
Высокоуровневое управления лентой позволяет управлять текущим эффектом (анимацией) на ленте. Для этого используется ROS-сервис `/led/set_effect`. Параметры сервиса:
* `effect` название необходимого эффекта.
* `r`, `g`, `b` цвет эффекта в формате [RGB](https://ru.wikipedia.org/wiki/RGB). Значения изменяются от 0 до 255.
Список доступных эффектов:
* `fill` (или пустая строка) залить всю ленту цветом;
* `blink` мигание цветом;
* `blink_fast` ускоренное мигание цветом;
* `fade` плавное перетекание в цвет;
* `wipe`  "надвигание" нового цвета;
* `flash` быстро мигнуть цветом 2 раза и вернуться к предыдущему эффекту;
* `rainbow` переливание ленты цветами радуги;
* `rainbow_fill` переливать заливку по цветам радуги.
Пример работы с сервисом из Python:
```python
import time
import rospy
from clever.srv import SetLEDEffect
from rpi_ws281x import Adafruit_NeoPixel
from rpi_ws281x import Color
# ...
set_effect = rospy.ServiceProxy('led/set_effect', SetLEDEffect) # define proxy to ROS-service
LED_COUNT = 10 # Количество светодиодов в ленте
LED_PIN = 21 # GPIO пин, к которому вы подсоединяете светодиодную ленту
LED_FREQ_HZ = 800000 # Частота несущего сигнала (обычно 800 кГц)
LED_DMA = 10 # DMA-канал для генерации сигнала (обычно 10)
LED_BRIGHTNESS = 255 # Яркость: 0 - наименьшая, 255 - наибольшая
LED_INVERT = False # True для инвертирования сигнала (для подключения через NPN транзистор)
LED_CHANNEL = 0 # '1' для GPIO 13, 19, 41, 45 или 53
# ..
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT)
set_effect(r=255, g=0, b=0) # fill strip with red color
rospy.sleep(2)
strip.begin()
set_effect(r=0, g=100, b=0) # fill strip with green color
rospy.sleep(2)
set_effect(effect='fade', r=0, g=0, b=255) # fade to blue color
rospy.sleep(2)
def colorWipe(strip, color, wait_ms=50):
"""Заполнение ленты цветом по одному светодиоду."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
time.sleep(wait_ms/1000.0)
set_effect(effect='flash', r=255, g=0, b=0) # flash twice with red color
rospy.sleep(5)
set_effect(effect='blink', r=255, g=255, b=255) # blink with white color
rospy.sleep(5)
print('Color wipe animations.')
colorWipe(strip, Color(255, 0, 0), wait_ms=100) # Заполнение красным
colorWipe(strip, Color(0, 255, 0), wait_ms=100) # Заполнение зелёным
colorWipe(strip, Color(0, 0, 255), wait_ms=100) # Заполнение синим
colorWipe(strip, Color(0, 0, 0), wait_ms=100) # Выключение ленты
set_effect(effect='rainbow') # show rainbow
```
> **Note** Вы так же можете использовать тестовый код разработчиков данного модуля. Вы можете его [скачать](https://github.com/rpi-ws281x/rpi-ws281x-python/tree/master/examples "Github разработчика") из репозитория разработчика.
Сохраните программу в ваш скрипт и запустите его используя права администратора:
Также лентой можно управлять из командной сроки (Bash):
```bash
sudo python YourScriptName.py
rosservice call /led/set_effect "{effect: 'fade', r: 0, g: 0, b: 255}"
```
## Основные функции используемые для работы со светодиодной лентой
```bash
rosservice call /led/set_effect "{effect: 'rainbow'}"
```
Для подключения библиотеки и её корректной работы требуется подключить следующие модули: `Adafruit_NeoPixel` и `Color` - для работы ленты и `time` для управления задержками.
## Настройка реакции ленты на события
Клевер умеет показывать LED-лентой текущее состояние полетного контроллера и сигнализировать о событиях. Данная функция настраивается в файле `~/catkin_ws/src/clever/clever/launch/led.launch` в разделе *events effects table*. Пример настройки:
```xml
startup: { r: 255, g: 255, b: 255 }
connected: { effect: rainbow }
disconnected: { effect: blink, r: 255, g: 50, b: 50 }
<!-- ... -->
```
В левой части таблицы указывается событие, на которая лента должна среагировать. В правой части указывается эффект (анимация), который необходимо включить при возникновении события. Список поддерживаемых событий:
* `startup` запуск всех систем Клевера;
* `connected` успешное подключение к полетному контроллеру;
* `disconnected` разрыв связи с полетным контроллером;
* `armed` переключение полетного контроллера в состояние Armed;
* `disarmed` переключение полетного контроллера в состояние Disarmed;
* `stabilized`, `acro`, `rattitude`, `altctl`, `posctl`, `offboard`, `mission`, `rtl`, `land` переключение полетных режимов;
* `error` возникновение ошибки в ROS-нодах или полетном контроллере (*ERROR*-сообщение в топике `/rosout`);
* `low_battery` – низкий заряд батареи (порог настраивается в параметре `threshold`).
> **Note** Для корректной работы сигнализации LED-лентой о низком заряде батареи необходимо корректная [калибровка электропитания](power.md#Калибровка-делителя-напряжения).
Для того, чтобы отключить реакцию светодиодной ленты на события, установите аргумент `led_notify` в файле `~/catkin_ws/src/clever/clever/launch/led.launch` в значение `false`:
```xml
<arg name="led_notify" default="false"/>
```
## Низкоуровневое управление лентой
Для управления отдельными светодиодами используется ROS-сервис `/led/set_leds`. В параметрах задается массив номеров и RGB-цветов светодиодов, которые необходимо переключить.
Пример работы с сервисом из Python:
```python
from rpi_ws281x import Adafruit_NeoPixel
from rpi_ws281x import Color
import time
import rospy
from led_msgs.srv import SetLEDs
from led_msgs.msg import LEDStateArray, LEDState
# ...
set_leds = rospy.ServiceProxy('led/set_leds', SetLEDs) # define proxy to ROS service
# ...
# switch LEDs number 0, 1 and 2 to red, green and blue color:
set_leds([LEDState(0, 255, 0, 0), LEDState(1, 0, 255, 0), LEDState(2, 0, 0, 255)])
```
Для работы с лентой необходимо создать объект типа `Adafruit_NeoPixel` и инициализировать библиотеку:
Сервис можно использовать из командной строки:
```python
# Создание объекта NeoPixel c заданной конфигурацией
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT)
# Инициализация библиотеки, должна быть выполнена перед другими функциями
strip.begin()
```bash
rosservice call /led/set_leds "leds:
- index: 0
r: 50
g: 100
b: 200"
```
Основные функции, которые используются для управления лентой:
При использовании ленты в ROS-топике `/led/state` публикуется текущие цвета светодиодов. Просмотр топика из командной строки:
+ `numPixels()` - возвращает количество пикселей в ленте. Удобно для цикличного управления всей лентой целиком.
+ `setPixelColor(pos, color)` устанавливает цвет пикселя в позиции `pos` в цвет `color`. Цвет должен быть 24 битным значением, где первые 8 бит - красный цвет \(red\), следующие 8 бит - зелёный цвет \(green\) и последние 8 бит - голубой \(blue\). Для получения значения `color` можно использовать функцию `Color(red, green, blue)`, которая составляет это значение из 3х компонент. Каждый компонент должен находиться в диапазоне 0-255, где 0 отсутствие цвета, а 255 наибольшая доступная яркость компонента в светодиодном модуле.
+ `setPixelColorRGB(pos, red, green, blue)` устанавливает цвет пикселя в позиции pos в цвет, состоящий из компонент `red`, `green`, `blue`. Каждый компонент должен находиться в диапазоне 0255, где 0 отсутствие цвета, а 255 наибольшая доступная яркость компонента в светодиодном модуле.
+ `show()` обновляет состояние ленты. Только после её использования все программные изменения перемещаются на светодиодную ленту.
## Почему именно так и можно ли по-другому?
Основной тип ленты, который используется для Клевера 3 управляются по принципу: для массива светодиодов в ленте отправляется пакет данных по 24 бита на светодиод; каждый светодиод считывает первые 24 бита из пришедших к нему данных и устанавливает соответствующий цвет, остальные данные он отправляет следующему светодиоду в ленте. Нули и единицы задаются разными сочетаниями длительностей высокого и низкого уровня в импульсе.
Используемый тип ленты поддерживаются для управления библиотекой [rpi_ws281x](https://github.com/jgarff/rpi_ws281x), при этом для управления используется модуль DMA \(direct memory access\) процессора распберри и один из каналов передачи данных: PWM, PCM или SPI, что гарантирует отсутствие задержек в управлении \(а управляется всё на многозадачной операционке, это важно\).
Есть некоторые особенности работы с каналами, например при передаче данных с помощью PWM \(ШИМ\) перестаёт работать встроенная аудиосистема распберри, при передаче данных по PCM блокируется использование подключенных цифровых аудиоустройств \(при этом встроенная система работает\), а при использовании SPI \(кстати, требуется специальная настройка размера буфера и частоты GPU распберри для правильной работы\) лента блокирует все остальные устройства, подключенные по этому каналу.
Есть некоторые особенности выбора канала DMA для управления лентой: некоторые каналы используются системой, поэтому их использование может привести к неприятным последствиям, например использование 5 канала рушит файловую систему Raspberry, т.к. этот канал используется при чтении-записи на SD карту. Безопасный канал 10, он же установлен по умолчанию в приведённой выше библиотеке.
Поэтому сценарии использования LED-ленты следующие:
1. Если нам не важна работоспособность встроенного аудио на распберри \(и мы его не используем, т. к. аудио и лента будут выдавать белиберду в этом случае\), то можно использовать PWM канал \(для этого требуется подключить вход ленты к одному из следующих GPIO портов распберри: 12, 18, 40, или 52 для PWM0 канала и 13, 19, 41, 45 или 53 для PWM1 канала\).
2. Если нам не важно наличие на шине SPI других устройств, то можно управлять лентой по каналу SPI \(GPIO на распберри 10 или 38\).
Здесь требуется произвести следующие настройки \(только для Raspberry Pi 3\):
+ увеличить размер буфера передачи данных для поддержки длинных лент, добавив стройку `spidev.bufsiz=32768` в файл `/boot/cmdline.txt`;
+ установить частоту GPU для правильной частоты работы SPI, добавив строку `core_freq=250` в файл `/boot/config.txt`.
+ перезагрузить вашу Raspberry, используя команду `sudo reboot`
3. Если нам важна и работа аудио, и подключение к SPI устройств кроме лед ленты, то можно управлять лентой по каналу PCM \(GPIO 21 или 31\). При этом никаких дополнительных манипуляций с Raspberry не требуется.
Исходя из вышеперечисленных способов управления лентой, наилучшим вариантом, позволяющим управлять лентой, сохранить работоспособность встроенной аудиосистемы и возможность подключения всяческих устройств и датчиков по SPI, является управление по каналу PCM \(GPIO 21\) с использованием 10 канала DMA.
```bash
rostopic echo /led/state
```

125
docs/ru/leds_old.md Normal file
View File

@@ -0,0 +1,125 @@
# Работа со светодиодной лентой на Raspberry 3
## Подключение и определение типа ленты
> **Note** Документация для версии образа, начиная с 0.14. Для более ранних версий см. [документацию для версий 0.13](https://github.com/CopterExpress/clever/blob/v0.13/docs/leds.md)
Подключите светодиодную ленту к питанию +5v - 5v, земле GND - GND и сигнальному порту DIN - GPIO30, GPIO21, GPIO18.
<img src="../assets/led_connection.png" height="400px" alt="leds">
> **Caution** Обратите внимание, что светодиодную ленту нужно питать от стабильного источника энергии. Если вы подключите питание напрямую к Raspberry, то это создаст слишком большую нагрузку на ваш микрокомпьютер. Для снятия нагрузки с Raspberry можно подключить питание к преобразователю `BEC`.
<!-- -->
> **Note** При работе с [GPIO](gpio.md) следует подключать ленту к пину GPIO21. В противном случае управление LED-лентой будет работать некорректно.
## Совместимость с ROS и Python
Чтобы корректно работать со светодиодной лентой вам нужно добавить в окружение необходимые пути к библиотекам Python и пакетам ROS, для этого необходимо добавить в файл `/etc/sudoers` следующие строки:
```
Defaults env_keep += "PYTHONPATH"
Defaults env_keep += "PATH"
Defaults env_keep += "ROS_ROOT"
Defaults env_keep += "ROS_MASTER_URI"
Defaults env_keep += "ROS_PACKAGE_PATH"
Defaults env_keep += "ROS_LOCATIONS"
Defaults env_keep += "ROS_HOME"
Defaults env_keep += "ROS_LOG_DIR"
```
## Пример программы для светодиодной ленты на RPI3
Для проверки работоспособности ленты можете использовать приведенный ниже код, данный код поочередно зажжет первые 10 диодов 3 цветами и в конце их погасит.
```python
import time
from rpi_ws281x import Adafruit_NeoPixel
from rpi_ws281x import Color
LED_COUNT = 10 # Количество светодиодов в ленте
LED_PIN = 21 # GPIO пин, к которому вы подсоединяете светодиодную ленту
LED_FREQ_HZ = 800000 # Частота несущего сигнала (обычно 800 кГц)
LED_DMA = 10 # DMA-канал для генерации сигнала (обычно 10)
LED_BRIGHTNESS = 255 # Яркость: 0 - наименьшая, 255 - наибольшая
LED_INVERT = False # True для инвертирования сигнала (для подключения через NPN транзистор)
LED_CHANNEL = 0 # '1' для GPIO 13, 19, 41, 45 или 53
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT)
strip.begin()
def colorWipe(strip, color, wait_ms=50):
"""Заполнение ленты цветом по одному светодиоду."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
time.sleep(wait_ms/1000.0)
print('Color wipe animations.')
colorWipe(strip, Color(255, 0, 0), wait_ms=100) # Заполнение красным
colorWipe(strip, Color(0, 255, 0), wait_ms=100) # Заполнение зелёным
colorWipe(strip, Color(0, 0, 255), wait_ms=100) # Заполнение синим
colorWipe(strip, Color(0, 0, 0), wait_ms=100) # Выключение ленты
```
> **Note** Вы так же можете использовать тестовый код разработчиков данного модуля. Вы можете его [скачать](https://github.com/rpi-ws281x/rpi-ws281x-python/tree/master/examples "Github разработчика") из репозитория разработчика.
Сохраните программу в ваш скрипт и запустите его используя права администратора:
```bash
sudo python YourScriptName.py
```
## Основные функции используемые для работы со светодиодной лентой
Для подключения библиотеки и её корректной работы требуется подключить следующие модули: `Adafruit_NeoPixel` и `Color` - для работы ленты и `time` для управления задержками.
```python
from rpi_ws281x import Adafruit_NeoPixel
from rpi_ws281x import Color
import time
```
Для работы с лентой необходимо создать объект типа `Adafruit_NeoPixel` и инициализировать библиотеку:
```python
# Создание объекта NeoPixel c заданной конфигурацией
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT)
# Инициализация библиотеки, должна быть выполнена перед другими функциями
strip.begin()
```
Основные функции, которые используются для управления лентой:
+ `numPixels()` - возвращает количество пикселей в ленте. Удобно для цикличного управления всей лентой целиком.
+ `setPixelColor(pos, color)` устанавливает цвет пикселя в позиции `pos` в цвет `color`. Цвет должен быть 24 битным значением, где первые 8 бит - красный цвет \(red\), следующие 8 бит - зелёный цвет \(green\) и последние 8 бит - голубой \(blue\). Для получения значения `color` можно использовать функцию `Color(red, green, blue)`, которая составляет это значение из 3х компонент. Каждый компонент должен находиться в диапазоне 0-255, где 0 отсутствие цвета, а 255 наибольшая доступная яркость компонента в светодиодном модуле.
+ `setPixelColorRGB(pos, red, green, blue)` устанавливает цвет пикселя в позиции pos в цвет, состоящий из компонент `red`, `green`, `blue`. Каждый компонент должен находиться в диапазоне 0255, где 0 отсутствие цвета, а 255 наибольшая доступная яркость компонента в светодиодном модуле.
+ `show()` обновляет состояние ленты. Только после её использования все программные изменения перемещаются на светодиодную ленту.
## Почему именно так и можно ли по-другому?
Основной тип ленты, который используется для Клевера 3 управляются по принципу: для массива светодиодов в ленте отправляется пакет данных по 24 бита на светодиод; каждый светодиод считывает первые 24 бита из пришедших к нему данных и устанавливает соответствующий цвет, остальные данные он отправляет следующему светодиоду в ленте. Нули и единицы задаются разными сочетаниями длительностей высокого и низкого уровня в импульсе.
Используемый тип ленты поддерживаются для управления библиотекой [rpi_ws281x](https://github.com/jgarff/rpi_ws281x), при этом для управления используется модуль DMA \(direct memory access\) процессора распберри и один из каналов передачи данных: PWM, PCM или SPI, что гарантирует отсутствие задержек в управлении \(а управляется всё на многозадачной операционке, это важно\).
Есть некоторые особенности работы с каналами, например при передаче данных с помощью PWM \(ШИМ\) перестаёт работать встроенная аудиосистема распберри, при передаче данных по PCM блокируется использование подключенных цифровых аудиоустройств \(при этом встроенная система работает\), а при использовании SPI \(кстати, требуется специальная настройка размера буфера и частоты GPU распберри для правильной работы\) лента блокирует все остальные устройства, подключенные по этому каналу.
Есть некоторые особенности выбора канала DMA для управления лентой: некоторые каналы используются системой, поэтому их использование может привести к неприятным последствиям, например использование 5 канала рушит файловую систему Raspberry, т.к. этот канал используется при чтении-записи на SD карту. Безопасный канал 10, он же установлен по умолчанию в приведённой выше библиотеке.
Поэтому сценарии использования LED-ленты следующие:
1. Если нам не важна работоспособность встроенного аудио на распберри \(и мы его не используем, т. к. аудио и лента будут выдавать белиберду в этом случае\), то можно использовать PWM канал \(для этого требуется подключить вход ленты к одному из следующих GPIO портов распберри: 12, 18, 40, или 52 для PWM0 канала и 13, 19, 41, 45 или 53 для PWM1 канала\).
2. Если нам не важно наличие на шине SPI других устройств, то можно управлять лентой по каналу SPI \(GPIO на распберри 10 или 38\).
Здесь требуется произвести следующие настройки \(только для Raspberry Pi 3\):
+ увеличить размер буфера передачи данных для поддержки длинных лент, добавив стройку `spidev.bufsiz=32768` в файл `/boot/cmdline.txt`;
+ установить частоту GPU для правильной частоты работы SPI, добавив строку `core_freq=250` в файл `/boot/config.txt`.
+ перезагрузить вашу Raspberry, используя команду `sudo reboot`
3. Если нам важна и работа аудио, и подключение к SPI устройств кроме лед ленты, то можно управлять лентой по каналу PCM \(GPIO 21 или 31\). При этом никаких дополнительных манипуляций с Raspberry не требуется.
Исходя из вышеперечисленных способов управления лентой, наилучшим вариантом, позволяющим управлять лентой, сохранить работоспособность встроенной аудиосистемы и возможность подключения всяческих устройств и датчиков по SPI, является управление по каналу PCM \(GPIO 21\) с использованием 10 канала DMA.