Escrita de aceleração (mão mágica): 4 etapas (com imagens)
Escrita de aceleração (mão mágica): 4 etapas (com imagens)
Anonim
Escrita Accel (Mão Mágica)
Escrita Accel (Mão Mágica)
Escrita Accel (Mão Mágica)
Escrita Accel (Mão Mágica)
Escrita Accel (Mão Mágica)
Escrita Accel (Mão Mágica)

Introdução

A Mão Mágica permite que pessoas com deficiência e dificuldades motoras desfrutem da criatividade de desenhar e escrever em um ambiente simulado. A Mão Mágica é uma luva vestível que detecta o movimento do seu dedo indicador e traduz isso no desenho de linhas na tela do computador.

Materiais necessários

LSM9DOF Breakout Board --- $ 24,95 ---

Adafruit Feather com Wifi --- $ 18,95 ---

Fios fêmea / fêmea --- $ 1,95 ---

Tiras de fita / velcro --- $ 3

Dois ímãs de igual força --- Os preços variam

Como funciona

Usando um acelerômetro, podemos coletar dados de aceleração para o eixo y, o que nos ajudará a determinar quando o dedo do usuário está se movendo para cima e para baixo. Devido ao fato de que nosso acelerômetro mede a aceleração em relação ao centro da Terra, não podemos determinar a aceleração do eixo x (esquerda ou direita). Felizmente, a placa de breakout LSM9DOF também contém um magnetômetro que nos permite coletar dados sobre campos magnéticos. Colocamos dois ímãs separados por 30 cm e colocamos a luva entre eles. Se os dados magnéticos forem positivos, sabemos que a luva está se movendo para a direita e vice-versa. Depois que todos os dados são coletados no acelerômetro / magnetômetro ele envia os dados via fio para a pena que está conectada a um computador de wi-fi e então encaminha os dados para o computador que podemos usar em nosso código.

Etapa 1: Protótipo Físico 1

Protótipo Físico 1
Protótipo Físico 1
Protótipo Físico 1
Protótipo Físico 1

Este protótipo deve ser costurado com uma luva frouxamente na mão para que escorregue sobre os dispositivos eletrônicos. O dispositivo eletrônico será então preso por velcro à base da manga da armadura combinada com uma luva básica na mão. Em seguida, a luva verde deslizará sobre a base e os dispositivos eletrônicos….

Passos para fazer a luva protótipo:

  • Pegue dois pedaços de tecido grandes o suficiente para traçar à mão
  • Desenhe a mão em ambas as peças de tecido e corte-as
  • Coloque os dois recortes de mão juntos para que fiquem perfeitamente alinhados
  • Em seguida, para preparar a máquina de costura, passe a linha pelos pontos indicados na máquina
  • Quando a máquina de costura estiver configurada, levante a agulha e coloque os dois pedaços de tecido juntos sob a agulha
  • Certifique-se de que a agulha esteja alinhada na borda do tecido, inicie a máquina e costure ao longo das bordas do tecido, deixando as duas peças sem costura no pulso para que uma mão possa caber.

Etapa 2: Protótipo Físico 2

Protótipo Físico 2
Protótipo Físico 2
Protótipo Físico 2
Protótipo Físico 2

Nosso protótipo final é uma luva normal combinada com uma tira de velcro ajustável a qualquer pulso. A luva e a tira são costuradas juntas e os dispositivos eletrônicos são presos à luva por meio de velcro.

Passos na confecção do 2º protótipo da luva:

  1. Compre uma luva, o material da luva não importa.
  2. Compre uma pulseira de velcro
  3. Compre uma bateria portátil
  4. Adquira Velcro Pegajoso
  5. Com uma agulha de costura, prenda a pulseira de velcro na base da luva
  6. A pulseira deve ser capaz de se ajustar a diferentes tamanhos de pulso.
  7. Prenda a fita adesiva na base do acelerômetro e prenda-a no dedo indicador da luva
  8. Cole uma fita adesiva na pena e prenda-a na parte superior da luva.
  9. Usando fios, conecte o pino 3V3 na pena ao pino VIN no acelerômetro
  10. Usando fios, conecte o pino GND na pena ao pino GND do acelerômetro.
  11. Usando fios, conecte o pino SCL na pena ao pino SCL do acelerômetro.
  12. Usando fios, conecte o pino SDA na pena ao pino SDA do acelerômetro.
  13. Conecte pelo menos uma bateria de 5 volts por USB à pena para fornecer energia.

