Dispositif pour empêcher le sommeil sur le dos et contrôler la posture du "Positionneur" UPSNS-KO



Un jour, j'ai découvert que les femmes qui attendaient un bébé risquaient de dormir sur le dos à des stades plus ou moins tardifs de la grossesse. Le problème est que dans ce cas, l'artère sanguine est pincée sous le poids du fœtus, ce qui menace des conséquences très graves, sinon plus.

Par conséquent, j'ai pensé qu'il ne serait probablement pas très difficile pour moi de faire quelque chose qui pourrait l'empêcher de se retrouver dans cette situation potentiellement dangereuse. Bien sûr, après un temps assez court, mes yeux se sont ouverts sur le fait que les femmes sages évitent le risque de manière complètement naturelle - elles ne sont tout simplement pas à l'aise de dormir sur le dos à ces dates très tardives.

Mais ne jetez pas les microcontrôleurs, accéléromètres et idées brillantes déjà achetés qui asservissent l'esprit, non?

Soit dit en passant, il y avait d'autres démotivateurs. En commençant par l'option hardcore:



Et se terminant par une correction de posture complètement glamour , que, honnêtement, j'ai appris plus tard que ma propre perspicacité.

En général, au début, je voulais simplement et sans fioritures, comme l'Occam normal, avec des rasoirs normaux. Autrement dit, l'appareil doit simplement fixer la position et, s'il ne change pas dans un délai donné, transmettre ces informations précieuses à son propriétaire par vibration. Le choix d'un tel avis était naturel pour moi, car depuis la deuxième année, je porte un bracelet podomètre avec une alarme vibrante, qui (un réveil) est un miracle.

Bien sûr, nous comprenons tous que le signal de vibration ne convient pas à tout le monde. Mais je n'ai rien à redire sur l'appareil universel - partout, voyez-vous, un équilibre raisonnable doit être maintenu. Au fait, c'est pourquoi dans la conception finale, il y a déjà notre environnement Arduino préféré, et de nombreuses solutions barbares, et même le ruban électrique bleu légendaire (vraiment - bleu, le plombier a apporté).

En général, le rasoir d'Occam s'est cassé lorsque j'ai commencé à rectifier les contours du futur réveil. Ce qui a soudain révélé d'autres talents potentiels, à savoir: le contrôle de la posture et la mise en garde [plancton de bureau] d'une trop longue immobilité. La raison de l'extension de la fonctionnalité est courante - il était dommage de voir comment les ressources du microcontrôleur même le plus puissant, mais toujours assez sérieux, disparaissent.

Comment ça fonctionne


Comme vous le savez déjà, le positionneur a trois modes de fonctionnement:

1) Prévention du sommeil sur le dos (enfin, ou dans toute autre position, cela ne lui importe pas)
2) Contrôle de la posture
3) Avertissement sur la faible mobilité

Et, comme vous ne le savez toujours pas, un seul bouton, qui remplit la fonction de réinitialisation du microcontrôleur.

Par conséquent, pour sélectionner le mode souhaité, il suffit d'effectuer deux actions: appuyez sur le bouton et maintenez le positionneur dans l'une des trois positions, si elles sont figurées - à l'arrière, sur le côté ou debout. Et pour mettre une chose simplement en mode veille (analogue à la mise hors tension), vous n'avez rien à faire du tout. Autrement dit, ils ont appuyé sur un bouton, l'ont déposé - et le positionneur s'endort.

Quelle est l'astuce? Après avoir choisi un mode ou pendant l'euthanasie, le positionneur doit rester assez immobile, car dans le premier cas, il a besoin de temps pour mémoriser la position, et dans le second - en comprenant qu'il est temps de dormir. Il y a deux intervalles principaux: les cinq premières secondes après la mise sous tension servent à sélectionner un mode et les dix suivantes à recevoir une position.

En même temps, soit dit en passant, dix secondes est un concept conditionnel, car le positionneur ne se souvient des «coordonnées» que si, dans le temps spécifié, la position est relativement inchangée. C'est ainsi que vous pouvez choisir le mode de fonctionnement et vous accrocher calmement à l'appareil sans vous soucier d'un délai d'attente dur pour cette opération. Mais dès que je l'ai accroché - gelez pendant dix secondes pour que le positionneur comprenne qu'il est temps de se mettre au travail.

