Мой коллега MVP Питер Новак из Германии указал мне на этот удивительный набор на Amazon.de, в котором есть огромный набор датчиков.
Он поставляется с 37 датчиками и периферийными устройствами, которыми можно управлять с помощью Raspberry PI2. Первоначально он был сделан для PI B +, но, поскольку он совместим по выводам с PI 2, это работает нормально. Он поставляется с мини-диском с примером кода, но, к сожалению, это все C — вам нужно скомпилировать его с помощью GCC. Не программируя на C с конца 90-х, это не тот код, с которым мне очень удобно возиться. С другой стороны, я также с нетерпением жду, чтобы это пылилось до появления Windows 10 для устройств.
Теперь все примеры кода на C, которые идут с этим комплектом, используют библиотеку wiringPI , созданную одним Гордоном Хендерсоном . Я в основном использовал эту библиотеку как основу для работы с C #. Сначала вы должны установить библиотеку. У Гордона есть простое пошаговое руководство о том, как это сделать. Просто откройте консоль, перейдите в каталог, куда вы хотите загрузить исходные коды библиотеки, и следуйте его инструкциям. «Установка» в Linux, очевидно, означает установку git, клонирование репозитория и запуск файла сборки, который, по-видимому, компилирует весь shebang и ставит это «где-то». Конечным результатом является то, что вы можете скомпилировать примеры программ на С, которые поставляются с комплектом, используя библиотеку Гордона для управления датчиками.
Затем есть этот парень, Даниэль Рише , который создал простую библиотеку для оболочки на C #. Как это работает, ошеломительно просто — он просто использует DllImport, чтобы обернуть вызовы в библиотеку C и сделать их доступными для C #. Я не видел эту технику в гневе с 1999 года, в проекте Visual Basic 6. Но, по-видимому, это все еще работает — и, что более важно, — оно, очевидно, работает и под Mono, даже если импортированный код вообще не приходит из DLL, а является файлом «так».
Он вроде описывает, что вам нужно сделать — после установки библиотеки Гордона вы переходите (все еще в командной строке, конечно) к подпапке «wiringPi» папки, в которой вы начали сборку, а затем запускаете три команды для создания: разделяемые библиотеки:
cc -shared wiringPi.o -o libwiringPi.so
cc -shared wiringPiI2C.o -o libwiringPiI2C.so
cc -shared wiringPiSPI.o -o libwiringPiSPI.so
И, очевидно, вы можете просто удалить папку, в которую вы скачали исходники wiringPi. Библиотека установлена и может использоваться.
Теперь пример Дэниела показывает, как, к сожалению, для моей цели не хватает одной ключевой функции — для управления светодиодом вам потребуется доступ к процедурам «softPwm» wiringPi. Просматривая источники Си, я нашел файл softPwm.c с процедурами, которые мне нужны для доступа. Итак, я создал свой собственный класс оболочки:
using System.Runtime.InteropServices; namespace WiringPi { public class SoftPwm { [DllImport("libwiringPi.so", EntryPoint = "softPwmCreate")] public static extern void Create(int pin, int initialValue, int pwmRange); [DllImport("libwiringPi.so", EntryPoint = "softPwmWrite")] public static extern void Write(int pin, int value); [DllImport("libwiringPi.so", EntryPoint = "softPwmStop")] public static extern void Stop(int pin); } }
Как видите, все это довольно уродливо — все общедоступно, оно очень близко следует макету исходного кода и в настоящее время полностью не объектно-ориентировано. Но как бы то ни было, все еще рано, и это временная мера, пока Windows 10 все равно не появится. Это делает несколько подпрограмм C доступными для C # — например, подпрограмма C «softPwmWrite», которая помещает значение в вывод GPIO, становится доступной как SoftPwm.Write.
И тогда я могу написать следующую простую программу, которая позволяет многоцветному светодиоду, входящему в комплект SunFounder, получать все виды цветов:
using System; using System.Threading; using WiringPi; namespace SunfounderTest { class Program { const int LedPinRed = 0; const int LedPinGreen = 1; const int LedPinBlue = 2; static void Main(string[] args) { if (Init.WiringPiSetup() != -1) { SoftPwm.Create(LedPinRed, 0, 100); SoftPwm.Create(LedPinGreen, 0, 100); SoftPwm.Create(LedPinBlue, 0, 100); Console.WriteLine("Init succeeded"); for (var i = 1; i < 3; i++) { ShowColor(255, 0, 0, "Red"); ShowColor(0, 255, 0, "Green"); ShowColor(0, 0, 255, "Blue"); ShowColor(255, 255, 0, "Yellow"); ShowColor(255, 0, 255, "Pink"); ShowColor(0, 255, 255, "Cyan"); ShowColor(195, 0, 255, "Purple"); ShowColor(255, 255, 255, "White"); } SoftPwm.Stop(LedPinRed); SoftPwm.Stop(LedPinGreen); SoftPwm.Stop(LedPinBlue); } else { Console.WriteLine("Init failed"); } } private static void ShowColor(int r, int g, int b, string label) { SetLedColor(r, g, b); Console.WriteLine(label); Thread.Sleep(1000); } private static void SetLedColor(int r, int g, int b) { SoftPwm.Write(LedPinRed, r); SoftPwm.Write(LedPinGreen, g); SoftPwm.Write(LedPinBlue, b); } } }
Я даже не начну притворяться, что я на самом деле полностью понимаю, что я делаю — и я даже меньше понимаю почему — но сначала вам нужно вызвать метод Init.WiringPiSetup — который уже был упакован Дэниелом — а затем вам нужно вызовите «Create» на трех выводах — только тогда вы можете установить значение для выводов, используя SoftPwm.Write. Я обернул вызовы этим в SetLedColor, который принимает значения красного, зеленого и синего (примерно 0-255), который, в свою очередь, обернут в процедуру, которая записывает информацию о прогрессе и немного ждет, прежде чем прогрессировать. И в конце вам нужно будет вызвать Stop на всех трех контактах, чтобы светодиод снова погас, иначе он с удовольствием останется включенным.
Чистый эффект: если вы подключите светодиодный контакт R к GPIO17, контакт G к 18, контакт B к 27 и контакт заземления к одному из заземления, светодиод будет мигать во всем диапазоне цветов.
Это будет работать только если вы запустите приложение с помощью sudo, поэтому
sudo mono SunfounderTest.exe
Раздражает то, что в образцах, поставляемых с этим набором, эти штифты 17, 18 и 27 обозначены как 0, 1 и 2. Это, очевидно, имеет исторические причины. На этой странице в element14 я нашел схему вывода с переводом с одного имени на другое. Обратите внимание, что контактный номер 11 называется как GPIO17, так и GPIO_GEN0. Это соответствует контакту 1 в коде . Я предполагаю, что где-то есть какая-то логика, но я еще должен это обнаружить ?
Как обычно, вы можете найти демонстрационное решение здесь . Имейте в виду — не весь код мой, часть его от Даниэля Рича