Manufactura industrial
Internet industrial de las cosas | Materiales industriales | Mantenimiento y reparación de equipos | Programación industrial |
home  MfgRobots >> Manufactura industrial >  >> Manufacturing Technology >> Proceso de manufactura

Arduino 101 - Vestido a juego con el patrón Intel Curie

Componentes y suministros

Tira de NeoPixel
Podría ser reemplazado por LED RGB individuales.
× 1
Arduino 101
× 1
Interruptor de botón SparkFun de 12 mm
× 1
Resistencia de 10k ohmios
× 1
Cables de puente (genéricos)
Es posible que necesite cables largos para guiar los LED desde su hombro hasta su mano.
× 1
batería de 9V (genérica)
× 1
Conector de conector de barril de 9 V
× 1
LED Adafruit Flora RGB Neopixel - Paquete de 4
Esto se puede usar para reemplazar la tira de Neopixel.
× 1
Hilo conductor cosible
Opción para reemplazar algunos cables.
× 1

Herramientas y máquinas necesarias

Pistola de pegamento caliente (genérica)
máquina de coser (genérica)
Soldador (genérico)

Aplicaciones y servicios en línea

Arduino IDE

Acerca de este proyecto

Introducción

Soy un ingeniero y artista al que le gustan los proyectos que combinan ciencia y arte. He estado haciendo diseños de vestidos con microcontroladores integrados para que se pueda usar cierta funcionalidad de los componentes electrónicos para mejorar el tema del diseño. Para este proyecto, quiero usar el motor de coincidencia de patrones (PME) y el acelerómetro dentro de Intel Curie en Arduino 101. Curie está hecho para aplicaciones PME ya que tiene capacidad de red neuronal, pero no ha habido muchos ejemplos de PME por ahí. . Espero que este ejemplo lo inspire a extraer la capacidad PME de Curie.

El vestido usa una página de mi novela gráfica como tela. Una científica y su robot miran por el telescopio. A medida que el usuario dibuja un patrón en el aire, un conjunto de LED dispuestos en forma de constelaciones brillarán en el cielo nocturno sobre la tela.

Instrucciones

* Nota:después de la publicación de este proyecto, renové la parte del circuito electrónico. Un método mejorado para unir los LED a la tela y cómo hacerlos duraderos ahora se publica a continuación después del paso 3.

** Actualización:usar este vestido para algunos eventos de demostración de todo el día proporcionó una estimación de la duración de la batería. Para alimentar este vestido, la batería de 9 V debe cambiarse aproximadamente cada 3 horas. La batería no se agota, pero cae por debajo de 9 V, lo que hace que sea ineficaz hacer la coincidencia de patrones. Puede guardar la batería para otros usos.

Paso 1

Usé una tira de NeoPixel de Adafruit, la corté en pedazos y los coloqué en forma de constelaciones. No dude en utilizar otros tipos de LED, como los LED RGB individuales. Péguelas o cóselas a la tela base.

Paso 2

Coloque una tela de interfaz en la parte superior y puede delinear las constelaciones. Este paso es opcional, pero me resultó útil tener varias capas de telas para fortalecer la estructura. De hecho, cosí otra tela gruesa en la parte posterior de la tela base. Entonces, tres capas en total como base, intercalando los LED.

Paso 3

Suelde los LED. Si usa los LED individuales cosibles, también puede usar hilos conductores para conectarlos. De cualquier manera, es mucho trabajo manual y requiere paciencia. Como tengo cuatro constelaciones (Orión, Osa Mayor, Cygnus y Cassiopeia), las separé en cuatro trazos. Cada uno estará conectado a un pin Arduino 101 diferente.

Pasos mejorados

La tela que utilicé para los pasos anteriores era demasiado suave, lo que facilita doblar los LED y los cables, rompiendo las juntas de soldadura. Volví a hacer todo el proceso con el siguiente método mejorado.

Coloque los LED

Usé una tira de NeoPixel de Adafruit y la corté en pedazos y los coloqué en formas de constelaciones. No dude en utilizar otros tipos de LED, como los LED RGB individuales. Péguelas o cóselas a la tela base.

El fieltro es un bonito tipo de tela gruesa que le da estructura y funciona bien con pegamento caliente. Coloque los LED en sus respectivas posiciones para que cuando se enciendan, reflejen las estrellas en constelaciones.

Planifique los LED y los cables