En d'autres termes, le lecteur attentif a déjà deviné que les lectures de l'accéléromètre sont utilisées pour sélectionner le mode, et je continue de me répandre dans l'arbre.

Ici, vous pouvez voir comment cela fonctionne sur l'exemple d'un prototype sur une maquette:



Comme vous pouvez le voir, tout est assez simple.

Dans une version plus ou moins définitive, l'alarme fonctionne comme suit:

1) Dans la prévention du sommeil sur le dos, le positionneur se déclenche au bout d'une minute environ et se réveille avec une série de 8 signaux, qui ne s'interrompt en aucun cas, sauf pour la décharge de la batterie. Et pour qu'il arrête de faire cela, vous devez vous allonger différemment et attendre la fin d'une série de signaux. Sinon, une série de signaux sera répétée.

2) En mode de contrôle de posture, le positionneur s'assure que la bonne posture est maintenue pendant environ 60% du temps à partir d'un intervalle de 5 minutes. Sinon, il commence à vibrer jusqu'à ce que vous reveniez à une bonne posture.

3) En mode d'avertissement de faible mobilité, le positionneur s'assure qu'au moins 8% du temps de l'intervalle de 30 minutes est consacré au mouvement. Si ce n'est pas le cas, il produit une fois une série de 10 signaux, qui n'est pas interrompue et commence à décompter un nouvel intervalle.

Bien sûr, l'alarme dans n'importe quel mode peut être interrompue en appuyant sur le bouton de réinitialisation.

Quant aux intervalles et notifications qui peuvent paraître étranges, je suis parti de ce qui suit. Une minute sur le dos à mon avis est assez longue, et 8 signaux sans interruption (et la perspective de recevoir le même montant à plusieurs reprises) semblent être une raison suffisante pour se réveiller.

D'un autre côté, le contrôle de la posture n'est pas si critique, donc, premièrement, un contrôle à cent pour cent n'est pas nécessaire et, deuxièmement, le contrôle de la posture est peu susceptible de se produire dans un rêve, par conséquent, les signaux qui s'arrêtent lorsque vous revenez à la position souhaitée sont assez suffisants. Eh bien, de rester assis tout le temps, comme s'il avait avalé de l'arshin - un peu stupide et pas très possible. Par conséquent, l'intervalle de contrôle est réglable.

Enfin, lorsque j'ai cherché sur le minimum d'activité motrice nécessaire, je suis tombé sur une mention selon laquelle 15-20 minutes toutes les trois heures semblent plus ou moins adéquates. Les paramètres du positionneur tiennent compte de ces informations, mais si vous le souhaitez, ils sont modifiés au stade du «flashage» du microcontrôleur. Encore une fois, il n'est pas nécessaire de secouer une personne jusqu'à ce qu'elle perde connaissance, car y aller ou ne pas y aller est volontaire. Par conséquent, seulement un rappel délicat sous la forme de dix signaux de vibration.

Bien sûr, tous ces intervalles ne sont pas des dogmes et peuvent facilement être modifiés. Ce serait un désir.

Le positionneur est alimenté par une pile au lithium CR2032. La consommation de courant en mode veille (quelque quatrième pseudo-mode du positionneur, pas le contrôleur) est de 4 μA, ce que j'ai considéré comme une raison suffisante pour simplifier la conception en termes de refus de l'interrupteur d'alimentation dédié. Au démarrage et lors de la détermination directe de la position, la consommation peut dépasser 2 mA pour des fractions de seconde, mais elle est principalement inférieure à 1 mA sauf pour les moments de fonctionnement du signal.

Dans les intervalles entre la détermination de la position, le contrôleur est en mode Power down, où la consommation est similaire au mode veille du positionneur - 4 μA. Le contrôleur se réveille par une minuterie toutes les 8 secondes environ - c'est en même temps l'économie de batterie maximale et est acceptable pour un fonctionnement plus ou moins correct de tous les modes.