Etapa 3: ímãs

Ímanes
Ímanes

Etapa 1: coloque os dois ímãs de igual força um em frente ao outro.

Etapa 2: Meça a lacuna de 30 cm entre os dois ímãs

Passo 3: coloque o magnetômetro exatamente no meio dos dois ímãs. Você deve receber dados em torno de 0, enquanto está no meio. Se você receber uma leitura de zero, pule para a etapa 5.

Passo 4: Se a leitura não for zero ou perto de zero, você deve ajustar a distância dos ímãs. Se a leitura for negativa, mova o ímã esquerdo um cm ou 2 para a esquerda ou até que a leitura seja zero. Se for positivo, faça a mesma coisa, exceto com o ímã certo.

Etapa 5: Escreva o código que aceita os dados do magnetômetro e lê se são positivos ou negativos. Se for positivo, faça com que o código desenhe uma linha à direita e, se negativo, desenhe uma linha à esquerda.

Etapa 4: Código

Código
Código

github.iu.edu/ise-e101-F17/MuscleMemory-Sw…

Introdução:

Para processar os dados do acelerômetro, uma relação cliente / servidor deve ser estabelecida entre a pena Adafruit e o servidor que processa os dados (rodando em um laptop / desktop). Dois arquivos de código precisarão ser criados: um para o cliente (a pena Adafruit) e outro para o servidor (neste caso, o laptop de Jarod). O cliente é escrito em C ++ e o servidor é escrito em python. A linguagem usada para o cliente é importante, pois o Arduino é principalmente uma linguagem C ++, e alterá-la para usar uma linguagem diferente é difícil. O servidor pode ser escrito em qualquer idioma, desde que tenha recursos de rede.

Configurando o cliente:

Primeiro, vamos configurar o código do cliente. A maior parte do código de conexão WiFi está disponível nas bibliotecas Adafruit. Começamos incluindo classes relevantes.

#include #include #include #include #include

Defina algumas variáveis que serão usadas em todo o código.

// Conectar a uma rede const char * ssid = "MMServer"; const char * password = "MMServer-Password"; // IP e porta do servidor que receberá os dados const char * host = "149.160.251.3"; porta int const = 12347; bool conectado = falso;

// Inicializa o detector de movimento

Adafruit_LSM9DS0 lsm = Adafruit_LSM9DS0 (1000);

Cliente WiFiClient;

Crie uma função setup () que será executada assim que a difusão começar.

// Configure a conexão WiFi e conecte-se ao servervoid setup () {Serial.begin (9600); atraso (100);

Serial.println ();

Serial.println (); Serial.print ("Conectando a"); Serial.println (ssid); // Iniciar WiFi WiFi.begin (ssid, senha); // Conectando… while (WiFi.status ()! = WL_CONNECTED) {delay (500); Serial.print ("."); } // Conectado com sucesso a WiFi Serial.println (""); Serial.println ("WiFi conectado"); Serial.println ("endereço IP:"); Serial.println (WiFi.localIP ());

#ifndef ESP8266

while (! Serial); #endif Serial.begin (9600); Serial.println ("Teste de sensor");

// Inicializa o sensor