Pegue las franjas de LED sobre fieltro en algunos puntos. No coloque pegamento debajo de toda la tira porque necesita cierto margen para deslizar los tubos termorretráctiles, como se muestra en la figura. Corte los alambres trenzados en las longitudes correctas y colóquelos en sus posiciones relativas en el mismo trozo de fieltro. Recomendaría no pegar en caliente los cables todavía. Mi cifra aquí es un error en ese sentido. Más bien, es mejor mantener los cables en sus posiciones con cinta temporal para que cuando suelde los cables a los LED, las posiciones de los cables se puedan ajustar.

Haga todas las piezas listas para coser

La figura muestra que preparé cuatro constelaciones (Orión, Osa Mayor, Cygnus y Cassiopeia) en cuatro piezas separadas. Después de soldar y encoger con calor alrededor de las uniones soldadas, puede pegar todo firmemente sobre el fieltro.

Prueba!

¡Prueba tu circuito antes de continuar! Solo puedo hacer una prueba de NeoPixel Strandtest para cada rastro.

De acuerdo, puse el nivel como "Fácil" ya que científicamente no es difícil una vez que entiendes el código, pero se necesita mucho trabajo para estabilizar los cables en la tela.

Asegúrese de que su Arduino IDE sea la última versión y tenga la biblioteca Curie PME. Recomendaría usar el editor web Arduino. Descarga la biblioteca aquí.

Haz el vestido

En paralelo (en sentido figurado), haz el vestido. Después de probar el circuito, cose las telas base con los LED en el interior del vestido. Los LED brillarán a través de los gráficos.

Como puede ver, el Arduino 101 está en mi mano. Hice una carcasa impresa en 3D para el Arduino 101 y la batería. Hay cables largos que conectan los LED y la placa, que están ocultos en la funda.

El siguiente código le dará información sobre cómo está programada la placa. Después de flashear el código, entrene primero a las neuronas para que aprendan qué patrones existen. Mire este video en ~ 0:30:

Para obtener más fotos y otros diseños de tecnología-moda / pinturas-sobre-tela, visite mi sitio web :)

Código

  • PME_4LED_new.ino
  • PME_LED