Malheureusement, je ne peux pas calculer l'autonomie totale, car je ne sais pas comment.

Comment cela se fait


Premièrement, tout est hors de ma tête, deuxièmement, impromptu, et troisièmement amateurement, car il était plus intéressant pour moi de fermer cette gestalt que de l'élever au degré d'absolu.

Par conséquent, à l'avenir, nous garderons à l'esprit qu'il s'agit d'une mise en œuvre très spécifique et unique. Pour lequel vous avez besoin:

1) Microcontrôleur ATtiny85 (par exemple, tel )
2) Accéléromètre ADXL335 assemblé (par exemple, tel ou immédiatement avec une alimentation de 3,3 V )
3) Moteur de vibration à partir d'un téléphone mobile (j'ai eu beaucoup de réparations à réparer)
4) Bouton (pris à partir d'une télécommande démontée)
5) Résistance 2.2Kohm
6) Diode de type 1N4007 (j'ai quelque chose comme KD522
7) Transistor NPN, par exemple 2N2222 (j'ai pris quelque chose d'un DVD cassé)
8) Batterie (CR2032)
9) Un cas approprié

Le schéma est le suivant:



j'ai honnêtement volé la partie concernant la connexion du moteur dans un projet ELSE très intéressant .

Soit dit en passant, je recommande fortement une si belle image de Sparkfun qu'il est impossible de ne pas la citer: il



y a encore une astuce. L'essentiel est qu'il existe au moins deux versions de cartes avec un accéléromètre ADXL335: 3,3 V et jusqu'à 5 V. En fait, la plage de tension de fonctionnement de l'accéléromètre est de 1,8 V à 3,6 V, de sorte que la deuxième version diffère de la première par la présence d'un stabilisateur de tension.

