Dispositivo para prevenir el sueño en la espalda y controlar la postura del "Posicionador" UPSNS-KO



Un día descubrí que las mujeres que esperan un bebé corren el riesgo de dormir boca arriba en las etapas más o menos tardías del embarazo. El problema es que, en este caso, la arteria sanguínea se pellizca bajo el peso del feto, lo que amenaza con consecuencias muy graves, si no más.

Por lo tanto, pensé que probablemente no sería muy difícil para mí hacer algo que pudiera evitar que entrara en esta situación potencialmente peligrosa. Por supuesto, después de un tiempo bastante corto, mis ojos se abrieron al hecho de que las mujeres sabias evitan el riesgo de una manera completamente natural, simplemente no se sienten cómodas durmiendo boca arriba en estas fechas tan tardías.

Pero no deseche los microcontroladores, acelerómetros e ideas brillantes ya comprados que esclavizan la mente, ¿verdad?

Por cierto, había otros desmotivadores. Comenzando con la opción hardcore:



Y terminando con correctores de postura completamente glamorosos , que, honestamente, aprendí más tarde que mi propia visión.

En general, al principio quería simplemente y sin lujos, como Occam normal, con maquinillas de afeitar normales. Es decir, el dispositivo simplemente debe fijar la posición y, si no cambia dentro de un tiempo determinado, transmitir esta información invaluable a su propietario por vibración. La elección de tal aviso fue natural para mí, porque por segundo año he estado usando un brazalete de podómetro con una alarma de vibración, lo que (un reloj despertador) es un milagro.

Por supuesto, todos entendemos que la señal de vibración no es adecuada para todos. Pero no tenía quejas sobre el dispositivo universal: en todas partes, como ve, debe mantenerse un equilibrio razonable. Por cierto, es por eso que en el diseño final ya existe nuestro entorno Arduino favorito, y muchas soluciones bárbaras, e incluso la legendaria cinta eléctrica azul (realmente azul, traída por el plomero).

En general, la navaja de Occam se rompió cuando comencé a moler los contornos de la futura alarma del reloj. Lo que de repente reveló otros talentos potenciales, a saber: control de la postura y advertencia [plancton de la oficina] sobre la inmovilidad durante demasiado tiempo. La razón para expandir la funcionalidad es común: fue una pena ver cómo desaparecen incluso los recursos del microcontrolador más poderoso, pero aún bastante serio.

Cómo funciona


Como ya sabe, el posicionador tiene tres modos de operación:

1) Prevención del sueño en la espalda (bueno, o en cualquier otra posición, no le importa)
2) Control de la postura
3) Advertencia sobre baja movilidad

Y, como todavía no sabe, solo un botón, que realiza la función de reiniciar el microcontrolador.

Por lo tanto, para seleccionar el modo deseado, es suficiente realizar dos acciones: presione el botón y sostenga el Posicionador en una de las tres posiciones, si es en sentido figurado: en la parte posterior, lateral o de pie. Y para poner una cosa simplemente en modo de espera (análogo a apagar), no necesita hacer nada en absoluto. Es decir, presionaron un botón, lo soltaron y el posicionador se duerme.

Cual es el truco Después de elegir un modo o durante la eutanasia, el Posicionador debe mantenerse bastante inmóvil, ya que en el primer caso necesita tiempo para memorizar la posición, y en el segundo, al comprender que es hora de dormir. Hay dos intervalos principales: los primeros cinco segundos después de encender el servicio para seleccionar un modo, y los siguientes diez para recibir una posición.

Al mismo tiempo, por cierto, diez segundos es un concepto condicional, ya que el Posicionador recuerda las "coordenadas" solo si la posición está relativamente sin cambios durante el tiempo especificado. Esto es para que pueda elegir el modo de funcionamiento y aferrarse con calma al dispositivo sin preocuparse por un tiempo de espera difícil para esta operación. Pero tan pronto como lo enganché, congélelo durante diez segundos para que el Posicionador comprenda que es hora de ponerse manos a la obra.

En otras palabras, el lector atento ya adivinó que las lecturas del acelerómetro se usan para seleccionar el modo, y todavía me estoy extendiendo por el árbol.

Aquí puede ver cómo funciona en el ejemplo de un prototipo en una placa de pruebas:



