Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Arduino 101 - платье соответствия шаблону Intel Curie

Компоненты и расходные материалы

полоса NeoPixel
Можно заменить отдельными светодиодами RGB.
× 1
Arduino 101
× 1
Кнопочный переключатель SparkFun, 12 мм
× 1
Резистор 10 кОм
× 1
Перемычки (общие)
Вам могут понадобиться длинные провода, чтобы провести светодиоды от плеча к руке.
× 1
Батарея 9 В (стандартная)
× 1
9 В для разъема Barrel Jack
× 1
Светодиоды Adafruit Flora RGB Neopixel - 4 шт.
Это можно использовать для замены полосы Neopixel.
× 1
Сшиваемая проводящая нить
Возможность замены некоторых проводов.
× 1

Необходимые инструменты и машины

Пистолет для горячего клея (общий)
швейная машина (универсальная)
Паяльник (общий)

Приложения и онлайн-сервисы

IDE Arduino

Об этом проекте

Введение

Я инженер и художник, мне нравятся проекты, в которых сочетаются наука и искусство. Я делаю дизайны платьев с помощью встроенных микроконтроллеров, чтобы можно было использовать определенные функции электронных компонентов для улучшения темы дизайна. В этом проекте я хочу использовать механизм сопоставления с образцом (PME) и акселерометр внутри Intel Curie на Arduino 101. Curie предназначен для приложений PME, поскольку имеет возможности нейронной сети, но примеров PME было не так много. . Я надеюсь, что этот пример может вдохновить вас на извлечение возможностей PME Кюри.

В качестве ткани для платья использована страница моего графического романа. Ученый и ее робот смотрят в телескоп. Когда пользователь рисует узор в воздухе, набор светодиодов, расположенных в форме созвездий, будет сиять в ночном небе на ткани.

Инструкции

* Примечание:после публикации этого проекта я обновил часть электронной схемы. Ниже после шага 3 опубликован улучшенный метод прикрепления светодиодов к ткани и то, как сделать их долговечными.

** Обновление:надев это платье на несколько демонстрационных мероприятий в течение всего дня, можно было оценить время автономной работы. Для питания этого платья батарею на 9 В необходимо менять каждые 3 часа. Батарея не разряжается, но ее напряжение падает ниже 9 В, что делает сопоставление с образцом неэффективным. Вы можете сэкономить аккумулятор для других целей.

Шаг 1

Я использовал полосу NeoPixel от Adafruit, разрезал ее на части и расположил их в форме созвездий. Не стесняйтесь использовать светодиоды других типов, например, отдельные светодиоды RGB. Приклейте или пришейте их к основной ткани.

Шаг 2

Сверху положите промежуточную ткань, и вы сможете очертить созвездия. Этот шаг не является обязательным, но я считаю полезным иметь несколько слоев ткани, чтобы укрепить структуру. Я пришила еще одну толстую ткань к обратной стороне основной ткани. Итак, всего три слоя в качестве основы, между светодиодами.

Шаг 3

Припаиваем светодиоды. Если вы используете сшиваемые отдельные светодиоды, вы также можете использовать токопроводящие нити для их соединения. В любом случае это большой ручной труд и требует терпения. Поскольку у меня четыре созвездия (Орион, Большая Медведица, Лебедь и Кассиопея), я разделил их на четыре следа. Каждый из них будет подключен к разному контакту Arduino 101.

Улучшенные шаги

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

Расположите светодиоды

Я использовал полоску NeoPixel от Adafruit, разрезал ее на части и расположил их в форме созвездий. Не стесняйтесь использовать светодиоды других типов, например, отдельные светодиоды RGB. Приклейте или пришейте их к основной ткани.

Фетр - это красивый вид плотной ткани, которая придает структуру и хорошо сочетается с горячим клеем. Расположите светодиоды в соответствующих положениях, чтобы, когда они загорались, в их положениях отражались звезды в созвездиях.

Спланируйте светодиоды и провода