. en voici un avec un stabilisateur (un cafard à trois pattes à gauche de l'accéléromètre). PhotoTinydeal


. et celui-ci est sans stabilisateur. Photo par Hobby Electronics


. il existe également une option hybride - où vous pouvez alimenter séparément à partir de 3,3 V (après le stabilisateur et de 5 V à travers le stabilisateur). Photo par Adafruit


J'avais maintenant une carte avec un stabilisateur qui fonctionne à la fois à partir de 5V, ce qui n'est pas surprenant, et à partir de 3,3V (j'ai vérifié). Mais comme je ne vois aucune raison de réchauffer le stabilisateur et, en conséquence, de gaspiller la batterie en vain, dans la version finale de l'appareil, j'ai connecté moi-même la puissance de l'accéléromètre, en contournant le stabilisateur.

. pour contourner le stabilisateur, vous pouvez naviguer à la fois sur la carte et sur la fiche technique ADXL335


Il est probablement toujours logique de parler du fait que les microcontrôleurs ATtiny85 sont également différents. Les puces avec des marquages ​​du type ATtiny85-20 sont le plus souvent et moins chères en magasin, et ATtiny85-10 sont de moins en moins chères. Du point de vue de la fabrication du positionneur (et selon la fiche technique ), la différence la plus importante est que l'ATtiny85-20 fonctionne dans la plage de tension 2,7V - 5,5V, et l'ATtiny85-10 - dans la plage 1,8V - 5,5V. Ceux. la seconde est beaucoup plus préférable du point de vue de l'utilisation la plus complète de la capacité de la batterie.

La deuxième différence est la fréquence d'horloge de 20 MHz contre 10 MHz. Bien que pour le positionneur, cela soit en général sans importance: il fonctionne à 1 MHz et ne se plaint pas de la vie. Mais depuis que je viens de saisir la première chose qui est apparue et moins chère, j'ai juste ATtiny85-20.

Enfin, si c'est un mystère pour quelqu'un, j'ai connecté l'accéléromètre au contrôleur parce qu'il est plus facile de le désactiver (l'accéléromètre) en mode veille du positionneur. Sinon, nous perdrons constamment jusqu'à 350 μA (selon la fiche technique ADXL335).

Il a tout assemblé avec une installation murale, reliant les éléments avec un fil émaillé de 0,1 mm (marqué avec du fil Jumper), une paire de bobines dont les bons chinois m'ont donné avec une station de soudage. Et que je ne connais pas depuis un an, où aller. Il s'est avéré idéalement: le fil est parfaitement déchiré avec un fer à souder 300C avec une colophane conventionnelle, et est assez pratique pour souder à la fois l'ATtiny85 et le transistor dans le boîtier SOT23.

Il en résulte un paysage assez utilitaire:

. quels composants étaient - et réglés. Il n'est pas rentable d'acheter une pièce à la fois dans une boutique B & D


Algorithme et code



L’algorithme de base du travail du positionneur est le suivant:



En tant qu’environnement de programmation, j’ai complètement choisi l’Arduino comme aucune alternative, car maintenant, laissez-le au moins mal, mais je ne le connais que. Eh bien, j'ai mentionné la gestalt au début - cela explique également le fait que je n'ai pas étudié le C ++ pour créer un positionneur.

Quant au code, je devrais faire quelques commentaires.

Sur la base du modèle d'utilisation de l'appareil (allumé et oublié jusqu'à ce qu'il le rappelle), il serait extrêmement souhaitable d'oublier le remplacement quotidien des piles. Et pour cela, vous devez sérieusement économiser de l'énergie, ce qui est très possible, car la fiche technique ATtiny85 mentionne que la consommation minimale est le dixième d'un microamère. Je dois dire tout de suite - à de telles hauteurs, je ne me suis pas levé (ou je ne suis pas tombé?).

Ici, j'ai de nouveau choisi la voie la plus simple. À savoir - googlé ce qui était nécessaire. Le premier est le code pour mettre ATtiny85 dans le mode de veille le plus profond avec réveil par la minuterie du chien de garde .

Dans le même temps, la consommation actuelle des unités de milliampères a chuté à des centaines de microampères. C'était déjà beau, mais pas encore assez beau.

Je devais regarder plus loin. Et puis, il s'est avéré que le sommeil était un rêve et que les périphériques devaient être éteints manuellement. Dans le même temps, la part du lion de l'énergie, même en mode veille, est consommée par l'ADC. Ici, c'est écrit .

Après avoir éteint l'ADC pendant le sommeil, l'alimentation du positionneur est devenue aussi harmonieuse que possible sur Google. Autrement dit, comme je l'ai écrit ci-dessus, la consommation minimale est de 4 μA, au réveil pendant la mesure - des dizaines ou des centaines de microampères, avec le vibromoteur en marche, elle peut dépasser 2 mA.

La viabilité de ce mélange de code peut être estimée par le fait que le CR2032 travaille depuis une semaine dans le positionneur en mode test depuis loin de la première fraîcheur. La plupart du temps, bien sûr, en mode veille, mais le temps actif est décent. En un mot, c'est proche d'un vrai modèle d'utilisation.

Concernant le travail avec l'accéléromètre. Le fait est que, autant que j'ai pu, je me suis abstenu des valeurs absolues. Il y a plusieurs raisons à cela. Tout d'abord, les accéléromètres peuvent être modifiés de cette façon sans penser au fonctionnement d'un matériel particulier. Deuxièmement, je n'avais pas, désolé pour la tautologie, le fer garantit qu'en cas de chute de tension inévitable pendant la décharge de la batterie, les lectures de l'accéléromètre qui sont associées à leur traitement de l'ADC dans le microcontrôleur ne "flottent" pas.

Enfin, les paramètres sont placés dans la section de déclaration des variables. C’est ainsi que je me vante - car pour affiner le positionneur, vous n’avez pas besoin de creuser tout le code et de vous souvenir de moi avec de mauvais mots tout en recherchant tous les fragments où vous devez remplacer les valeurs.

Le code a été téléchargé sur ATtiny85 via Arduino Mega selon les instructions courantes. Ceux. a d'abord téléchargé le support ATtiny pour sa version de l'environnement Arduino ici .

Et, comme d'habitude, il a déballé le contenu de l'archive (petit répertoire avec tout le contenu) dans le dossier matériel de son répertoire Arduino:



Ensuite, je suis allé dans ce répertoire et, selon les instructions, j'ai créé le fichier boards.txt dans lequel j'ai copié Prospective Boards.txt du fichier existant ce dont j'avais besoin - c.-à-d. ATtiny 1 MHz descriptions et, au cas où, 8 MHz.

Voici 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
 
###########################################################################
###########################################################################



Après cela, j'ai démarré Arduino, je me suis assuré que l'ATtiny nécessaire apparaissait dans le menu Service - Board: j'ai



connecté (et, bien sûr, j'ai choisi la bonne carte) Arduino Mega 2560,



j'ai écrit le croquis Arduino ISP à partir des exemples: Ensuite, j'ai connecté ATtiny à Mega, guidé par le brochage Mega 2560 et instructions du croquis du FAI Arduino:

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


Bien sûr, j'ai connecté ATtiny à l'alimentation et à la terre, dans mon cas, les deux lignes ont été partagées avec le programmeur, c'est-à-dire Mega 2560, bien que nous comprenions tous que le minimum nécessaire du total est le SPI, la réinitialisation et les lignes de masse.

Et quand tout était prêt, puis d'abord (sans oublier de choisir la carte ATtiny85), le bootloader a écrit:



Et après lui - en fait un croquis
// 
// 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);
}






Logement


Dès le début, je ne me suis pas fait d'illusions sur le fait que l'affaire devra être refaite à partir de ce qui est à portée de main. La première idée, que j'ai rapidement rejetée, était d'obtenir une boîte de plusieurs plaques de polystyrène collées. Il serait pathétique - enfin, comme un boîtier de composition d'une montre suisse - et assez fiable en raison de la résistance et de la rigidité suffisamment élevées du matériau.

Cependant, ma ferveur s'est estompée un peu après avoir coupé un couvercle en polystyrène spécifié (seulement 1,5 mm d'épaisseur) pour la deuxième incarnation d' Eulampia . Cela s'est avéré difficile - découpé en polystyrène avec un seul couteau à tapis.