Como puede ver, todo es bastante simple.

En una versión más o menos final, la alarma funciona de la siguiente manera:

1) En la prevención del sueño en la espalda, el Posicionador se activa después de aproximadamente un minuto y se activa con una serie de 8 señales, que no interrumpe bajo ninguna circunstancia, excepto por la descarga de la batería. Y para que deje de hacer esto, debes acostarte de alguna manera diferente y esperar el final de una serie de señales. De lo contrario, se repetirá una serie de señales.

2) En el modo de control de postura, el posicionador asegura que se mantenga la postura correcta durante aproximadamente el 60% del tiempo desde un intervalo de 5 minutos. De lo contrario, comienza a vibrar hasta que vuelva a la postura adecuada.

3) En el modo de advertencia de baja movilidad, el Posicionador se asegura de que al menos el 8% del tiempo del intervalo de 30 minutos se dedique al movimiento. Si esto no es así, una vez produce una serie de 10 señales, que no se interrumpe y comienza a contar un nuevo intervalo.

Por supuesto, la alarma en cualquier modo se puede interrumpir presionando el botón de reinicio.

En cuanto a los intervalos y notificaciones que pueden parecer extraños, procedí de lo siguiente. Un minuto en la parte posterior en mi opinión es lo suficientemente largo, y 8 señales sin interrupción (y la posibilidad de recibir la misma cantidad repetidamente) parecen ser una razón suficiente para despertarse.

Por otro lado, el control de la postura no es tan crítico, por lo tanto, en primer lugar, no se requiere un control del cien por ciento y, en segundo lugar, es poco probable que ocurra un control de la postura en un sueño, por lo tanto, las señales que se detienen cuando regresa a la posición deseada son suficientes. Bueno, estar sentado todo el tiempo, como si se hubiera tragado arshin, un poco estúpido y poco posible. Por lo tanto, el intervalo de control es ajustable.

Finalmente, cuando busqué en Google el mínimo necesario de actividad motora, me encontré con una mención de que 15-20 minutos cada tres horas parece más o menos adecuado. La configuración del posicionador tiene en cuenta esta información, pero si se desea, se modifican en la etapa de "parpadeo" del microcontrolador. Nuevamente, no hay necesidad de sacudir a una persona hasta que pierda el conocimiento, ya que ir o no ir es voluntario. Por lo tanto, solo un recordatorio delicado en forma de diez señales de vibración.

Por supuesto, todos estos intervalos no son dogmas y pueden cambiarse fácilmente. Sería un deseo

El posicionador funciona con una batería de litio CR2032. El consumo de corriente en el modo de reposo (un cuarto pseudo-modo del Posicionador, no el controlador) es de 4 μA, lo que consideré una razón suficiente para simplificar el diseño en términos de rechazar el interruptor de alimentación dedicado. Al comienzo y al determinar directamente la posición, el consumo puede exceder los 2 mA para fracciones de segundo, pero está principalmente dentro de 1 mA, excepto en los momentos de la operación de la señal.

En los intervalos entre la determinación de la posición, el controlador está en modo de apagado, donde el consumo es similar al modo de reposo del posicionador: 4 μA. El controlador se activa con un temporizador aproximadamente cada 8 segundos; esto es al mismo tiempo el ahorro máximo de batería y es aceptable para un funcionamiento más o menos correcto de todos los modos.



Lamentablemente, no puedo calcular la autonomía total, porque no sé cómo.

¿Cómo se hace esto?


En primer lugar, todo está fuera de mi cabeza, en segundo lugar, improvisado y en tercer lugar amateur, ya que fue más interesante para mí cerrar esta gestalt que elevarla al grado absoluto.

Por lo tanto, en el futuro tendremos en cuenta que estamos hablando de una implementación muy específica y única. Para lo que necesita:

1) microcontrolador ATtiny85 (por ejemplo, tal )
2) Acelerómetro ADXL335 ensamblado (por ejemplo, tal o inmediatamente con una fuente de alimentación de 3.3V)
3) Motor de vibración desde un teléfono móvil (Recibí muchas reparaciones para reparar)
4) Botón (tomé desde un control remoto desmontado)
5) Resistencia de 2.2Kohm
6) Diodo tipo 1N4007 (Tengo algo como KD522
7) Transistor NPN, por ejemplo 2N2222 (tomé algo de un DVD roto)
8) Batería (CR2032)
9) Un caso adecuado

