Как управлять светодиодом RGB с помощью Golang и C

Содержание

  • Обзор
  • Предпосылки
  • Информация, которая была бы полезна
  • Светодиод RGB в C (программная ШИМ)
  • Светодиод RGB в C (аппаратная ШИМ)
  • Светодиод RGB в Go (аппаратная ШИМ)
  • Краткое содержание
  • Рекомендации

Обзор

Это вторая статья из серии, посвященной программированию GPIO на Raspberry Pi 3B+. Первый — Raspberry Pi GPIO в Go и C — мигающий светодиод. Является дополнением к проекту Sunfounder RGB LED. Полную серию вы можете найти здесь.

В этой статье рассматривается использование широтно-импульсной модуляции (ШИМ) для управления светодиодом RGB, а также способы управления яркостью отдельных выводов светодиода. Примеры кода будут на Go и C.

Предпосылки

Если у вас его нет, вам понадобится Raspberry Pi. Я использовал Raspberry Pi 3B+ с «растянутой» версией ОС Raspbian. Учитывая, что Sunfounder Ultimate Starter Kit рекламируется для работы с Raspberry Pi 4, я ожидаю, что 4-я серия также будет работать. Я менее уверен в других версиях Raspberry Pi, особенно в версиях с 26 или 40 контактами GPIO.

Далее вам понадобится

  1. Макетная доска
  2. Какие-то перемычки
  3. Резистор 220 Ом и светодиод RGB.

Вам также следует подумать о приобретении 40-контактного разъема «мама-мама с адаптером T-типа» для подключения выходов GPIO к макетной плате. Вы можете использовать только перемычки, но кабель упростит задачу и поможет предотвратить повреждение контактов GPIO на Raspberry Pi. Если вы решите не покупать 40-контактный кабель с адаптером T-типа, вам нужно будет купить перемычки типа «папа-мама. Однако покупка всех этих вещей по отдельности будет стоить дороже, чем комплект. Вот простой комплект, в котором есть все вышеперечисленное. Если вы планируете следовать этой серии, я рекомендую купить Sunfounder Raspberry Pi Ultimate Starter Kit.

Вам также потребуются некоторые базовые знания программирования на C и Go, а также знакомство с входом в терминал Raspberry Pi или в графический интерфейс рабочего стола, который поставляется с некоторыми версиями ОС. В зависимости от выбранного вами подхода вам может потребоваться подключить клавиатуру и монитор к Raspberry Pi. Я просто SSH в Pi. Вам также понадобится знакомство с тем, как использовать такие редакторы, как Vi или nano.

Для компиляции и запуска программы на C вам понадобится библиотека WiringPi. Это легко получить:

sudo apt-get install wiringpi

Затем проверьте установку, используя:

pi@pi-node1:~/go/src/github.com/youngkin/gpio/rgbled $ gpio -v
gpio version: 2.50
Copyright (c) 2012-2018 Gordon Henderson
This is free software with ABSOLUTELY NO WARRANTY.
For details type: gpio -warranty
Raspberry Pi Details:
  Type: Pi 3B+, Revision: 03, Memory: 1024MB, Maker: Sony
  * Device tree is enabled.
  *--> Raspberry Pi 3 Model B Plus Rev 1.3
  * This Raspberry Pi supports user-level GPIO access.

В приведенном выше вы заметите gpio version: 2.50. Если вы используете Rasberry Pi 4, воспользуйтесь инструкциями, приведенными в Sunfounder Проверка WiringPi.

WiringPi уникален тем, что включает инструмент командной строки gpio, как показано выше, который можно использовать для управления, контроля и запроса платы GPIO. Это может быть очень удобно. См. Справочник по gpio для получения дополнительной информации о том, что он может делать и как его использовать.

Я решил не загружать код с сайта Sunfounder, предпочитая вместо этого писать свой собственный, даже если все, что я делал, это копировал прямо из проектной документации. В связи с этим я создал собственное местоположение для создания кода. По сути, мой код лежит на Github. Если вам нравится загружать код, у вас есть возможность загрузить, клонировать или разветвить его из моего репозитория Github. В качестве дополнительного бонуса там же находится код проекта, написанный на Go. Код этого проекта находится по адресу gpio/rgbled.

Если вы заинтересованы в разработке Go на Raspberry Pi, вам необходимо установить среду разработки на Raspberry Pi. Вот простой источник, который объясняет, как это сделать. Этот источник немного устарел, но единственная существенная проблема связана с версией Go для установки. Источник показывает установку Go 1.14.4.linux-arm64.tar.gz и 1.14.4.linuxarmv6l.tar.gz. Текущие версии: 1.17.1.linux-arm64.tar.gz и 1.17.1.linuxarmv6l.tar.gz. Для Raspberry Pi 3B+ правильным выбором будет 1.17.1.linuxarmv6l.tar.gz. Другой предназначен для 64-битных систем, таких как серия Raspberry Pi 4.