Par conséquent, j'étais très heureux quand un autre éclairage s'est produit - vous devez prendre de la pâte polymère, qui est facile à donner la forme souhaitée, puis cuire jusqu'à ce qu'elle soit solide. Plus précisément, cela m'a semblé ainsi, car je n'ai pas pris en compte un détail important: j'ai que l'époxy ne durcit pas, que la pâte polymère ne durcit pas particulièrement bien. Mais ce sont des paroles.

J'ai décomposé les composants de la manière la plus compacte, estimé les dimensions du corps et réalisé un coffrage en carton de la forme correspondante, rempli de pâte polymère. Puis il a coupé les trous nécessaires dans une masse encore molle et a mis à cuire selon les instructions. Et puis pour le même laps de temps, puisque l'argile ne voulait pas durcir.

À propos, il était logique que la batterie fasse un trou d'un diamètre légèrement plus grand.Par conséquent, après avoir étudié le site Web de la Banque de Russie, j'ai découvert qu'une pièce de 10 roubles convenait à ce rôle, frappé depuis 2010, car son diamètre est de 22 mm. Juste une marge pour que le CR2032 tombe normalement dans le compartiment à piles, que j'ai chargé avec un contact retiré il y a longtemps d'un autre compartiment à piles.

Bien sûr, j'ai également emprunté la conception du compartiment à piles, car je peux difficilement trouver quelque chose de mieux, ce qui élimine les maux de tête lors des reculs.

. quelque chose comme ça dans le processus


. et donc après avoir dû démonter le corps déjà collé


Autrement dit, tout est assez simple: j'ai attaché le composant, l'ai légèrement enfoncé, je l'ai retiré - je l'ai découpé le long du contour. Eh bien, plus les créneaux horaires et les canaux de publication. Ce qui est bien: une toute petite argile est allée au positionneur. Naturellement, j'ai acheté le plus petit paquet de 57, et j'ai encore 50 grammes de cette précieuse matière première. C'est le premier. Et la seconde: afin de ne pas perturber la géométrie de la disposition encore en plastique, vous pouvez la faire cuire sans la retirer du carton, car la température requise est de 100 ° C à 110 ° C, c'est-à-dire loin du feu de papier.