El esquema es el siguiente:



Honestamente robé la parte relacionada con la conexión del motor en un proyecto ELSE muy interesante .

Por cierto, recomiendo una foto tan hermosa de Sparkfun que es imposible no citarla:



hay un truco más. La conclusión es que hay al menos dos versiones de placas con un acelerómetro ADXL335: 3.3V y hasta 5V. En realidad, el rango de voltaje de funcionamiento del acelerómetro es de 1.8V a 3.6V, por lo que la segunda versión difiere de la primera por la presencia de un estabilizador de voltaje.

. esta con un estabilizador (una cucaracha de tres patas a la izquierda del acelerómetro). FotoTinydeal


. y este no tiene estabilizador Foto de Hobby Electronics


. También hay una opción híbrida, donde puede alimentar por separado desde 3.3V (más allá del estabilizador, y desde 5V a través del estabilizador). Foto de Adafruit


Ahora tenía una placa con un estabilizador que funciona tanto desde 5V, lo cual no es sorprendente, como desde 3.3V (lo comprobé). Pero como no veo ninguna razón para calentar el estabilizador y, en consecuencia, gastar la batería en vano, en la versión final del dispositivo conecté la potencia del acelerómetro directamente a mí mismo, evitando el estabilizador.

. para evitar el estabilizador, puede navegar tanto en el tablero como en la hoja de datos ADXL335


Probablemente todavía tenga sentido hablar sobre el hecho de que los microcontroladores ATtiny85 también son diferentes. Los chips con marcas del tipo ATtiny85-20 son más frecuentes y más baratos en las tiendas, y ATtiny85-10 son cada vez menos costosos. Desde el punto de vista de la fabricación del posicionador (y según la hoja de datos ), la diferencia más importante es que el ATtiny85-20 opera en el rango de voltaje 2.7V - 5.5V, y el ATtiny85-10 - en el rango 1.8V - 5.5V. Aquellos. el segundo es mucho más preferible desde el punto de vista del uso más completo de la capacidad de la batería.

La segunda diferencia es la frecuencia de reloj de 20 MHz frente a 10 MHz. Aunque para el Posicionador esto, en general, no es importante: funciona a 1 MHz y no se queja de la vida. Pero como acabo de agarrar lo primero que me pareció más barato, solo tengo ATtiny85-20.

Finalmente, si es un misterio para alguien, conecté el acelerómetro al controlador porque es más fácil apagarlo (el acelerómetro) en el modo de reposo del posicionador. De lo contrario, perderemos constantemente hasta 350 μA (de acuerdo con la hoja de datos ADXL335).

Lo ensambló todo con una instalación montada en la pared, conectando los elementos con un cable esmaltado de 0.1 mm (marcado con un cable Jumper), un par de bobinas que los buenos chinos me dieron junto con una estación de soldadura. Y que no he sabido desde hace un año, a dónde ir. Resultó idealmente: el cable está perfectamente roto con un soldador 300C con una resina convencional, y es lo suficientemente conveniente para soldar tanto el ATtiny85 como el transistor en el paquete SOT23.

Esto se traduce en un paisaje bastante utilitaria:

. qué componentes eran y qué conjunto. No es rentable comprar una pieza a la vez en una boutique de B & D


Algoritmo y Código



El algoritmo básico del trabajo del posicionador es el siguiente:



como entorno de programación, elegí completamente el Arduino como alternativa, ya que ahora lo dejo al menos mal, pero solo estoy familiarizado con él. Bueno, mencioné gestalt al principio, esto también explica el hecho de que no estudié C ++ para hacer un posicionador.

En cuanto al código, debería dar algunos comentarios.

Según el modelo de uso del dispositivo (encendido y olvidado hasta que lo recuerde), sería extremadamente deseable olvidarse del reemplazo diario de las baterías. Y para esto necesita ahorrar energía seriamente, lo cual es muy posible, ya que la hoja de datos ATtiny85 menciona que el consumo mínimo es de décimas de un microamer. Debo decir de inmediato: a tales alturas, no subí (¿o no caí?).