Наклейте светодиодные ленты на войлок в нескольких точках. Не кладите клей под всю полосу, потому что вам нужно немного свободы, чтобы перемещать термоусадочные трубки, как показано на рисунке. Нарежьте многожильные провода нужной длины и поместите их в соответствующие положения на одном и том же куске фетра. Я бы рекомендовал пока не приклеивать провода горячим клеем. Моя фигура здесь - грубая ошибка в этом отношении. Лучше закрепить провода на своих местах с помощью временной ленты, чтобы при пайке проводов к светодиодам положение проводов можно было регулировать.

Подготовьте все детали к шитью

На рисунке показано, что я приготовил четыре созвездия (Орион, Большая Медведица, Лебедь и Кассиопея) на четыре отдельные части. После пайки и термоусадки паяных стыков можно все плотно приклеить на войлок.

Тест!

Прежде чем двигаться дальше, проверьте свою схему! Можно просто сделать NeoPixel Strandtest для каждой трассы.

Хорошо, я поставил уровень как «Легкий», поскольку с научной точки зрения это несложно, если вы понимаете код, но для стабилизации кабелей на ткани требуется много работы.

Убедитесь, что ваша IDE Arduino является последней версией и имеет библиотеку Curie PME. Я бы рекомендовал использовать веб-редактор Arduino. Загрузите библиотеку здесь.

Сшить платье

Параллельно (образно) шить платье. После проверки схемы пришейте ткань основы со светодиодами на внутренней стороне платья. Светодиоды будут светить сквозь графику.

Как видите, Arduino 101 у меня в руке. Я сделал 3D-печатный корпус для Arduino 101 и аккумулятора. Светодиоды и плату соединены длинными проводами, которые спрятаны в гильзе.

Приведенный ниже код предоставит вам информацию о том, как программируется плата. После того, как вы запрограммируете код, сначала обучите нейроны, чтобы они узнали, какие шаблоны существуют. Посмотрите это видео ~ 0:30:

Больше фотографий и других модных дизайнов и рисунков на ткани можно найти на моем сайте :)

Код

  • PME_4LED_new.ino
  • PME_LED