if (! lsm.begin ()) {// Houve um problema ao detectar o LSM9DS0 Serial.print (F ("Opa, nenhum LSM9DS0 detectado … Verifique sua fiação ou I2C ADDR!")); enquanto (1); } Serial.println (F ("Encontrado LSM9DS0 9DOF")); // Comece a se conectar ao servidor Serial.print ("Connecting to"); Serial.println (host);

// Verifique se a conexão foi bem-sucedida. Se falhou, então aborte

if (! client.connect (host, port)) {Serial.println ("conexão falhou"); conectado = falso; Retorna; } else {conectado = verdadeiro; }

// Configure o ganho do sensor e o tempo de integração

configureSensor (); }

Precisamos então de uma função de loop que fará loop repetidamente. Neste caso, ele é usado para enviar dados repetidamente do acelerômetro para o servidor na forma de “[z_accel]: [y_mag]: [z_mag]”. O client.print (números); função é o que envia dados para o servidor.

loop vazio () {atraso (250); if (conectado) {// Isso irá enviar dados para o servidor sensores_event_t accel, mag, gyro, temp; lsm.getEvent (& accel, & mag, & gyro, & temp); Números de string; números + = aceleração.aceleração.z; números + = ":"; números + = mag.magnetic.y; números + = ":"; números + = mag.magnetic.z; Serial.print (números); client.print (números); Serial.println (); } else {estabelecerConnection (); }}

Para algumas funções utilitárias, precisamos de uma para estabelecer a conexão entre a pena e o servidor.

void activateConnection () {if (! client.connect (host, port)) {Serial.println ("conexão falhou"); conectado = falso; Retorna; } mais {conectado = verdadeiro; }}

Também precisamos configurar o sensor e fornecer a faixa de valores que ele lerá. Por exemplo, a aceleração tem 5 opções para a faixa: 2g, 4g, 6g, 8g e 16g.

void configureSensor (void) {// Definir o intervalo do acelerômetro //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_2G); lsm.setupAccel (lsm. LSM9DS0_ACCELRANGE_4G); //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_6G); //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_8G); //lsm.setupAccel(lsm. LSM9DS0_ACCELRANGE_16G); // Definir a sensibilidade do magnetômetro //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_2GAUSS); //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_4GAUSS); //lsm.setupMag(lsm. LSM9DS0_MAGGAIN_8GAUSS); lsm.setupMag (lsm. LSM9DS0_MAGGAIN_12GAUSS);

// Configure o giroscópio

lsm.setupGyro (lsm. LSM9DS0_GYROSCALE_245DPS); //lsm.setupGyro(lsm. LSM9DS0_GYROSCALE_500DPS); //lsm.setupGyro(lsm. LSM9DS0_GYROSCALE_2000DPS); }

Configurando o servidor:

O servidor será um arquivo python que será executado na linha de comando de um computador. Para começar, importe as classes necessárias.

import socketimport re import pyautogui

socket é usado para rede. re é usado para regex ou manipulações de strings. pyautogui é uma biblioteca python que permitirá que o desenho aconteça (discutido mais tarde).

A seguir, devemos definir algumas variáveis. Essas serão variáveis globais, portanto, serão acessadas em várias funções. Eles serão usados posteriormente no código.

i = 0n = 0 linha = 1

data_list =

mag_data =

mag_calib_y = 0 mag_offset_y = 0

z_calib = 0

z_offset = 0 z_moving_offset = 0 z_diff = 0 z_real = 0 z_velo = 0 z_pos = 0

keep_offset = False

first_data = True

Agora precisamos de uma função para criar um servidor e abri-lo para conexões de entrada.

def startServer (): global i global first_data # inicializar soquete do servidor serversocket = socket.socket (socket. AF_INET, socket. SOCK_STREAM) serversocket.setsockopt (socket. SOL_SOCKET, socket. SO_REUSEADDR, 1) # Endereço IP do servidor e porta host = " 149.160.251.3 "port = 12347 server_address = (host, porta) # Abra o servidor e escute as conexões de entrada print ('Iniciando servidor na porta% s% s'% server_address) serversocket.bind (server_address) serversocket.listen (5) # Aguarde conexões … enquanto True: print ('Aguardando conexão …') # Aceite uma conexão de entrada (clientsocket, endereço) = serversocket.accept () # Tente analisar os dados recebidos try: print ('Conexão estabelecida de', endereço) enquanto True: # Receber os dados e enviá-los para processamento de dados = clientsocket.recv (25) accel_data = re.split ('[:]', str (data)) accel_data [0] = accel_data [0] [2:] accel_data [1] = accel_data [1] accel_data [2] = accel_data [2] [1: -1] print (accel_data) i + = 1 if (i <51): calibData (accel_data) else: movingAcce l (accel_data [0]) processData (accel_data) first_data = False finally: # Feche o soquete para evitar vazamento de dados desnecessário clientsocket.close ()

Agora exigimos as funções que irão processar todos os dados. O primeiro passo a ser executado, e a primeira função chamada, é a calibração do sensor para fins de cálculo.

def calibData (lista): global z_calib global z_offset global mag_data global mag_calib_y global mag_offset_y z_calib + = float (lista [0]) mag_calib_y + = float (lista [1]) if (i == 50): z_offset = z_calib / 50 mag_offset_y = mag_calib_y / 50 z_calib = 0 mag_calib_y = 0 mag_data.append (mag_offset_y)

Em seguida, criamos um deslocamento de aceleração móvel. Isso faz com que o programa reconheça quando alguém para de mover o dedo porque todos os valores de aceleração que são enviados para o servidor devem ser os mesmos naquele momento.

def movingAccel (num): global z_calib global z_diff global z_moving_offset global z_offset global data_list global n global keep_offset se (n 0,2 ou z_diff <-0,2): # movimento detectado nos dados, reinicie keep_offset = True n = 0 z_calib = 0 z_moving_offset = 0 z_diff = 0 data_list = quebrar se não keep_offset: # estacionário nos dados, definir novo z_offset z_offset = z_moving_offset print ("Novo z_offset:") print (z_offset) n = 0 z_calib = 0 z_moving_offset = 0 z_diff = 0 data_list = keep_offset = False keep_offset = False

Em seguida, fazemos o pior da matemática. Isso envolve a tradução dos dados de aceleração em dados de posição que nos permitirão dizer a direção em que o usuário move o dedo.

def processData (list): # [accel.z, mag.y] global z_offset global z_real global z_velo global z_pos global first_data global mag_data

z_real = float (list [0]) - z_offset

mag_y = list [1] mag_z = list [2] left = False right = False # Não processe a aceleração até que tenha certeza absoluta de que ela foi acelerada # Impede que ruído mecânico contribua para a posição if (z_real -0.20): z_real = 0 #Início integrações para encontrar a posição if (first_data): mag_data.append (mag_y) z_pos = (0,5 * z_real * 0,25 * 0,25) + (z_velo * 0,25) + z_pos z_velo = z_real * 0,25 pyautogui.moveTo (1500, 1000) else: z_pos = (0,5 * z_real * 0,25 * 0,25) + (z_velo * 0,25) + z_pos z_velo = (z_real * 0,25) + z_velo del mag_data [0] mag_data.append (mag_y) if (float (mag_data [1]) - float (mag_data [0])> 0,03): right = True elif (float (mag_data [1]) - float (mag_data [0]) <-0,03): left = True if (right): movimento (50, int (z_pos * 1000)) elif (esquerda): movimento (-50, int (z_pos * 1000)) z_velo = 0 z_pos = 0

Agora, finalmente, movemos o cursor! Para fazer isso, abrimos uma janela de pintura e a colocamos em tela inteira. A biblioteca pyautogui contém uma função chamada pyautogui.dragRel (x, y); que usamos para arrastar o cursor do mouse de um ponto para o próximo. Ele usa dados de posição relativa para que o movimento seja relativo à última posição do cursor.

movimento def (x, y): print ("movendo para", x, -y) pyautogui.dragRel (x, -y)

Por último, precisamos chamar a função principal para permitir que todo esse código seja executado.

# Chama a função para iniciar o serverstartServer ()