Aquí nuevamente elegí la forma más fácil. A saber: busqué en Google lo que se necesitaba. El primero es el código para poner ATtiny85 en el modo de reposo más profundo con el despertador mediante el temporizador de vigilancia .

Al mismo tiempo, el consumo actual de unidades de miliamperios se redujo a cientos de microamperios. Ya era hermoso, pero aún no lo suficientemente hermoso.

Tuve que mirar más allá. Y luego resultó que dormir era un sueño, y los periféricos debían apagarse manualmente. En este caso, el ADC consume la mayor parte de la energía, incluso en modo de suspensión. Aquí está escrito .

Después de apagar el ADC durante la suspensión, la fuente de alimentación del posicionador se volvió tan armoniosa como pude googlearla. Es decir, como escribí anteriormente, el consumo mínimo es de 4 μA, durante el despertar durante la medición: decenas o cientos de microamperios, con el vibromotor en funcionamiento, puede superar los 2 mA.

La viabilidad de esta mezcla de código se puede estimar por el hecho de que el CR2032 ha estado funcionando durante una semana en el posicionador en modo de prueba, lejos de la primera actualización. La mayoría de las veces, por supuesto, en modo de espera, pero el tiempo activo es decente. En una palabra, está cerca de un modelo de uso real.

En cuanto al trabajo con el acelerómetro. El hecho es que, hasta donde pude, abstraje de los valores absolutos. Hay varias razones para esto. Primero, los acelerómetros se pueden cambiar de esta manera sin pensar en cómo funciona una pieza de hardware en particular. En segundo lugar, no tenía, perdón por la tautología, garantías de hierro de que, en caso de una caída de voltaje inevitable durante la descarga de la batería, las lecturas del acelerómetro asociadas con su procesamiento del ADC en el microcontrolador no "floten".

Finalmente, la configuración se coloca en la sección de declaración de variables. Así es como me elogio a mí mismo, porque para ajustar el posicionador, no tiene que cavar todo el código y recordarme con malas palabras mientras busca todos los fragmentos donde necesita reemplazar los valores.

El código se cargó en ATtiny85 a través de Arduino Mega de acuerdo con las instrucciones comunes. Aquellos. primero descargué el soporte de ATtiny para su versión del entorno Arduino aquí .

Y, como de costumbre, descomprimió el contenido del archivo (pequeño directorio con todo el contenido) en la carpeta de hardware de su directorio Arduino:



luego entré en este directorio y, de acuerdo con las instrucciones, hice el archivo boards.txt en el que copié Prospective Boards.txt del archivo existente lo que necesitaba, es decir ATtiny 1 MHz descripciones y, por si acaso, 8 MHz.

Aquí está boards.txt
attiny85at8.name=ATtiny85 @ 8 MHz  (internal oscillator; BOD disabled)

# The following do NOT work...
# attiny85at8.upload.using=avrispv2
# attiny85at8.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny85at8.upload.using=arduino:arduinoisp
# attiny85at8.upload.protocol=avrispv2
# attiny85at8.upload.using=pololu

attiny85at8.upload.maximum_size=8192

# Default clock (slowly rising power; long delay to clock; 8 MHz internal)
# Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 64 ms; [CKSEL=0010 SUT=10]; default value
# Brown-out detection disabled; [BODLEVEL=111]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]

attiny85at8.bootloader.low_fuses=0xE2
attiny85at8.bootloader.high_fuses=0xD7
attiny85at8.bootloader.extended_fuses=0xFF
attiny85at8.bootloader.path=empty
attiny85at8.bootloader.file=empty85at8.hex

attiny85at8.build.mcu=attiny85
attiny85at8.build.f_cpu=8000000L
attiny85at8.build.core=tiny
 
###########################################################################
###########################################################################

attiny85at1.name=ATtiny85 @ 1 MHz  (internal oscillator; BOD disabled)

# The following do NOT work...
# attiny85at1.upload.using=avrispv2
# attiny85at1.upload.using=Pololu USB AVR Programmer

# The following DO work (pick one)...
attiny85at1.upload.using=arduino:arduinoisp
# attiny85at1.upload.protocol=avrispv2
# attiny85at1.upload.using=pololu

