Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Processo de manufatura

Arduino 101 - Intel Curie Pattern Matching Dress

Componentes e suprimentos

NeoPixel strip
Pode ser substituído por LEDs RGB individuais.
× 1
Arduino 101
× 1
SparkFun Botão de pressão 12 mm
× 1
Resistor 10k ohm
× 1
Fios de jumpers (genérico)
Você pode precisar de fios longos para guiar os LEDs do ombro até a mão.
× 1
Bateria de 9 V (genérica)
× 1
9V para conector Barrel Jack
× 1
Adafruit Flora RGB Neopixel LEDs - Pacote de 4
Isso pode ser usado para substituir a faixa de Neopixel.
× 1
Linha condutiva costurável
Opção para substituir alguns fios.
× 1

Ferramentas e máquinas necessárias

Pistola de cola quente (genérica)
máquina de costura (genérica)
Ferro de soldar (genérico)

Aplicativos e serviços online

Arduino IDE

Sobre este projeto







Introdução


Sou um engenheiro e artista que gosta de projetos que combinem ciência e arte. Tenho feito designs de vestidos com microcontroladores embutidos para que certas funcionalidades de componentes eletrônicos possam ser usados ​​para aprimorar o tema do design. Para este projeto, quero usar o mecanismo de correspondência de padrões (PME) e o acelerômetro dentro do Intel Curie no Arduino 101. Curie é feito para aplicações PME, pois tem capacidade de rede neural, mas não há muitos exemplos de PME por aí . Espero que este exemplo possa inspirá-lo a extrair a capacidade de PME de Curie.

O vestido usa uma página da minha história em quadrinhos como tecido. Uma cientista e seu robô estão olhando para o telescópio. Conforme o usuário desenha um padrão no ar, um conjunto de LEDs dispostos em forma de constelações brilhará no céu noturno sobre o tecido.





Instruções


* Obs:após a publicação deste projeto, renovei a parte do circuito eletrônico. Um método aprimorado para anexar os LEDs ao pano e como torná-los duráveis ​​agora é publicado abaixo, após a etapa 3.

** Atualização:usar este vestido para alguns eventos de demonstração durante todo o dia forneceu uma estimativa da vida útil da bateria. Para alimentar este vestido, a bateria de 9 V precisa ser trocada a cada 3 horas. A bateria não esgota, mas cai abaixo de 9 V, tornando-a ineficiente para fazer a correspondência de padrões. Você pode economizar bateria para outros usos.





Etapa 1


Usei uma tira de NeoPixel de Adafruit, cortei-a em pedaços e organizei-os em formas de constelações. Sinta-se à vontade para usar outros tipos de LEDs, como LEDs RGB individuais. Cole ou costure no tecido de base.





Etapa 2


Coloque um tecido de interface no topo e você pode delinear as constelações. Esta etapa é opcional, mas achei útil ter várias camadas de tecido para fortalecer a estrutura. Na verdade, costurei outro tecido grosso na parte de trás do tecido base. Portanto, três camadas no total como base, imprensando os LEDs.





Etapa 3


Solde os LEDs. Se você usar LEDs individuais costuráveis, também poderá usar fios condutores para conectá-los. De qualquer forma, é muito trabalho manual e requer paciência. Como tenho quatro constelações (Orion, Big Dipper, Cygnus e Cassiopeia), separei-as em quatro traços. Cada um será conectado a um pino Arduino 101 diferente.





Passos aprimorados


O tecido que usei nas etapas acima era muito macio, o que facilita dobrar os LEDs e os fios, quebrando as juntas de solda. Refiz todo o processo com o seguinte método aprimorado.





Posicione os LEDs


Usei uma tira de NeoPixel de Adafruit, cortei-a em pedaços e arrumei-os em formas de constelações. Sinta-se à vontade para usar outros tipos de LEDs, como LEDs RGB individuais. Cole ou costure no tecido de base.

O feltro é um bom tipo de tecido grosso que dá estrutura e funciona bem com cola quente. Organize os LEDs nas respectivas posições de modo que, quando acenderem, suas posições reflitam as estrelas nas constelações.