PME_4LED_new.ino Arduino
Это обновленный скрипт по сравнению с предыдущим. В нем хранятся данные обучения. В настоящее время он настроен на этапе инициализации. Первая серия светодиодов светится красным при включении питания. Удерживая Arduino101 горизонтально с USB-портом, направленным в горизонтальном направлении, при нажатой кнопке можно использовать предыдущее обучение. Эти светодиоды меняют цвет на зеленый, а затем на синий, когда кнопка отпускается, это означает, что система готова. Если удерживать Arduino101 так, чтобы порт USB был направлен в вертикальном направлении, при нажатой кнопке предыдущие данные обучения стираются. Систему можно переобучить, отпустив кнопку.
 / * * В этом примере демонстрируется использование механизма сопоставления с образцом (CuriePME) * для классификации потоков данных акселерометра от CurieIMU. * * Во-первых, эскиз предложит вам нарисовать в воздухе несколько букв (просто * представьте, что вы пишете на невидимой доске, используя * доску как перо), и данные IMU из этих движений используются в качестве обучающих данных для * PME. По окончании обучения вы можете продолжать рисовать буквы, и PME * попытается угадать, какую букву вы рисуете. * * В этом примере требуется, чтобы кнопка была подключена к цифровому выводу 4 * https://www.arduino.cc/en/Tutorial/Button * * ПРИМЕЧАНИЕ. Для достижения наилучших результатов рисуйте большие буквы, высотой не менее 1-2 футов. * * Авторские права (c) Корпорация Intel, 2016 г. Все права защищены. * См. Уведомление о лицензии в конце файла. * / # include "CurieIMU.h" #include "CuriePME.h" #include  #include  #include  #define PINM 6 //// какой штифт NeoPixels подключен к? # определить PINC 3 # определить PINS 9 # определить PINO 5 Adafruit_NeoPixel stripM =Adafruit_NeoPixel (10, PINM, NEO_GRB + NEO_KHZ800); /// длина полосы 15 пикселей. Вы можете изменить это для количества пикселей в вашей отдельной полосе. , NEO_GRB + NEO_KHZ800); int tr =0; // Некоторые переменные для хранения "цветовой цели" и "цветовой текущей" для сглаживания ... int tg =0; int tb =0; int r =0; int g =0; int b =0; int rawX =0; ///// для хранения значений из акселерометра Кюри int rawY =0; // int rawZ =0; float angle =0.0; / * Это контролирует, сколько раз буква должна быть нарисована во время обучения. * Любое значение выше 4, и у вас может не хватить нейронов для всех 26 букв * алфавита. Меньше 4 означает, что вам будет труднее обучить букву *, но PME может быть труднее классифицировать эту букву. * / const unsigned int trainingReps =4; / * Увеличьте это значение до «AZ», если хотите - обучение занимает намного больше времени * / const unsigned char trainingStart ='A'; const unsigned char trainingEnd ='D'; / * Входной контакт, используемый для подачи сигнала, когда буква рисуется - вам * необходимо убедиться, что к этому контакту прикреплена кнопка * / const unsigned int buttonPin =4; / * Частота дискретизации для акселерометра * / const unsigned int sampleRateHZ =200; / * Количество байтов, которое может содержать один нейрон * / const unsigned int vectorNumBytes =128; / * Количество обработанных выборок (1 выборка ==ускорение x, y, z) *, которые могут поместиться внутри нейрона * / const unsigned int samplesPerVector =(vectorNumBytes / 3); / * Это значение используется для преобразования символов ASCII AZ * в десятичные значения 1-26 и обратно. * / const unsigned int upperStart =0x40; const unsigned int sensorBufSize =2048; const int IMULow =-32768; const int IMUHigh =32767; const char * filename ="NeurDataDress.dat"; void setup () {Serial.begin (9600 ); // while (! Serial); pinMode (buttonPin, ВВОД); / * Запускаем IMU (Intertial Measurement Unit) * / CurieIMU.begin (); / * Запускаем PME (механизм сопоставления с образцом) * / CuriePME.begin (); CurieIMU.setAccelerometerRate (sampleRateHZ); CurieIMU.setAccelerometerRange (2); /* В этом. Микросхема SPI Flash * / if (! SerialFlash.begin (ONBOARD_FLASH_SPI_PORT, ONBOARD_FLASH_CS_PIN)) {Serial.println («Невозможно получить доступ к микросхеме SPI Flash»); } stripM.begin (); // инициализировать неопиксельную полосу stripS.begin (); stripC.begin (); stripO.begin (); stripM.show (); // Инициализируем все пиксели как "выключенные" stripS.show (); stripC.show (); stripO.show (); solidM (stripM.Color (255, 0, 0), 50); // Красный для готовности к вводу} / * Эта функция читает файл, сохраненный в предыдущем примере * Файл содержит все данные, которые были изучены, а затем сохранены ранее. * После восстановления сети она может снова классифицировать шаблоны без * повторного обучения. * / Void restoreNetworkKnowledge (void) {SerialFlashFile file; int32_t fileNeuronCount =0; Intel_PMT ::нейрондата нейрондата; // Открываем файл и записываем тестовые данные file =SerialFlash.open (filename); CuriePME.beginRestoreMode (); if (file) {// перебираем по сети и сохраняем данные. while (1) {Serial.print ("Читающий нейрон:"); uint16_t NeuronFields [4]; file.read ((void *) neronFields, 8); file.read ((void *) neronData.vector, 128); нейронДата.контекст =нейронПоля [0]; нейронДата.influence =нейронПоля [1]; нейронДата.минИнфлюенс =нейронПоля [2]; нейронДата.категория =нейронПоля [3]; если (нейронные поля [0] ==0 || нейронные поля [0]> 127) break; fileNeuronCount ++; // эта часть просто печатает каждый нейрон по мере его восстановления, // чтобы вы могли видеть, что происходит. Serial.print (fileNeuronCount); Serial.print ("\ n"); Serial.print (нейронПоля [0]); Serial.print ("\ t"); Serial.print (нейронПоля [1]); Serial.print ("\ t"); Serial.print (нейронПоля [2]); Serial.print ("\ t"); Serial.print (нейронПоля [3]); Serial.print ("\ t"); Serial.print (нейронДата.вектор [0]); Serial.print ("\ t"); Serial.print (нейронДата.вектор [1]); Serial.print ("\ t"); Serial.print (нейронДата.вектор [2]); Serial.print ("\ n"); CuriePME.iterateNeuronsToRestore (нейронДата); }} CuriePME.endRestoreMode (); Serial.print ("Набор знаний восстановлен. \ N");} логическое longPress =false; int startTime =0; int lastOrientation =- 1; // предыдущая ориентация (для сравнения) int lastReading =-1; логическое lastPress =false; void loop () {int direction =- 1; // ориентация платы String directionString; // строка для печати описания ориентации // Ориентация платы:// 0:плоская, процессор обращен вверх // 1:плоский, процессор обращен вниз // 2:альбомная, аналоговые контакты вниз // 3:альбомная, аналоговая контакты вверх // 4:портрет, разъем USB вверху // 5:портрет, разъем USB вниз // чтение акселерометра:int x =CurieIMU.readAccelerometer (X_AXIS); int y =CurieIMU.readAccelerometer (Y_AXIS); int z =CurieIMU.readAccelerometer (Z_AXIS); // вычисляем абсолютные значения, чтобы определить наибольшее int absX =abs (x); int absY =abs (у); int absZ =abs (z); if ((absZ> absX) &&(absZ> absY)) {// базовая ориентация по Z if (z> 0) {directionString ="up"; ориентация =0; } еще {ориентацияString ="вниз"; ориентация =1; }} else if ((absY> absX) &&(absY> absZ)) {// базовая ориентация по Y if (y> 0) {directionString ="digital pins up"; ориентация =2; } else {ОриентацияString ="аналоговые контакты вверх"; ориентация =3; }} else {// базовая ориентация по X if (x <0) {directionString ="connector up"; ориентация =4; } else {ОриентацияString ="соединитель вниз"; ориентация =5; }} // если ориентация изменилась, распечатываем описание:if (Ориентация! =lastOrientation) {Serial.println (ОриентацияString); lastOrientation =ориентация; } // если ориентация изменилась, распечатываем описание:if (Ориентация! =lastOrientation) {lastOrientation =Ориентация; } int чтение =digitalRead (buttonPin); если (lastReading! =чтение) {Serial.print ("buttonPin ="); Serial.println (чтение); lastReading =чтение; } если (чтение ==ВЫСОКИЙ) {если (startTime ==0) {startTime =millis (); } иначе, если ((millis () - startTime)> 2000) {longPress =true; если (! lastPress) {Serial.println ("longPress"); // зеленый при длительном нажатии solidM (stripM.Color (0, 255, 0), 50); // зеленый lastPress =true; }}} if (чтение ==LOW &&longPress) {blackout (5); Serial.print ("ориентация ="); Serial.print (ориентация); Serial.print ("SerialFlash.exists (имя файла) ="); Serial.println (SerialFlash.exists (имя файла)); если (ориентация! =4 &&SerialFlash.exists (имя файла)) {restoreNetworkKnowledge (); Serial.print («Обучение восстановлено.»); } еще {trainLetters (); затемнение (5); Serial.print («Обучение завершено.»); } Serial.println ("Теперь нарисуйте несколько букв (не забудьте"); Serial.println ("удерживайте кнопку) и посмотрите, сможет ли PME их классифицировать."); solidM (stripM.Color (0, 0, 255), 500); // Синий означает готовность к сопоставлению blackout (5); // отключение для сопоставления while (true) {match (); }}} void solidM (uint32_t c, uint8_t wait) {for (uint16_t i =0; i  (num * 3) - (step * 3)) {ret =samples [pos]; } еще {ret =0; pos - =(шаг * 3); для (беззнаковое int я =0; я <размер; ++ я) {ret + =образцы [pos - (3 * я)]; } ret / =размер; } return (byte) ret;} / * Нам нужно сжать поток необработанных данных акселерометра до 128 байт, чтобы * он поместился в нейрон, сохраняя при этом как можно большую часть исходного шаблона *. Предполагая, что данные акселерометра на частоте 200 Гц обычно составляют 1-2 секунды, нам нужно будет выбросить более 90% их, чтобы * достичь этой цели! * * Это делается двумя способами:* * 1. Каждая выборка состоит из 3 знаковых 16-битных значений (по одному для X, Y и Z). * Сопоставьте каждое 16-битное значение с диапазоном 0-255 и упакуйте его в байт, * уменьшив размер выборки вдвое. * * 2. Недодискретизация. Если мы будем производить выборку на частоте 200 Гц и удерживать кнопку в течение 1,2 * секунды, то у нас будет ~ 240 выборок. Поскольку теперь мы знаем, что каждая * выборка после сжатия будет занимать 3 из 128 байтов * нашего нейрона (см. # 1), то мы знаем, что можем уместить только 42 из этих 240 выборок в * один нейрон (128/3 =42,666 ). Итак, если мы берем (например) каждую пятую * выборку, пока у нас не будет 42, то мы должны покрыть большую часть окна выборки * и иметь некоторое подобие исходного рисунка. * / void undersample (byte samples [], int numSamples, byte vector []) {unsigned int vi =0; беззнаковое int si =0; unsigned int step =numSamples / samplesPerVector; беззнаковый int остаток =numSamples - (шаг * samplesPerVector); / * Центр окна выборки * / samples + =(остаток / 2) * 3; for (unsigned int i =0; i  sensorBufSize) {break; }}} undersample (Accel, samples, vector);} void trainLetter (char letter, unsigned int repeat) {unsigned int i =0; в то время как (я <повтор) {вектор байтов [vectorNumBytes]; если (буква =='А') {colorWipeM (stripM.Color (0, 255, 0), 50); // Зеленый театрChaseM (stripM.Color (127, 127, 127), 50); // Белая полоскаM.show (); } иначе, если (буква =='B') {colorWipeS (stripS.Color (255, 0, 0), 50); // Красный TheaterChaseS (stripS.Color (127, 127, 127), 50); // Белая полоскаS.show (); } иначе, если (буква =='C') {colorWipeC (stripC.Color (0, 0, 255), 50); // Синий TheaterChaseC (stripC.Color (127, 127, 127), 50); // Белая полоска C.show (); } иначе, если (буква =='D') {colorWipeO (stripO.Color (255, 0, 255), 50); // Синий TheaterChaseO (stripO.Color (127, 127, 127), 50); // Белая полоскаO.show (); } if (i) Serial.println ("И снова ..."); readVectorFromIMU (вектор); CuriePME.learn (вектор, vectorNumBytes, буква - upperStart); Serial.println («Понятно!»); задержка (1000); ++ i; }} bool create_if_not_exists (const char * filename, uint32_t fileSize) {if (! SerialFlash.exists (filename)) {Serial.println ("Создание файла" + String (имя файла)); вернуть SerialFlash.createErasable (имя файла, размер файла); } Serial.println («Файл» + Строка (имя файла) + «уже существует»); return true;} void saveNetworkKnowledge (void) {// const char * filename ="NeurData.dat"; SerialFlashFile файл; Intel_PMT ::нейрондата нейрондата; uint32_t fileSize =128 * sizeof (нейрондата); Serial.print ("Размер файла для сохранения ="); Serial.print (размер файла); Serial.print ("\ n"); create_if_not_exists (имя файла, размер файла); // Открываем файл и записываем тестовые данные file =SerialFlash.open (filename); file.erase (); CuriePME.beginSaveMode (); if (file) {// перебираем по сети и сохраняем данные. while (uint16_t nCount =CuriePME.iterateNeuronsToSave (neuronData)) {если (nCount ==0x7FFF) перерыв; Serial.print («Спасение нейрона:»); Serial.print (nCount); Serial.print ("\ n"); uint16_t NeuronFields [4]; нейронПоля [0] =нейронДата.контекст; нейронПоля [1] =нейронДата.influence; нервные поля [2] =нейронДанные.minInfluence; нейронПоля [3] =нейронДата.категории; file.write ((void *) neronFields, 8); file.write ((void *) neuroonData.vector, 128); }} CuriePME.endSaveMode (); Serial.print ("Набор знаний сохранен. \ N");} void trainLetters () {for (char i =trainingStart; i <=trainingEnd; ++ i) {Serial.print ("Удерживая кнопку, нарисуйте букву '"); Serial.print (String (i) + "'в воздухе. Отпустите кнопку, как только"); Serial.println ("как вы сделали."); trainLetter (i, trainingReps); Serial.println («ОК, закончили с этим письмом.»); задержка (2000); } // В этом. Микросхема SPI Flash, если (! SerialFlash.begin (ONBOARD_FLASH_SPI_PORT, ONBOARD_FLASH_CS_PIN)) {Serial.println («Невозможно получить доступ к микросхеме SPI Flash»); } saveNetworkKnowledge ();} / * Специальные функции освещения из примера кода Adafruit Strandtest * Введите значение от 0 до 255, чтобы получить значение цвета. Используется для эффекта радуги выше. * Theatre Chase lights из примера кода Adafruit strandtest. Это берет любое текущее значение RGB и создает с ним эффект "театральной погони". * // * Ползучие огни в театральном стиле. * / Void TheaterChasePIN (uint8_t p, uint32_t c, uint8_t wait) {Adafruit_NeoPixel strip =Adafruit_NeoPixel (10, p, NEO_GRB + NEO_KHZ800); for (int j =0; j <10; j ++) {// делаем 10 циклов погони за (int q =0; q <3; q ++) {for (uint16_t i =0; i  