attiny85at1.upload.maximum_size=8192

# Default clock (slowly rising power; long delay to clock; 8 MHz internal; divide clock by 8)
# Int. RC Osc. 8 MHz; Start-up time PWRDWN/RESET: 6 CK/14 CK + 64 ms; [CKSEL=0010 SUT=10]; default value
# Divide clock by 8 internally; [CKDIV8=0]
# Brown-out detection disabled; [BODLEVEL=111]
# Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0]

attiny85at1.bootloader.low_fuses=0x62
attiny85at1.bootloader.high_fuses=0xD7
attiny85at1.bootloader.extended_fuses=0xFF
attiny85at1.bootloader.path=empty
attiny85at1.bootloader.file=empty85at1.hex

attiny85at1.build.mcu=attiny85
attiny85at1.build.f_cpu=1000000L
attiny85at1.build.core=tiny
 
###########################################################################
###########################################################################



Después de eso, lancé Arduino, me aseguré de que apareciera el ATtiny necesario en el menú Servicio - Tablero:



conecté (y, por supuesto, elegí el tablero correcto) Arduino Mega 2560, escribí el boceto Arduino ISP en él de los ejemplos:



Luego conecté ATtiny a Mega, guiado por el pinout Mega 2560 e instrucciones del boceto del ISP Arduino:

// pin name:    not-mega:         mega(1280 and 2560)
// slave reset: 10:               53 
// MOSI:        11:               51 
// MISO:        12:               50 
// SCK:         13:               52 


Por supuesto, conecté ATtiny a la alimentación y a tierra, en mi caso ambas líneas fueron compartidas con el programador, es decir. Mega 2560, aunque todos entendemos que el mínimo necesario del total es el SPI, el reinicio y las líneas de tierra.

Y cuando todo estaba listo, primero (sin olvidar elegir la placa ATtiny85), el gestor de arranque escribió:



Y después de él, en realidad un boceto
// 
// http://donalmorrissey.blogspot.ru/2010/04/sleeping-arduino-part-5-wake-up-via.html
// http://www.technoblogy.com/show?KX0

/* 
 . 			
 - . 		
 - ..		
 - ...		
 - 			    
 ...			 
 --			, 
 .......... 	
 */


#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>

volatile int f_wdt=1;

#define xPin A1 //   X
#define yPin A2 //   Y
#define zPin A3 //   Z
#define alPin 0 //   
#define posPowPin 1 //   
#define timeLimit 10000 //    
 #define posCountSleep 9 //      (*8 ) 8
#define posCountMove 231 //      (*8 ) 230
#define posCountBack 41 //      40
#define tresholdSleep 25 //     
#define tresholdMove 25 //    
#define tresholdBack 20 //     
#define movPercentMove 92 //   ( %)   
#define movPercentBack 40 //    ( %)   
#define startTimeOut 5000//         
#define motionTimeOut 1500//        

unsigned long timeOut; //    
byte treshold = 15; //    
int posCounter = 1; //    
byte posMode = 0; //   (  -  = 0;    - 1;  - 2;  - 3)
int posTolerance = 0; //         ( 009b).
int x, y, z, x1, y1, z1; // 
int relX, relY, relZ; //    
int posCount; //     
boolean alarmRaised = false; //  
boolean standBy = false; //    

// http://www.technoblogy.com/show?KX0
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before power-off) 
#define adc_enable()  (ADCSRA |=  (1<<ADEN)) // re-enable ADC

ISR(WDT_vect)
{
  if(f_wdt == 0)
  {
    f_wdt=1;
  }
}

void enterSleep(void)
{
  pinMode(alPin, INPUT);
  pinMode(posPowPin, INPUT);

  adc_disable();
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);  

  sleep_enable();

  sleep_mode();

  sleep_disable(); 

  power_all_enable();
  adc_enable();

  pinMode(alPin, OUTPUT);
  digitalWrite(alPin, LOW);

  pinMode(posPowPin, OUTPUT);
  digitalWrite(posPowPin, LOW);
}