Planeje os LEDs e os fios


Cole as listras de LED no feltro em alguns pontos. Não coloque cola sob a tira inteira porque você precisa de alguma margem de manobra para deslizar os tubos termorretráteis, conforme mostrado na figura. Corte os fios trançados nos comprimentos corretos e coloque-os em suas posições relativas no mesmo pedaço de feltro. Eu recomendaria não colar os fios com cola quente ainda. Minha figura aqui é um erro crasso a esse respeito. Em vez disso, é melhor segurar os fios em suas posições com fita temporária para que, quando você os soldar aos LEDs, as posições dos fios possam ser ajustadas.





Faça todas as peças prontas para costurar


A figura mostra que preparei quatro constelações (Orion, Ursa Maior, Cygnus e Cassiopeia) em quatro peças separadas. Depois de soldar e encolher por calor ao redor das juntas soldadas, você pode colar tudo firmemente no feltro.





Teste!


Teste seu circuito antes de prosseguir! Pode apenas fazer um NeoPixel Strandtest para cada traço.

Ok, coloquei o nível como "Fácil", pois cientificamente não é difícil depois que você entende o código, mas dá muito trabalho estabilizar os cabos no tecido.

Certifique-se de que seu Arduino IDE seja a versão mais recente e tenha a biblioteca Curie PME. Eu recomendo usar o Arduino Web Editor. Baixe a biblioteca aqui.





Faça o vestido


Paralelamente (figurativamente), faça o vestido. Depois de testar o circuito, costure os tecidos de base com os LEDs na parte interna do vestido. Os LEDs brilharão nos gráficos.



Como você pode ver, o Arduino 101 está em minhas mãos. Eu fiz uma caixa impressa em 3D para o Arduino 101 e a bateria. Existem fios longos conectando os LEDs e a placa, que estão escondidos na manga.

O código abaixo fornecerá informações sobre como a placa está programada. Depois de atualizar o código, treine os neurônios primeiro para que aprendam quais padrões existem. Assista a este vídeo às ~ 0:30:

Para mais fotos e outros designs de moda / pinturas em tecido, confira meu site :)

Código

  • PME_4LED_new.ino
  • PME_LED
