Industriële fabricage
Industrieel internet der dingen | Industriële materialen | Onderhoud en reparatie van apparatuur | Industriële programmering |
home  MfgRobots >> Industriële fabricage >  >> Manufacturing Technology >> Productieproces

Arduino 101 - Intel Curie patroon bijpassende jurk

Componenten en benodigdheden

NeoPixel-strip
Kan worden vervangen door afzonderlijke RGB-leds.
× 1
Arduino 101
× 1
SparkFun Drukknopschakelaar 12 mm
× 1
Weerstand 10k ohm
× 1
Jumperdraden (algemeen)
Je hebt misschien lange draden nodig om de led's van je schouder naar je hand te geleiden.
× 1
9V-batterij (algemeen)
× 1
9V naar Barrel Jack Connector
× 1
Adafruit Flora RGB Neopixel LED's - Set van 4
Dit kan worden gebruikt om de Neopixel-strip te vervangen.
× 1
Naaibare geleidende draad
Optie om sommige draden te vervangen.
× 1

Benodigde gereedschappen en machines

Hot lijmpistool (algemeen)
naaimachine (algemeen)
Soldeerbout (algemeen)

Apps en online services

Arduino IDE

Over dit project

Inleiding

Ik ben een ingenieur en kunstenaar die geniet van projecten die wetenschap en kunst combineren. Ik heb jurkontwerpen gemaakt met ingebouwde microcontrollers, zodat bepaalde functionaliteit van elektronische componenten kan worden gebruikt om het ontwerpthema te verbeteren. Voor dit project wil ik de Pattern Matching Engine (PME) en de accelerometer in Intel Curie op Arduino 101 gebruiken. Curie is gemaakt voor PME-toepassingen omdat het neurale netwerkmogelijkheden heeft, maar er zijn niet veel PME-voorbeelden die er zijn . Ik hoop dat dit voorbeeld je kan inspireren om Curie's PME-capaciteiten te extraheren.

De jurk gebruikt een pagina van mijn graphic novel als stof. Een wetenschapper en haar robot kijken in de telescoop. Terwijl de drager een patroon in de lucht tekent, zal een reeks LED's in de vorm van sterrenbeelden aan de nachtelijke hemel op de stof schijnen.

Instructies

*Opmerking:nadat dit project was gepubliceerd, heb ik het elektronische circuitgedeelte gerenoveerd. Een verbeterde methode om de LED's aan het doek te bevestigen en hoe ze duurzaam te maken, wordt nu hieronder gepubliceerd na stap 3.

** Update:het dragen van deze jurk voor een paar demo-evenementen die de hele dag duren, gaf een schatting van de levensduur van de batterij. Om deze jurk van stroom te voorzien, moet de 9 V-batterij ongeveer elke 3 uur worden vervangen. De batterij raakt niet leeg, maar zakt onder de 9 V, waardoor het inefficiënt is om het patroon te matchen. U kunt de batterij voor ander gebruik bewaren.

Stap 1

Ik gebruikte een NeoPixel-strip van Adafruit, sneed deze in stukjes en rangschikte ze in de vorm van sterrenbeelden. Gebruik gerust andere soorten LED's zoals de individuele RGB LED's. Lijm of naai ze op de basisstof.

Stap 2

Leg er een interfacing-stof op en je kunt de sterrenbeelden omlijnen. Deze stap is optioneel, maar ik vond het handig om meerdere lagen stof te hebben om de structuur te versterken. Ik naaide eigenlijk nog een dikke stof op de achterkant van de basisstof. Dus in totaal drie lagen als basis, met daartussen de LED's.

Stap 3

Soldeer de LED's. Als u de opnaaibare individuele LED's gebruikt, kunt u ook geleidende draden gebruiken om ze te verbinden. Hoe dan ook, het is veel handwerk en vereist geduld. Omdat ik vier sterrenbeelden heb (Orion, Grote Beer, Cygnus en Cassiopeia), heb ik ze in vier sporen gescheiden. Elk wordt verbonden met een andere Arduino 101-pin.

Verbeterde stappen

De stof die ik gebruikte voor de bovenstaande stappen was te zacht, waardoor het gemakkelijk is om de LED's en draden te buigen en de soldeerverbindingen te breken. Ik heb het hele proces opnieuw gedaan met de volgende verbeterde methode.

Plaats de LED's

Ik gebruikte een NeoPixel-strip van Adafruit en sneed deze in stukjes en rangschikte ze in de vorm van sterrenbeelden. Gebruik gerust andere soorten LED's zoals de individuele RGB LED's. Lijm of naai ze op de basisstof.

Vilt is een mooie dikke stof die structuur geeft en goed werkt met hete lijm. Schik de LED's in respectieve posities zodat wanneer ze oplichten, hun posities de sterren in sterrenbeelden weerspiegelen.