void setup() {

  /*** Setup the WDT ***/

  /* Clear the reset flag. */
  MCUSR &= ~(1<<WDRF);

  /* In order to change WDE or the prescaler, we need to
   * set WDCE (This will allow updates for 4 clock cycles).
   */
  WDTCR |= (1<<WDCE) | (1<<WDE);

  /* set new watchdog timeout prescaler value */
  WDTCR = 1<<WDP0 | 1<<WDP3; /* 8.0 seconds */

  /* Enable the WD interrupt (note no reset). */
  WDTCR |= _BV(WDIE);

  //   
  pinMode(alPin, OUTPUT);
  digitalWrite(alPin, LOW);

  //   
  pinMode(posPowPin, OUTPUT);
  digitalWrite(posPowPin, LOW);

  pinMode(xPin, INPUT);
  pinMode(yPin, INPUT);
  pinMode(zPin, INPUT);

  delay(1000); // -
  blinker(500, 1); //   

  if (motionDetect(startTimeOut) == true) {

    getPos(); //  	

    if (abs(x1-y1) > abs(x1-z1)) {
      if (abs(x1-z1) > abs(y1-z1)) {
        selectX(); // x
      } 
      else {
        posMode = 2; // y
        posCount = posCountMove; //   
        treshold = tresholdMove;		
        blinker(1000, 1);
        blinker(500, 2);  
      }
    } 
    else {
      if (abs(x1-y1) > abs(z1-y1)) {
        selectX(); //x
      } 
      else {
        posMode = 1; // z
        posCount = posCountSleep; //    		
        treshold = tresholdSleep;
        blinker(1000, 1);
        blinker(500, 1);    
      }
    }
  }

  if (posMode > 0) {

    getPos(); //  
    x = x1; //  
    y = y1;
    z = z1;
    timeOut = millis();	

    while ((millis() - timeOut) < timeLimit) {
      getPos();
      if (comparePos(x, y, z, x1, y1, z1) == false) { //    -  
        blinker(1000, 1); //    
        x = x1; 
        y = y1; 
        z = z1;
        timeOut = millis();
      }
    }

    //       
    standBy = true;
    blinker(500, 3); //   
  }
  else {
    blinker(1500, 2);
  }	


}

void loop() {

  if(f_wdt == 1) {

    if (posMode == 0) {
      /* Don't forget to clear the flag. */
      f_wdt = 0;

      /* Re-enter sleep mode. */
      enterSleep();
    }
    else {

      getPos();

      if (posCounter <= posCount && alarmRaised == false) { //          
      
      if (posMode == 2) { //    
        if (motionDetect(motionTimeOut) == true) { //      
          posTolerance = posTolerance++; //   
        }

        if ((posCounter - posTolerance) > (posCount*movPercentMove)/100) { //      %   
          alarmRaised = true; //   
        } 

      } else { //   
          if (comparePos(x, y, z, x1, y1, z1) == true) { //    
            posTolerance = posTolerance++; //   ""  (       )
          }
        }
      
        
        if (posMode == 1) { //   
          if (posTolerance >= (posCount - 1)) { //     
            alarmRaised = true; //   
          } 
        }

        if (posMode == 3) { //    
          if ((posCounter - posTolerance) > (posCount*movPercentBack)/100) { //       %   
            alarmRaised = true; //   
          } 
        }

       posCounter++;

      } 
      else { //    

       posCounter = 1; //   
       posTolerance = 0;
       
      }

      if (alarmRaised == true) { //   

        if (posMode == 1) { //   
          blinker(500, 8); // 8  ...
          getPos(); 
          if (comparePos(x, y, z, x1, y1, z1) == false) { // ... 
            alarmRaised = false; //  
            posCounter = 0;
          }
        }

        if (posMode == 2) { //   
          blinker(500, 10); // 10 
          alarmRaised = false; //   
          posCounter = 0;
        } 

        if (posMode == 3) { //   
          blinker(500, 1); //    ...
          getPos();
          if (comparePos(x, y, z, x1, y1, z1) == true) { // ...  
            alarmRaised = false; //   
            posCounter = 0;
          }
        }
        
        posTolerance = 0; //    
      } 
      else {
        /* Don't forget to clear the flag. */
        f_wdt = 0;

        /* Re-enter sleep mode. */
        enterSleep();
      }
    } // posMode == 0
  } // wdt
} // loop

// 