PME_4LED_new.ino Arduino
Este é um script atualizado do anterior. Ele armazena os dados de treinamento. Atualmente, ele está configurado com uma etapa de inicialização. A primeira série de LEDs mostra vermelho quando a alimentação está ligada. Segurar o Arduino101 na horizontal com a porta USB apontando na direção horizontal, enquanto pressiona o botão, permite o uso do treinamento anterior. Esses LEDs mudam para Verde e depois para Azul quando o botão é liberado, indicando que o sistema está pronto. Se o Arduino101 for segurado com a porta USB apontando na direção vertical, enquanto pressiona o botão, os dados de treinamento anteriores são apagados. O sistema pode ser retreinado ao liberar o botão.
 / * * Este exemplo demonstra o uso do mecanismo de correspondência de padrões (CuriePME) * para classificar fluxos de dados do acelerômetro do CurieIMU. * * Primeiro, o esboço solicitará que você desenhe algumas letras no ar (apenas * imagine que você está escrevendo em um quadro branco invisível, usando seu quadro como a * caneta), e os dados IMU desses movimentos são usados ​​como dados de treinamento para o * PME. Depois de concluído o treinamento, você pode continuar desenhando letras e o PME * tentará adivinhar qual letra você está desenhando. * * Este exemplo requer que um botão seja conectado ao pino digital 4 * https://www.arduino.cc/en/Tutorial/Button * * NOTA:Para obter melhores resultados, desenhe letras grandes, de pelo menos 1-2 pés de altura. * * Copyright (c) 2016 Intel Corporation. Todos os direitos reservados. * Veja o aviso de licença no final do arquivo. * / # include "CurieIMU.h" #include "CuriePME.h" #include  #include  #include  #define PINM 6 //// quais pinos são os NeoPixels conectado a? #define PINC 3 # define PINS 9 # define PINO 5 Adafruit_NeoPixel stripM =Adafruit_NeoPixel (10, PINM, NEO_GRB + NEO_KHZ800); /// a faixa tem 15 pixels de comprimento. Você pode alterar isso para o número de pixels em sua faixa individual.Adafruit_NeoPixel stripS =Adafruit_NeoPixel (10, PINS, NEO_GRB + NEO_KHZ800); Adafruit_NeoPixel stripC =Adafruit_NeoPixel (10, PINC, NEO_GRB + NEO_KHZ800); , NEO_GRB + NEO_KHZ800); int tr =0; // Algumas variáveis ​​para conter "cor-alvo" e "cor-atual" para suavização ... int tg =0; int tb =0; int r =0; int g =0; int b =0; int rawX =0; ///// para manter os valores do acelerômetro de Curieint rawY =0; // int rawZ =0; ângulo de flutuação =0,0; / * Isso controla quantas vezes uma letra deve ser desenhada durante o treinamento. * Qualquer valor superior a 4, e você pode não ter neurônios suficientes para todas as 26 letras * do alfabeto. Menos de 4 significa menos trabalho para você treinar uma carta, * mas o PME pode ter mais dificuldade em classificar essa carta. * / const unsigned int trainingReps =4; / * Aumente para 'AZ' se quiser - leva muito mais tempo para treinar * / const unsigned char trainingStart ='A'; const unsigned char trainingEnd ='D'; / * O pino de entrada usado para sinalizar quando uma letra está sendo desenhada - você * precisa se certificar de que um botão está anexado a este pino * / const unsigned int buttonPin =4; / * Taxa de amostragem para acelerômetro * / const unsigned int sampleRateHZ =200; / * Nº de bytes que um neurônio pode conter * / const unsigned int vectorNumBytes =128; / * Número de amostras processadas (1 amostra ==accel x, y, z) * que pode caber dentro de um neurônio * / const unsigned int samplesPerVector =(vectorNumBytes / 3); / * Este valor é usado para converter caracteres ASCII AZ * em valores decimais 1-26 e vice-versa. * / 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, INPUT); / * Iniciar a IMU (Unidade de Medição Intercalar) * / CurieIMU.begin (); / * Inicie o PME (Pattern Matching Engine) * / CuriePME.begin (); CurieIMU.setAccelerometerRate (sampleRateHZ); CurieIMU.setAccelerometerRange (2); /* Iniciar. Chip SPI Flash * / if (! SerialFlash.begin (ONBOARD_FLASH_SPI_PORT, ONBOARD_FLASH_CS_PIN)) {Serial.println ("Não foi possível acessar o chip SPI Flash"); } stripM.begin (); // inicializa a tira de neopixel stripS.begin (); stripC.begin (); stripO.begin (); stripM.show (); // Inicializa todos os pixels para 'desligar' stripS.show (); stripC.show (); stripO.show (); solidM (stripM.Color (255, 0, 0), 50); // Vermelho para pronto para entrada} / * Esta função lê o arquivo salvo pelo exemplo anterior * O arquivo contém todos os dados que foram aprendidos e salvos antes. * Assim que a rede for restaurada, ela será capaz de classificar os padrões novamente sem * precisar ser treinado novamente. * / Void restoreNetworkKnowledge (void) {Arquivo SerialFlashFile; int32_t fileNeuronCount =0; Intel_PMT ::neuronData neuronData; // Abra o arquivo e grave os dados de teste file =SerialFlash.open (nome do arquivo); CuriePME.beginRestoreMode (); if (arquivo) {// iterar na rede e salvar os dados. 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) quebra; fileNeuronCount ++; // esta parte apenas imprime cada neurônio conforme ele é restaurado, // para que você possa ver o que está acontecendo. 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 conhecimento restaurado. \ N");} boolean longPress =false; int startTime =0; int lastOrientation =- 1; // orientação anterior (para comparação) int lastReading =-1; booleano lastPress =false; void loop () {int orientação =- 1; // a orientação do tabuleiro StringidanceString; // string para imprimir a descrição da orientação // As orientações da placa:// 0:plano, processador voltado para cima // 1:plano, processador voltado para baixo // 2:paisagem, pinos analógicos para baixo // 3:paisagem, analógico pinos para cima // 4:retrato, conector USB para cima // 5:retrato, conector USB para baixo // ler acelerômetro:int x =CurieIMU.readAccelerometer (X_AXIS); int y =CurieIMU.readAccelerometer (Y_AXIS); int z =CurieIMU.readAccelerometer (Z_AXIS); // calcula os valores absolutos, para determinar o maior int absX =abs (x); absY int =abs (y); absZ int =abs (z); if ((absZ> absX) &&(absZ> absY)) {// orientação de base em Z if (z> 0) {idanceString ="up"; orientação =0; } else {idanceString ="down"; orientação =1; }} else if ((absY> absX) &&(absY> absZ)) {// orientação de base em Y if (y> 0) {idanceString ="digital pins up"; orientação =2; } else {idanceString ="pinos analógicos para cima"; orientação =3; }} else {// orientação de base em X if (x <0) {idanceString ="conector para cima"; orientação =4; } else {idanceString ="conector inativo"; orientação =5; }} // se a orientação mudou, imprima uma descrição:if (orientação! =lastOrientation) {Serial.println (idanceString); lastOrientation =orientação; } // se a orientação mudou, imprima uma descrição:if (orientação! =lastOrientation) {lastOrientation =idance; } leitura interna =digitalRead (buttonPin); if (lastReading! =reading) {Serial.print ("buttonPin ="); Serial.println (leitura); lastReading =leitura; } if (leitura ==HIGH) {if (startTime ==0) {startTime =millis (); } else if ((millis () - startTime)> 2000) {longPress =true; if (! lastPress) {Serial.println ("longPress"); // verde para pressionar longamente solidM (stripM.Color (0, 255, 0), 50); // Verde lastPress =true; }}} if (leitura ==LOW &&longPress) {blackout (5); Serial.print ("orientação ="); Serial.print (orientação); Serial.print ("SerialFlash.exists (nome do arquivo) ="); Serial.println (SerialFlash.exists (nome do arquivo)); if (orientação! =4 &&SerialFlash.exists (nome do arquivo)) {restoreNetworkKnowledge (); Serial.print ("Treinamento restaurado."); } else {trainLetters (); blecaute (5); Serial.print ("Treinamento concluído."); } Serial.println ("Agora, desenhe algumas letras (lembre-se de"); Serial.println ("segure o botão) e veja se a PME pode classificá-las."); solidM (stripM.Color (0, 0, 255), 500); // Azul para pronto para blecaute correspondente (5); // desativa a correspondência while (true) {match (); }}} void solidM (uint32_t c, uint8_t wait) {for (uint16_t i =0; i  (num * 3) - (etapa * 3)) {ret =amostras [pos]; } mais {ret =0; pos - =(etapa * 3); para (int sem sinal i =0; i  sensorBufSize) {break; }}} undersample (accel, samples, vector);} void trainLetter (letra char, unsigned int repeat) {unsigned int i =0; while (i  
PME_LEDArduino
This is using the Curie PME to control LEDs. It's basically a combination of the Draw in the Air PME code and the Adafruit NeoPixel example code. This code is not exactly what I used (which is a bit complex) as I doubt you'll make the exact same kind of constellation arrangement. Rather, here is a generic code which you can modify to personalize your need, e.g. you can change how to distribute the pins for different LED strips. 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. Todos os direitos reservados. * 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.

Processo de manufatura

  1. Estampa de roupas
  2. Construindo placas de ensaio Arduino sem fios de jumper
  3. Sensor DHT11 com LEDs e um alto-falante Piezo
  4. Arduino Spybot
  5. FlickMote
  6. TV B-Gone caseiro
  7. Relógio mestre
  8. Arduino + LEDs + Teclado MIDI + MuseScore =Piano Tutor
  9. LEDs controlados por Alexa através do Raspberry Pi
  10. Encontre-me