Plan de LED's en draden

Lijm de LED-strepen op enkele punten op vilt. Breng geen lijm aan onder de hele strip omdat je wat speling nodig hebt om krimpkousen rond te schuiven, zoals weergegeven in de afbeelding. Knip gevlochten draden in de juiste lengtes en plaats ze op hun relatieve posities op hetzelfde stuk vilt. Ik zou aanraden om de draden nog niet warm te lijmen. Mijn figuur hier is in dat opzicht een blunder. Het is eerder beter om de draden op hun plaats te houden met tijdelijke tape, zodat wanneer u de draden aan de LED's soldeert, de draadposities kunnen worden aangepast.

Maak alle stukken klaar om te naaien

De afbeelding laat zien dat ik vier sterrenbeelden (Orion, Grote Beer, Cygnus en Cassiopeia) op vier afzonderlijke stukken heb voorbereid. Na het solderen en krimpen rond de soldeerverbindingen, kun je alles stevig op het vilt lijmen.

Test!

Test je circuit voordat je verder gaat! Kan gewoon een NeoPixel Strandtest doen voor elk spoor.

Oké, ik heb het niveau op "Eenvoudig" gezet, omdat het wetenschappelijk gezien niet moeilijk is als je de code eenmaal begrijpt, maar het kost veel werk om de kabels op de stof te stabiliseren.

Zorg ervoor dat uw Arduino IDE de nieuwste versie is en een Curie PME-bibliotheek heeft. Ik raad aan om de Arduino Web Editor te gebruiken. Download de bibliotheek hier.

Maak de jurk

Maak tegelijkertijd (figuurlijk) de jurk. Nadat je het circuit hebt getest, naai je de basisstoffen met de LED's aan de binnenkant van de jurk. LED's schijnen door de graphics heen.

Zoals je kunt zien, heb ik de Arduino 101 in mijn hand. Ik heb een 3D-geprint hoesje gemaakt voor de Arduino 101 en batterij. Er zijn lange draden die de LED's en het bord verbinden, die verborgen zijn in de hoes.

De onderstaande code geeft u informatie over hoe het bord is geprogrammeerd. Nadat je de code hebt geflitst, train je eerst de neuronen zodat ze leren welke patronen er zijn. Bekijk deze video om ~0:30:

Voor meer foto's en andere tech-fashion/schilderijen-op-stof ontwerpen, kijk op mijn website :)

Code

  • PME_4LED_new.ino
  • PME_LED