void blinker(unsigned int impulse, byte times) {

  for (byte ttimes = 0; ttimes < times; ttimes++) {

    digitalWrite(alPin, HIGH);
    delay(impulse);
    digitalWrite(alPin, LOW);
    delay(impulse);

  }

}


//     
boolean comparePos(int xOne, int yOne, int zOne, int xTwo, int yTwo, int zTwo) {

  boolean compareRes = false;

  relX = xOne - xTwo;
  relY = yOne - yTwo;
  relZ = zOne - zTwo;

  if (abs(relX) < treshold && abs(relY) < treshold && abs(relZ) < treshold) {
    compareRes = true; //      
  }
  return compareRes;

}

boolean motionDetect(int detectTimeOut) {
 
  boolean motionDetected = false;
  
  getPos();
  x = x1; y = y1; z = z1; //   ,       ,    
  timeOut = millis();
  
  while (((millis() - timeOut) < detectTimeOut)) { //    detectTimeOut ,       
   if (motionDetected == false) { //    
    if (comparePos(x, y, z, x1, y1, z1) == false) { //     
      motionDetected = true; //   
    } 
    else {
      getPos();
    }
   }
  }
  
  return motionDetected;
}

//   
void getPos(){

  digitalWrite(posPowPin, HIGH);
  delay(10);

  byte i;
  unsigned int posX = 0;
  unsigned int posY = 0;
  unsigned int posZ = 0;

  for (i = 0; i < 100; i++) {
    posX = posX + analogRead(xPin);
    posY = posY + analogRead(yPin);
    posZ = posZ + analogRead(zPin);
  }

  x1 = posX/100;
  y1 = posY/100;
  z1 = posZ/100;

  digitalWrite(posPowPin, LOW); 
}

void selectX() {
  posMode = 3;
  posCount = posCountBack; //   		
  treshold = tresholdBack;
  blinker(1000, 1);
  blinker(500, 3);
}






Alojamiento


Desde el principio, no me hice ilusiones sobre el hecho de que el caso tendrá que hacerse desde cero a partir de lo que está a la mano. La primera idea, que rechacé rápidamente, fue obtener una caja de varias placas de poliestireno pegadas. Sería patético, bueno, como una caja tipográfica de un reloj suizo, y bastante confiable debido a la resistencia y rigidez suficientemente altas del material.

Sin embargo, mi fervor se desvaneció un poco después de cortar una tapa del poliestireno especificado (solo 1,5 mm de grosor) para la segunda encarnación de Eulampia . Resultó ser difícil: cortar de poliestireno con solo un cuchillo de alfombra.

Por lo tanto, me alegré mucho cuando sucedió otra iluminación: debe tomar arcilla polimérica, que es fácil de dar la forma deseada, y luego hornear hasta que esté sólida. Más precisamente, me pareció así, porque no tuve en cuenta un detalle importante: tengo que el epoxi no se endurece, que la arcilla polimérica no se endurece particularmente bien. Pero esta es la letra.

Descompuse los componentes de la manera más compacta, calculé las dimensiones del cuerpo y realicé el encofrado de cartón del formulario correspondiente, lo llené con arcilla polimérica. Luego cortó los agujeros necesarios en una masa todavía suave y se preparó para hornear de acuerdo con las instrucciones. Y luego por la misma cantidad de tiempo, ya que la arcilla no quería endurecerse.

Por cierto, era lógico que la batería hiciera un agujero con un diámetro un poco más grande, por lo tanto, después de estudiar el sitio web del Banco de Rusia, descubrí que una moneda de 10 rublos ha sido adecuada para este papel, que se acuñó desde 2010, ya que su diámetro es de 22 mm. Solo un margen para que el CR2032 normalmente caiga en el compartimiento de la batería, que cargué con un contacto que hace mucho tiempo quité de otro compartimento de la batería.

Por supuesto, también tomé prestado el diseño del compartimento de la batería, ya que apenas puedo encontrar algo mejor, lo que elimina el dolor de cabeza al revertir.

. algo como esto en el proceso


. y luego tuve que desmontar el cuerpo ya pegado