PME_LED Arduino
Это использование PME Кюри для управления светодиодами. По сути, это комбинация кода Draw in the Air PME и кода примера Adafruit NeoPixel. Этот код - не совсем то, что я использовал (что немного сложно), поскольку я сомневаюсь, что вы создадите точно такой же вид расположения созвездий. Скорее, вот общий код, который вы можете изменить, чтобы персонализировать свои потребности, например вы можете изменить способ распределения контактов для разных светодиодных лент. Я могу обновить его улучшенным кодом позже.
 / * * Этот пример демонстрирует использование механизма сопоставления с образцом (CuriePME) * для классификации потоков данных акселерометра от CurieIMU. Код является модификацией примера Draw in the Air:* https://github.com/01org/Intel-Pattern-Matching-Technology * * First, the sketch will prompt you to draw patterns in the air (just * imagine you are writing on an invisible whiteboard, using your board as the * pen), and the IMU data from these motions is used as training data for the * PME. Once training is finished, you can keep drawing letters and the PME * will try to guess which letter you are drawing. * * This example requires a button to be connected to digital pin 4 * https://www.arduino.cc/en/Tutorial/Button * * NOTE:For best results, draw big letters, at least 1-2 feet tall. * * Copyright (c) 2016 Intel Corporation. Все права защищены. * See license notice at end of file. */#include "CurieIMU.h"#include "CuriePME.h"#include #define PIN 6 //// what pin are the NeoPixels connected to?Adafruit_NeoPixel strip =Adafruit_NeoPixel(54, PIN, NEO_GRB + NEO_KHZ800); /// the strip is 15 pixels long. You can change this for the number of pixels in your individual strip.int tr =0; //Some variables to hold "color-target" and "color-current" for smoothing...int tg =0;int tb =0;int r =0;int g =0;int b =0;int rawX =0; ///// to hold values from the Curie's accelerometerint rawY =0;//int rawZ =0;float angle =0.0;/* This controls how many times a letter must be drawn during training. * Any higher than 4, and you may not have enough neurons for all 26 letters * of the alphabet. Lower than 4 means less work for you to train a letter, * but the PME may have a harder time classifying that letter. */const unsigned int trainingReps =4;/* Increase this to 'A-Z' if you like-- it just takes a lot longer to train */const unsigned char trainingStart ='A';const unsigned char trainingEnd ='D';/* The input pin used to signal when a letter is being drawn- you'll * need to make sure a button is attached to this pin */const unsigned int buttonPin =4;/* Sample rate for accelerometer */const unsigned int sampleRateHZ =200;/* No. of bytes that one neuron can hold */const unsigned int vectorNumBytes =128;/* Number of processed samples (1 sample ==accel x, y, z) * that can fit inside a neuron */const unsigned int samplesPerVector =(vectorNumBytes / 3);/* This value is used to convert ASCII characters A-Z * into decimal values 1-26, and back again. */const unsigned int upperStart =0x40;const unsigned int sensorBufSize =2048;const int IMULow =-32768;const int IMUHigh =32767;void setup(){ Serial.begin(9600); // while(!Serial); pinMode(buttonPin, INPUT); /* Start the IMU (Intertial Measurement Unit) */ CurieIMU.begin(); /* Start the PME (Pattern Matching Engine) */ CuriePME.begin(); CurieIMU.setAccelerometerRate(sampleRateHZ); CurieIMU.setAccelerometerRange(2); trainLetters(); //Serial.println("Training complete. Now, draw some letters (remember to "); // Serial.println("hold the button) and see if the PME can classify them."); strip.begin (); // intialize neopixel strip strip.show(); // Initialize all pixels to 'off'}void loop (){ /// these functions are written out at the bottom of the sketch. Serial.println("Training complete. Now, draw some letters (remember to ");Serial.println("hold the button) and see if the PME can classify them."); byte vector[vectorNumBytes]; unsigned int category; char letter; char pattern; /* Record IMU data while button is being held, and * convert it to a suitable vector */ readVectorFromIMU(vector); /* Use the PME to classify the vector, i.e. return a category * from 1-26, representing a letter from A-Z */ category =CuriePME.classify(vector, vectorNumBytes); if (category ==CuriePME.noMatch) { Serial.println("Don't recognise that one-- try again."); //theaterChase(); theaterChase(strip.Color(127, 127, 127), 50); // White strip.show(); // delay(10); } else { letter =category + upperStart; pattern =letter; if ( pattern =='A' ) { //red colorWipe(strip.Color(0, 255, 0), 50); // Green theaterChase(strip.Color(127, 127, 127), 50); // White strip.show(); } else if ( pattern =='B') { colorWipe(strip.Color(255, 0, 0), 50); // Red theaterChase(strip.Color(127, 127, 127), 50); // White strip.show(); } else if ( pattern =='C') { colorWipe(strip.Color(0, 0, 255), 50); // Blue theaterChase(strip.Color(127, 127, 127), 50); // White strip.show(); } else if ( pattern =='D') { colorWipe(strip.Color(255, 0, 255), 50); // Blue theaterChase(strip.Color(127, 127, 127), 50); // White strip.show(); }Serial.println(letter); } }/* Simple "moving average" filter, removes low noise and other small * anomalies, with the effect of smoothing out the data stream. */byte getAverageSample(byte samples[], unsigned int num, unsigned int pos, unsigned int step){ unsigned int ret; unsigned int size =step * 2; if (pos <(step * 3) || pos> (num * 3) - (step * 3)) { ret =samples[pos]; } else { ret =0; pos -=(step * 3); for (unsigned int i =0; i  sensorBufSize) { break; } } } undersample(accel, samples, vector);}void trainLetter(char letter, unsigned int repeat){ unsigned int i =0; while (i  

Схема

It's just connecting the LEDs to the Arduino 101 pins and a button to pin 4 (as described in the code:https://www.arduino.cc/en/Tutorial/Button). The circuit diagram is similar to this Fritzing from Adafruit:https://learn.adafruit.com/adafruit-neopixel-uberguide/basic-connections
I plugged the 9 V battery directly into the barrel jack.

Производственный процесс

  1. Выкройка одежды
  2. Сборка макетов Arduino без перемычек
  3. Датчик DHT11 со светодиодами и пьезо-динамиком
  4. Arduino Spybot
  5. FlickMote
  6. Самодельный телевизор B-Gone
  7. Основные часы
  8. Arduino + светодиоды + MIDI-клавиатура + MuseScore =Piano Tutor
  9. Светодиоды, управляемые Alexa через Raspberry Pi
  10. Найди меня