Для разработки на Go вам также понадобится библиотека go-rpio. Я выбрал его по нескольким причинам:

  1. Кажется, он довольно широко используется
  2. Вроде бы достаточно полный
  3. Он относительно активен
  4. Он поставляется с примером кода и хорошей документацией.
  5. Его API похож на WiringPi.

Другой вариант Go — periph (код) с documentation. Он более активен, и документация очень хорошая, лучше, чем у go-rpio. Но для примеров со светодиодами, которые я смог найти, go-rpio лучше соответствовал тому, что я искал, особенно в отношении этого проекта. Но это отличная альтернатива go-rpio и наоборот.

Наконец, я предполагаю, что у вас есть базовые знания Linux, если вы хотите отойти от стиля поваренной книги документации Sunfounder. Например, я не буду объяснять, что такое привилегии root.

Информация, которая была бы полезна

В этом проекте используется ШИМ (широтно-импульсная модуляция) на выводах GPIO для достижения желаемого эффекта, а именно демонстрации того, как создавать разные цвета с помощью простого светодиода RGB. К сожалению, в документации Sunfounder отсутствует информация о ШИМ, например, что такое ШИМ и как он реализован на Raspberry Pi? Я начал включать в этот раздел всю информацию, которую мне не хватало в Документации проекта Sunfounder, но быстро стало понятно, что лучше оставить ее для отдельной статьи. Поэтому, если у вас еще нет хорошего понимания ШИМ, я бы порекомендовал прочитать мою статью Широтно-импульсная модуляция для чайников с кусочком Raspberry Pi, прежде чем продолжить эту статью. В этой статье я буду использовать терминологию, объясненную в этой статье.

Светодиод RGB в C (программная ШИМ)

В зависимости от вашего опыта, вам следует подумать о пересмотре проекта RGB LED, начиная с Списка компонентов и введения. Просмотрите его в разделе Игра с C. Если у вас есть опыт работы с базовой электроникой и такими компонентами, как макетные платы и резисторы, вы можете пропустить это.

Вам следует настроить макетную плату, как описано в документации проекта или на схеме ниже:

Утилита WiringPi gpio при необходимости может помочь с отладкой. У вас уже есть эта утилита, вы использовали ее для проверки установки WiringPi в разделе «Предварительные требования» выше.

Код C, описанный в проекте Sunfounder RGB LED, использует программную ШИМ. При запуске цвета светодиода RGB меняются, как и ожидалось. Изменение напряжения на соответствующих контактах RGB с помощью программного ШИМ создает свет различной яркости (от выключенного до полного), что дает широкий диапазон цветов.

Вот немного модифицированная версия программы Sunfounder C, которая управляет светодиодом RGB:

Строка 8 содержит команду, необходимую для сборки программы — gcc -o rgbled rgbled.c -lwiringPi -lpthread. Флаги -l ссылаются на библиотеки, необходимые для сборки программы. -lwiringPi относится к библиотеке WiringPi. Он должен быть установлен в правильном месте вместе с WiringPi, и команда сборки должна просто работать. Библиотеки обычно расположены в /usr/lib. В строке 9 содержится команда для запуска программы.

Строки 18–20 определяют, используя схему нумерации выводов WiringPi, выводы 0, 1 и 2 GPIO для LedPinRed, LedPinGreen и LedPinBlue соответственно.

Строка 24 содержит объявление обработчика сигналов прерывания (SIGINT).

Строки 27–29 используют функцию softPwmCreate() для инициализации выводов. Начальные символы в имени функции, softPwm, указывают на то, что контакты инициализируются для программного ШИМ. Первым параметром функции является номер вывода. Второй параметр — начальная ширина импульса. Последним параметром является диапазон. См. Широко-импульсная модуляция для чайников с помощью кусочка Raspberry Pi, если вы не понимаете эти термины.

Строки 33–35, softPwmWrite() отправляют желаемый сигнал/напряжение на соответствующий контакт. Первый параметр — это номер вывода, такой же, как в softPwmCreate() выше. Второй параметр — ширина импульса. Обратите внимание, что ширина импульса была 0 в softPwmCreate(). Это приводит к установке вывода на ноль вольт. В softPwmWrite() ширина импульса устанавливается на значения, указанные r_val, g_val и b_val. Эти значения представляют значения красного, зеленого и синего соответственно. Максимальное эффективное значение длительности импульса — это диапазон. Это приведет к полной яркости/напряжению. Любые значения, превышающие диапазон, не будут иметь дополнительного влияния. Важно отметить, что желаемое напряжение будет продолжать поступать на контакты, пока не будет сброшено другим softPwmWrite().