Es decir, todo es bastante simple: conecté el componente, lo presioné ligeramente hacia abajo, lo quité, lo corté a lo largo del contorno. Bueno, además de tragamonedas y canales para publicar. Lo que es bueno: una arcilla muy pequeña fue al posicionador. Naturalmente, compré el paquete más pequeño de 57 y todavía tengo 50 gramos de esta valiosa materia prima. Este es el primero. Y el segundo: para no alterar la geometría de la disposición de plástico inmóvil, puede hornearlo sin quitarlo del cartón, ya que la temperatura requerida es de 100C - 110C, es decir. lejos del fuego de papel.

Después de que el marco de la caja se horneó de alguna manera cortó ligeramente los bordes con un cuchillo. Y después de probar los componentes descubrí que esta arcilla # $% & * # no solo no se endurece como debería, sino que también se "fríe" en el proceso de cocción. Por lo tanto, tuve que expandir cuidadosamente los recortes. Afortunadamente, el material resultante no era una piedra.

El problema de las paredes superior e inferior se resolvió con la ayuda de fragmentos de una tarjeta de plástico que, a diferencia de un poliestireno de medio milímetro, se corta perfectamente con unas tijeras simples. Inmediatamente pegué la pared inferior (y la superior también, pero en vano), pero al final actué de manera diferente a la superior. A saber: colóquese el marco y empaquete cuidadosamente la estructura resultante en un tubo termocontraíble. La ventaja de este enfoque es que, si es necesario, todo se puede desmontar fácilmente para flashear e igualmente fácil de ensamblar nuevamente.

. espectáculo desgarrador




Bueno, la mirada, ¿qué le pasa? De todos modos, iba a hacer una funda textil para el Posicionador, ya que esto es más racional para el dispositivo, que teóricamente se lleva a la cama. Y el caso solo mejorará tanto la apariencia como las sensaciones táctiles.

Por cierto, no recomiendo el encogimiento blanco si sigues mis pasos: elegante, por supuesto, pero se ensucia muy rápido.

¿Por qué no imprimir en una impresora 3D? En primer lugar, no lo tengo. Y los dueños no lo saben. En segundo lugar, no sé cómo dibujar modelos. En tercer lugar, tendría que imprimir mucho, ya que primero planeé este marco de 30x70 mm, y en el proceso se transformó en un poco menos de 30 mm de ancho y aproximadamente 65 mm de largo. Además, en la arcilla que aún no había tenido tiempo de agarrar, logré cortar la muesca para el botón, que había olvidado al principio.

Y el plástico cada vez se vuelve a imprimir. Aunque no discuto, sería mucho más genial que mi versión del modelado 3D Redneck.

Renuncia a la garantía


En primer lugar, quiero decir que el Posicionador no solo no tiene la más mínima relación con los dispositivos médicos, sino incluso con los suplementos dietéticos para él y la Luna. Este es un experimento. Este es un escape de la pereza y el aburrimiento. Este es un intento de inventar y hacer algo como esto con sus propias manos.

Por lo tanto, por supuesto, no puede considerarse como un salvavidas o algo así. Compañero divertido, asistente, sí. Y, por supuesto, puede ser engañado a propósito, pero es posible, no a propósito. Especialmente si está mal elegir un lugar para la fijación.

Por ejemplo, para evitar que duerma boca arriba, el Posicionador debe, después de haberlo ideado, fijar esa parte del cuerpo que ocupa una posición muy inequívoca cuando el resto del cuerpo se ha vuelto hacia atrás. Y al controlar la movilidad, es mejor si el Posicionador está en la parte más móvil del cuerpo, aunque verifiqué que se adapta bien a la configuración actual en el bolsillo de la hora de los jeans. Bueno, si se trata de la postura, entonces el Posicionador necesita ser reparado para que si estás torcido, entonces él estaba en esta parte muy torcida.

De lo contrario, no sirve.

Estoy de acuerdo en que sería posible usar otro controlador y otro acelerómetro, sería posible tener más C ++ y más con mis propios cerebros y ... Así que no lo prohíbo, hazlo, pruébalo. Estoy seguro de que tendrá éxito, mejor que el mío.

En realidad, por eso escribo en Geek, y no en Habré. Para, por así decirlo, no comprometer lo último, que en realidad es lo primero.

Source: https://habr.com/ru/post/es381771/


All Articles