Après le cadre de l'affaire en quelque sorte cuit légèrement coupé les bords avec un couteau. Et après avoir essayé les composants, j'ai découvert que cette argile # $% & * # non seulement ne durcit pas comme elle le devrait, mais aussi "frite" en cours de cuisson. Par conséquent, j'ai dû étendre soigneusement les découpes. Heureusement, le matériau résultant n'était pas une pierre.

Le problème des parois supérieures et inférieures a été résolu à l'aide de fragments d'une carte en plastique qui, contrairement à un polystyrène d'un demi-millimètre, est parfaitement coupé avec de simples ciseaux. J'ai immédiatement collé le mur du bas (et le haut aussi, mais en vain), mais au final j'ai agi différemment du haut. À savoir: mettre le cadre et soigneusement emballé la structure résultante dans un tube thermorétractable. L'avantage de cette approche est que, si nécessaire, tout peut être facilement démonté pour le solin et tout aussi facile à remonter.

. spectacle déchirant




Eh bien, le regard - qu'est-ce qui ne va pas avec lui? Quoi qu'il en soit, j'allais fabriquer un étui textile pour le positionneur, car c'est le plus rationnel pour l'appareil, qui théoriquement se couche. Et le boîtier améliorera simplement l'apparence et les sensations tactiles.

Soit dit en passant, je ne recommande pas le rétrécissement blanc si vous suivez mes traces: élégant, bien sûr, mais il se salit très rapidement.

Pourquoi ne pas imprimer sur une imprimante 3D? Premièrement, je ne l'ai pas. Et les propriétaires ne savent pas. Deuxièmement, je ne sais pas dessiner de modèles. Troisièmement, je devrais imprimer beaucoup, car j'ai prévu ce cadre 30x70 mm pour la première fois, et ce faisant, il a été transformé en un peu moins de 30 mm de largeur et environ 65 mm de longueur. De plus, dans l'argile qui n'avait pas encore eu le temps de saisir, j'ai réussi à couper l'encoche du bouton, que j'avais d'abord oubliée.

Et le plastique réimprime à chaque fois. Bien que je ne conteste pas, ce serait beaucoup plus cool que ma version de la modélisation 3D Redneck.

Déclaration de garantie


Tout d'abord, je tiens à dire que le positionneur n'a pas seulement la moindre relation avec les appareils médicaux, mais même avec les compléments alimentaires pour lui comme pour la lune. Ceci est une expérience. C'est une évasion de la paresse et de l'ennui. C'est une tentative d'inventer et de faire quelque chose comme ça de vos propres mains.

Par conséquent, bien sûr, cela ne peut pas être considéré comme une bouée de sauvetage ou quelque chose comme ça. Compagnon drôle, assistant - oui. Et, bien sûr, cela peut être trompé exprès, mais c'est possible - pas exprès. Surtout si c'est mal de choisir un endroit pour la fixation.

Par exemple, pour éviter de dormir sur le dos, le positionneur devrait, après avoir inventé, fixer sur la partie du corps qui occupe une position très sans équivoque lorsque le reste du corps a tourné sur ce même dos. Et lors du contrôle de la mobilité, il est préférable que le positionneur se trouve sur la partie la plus mobile du corps, même si j'ai vérifié qu'il s'adapte bien aux réglages actuels dans la poche horaire du jean. Eh bien, s'il s'agit de posture, le positionneur doit être fixé de sorte que si vous êtes tordu, il était sur cette partie très tordue.

Sinon, inutile.

Je suis d'accord qu'il serait possible d'utiliser un autre contrôleur et un autre accéléromètre, il serait possible d'avoir plus de C ++, et plus avec mes propres cerveaux et ... Donc je n'interdis pas - faites-le, essayez-le. Je suis sûr que vous réussirez, mieux que le mien.

En fait, c'est pourquoi j'écris sur Geek, et non sur Habré. Afin, pour ainsi dire, de ne pas compromettre ce dernier, qui est en fait le premier.

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


All Articles