Фрагмент кода выше является продолжением программы. Он показывает функцию main(). Строки 2–5 инициализируют библиотеку WiringPi. Программа завершает работу, если эта инициализация не удалась.

Строка 7 определяет обработчик сигнала, который будет вызываться при получении программой сигнала SIGINT. Это сигнал, установленный, когда пользователь вводит ctl-C на клавиатуре. Этот обработчик сигнала завершит программу. Эта функция была объявлена ​​в предыдущем фрагменте кода.

Вызовы ledColorSet(...) внутри цикла while(keepRunning) в строке 11 используют шестнадцатеричные числа для установки цветов. Они используются для создания полного спектра доступных цветов. Они должны находиться в диапазоне от 0 до 0xff, помните, что значение диапазона было указано в softPwmCreate(). Я изменил значения из исходного кода Sunfounder, поскольку используемый зеленый светодиод, по-видимому, имеет меньшее сопротивление, поскольку он немного ярче, чем красный и синий светодиоды, и, следовательно, отбрасывает генерируемые цвета. Точно так же синий светодиод, кажется, имеет большее сопротивление, поскольку он немного тусклее, чем два других светодиода. Изменение значений, по крайней мере, для моего конкретного RGB-светодиода, дало более точные цвета. Код зацикливается, меняя цвет светодиода, пока не будет завершен нажатием ctl-C на клавиатуре.

Приведенный выше фрагмент кода является продолжением предыдущего фрагмента кода. Он содержит реализацию обработчика прерывания, описанного ранее. Он отключает все контакты светодиода RGB, в результате чего светодиод полностью выключается. pinMode() устанавливает режим для указанного вывода (первый параметр) на OUTPUT (второй параметр). Это изменяет контакт с контакта PWM на контакт, который может быть установлен только в положение ON или OFF. Напряжение выходного вывода не может быть изменено. digitalWrite() устанавливает напряжение для указанного вывода равным нулю (LOW).

Программу можно запустить после компиляции с помощью ./rgbled.

Светодиод RGB в C (аппаратная ШИМ)

Поскольку в документации Sunfounder нет аппаратного ШИМ-решения на C, я решил создать его для себя. Для этой программы измените макет, как показано ниже:

На этот раз я использую контакты 24, 1 и 23 WiringPi для красного, зеленого и синего, которые соответствуют контактам 19, 18 и 13 BCM соответственно. Это связано с тем, что это 3 из 4 аппаратных контактов ШИМ на плате Broadcomm BCM2835. Обязательно перемонтируйте плату, чтобы она соответствовала этим новым назначениям контактов. Утилита WiringPi gpio при необходимости может помочь с отладкой. У вас уже есть эта утилита, вы использовали ее для проверки установки WiringPi в разделе «Предварительные требования» выше.

Эта версия RGB-светодиода очень похожа на вышеописанную программную ШИМ-версию. Есть 2 существенных отличия.

  1. Обратите внимание на нумерацию контактов, используемую в строках 14–16. Используемые здесь номера контактов WiringPi соответствуют аппаратным контактам PWM, доступным на плате GPIO.
  2. Функции ledInit() и ledColorSet() (строки 30-48) совершенно разные. В этих функциях режим вывода установлен на PWM_OUTPUT по сравнению с использованием softPwmCreate(), а pwmWrite() используется вместо softPwmWrite(). Строка 34 устанавливает диапазон. Обратите внимание, что для вызова pwmSetRange() пин-код не указан. На это есть 2 причины. Во-первых, диапазон устанавливается на уровне канала, а не для отдельных контактов. Во-вторых, библиотека WiringPi не позволяет указывать два канала отдельно. Он устанавливает оба канала на одно и то же значение. Строка 35, pwmSetClock(), (косвенно) устанавливает частоту. Он указывает делитель, в данном случае 2, который используется для деления тактовой частоты генератора платы на частоту, используемую для управления контактами. делитель должен быть числом от 2 до 4095. Как и pwmSetRange(), pwmSetClock() указывается на уровне канала, а не для отдельных контактов. См. Широтно-импульсная модуляция для чайников с помощью кусочка Raspberry Pi для получения дополнительной информации о тактовых частотах, частоте и делителе в их отношении к ШИМ.

Фрагмент кода выше содержит оставшуюся часть программы, main() и обработчик прерывания. Обработчик прерывания точно такой же, как обработчик прерывания в программной версии PWM. Как и версия программы с программным ШИМ, программа зацикливается до тех пор, пока не будет прервана с помощью ctl-C.