PME_4LED_new.ino Arduino
Este es un script actualizado del anterior. Almacena los datos de entrenamiento. Actualmente, está configurado con un paso de inicialización. La primera serie de LED se muestra en rojo cuando está encendido. Sostener el Arduino101 plano con el puerto USB apuntando en la dirección horizontal, mientras presiona el botón, permite el uso del entrenamiento anterior. Estos LED cambian a verde y luego a azul cuando se suelta el botón, lo que indica que el sistema está listo. Si se sostiene el Arduino101 con el puerto USB apuntando en dirección vertical, mientras se presiona el botón, se borran los datos de entrenamiento anteriores. El sistema se puede volver a entrenar al soltar el botón.
 / * * Este ejemplo demuestra el uso del motor de coincidencia de patrones (CuriePME) * para clasificar flujos de datos del acelerómetro de CurieIMU. * * Primero, el boceto te pedirá que dibujes algunas letras en el aire (solo * imagina que estás escribiendo en una pizarra invisible, usando tu pizarra como * bolígrafo), y los datos de IMU de estos movimientos se utilizan como datos de entrenamiento para el * PME. Una vez finalizado el entrenamiento, puede seguir dibujando letras y el PME * intentará adivinar qué letra está dibujando. * * Este ejemplo requiere que se conecte un botón al pin digital 4 * https://www.arduino.cc/en/Tutorial/Button * * NOTA:Para obtener mejores resultados, dibuje letras grandes, de al menos 1-2 pies de altura. * * Copyright (c) 2016 Intel Corporation. Reservados todos los derechos. * Vea el aviso de licencia al final del archivo. * / # include "CurieIMU.h" #include "CuriePME.h" #include  #include  #include  #define PINM 6 //// qué pin son los NeoPixels conectado a? #define PINC 3 # define PINS 9 # define PINO 5 Adafruit_NeoPixel stripM =Adafruit_NeoPixel (10, PINM, NEO_GRB + NEO_KHZ800); /// la tira tiene 15 píxeles de largo. Puede cambiar esto por el número de píxeles en su tira individual. Adafruit_NeoPixel stripS =Adafruit_NeoPixel (10, PINS, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel stripC =Adafruit_NeoPixel (10, PINC, Adafruit_NeoPixel + NEO_KHeoPixel , NEO_GRB + NEO_KHZ800); int tr =0; // Algunas variables para contener "color-target" y "color-current" para suavizar ... int tg =0; int tb =0; int r =0; int g =0; int b =0; int rawX =0; ///// para contener valores del acelerómetro de Curieint rawY =0; // int rawZ =0; float angle =0.0; / * Esto controla cuántas veces se debe dibujar una letra durante el entrenamiento. * Cualquier valor superior a 4, y es posible que no tenga suficientes neuronas para las 26 letras * del alfabeto. Menos de 4 significa menos trabajo para entrenar una letra, * pero el PME puede tener más dificultades para clasificar esa letra. * / const unsigned int trainingReps =4; / * Aumente esto a 'AZ' si lo desea; solo toma mucho más tiempo entrenar * / const unsigned char trainingStart ='A'; const unsigned char trainingEnd ='D'; / * El pin de entrada utilizado para señalar cuando se está dibujando una letra; necesitará * asegurarse de que haya un botón conectado a este pin * / const unsigned int buttonPin =4; / * Frecuencia de muestreo para acelerómetro * / const unsigned int sampleRateHZ =200; / * No. de bytes que una neurona puede contener * / const unsigned int vectorNumBytes =128; / * Número de muestras procesadas (1 muestra ==accel x, y, z) * que pueden caber dentro de una neurona * / const unsigned int samplesPerVector =(vectorNumBytes / 3); / * Este valor se usa para convertir los caracteres ASCII AZ * en valores decimales 1-26, y viceversa. * / 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 ); // mientras (! Serial); pinMode (buttonPin, INPUT); / * Iniciar la IMU (Unidad de medida intertial) * / CurieIMU.begin (); / * Iniciar el PME (motor de coincidencia de patrones) * / CuriePME.begin (); CurieIMU.setAccelerometerRate (sampleRateHZ); CurieIMU.setAccelerometerRange (2); /* En eso. Chip SPI Flash * / if (! SerialFlash.begin (ONBOARD_FLASH_SPI_PORT, ONBOARD_FLASH_CS_PIN)) {Serial.println ("No se puede acceder al chip SPI Flash"); } stripM.begin (); // inicializar la tira de neopixel stripS.begin (); stripC.begin (); stripO.begin (); stripM.show (); // Inicializar todos los píxeles en 'off' stripS.show (); stripC.show (); stripO.show (); solidM (tiraM.Color (255, 0, 0), 50); // Rojo para listo para entrada} / * Esta función lee el archivo guardado por el ejemplo anterior * El archivo contiene todos los datos que se aprendieron y luego se guardaron antes. * Una vez que se restaura la red, es capaz de clasificar patrones nuevamente sin * tener que ser reentrenado. * / Void restoreNetworkKnowledge (void) {SerialFlashFile file; int32_t fileNeuronCount =0; Intel_PMT ::neuronData neuronData; // Abra el archivo y escriba el archivo de datos de prueba =SerialFlash.open (nombre de archivo); CuriePME.beginRestoreMode (); if (archivo) {// iterar sobre la red y guardar los datos. while (1) {Serial.print ("Neurona de lectura:"); 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) break; fileNeuronCount ++; // esta parte simplemente imprime cada neurona a medida que se restaura, // para que pueda ver lo que está sucediendo. Serial.print (fileNeuronCount); Serial.print ("\ n"); Serial.print (neuronFields [0]); Serial.print ("\ t"); Serial.print (neuronFields [1]); Serial.print ("\ t"); Serial.print (neuronFields [2]); Serial.print ("\ t"); Serial.print (neuronFields [3]); Serial.print ("\ t"); Serial.print (neuronData.vector [0]); Serial.print ("\ t"); Serial.print (neuronData.vector [1]); Serial.print ("\ t"); Serial.print (neuronData.vector [2]); Serial.print ("\ n"); CuriePME.iterateNeuronsToRestore (neuronData); }} CuriePME.endRestoreMode (); Serial.print ("Conjunto de conocimientos restaurado. \ N");} boolean longPress =false; int startTime =0; int lastOrientation =- 1; // orientación anterior (para comparación) int lastReading =-1; boolean lastPress =false; void loop () {int orientación =- 1; // la orientación del tablero String OrientationString; // cadena para imprimir la descripción de la orientación // Las orientaciones de la placa:// 0:plano, procesador hacia arriba // 1:plano, procesador hacia abajo // 2:paisaje, pines analógicos abajo // 3:paisaje, analógico pines arriba // 4:retrato, conector USB arriba // 5:retrato, conector USB abajo // leer acelerómetro:int x =CurieIMU.readAccelerometer (X_AXIS); int y =CurieIMU.readAccelerometer (Y_AXIS); int z =CurieIMU.readAccelerometer (Z_AXIS); // calcula los valores absolutos, para determinar el mayor int absX =abs (x); int absY =abs (y); int absZ =abs (z); if ((absZ> absX) &&(absZ> absY)) {// base de la orientación en Z if (z> 0) {directionString ="up"; orientación =0; } else {OrientaciónString ="abajo"; orientación =1; }} else if ((absY> absX) &&(absY> absZ)) {// orientación base en Y if (y> 0) {OrientationString ="pines digitales arriba"; orientación =2; } else {OrientaciónString ="pines analógicos arriba"; orientación =3; }} else {// orientación de base en X if (x <0) {OrientationString ="conector arriba"; orientación =4; } else {OrientationString ="conector hacia abajo"; orientación =5; }} // si la orientación ha cambiado, imprima una descripción:if (orientación! =lastOrientation) {Serial.println (orientaciónString); lastOrientation =orientación; } // si la orientación ha cambiado, imprima una descripción:if (orientación! =última orientación) {última orientación =orientación; } lectura int =digitalRead (buttonPin); if (lastReading! =reading) {Serial.print ("buttonPin ="); Serial.println (lectura); lastReading =lectura; } if (lectura ==HIGH) {if (startTime ==0) {startTime =millis (); } else if ((millis () - startTime)> 2000) {longPress =true; if (! lastPress) {Serial.println ("longPress"); // verde para pulsación larga solidM (stripM.Color (0, 255, 0), 50); // Green lastPress =true; }}} if (lectura ==LOW &&longPress) {apagón (5); Serial.print ("orientación ="); Serial.print (orientación); Serial.print ("SerialFlash.exists (nombre de archivo) ="); Serial.println (SerialFlash.exists (nombre de archivo)); if (orientación! =4 &&SerialFlash.exists (nombre de archivo)) {restoreNetworkKnowledge (); Serial.print ("Entrenamiento restaurado"); } else {trainLetters (); apagón (5); Serial.print ("Entrenamiento completo"); } Serial.println ("Ahora, dibuje algunas letras (recuerde"); Serial.println ("mantenga presionado el botón) y vea si el PME puede clasificarlas."); solidM (tiraM.Color (0, 0, 255), 500); // Azul para listo para emparejar apagón (5); // apagar para hacer coincidir while (true) {match (); }}} void solidM (uint32_t c, uint8_t wait) {for (uint16_t i =0; i  (num * 3) - (paso * 3)) {ret =samples [pos]; } más {ret =0; pos - =(paso * 3); for (unsigned int i =0; i  sensorBufSize) {break; }}} submuestra (acel, muestras, vector);} void trainLetter (letra char, unsigned int repeat) {unsigned int i =0; while (i  