PME_4LED_new.inoArduino
Dit is een bijgewerkt script van het vorige. Het slaat de trainingsgegevens op. Momenteel is het ingesteld met een initialisatiestap. De eerste reeks LED's is rood wanneer de stroom is ingeschakeld. Door de Arduino101 plat te houden met de USB-poort in horizontale richting wijzend, terwijl u op de knop drukt, kunt u gebruik maken van eerdere training. Deze LED's veranderen in groen en dan blauw wanneer de knop wordt losgelaten, wat aangeeft dat het systeem gereed is. Als de Arduino101 wordt vastgehouden met de USB-poort in verticale richting wijzend, terwijl de knop wordt ingedrukt, worden eerdere trainingsgegevens gewist. Het systeem kan opnieuw worden getraind door de knop los te laten.
/* * Dit voorbeeld demonstreert het gebruik van de patroonafstemmingsengine (CuriePME) * om stromen versnellingsmetergegevens van CurieIMU te classificeren. * * Eerst zal de schets je vragen om enkele letters in de lucht te tekenen (stel je *stel je voor dat je op een onzichtbaar whiteboard schrijft, je bord als de * pen gebruikt), en de IMU-gegevens van deze bewegingen worden gebruikt als trainingsgegevens voor de * PME. Als de training klaar is, kun je letters blijven tekenen en zal de PME* proberen te raden welke letter je aan het tekenen bent. * * Voor dit voorbeeld moet een knop worden aangesloten op digitale pin 4 * https://www.arduino.cc/en/Tutorial/Button * * OPMERKING:Voor de beste resultaten tekent u grote letters, minstens 1-2 voet lang. * * Copyright (c) 2016 Intel Corporation. Alle rechten voorbehouden. * Zie licentiekennisgeving aan het einde van het bestand. */#include "CurieIMU.h"#include "CuriePME.h"#include #include #include #define PINM 6 //// welke pin zijn de NeoPixels verbonden met?#define PINC 3#define PINS 9#define PINO 5 Adafruit_NeoPixel stripM =Adafruit_NeoPixel(10, PINM, NEO_GRB + NEO_KHZ800); /// de strip is 15 pixels lang. U kunt dit wijzigen voor het aantal pixels in uw individuele strip.Adafruit_NeoPixel stripS =Adafruit_NeoPixel(10, PINS, NEO_GRB + NEO_KHZ800);Adafruit_NeoPixel stripC =Adafruit_NeoPixel(10, PINC, NEO_GRB + Nix_PINS, NEO_GRB + NEO_KHZ800); , NEO_GRB + NEO_KHZ800);int tr =0; //Sommige variabelen om "kleurdoel" en "kleurstroom" vast te houden voor afvlakking ... int tg =0;int tb =0;int r =0;int g =0;int b =0;int rawX =0; ///// om waarden vast te houden van de Curie's accelerometerint rawY =0;//int rawZ =0;float angle =0.0;/* Dit bepaalt hoe vaak een letter moet worden getekend tijdens de training. * Elke hoger dan 4, en je hebt mogelijk niet genoeg neuronen voor alle 26 letters * van het alfabet. Lager dan 4 betekent minder werk voor u om een ​​letter te trainen, * maar de PME kan het moeilijker hebben om die letter te classificeren. */const unsigned int trainingReps =4;/* Verhoog dit naar 'AZ' als je wilt -- het duurt gewoon veel langer om te trainen */const unsigned char trainingStart ='A';const unsigned char trainingEnd ='D'; /* De invoerpin die wordt gebruikt om aan te geven wanneer een letter wordt getekend - je moet * ervoor zorgen dat er een knop aan deze pin is bevestigd */const unsigned int buttonPin =4;/* Sample rate voor accelerometer */const unsigned int sampleRateHZ =200;/* Aantal bytes dat één neuron kan bevatten */const unsigned int vectorNumBytes =128;/* Aantal verwerkte samples (1 sample ==accel x, y, z) * dat in een neuron past * /const unsigned int samplesPerVector =(vectorNumBytes / 3);/* Deze waarde wordt gebruikt om ASCII-tekens AZ * om te zetten in decimale waarden 1-26, en weer terug. */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) ); //terwijl (! Serieel); pinMode (knopPin, INPUT); /* Start de IMU (Intertial Measurement Unit) */ CurieIMU.begin(); /* Start de PME (Pattern Matching Engine) */ CuriePME.begin(); CurieIMU.setAccelerometerRate(sampleRateHZ); CurieIMU.setVersnellingsmeterBereik(2); /* In het. SPI Flash-chip */ if (!SerialFlash.begin(ONBOARD_FLASH_SPI_PORT, ONBOARD_FLASH_CS_PIN)) {Serial.println("Kan geen toegang krijgen tot SPI Flash-chip"); } stripM.begin(); // initialiseer neopixel strip stripS.begin(); stripC.begin(); stripO.begin(); stripM.show(); // Initialiseer alle pixels op 'uit' stripS.show(); stripC.show(); stripO.show(); vaste M(stripM.Kleur(255, 0, 0), 50); //Rood voor gereed voor invoer}/* Deze functie leest het bestand dat is opgeslagen door het vorige voorbeeld * Het bestand bevat alle gegevens die zijn geleerd en eerder zijn opgeslagen. * Zodra het netwerk is hersteld, kan het patronen opnieuw classificeren zonder * opnieuw getraind te hoeven worden.*/void restoreNetworkKnowledge ( void ){ SerialFlashFile-bestand; int32_t bestandNeuronCount =0; Intel_PMT::neuronData neuronData; // Open het bestand en schrijf testgegevensbestand =SerialFlash.open(bestandsnaam); CuriePME.beginRestoreMode(); if (file) { // itereer via het netwerk en sla de gegevens op. while(1) { Serial.print("Reading Neuron:"); uint16_t neuronFields[4]; file.read( (void*) neuronFields, 8); file.read( (void*) neuronData.vector, 128); neuronData.context =neuronFields[0]; neuronData.influence =neuronFields[1]; neuronData.minInfluence =neuronFields[2]; neuronData.category =neuronFields[3]; if (neuronFields[0] ==0 || neuronFields[0]> 127) breken; bestandNeuronCount++; // dit deel drukt gewoon elk neuron af zoals het is hersteld, // zodat je kunt zien wat er gebeurt. Serial.print(bestandNeuronCount); Serieel.print("\n"); Serial.print( neuronFields[0] ); Serieel.print( "\t"); Serial.print( neuronFields[1] ); Serieel.print( "\t"); Serial.print( neuronFields[2] ); Serieel.print( "\t"); Serial.print( neuronFields[3] ); Serieel.print( "\t"); Serial.print( neuronData.vector[0] ); Serieel.print( "\t"); Serial.print( neuronData.vector[1] ); Serieel.print( "\t"); Serial.print( neuronData.vector[2] ); Serieel.print( "\n"); CuriePME.iterateNeuronsToRestore (neuronData); } } CuriePME.endRestoreMode(); Serial.print("Kennisset hersteld. \n");}boolean longPress=false;int startTime=0;int lastOrientation =- 1; // vorige oriëntatie (ter vergelijking) int lastReading =-1; boolean lastPress =false; lege lus () {int oriëntatie =- 1; // de oriëntatie van het bord String oriëntatieString; // tekenreeks voor afdrukken beschrijving van oriëntatie // De oriëntaties van het bord:// 0:plat, processor naar boven gericht // 1:plat, processor naar beneden gericht // 2:liggend, analoog pinnen omlaag // 3:liggend, analoog pinnen omhoog // 4:portret, USB-connector omhoog // 5:portret, USB-connector omlaag // lees versnellingsmeter:int x =CurieIMU.readAccelerometer (X_AXIS); int y =CurieIMU.readAccelerometer(Y_AXIS); int z =CurieIMU.readAccelerometer(Z_AXIS); // bereken de absolute waarden om de grootste te bepalen int absX =abs(x); int absY =abs(y); int absZ =abs(z); if ( ((absZ> absX) &&(absZ> absY)) { // basisoriëntatie op Z if (z> 0) {oriëntatieString ="omhoog"; oriëntatie =0; } else {orientString ="omlaag"; oriëntatie =1; } } else if ( (absY> absX) &&(absY> absZ)) { // basisoriëntatie op Y if (y> 0) {orientatieString ="digitale pinnen omhoog"; oriëntatie =2; } else {orientString ="analoog pinnen omhoog"; oriëntatie =3; } } else { // basisoriëntatie op X if (x <0) {oriëntatieString ="connector omhoog"; oriëntatie =4; } else {orientString ="connector omlaag"; oriëntatie =5; } } // als de oriëntatie is veranderd, druk dan een beschrijving af:if (orientation !=lastOrientation) { Serial.println(orientationString); lastOrientation =oriëntatie; } // als de oriëntatie is veranderd, print dan een beschrijving uit:if (orientation !=lastOrientation) { lastOrientation =oriëntatie; } int lezen =digitalRead (buttonPin); if (lastReading! =lezen) { Serial.print("buttonPin="); Serial.println (lezen); lastReading =lezen; } if (lezing ==HOOG) { if (startTime ==0) { startTime=millis(); } else if ((millis() - startTime)>2000) { longPress=true; if (!lastPress) { Serial.println("longPress"); // groen voor lang indrukken solidM (stripM.Color (0, 255, 0), 50);// Groen lastPress =true; } } } if ( lezen ==LAAG &&longPress ) { blackout(5); Serial.print("oriëntatie="); Serial.print(oriëntatie); Serial.print("SerialFlash.exists(bestandsnaam)="); Serial.println(SerialFlash.exists(bestandsnaam)); if (oriëntatie!=4 &&SerialFlash.exists(bestandsnaam)) { restoreNetworkKnowledge(); Serial.print("Training hersteld."); } else { trainLetters(); stroomuitval (5); Serial.print("Training voltooid."); } Serial.println(" Teken nu wat letters (vergeet niet om "); Serial.println("houd de knop ingedrukt) en kijk of de PME ze kan classificeren."); vaste M(stripM.Kleur(0, 0, 255), 500); // Blauw voor klaar voor bijpassende blackout (5); // uitschakelen voor matching while (true) { match(); } }}void solidM(uint32_t c, uint8_t wait) { for (uint16_t i=0; i  (num * 3) - (stap * 3)) { ret =samples[pos]; } anders { ret =0; pos -=(stap * 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  
PME_LEDArduino
Dit gebruikt de Curie PME om LED's aan te sturen. Het is eigenlijk een combinatie van de Draw in the Air PME-code en de Adafruit NeoPixel-voorbeeldcode. Deze code is niet precies wat ik heb gebruikt (wat een beetje ingewikkeld is), omdat ik betwijfel of je precies hetzelfde soort constellatie-arrangement zult maken. In plaats daarvan is hier een generieke code die u kunt wijzigen om uw behoefte te personaliseren, b.v. u kunt wijzigen hoe u de pinnen voor verschillende LED-strips verdeelt. I may update it with an improved code later.
/* * This example demonstrates using the pattern matching engine (CuriePME) * to classify streams of accelerometer data from CurieIMU.The code is a modification of the Draw in the Air example:* 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. Alle rechten voorbehouden. * 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   

Schema's

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.

Productieproces

  1. Kledingpatroon
  2. Arduino breadboards bouwen zonder jumperdraden
  3. DHT11-sensor met LED's en een piëzo-luidspreker
  4. Arduino Spybot
  5. FlickMote
  6. Zelfgemaakte tv B-Gone
  7. Hoofdklok
  8. Arduino + LED's + MIDI Keyboard + MuseScore =Piano Tutor
  9. Alexa gestuurde LED's via Raspberry Pi
  10. Vind mij
  11. Arduino Power