Программа запускается с правами суперпользователя с sudo ./rgbledHardware. sudo необходим, поскольку прямой доступ к оборудованию ограничен пользователями с привилегиями root. sudo предоставляет root-привилегии командам с префиксом sudo.

При запуске программы вы заметите, что светодиод RGB не воспроизводит ожидаемые цвета. Иногда он может отображаться фиолетовым, когда должен быть синим. Иногда он может быть полностью отключен, когда он должен показывать цвет. Это происходит из-за того, что контакт 13 BCM (синий) и контакт 19 BCM (красный) находятся на одном и том же аппаратном канале. Как объяснялось выше, когда сигнал отправляется на один канал, он распространяется на оба вывода, которые совместно используют этот канал. Зеленый на контакте 12 модуля BCM не изменяется. Одно поведение, которое я не понимаю, это то, почему иногда светодиод не горит, когда он должен показывать цвет. Это происходит только для красных (BCM19) и синих (BCM 13) контактов. Возможно, контакты, которые имеют общий канал, не производят сигнал в одно и то же время. Представьте себе случай, когда синий контакт установлен на 0xff, а красный контакт установлен на 0x00. Если сигнал красного вывода поступает немного позже сигнала синего, он перекроет сигнал синего вывода, отключив светодиод. Вывод из всего этого заключается в том, что для всех намерений и целей одновременно могут использоваться только 2 аппаратных контакта ШИМ, и они не могут быть на одном канале.

Светодиод RGB в Go (аппаратная ШИМ)

Эта версия RGB LED будет работать с той же макетной платой, что и аппаратная версия C PWM. То есть он использует аппаратные контакты PWM на плате GPIO. В отличие от версии Sunfounder C и первой версии C в этой статье, библиотека Go поддерживает только аппаратную ШИМ. В моей статье Широтно-импульсная модуляция для чайников с кусочком Raspberry Pi я включил программную версию PWM в Go. Он реализован в сопутствующей программе freqtest.go в функции runSoftwarePWM(). Вот код:

Строки 27–29 определяют контакты, используемые для красных, зеленых и синих элементов светодиода.

Строки 30–31 определяют значения по умолчанию для использования в настройках.

Строки 35–75 устанавливают Mode на ШИМ, а DutyCycle на контакты светодиода. В DutyCycle() первым параметром является ширина импульса, которую go-rpio называет duty. Второй параметр — это диапазон, который go-rpio называет cycle. Остальные строки содержат комментарии и код, устраняющие проблемы с попыткой использовать 2 контакта аппаратного ШИМ, находящихся на одном канале, как указано в разделе Аппаратное ШИМ в C выше.

Этот фрагмент кода является продолжением программы выше. Эта суть показывает ledInit(). Он инициализирует контакты GPIO для использования в программе. Они устанавливают режим (ШИМ), частоту и рабочий цикл (предоставляя параметры для ширины импульса (также известного как рабочий цикл) и диапазона (также известного как цикл)). Как описано в Широко-импульсной модуляции для чайников с помощью кусочка Raspberry Pi, указанная частота должна находиться в диапазоне от 4688 до 9 600 000.

Это часть 3 программы и показывает реализацию main(). Строки 2-4 инициализируют библиотеку go-rpio. Строка 5 обеспечивает освобождение используемых ресурсов при выходе из программы.

Оставшаяся часть программы предлагает пользователю использовать значения красного, зеленого и синего цветов и соответствующим образом устанавливает контакты.

Полную программу rgbled.go можно найти в репозитории gpio github.

Краткое содержание

Вот и все, надеюсь, вам была интересна эта статья. Чтобы быстро просмотреть, эта статья охватывает следующее:

  1. Настройка физической среды, необходимой для экспериментов со светодиодом RGB на Raspberry Pi 3B+.
  2. Предоставлено по ссылке Широтно-импульсная модуляция для чайников с кусочком Raspberry Pi подробное знание ШИМ, отсутствующее в Светодиодном проекте Sunfounder RGB.
  3. Предоставлен и объяснен код C и Go, необходимый для установки цветов в светодиоде RGB с использованием как аппаратного, так и программного ШИМ.

Рекомендации

  1. Проект Sunfounder RGB LED послужил основой для этой статьи.
  2. WiringPi — библиотека C, используемая в этой статье для программирования GPIO.
  3. go-rpio — библиотека Go, используемая в этой статье для программирования GPIO.
  4. Широтно-импульсная модуляция для чайников с кусочком Raspberry Pi содержит все, что вам нужно знать о ШИМ на Raspberry Pi, по крайней мере, до тех пор, пока вы не захотите стать экспертом по ШИМ!