PME_LED Arduino
Esto está utilizando Curie PME para controlar los LED. Es básicamente una combinación del código Draw in the Air PME y el código de ejemplo de Adafruit NeoPixel. Este código no es exactamente lo que usé (lo cual es un poco complejo) ya que dudo que hagas exactamente el mismo tipo de disposición de constelaciones. Más bien, aquí hay un código genérico que puede modificar para personalizar sus necesidades, p. Ej. puede cambiar la forma de distribuir los pines para diferentes tiras de LED. Puedo actualizarlo con un código mejorado más adelante.
 / * * Este ejemplo demuestra el uso del motor de coincidencia de patrones (CuriePME) * para clasificar flujos de datos de acelerómetro de CurieIMU. El código es una modificación del ejemplo 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. Reservados todos los derechos. * 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   

Esquemas

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.

Proceso de manufactura

  1. Patrón de ropa
  2. Construyendo placas de prueba Arduino sin cables de puente
  3. Sensor DHT11 con LED y altavoz piezoeléctrico
  4. Arduino Spybot
  5. FlickMote
  6. Televisión casera B-Gone
  7. Reloj maestro
  8. Arduino + LED + Teclado MIDI + MuseScore =Tutor de piano
  9. LED controlados por Alexa a través de Raspberry Pi
  10. Encuéntrame
  11. Arduino Power