Gerät zur Verhinderung von Schlafstörungen auf dem Rücken und zur Kontrolle der Körperhaltung des UPSNS-KO "Positionierer"



Eines Tages fand ich heraus, dass Frauen, die ein Baby erwarten, in mehr oder weniger späten Stadien der Schwangerschaft in Gefahr sind, auf dem Rücken zu schlafen. Das Problem ist, dass in diesem Fall die Blutarterie unter dem Gewicht des Fötus eingeklemmt wird, was sehr schwerwiegende, wenn nicht sogar weitere Folgen hat.

Daher dachte ich, dass es für mich wahrscheinlich nicht sehr schwierig sein würde, etwas zu tun, das verhindern könnte, dass es in diese potenziell gefährliche Situation gerät. Natürlich öffneten sich mir nach kurzer Zeit die Augen für die Tatsache, dass weise Frauen Risiken auf ganz natürliche Weise vermeiden - sie fühlen sich zu diesen sehr späten Terminen einfach nicht wohl auf dem Rücken zu schlafen.

Aber werfen Sie nicht bereits gekaufte Mikrocontroller, Beschleunigungsmesser und brillante Ideen weg, die den Geist versklaven, oder?

Übrigens gab es noch andere Demotivatoren. Beginnend mit der Hardcore-Option:



Und am Ende mit einem völlig glamourösen Haltungskorrektor , den ich ehrlich gesagt später als meine eigenen Einsichten gelernt habe.

Im Allgemeinen wollte ich zunächst einfach und ohne Schnickschnack, wie normales Occam, mit normalen Rasierapparaten. Das heißt, das Gerät sollte einfach die Position festlegen und, wenn es sich nicht innerhalb einer bestimmten Zeit ändert, diese unschätzbaren Informationen seinem Besitzer durch Vibration übermitteln. Die Wahl eines solchen Hinweises war für mich selbstverständlich, da ich seit dem zweiten Jahr ein Schrittzählerarmband mit Vibrationsalarm trage, was (ein Wecker) ein Wunder ist.

Natürlich verstehen wir alle, dass das Vibrationssignal nicht für jeden geeignet ist. Aber ich hatte keine Beschwerden über das Universalgerät - überall muss ein angemessenes Gleichgewicht aufrechterhalten werden. Übrigens, deshalb gibt es im endgültigen Design bereits unsere Lieblings-Arduino-Umgebung, viele barbarische Lösungen und sogar das legendäre blaue (wirklich blaue, vom Klempner mitgebrachte) Isolierband.

Im Allgemeinen brach Occams Rasiermesser, als ich anfing, die Konturen des zukünftigen Weckers zu schleifen. Was plötzlich andere potenzielle Talente enthüllte, nämlich: Kontrolle der Haltung und Warnung [Büroplankton] vor zu langer Immobilität. Der Grund für die Erweiterung der Funktionalität ist alltäglich - es war schade zu sehen, wie die Ressourcen selbst des leistungsstärksten, aber immer noch recht ernsthaften Mikrocontrollers verschwinden.

Wie es funktioniert


Wie Sie bereits wissen, verfügt der Positionierer über drei Betriebsarten:

1) Verhinderung des Schlafes auf dem Rücken (gut oder in jeder anderen Position spielt es für ihn keine Rolle)
2) Kontrolle der Körperhaltung
3) Warnung vor geringer Mobilität

Und, wie Sie immer noch nicht wissen, nur eine Taste, welches die Funktion des Zurücksetzens des Mikrocontrollers ausführt.

Um den gewünschten Modus auszuwählen, müssen daher zwei Aktionen ausgeführt werden: Drücken Sie die Taste und halten Sie den Positionierer in einer von drei Positionen, wenn im übertragenen Sinne - auf der Rückseite, der Seite oder im Stehen. Und um etwas einfach in den Standby-Modus zu versetzen (analog zum Ausschalten), müssen Sie überhaupt nichts tun. Das heißt, sie drückten einen Knopf, legten ihn hin - und der Stellungsregler schläft ein.

Was ist der Trick? Nach der Auswahl eines Modus oder während der Sterbehilfe muss der Positionierer ganz ruhig gehalten werden, da er im ersten Fall Zeit benötigt, um sich die Position zu merken, und im zweiten Fall - wenn er versteht, dass es Zeit zum Schlafen ist. Es gibt zwei Hauptintervalle: Die ersten fünf Sekunden nach dem Einschalten dienen zur Auswahl eines Modus und die nächsten zehn Sekunden zum Empfangen einer Position.

Gleichzeitig sind zehn Sekunden übrigens ein bedingtes Konzept, da sich der Positionierer die „Koordinaten“ nur dann merkt, wenn die Position innerhalb der angegebenen Zeit relativ unverändert ist. Auf diese Weise können Sie den Betriebsmodus auswählen und ruhig am Gerät festhalten, ohne sich über ein hartes Timeout für diesen Vorgang Gedanken machen zu müssen. Aber sobald ich es angeschlossen habe - friere zehn Sekunden lang ein, damit der Positionierer versteht, dass es Zeit ist, zur Sache zu kommen.

Mit anderen Worten, der aufmerksame Leser hat bereits vermutet, dass die Beschleunigungsmesser-Messwerte zur Auswahl des Modus verwendet werden, und ich verteile mich immer noch im Baum.

Hier können Sie am Beispiel eines Prototyps auf einem Steckbrett sehen, wie es funktioniert:



Wie Sie sehen können, ist alles ganz einfach.

In einer mehr oder weniger endgültigen Version funktioniert der Alarm wie folgt:

1) Um Schlafstörungen auf dem Rücken zu vermeiden, wird der Positionierer nach etwa einer Minute ausgelöst und wacht mit einer Reihe von 8 Signalen auf, die unter keinen Umständen unterbrechen, außer beim Entladen der Batterie. Und damit er damit aufhört, sollten Sie sich irgendwie anders hinlegen und auf das Ende einer Reihe von Signalen warten. Andernfalls wird eine Reihe von Signalen wiederholt.

2) Im Haltungskontrollmodus stellt der Positionierer sicher, dass die richtige Haltung in einem Intervall von 5 Minuten für ungefähr 60% der Zeit beibehalten wird. Andernfalls beginnt es zu vibrieren, bis Sie wieder in die richtige Haltung zurückkehren.

3) Im Warnmodus für geringe Mobilität stellt der Positionierer sicher, dass mindestens 8% der Zeit ab dem 30-Minuten-Intervall der Bewegung gewidmet sind. Ist dies nicht der Fall, erzeugt es einmal eine Reihe von 10 Signalen, die nicht unterbrochen werden und ein neues Intervall herunterzählen.

Natürlich kann der Alarm in jedem Modus durch Drücken der Reset-Taste unterbrochen werden.

In Bezug auf die Intervalle und Benachrichtigungen, die seltsam erscheinen mögen, ging ich wie folgt vor. Eine Minute auf der Rückseite ist meiner Ansicht nach lang genug, und 8 Signale ohne Unterbrechung (und die Aussicht, wiederholt denselben Betrag zu erhalten) scheinen ein ausreichender Grund zu sein, aufzuwachen.

Andererseits ist die Haltungskontrolle nicht so kritisch, daher ist zum einen keine hundertprozentige Kontrolle erforderlich, und zum anderen ist es unwahrscheinlich, dass die Haltungskontrolle in einem Traum auftritt. Daher sind Signale, die aufhören, wenn Sie in die gewünschte Position zurückkehren, völlig ausreichend. Nun, die ganze Zeit zu sitzen, als hätte er Arshin geschluckt - ein bisschen dumm und nicht sehr möglich. Daher ist das Regelintervall einstellbar.

Als ich schließlich über das notwendige Minimum an motorischer Aktivität googelte, stieß ich auf die Erwähnung, dass 15 bis 20 Minuten alle drei Stunden mehr oder weniger angemessen erscheinen. Die Positionierereinstellungen berücksichtigen diese Informationen, werden jedoch auf Wunsch beim „Blinken“ des Mikrocontrollers geändert. Auch hier besteht keine Notwendigkeit, eine Person zu schütteln, bis sie das Bewusstsein verliert, da es freiwillig ist, zu gehen oder nicht zu gehen. Daher nur eine feine Erinnerung in Form von zehn Schwingungssignalen.

Natürlich sind alle diese Intervalle kein Dogma und können leicht geändert werden. Es wäre ein Wunsch.

Der Stellungsregler wird von einer CR2032-Lithiumbatterie gespeist. Der Stromverbrauch im Ruhemodus (ein vierter Pseudomodus des Positionierers, nicht des Controllers) beträgt 4 μA, was ich als ausreichenden Grund angesehen habe, um das Design hinsichtlich der Ablehnung des dedizierten Netzschalters zu vereinfachen. Zu Beginn und bei direkter Positionsbestimmung kann der Verbrauch für Sekundenbruchteile 2 mA überschreiten, liegt jedoch mit Ausnahme der Momente des Signalbetriebs hauptsächlich innerhalb von 1 mA.

In den Intervallen zwischen der Positionsbestimmung befindet sich der Regler im Ausschaltmodus, wobei der Verbrauch dem Schlafmodus des Stellungsreglers ähnlich ist - 4 μA. Der Controller wird ungefähr alle 8 Sekunden durch einen Timer aufgeweckt - dies ist gleichzeitig die maximale Batterieeinsparung und für einen mehr oder weniger korrekten Betrieb aller Modi akzeptabel.



Leider kann ich keine vollständige Autonomie berechnen, da ich nicht weiß, wie.

Wie wird das gemacht?


Erstens ist alles aus meinem Kopf, zweitens spontan und drittens amateurhaft, da es für mich interessanter war, diese Gestalt zu schließen, als sie auf das Absolute zu heben.

Daher werden wir in Zukunft bedenken, dass es sich um eine sehr spezifische und eine einzige Implementierung handelt. Für die Sie:

1) ATtiny85 Mikrocontroller (zum Beispiel solchen )
2) Accelerometer ADXL335 montiert (zum Beispiel solchen oder unmittelbar mit 3,3V Spannungsversorgung)
3) Vibrationsmotor von einem Mobiltelefon (bekam ich eine Menge Reparaturen Reparatur)
4) Button (nahm von einer zerlegten Fernbedienung)
5) 2,2 kOhm Widerstand
6) Diode Typ 1N4007 (ich habe so etwas wie KD522
7) NPN-Transistor, zum Beispiel 2N2222 (ich habe etwas von einer kaputten DVD genommen)
8) Batterie (CR2032)
9) Ein geeigneter Fall

Das Schema lautet wie folgt:



Ich habe den Teil bezüglich des Anschlusses des Motors in einem sehr interessanten ELSE-Projekt ehrlich gestohlen .

Übrigens empfehle ich ein so schönes Bild von Sparkfun sehr, dass es unmöglich ist, es nicht zu zitieren:



Es gibt noch einen Trick. Unter dem Strich gibt es mindestens zwei Versionen von Karten mit einem ADXL335-Beschleunigungsmesser: 3,3 V und bis zu 5 V. Tatsächlich liegt der Betriebsspannungsbereich des Beschleunigungsmessers zwischen 1,8 V und 3,6 V, so dass sich die zweite Version von der ersten durch das Vorhandensein eines Spannungsstabilisators unterscheidet.

. Hier ist einer mit einem Stabilisator (eine dreibeinige Kakerlake links vom Beschleunigungsmesser). FotoTinydeal


. und dieser ist ohne Stabilisator. Foto von Hobby Electronics


. Es gibt auch eine Hybridoption, bei der Sie separat von 3,3 V (hinter dem Stabilisator und von 5 V über den Stabilisator) mit Strom versorgen können. Foto von Adafruit


Ich hatte jetzt ein Board mit einem Stabilisator, der sowohl mit 5 V, was nicht überraschend ist, als auch mit 3,3 V funktioniert (ich habe es überprüft). Da ich jedoch keinen Grund sehe, den Stabilisator zu erwärmen und dementsprechend die Batterie vergeblich zu verschwenden, habe ich in der endgültigen Version des Geräts die Leistung des Beschleunigungsmessers direkt daran angeschlossen und den Stabilisator umgangen.

. Um den Stabilisator zu umgehen, können Sie sowohl auf der Karte als auch im ADXL335-Datenblatt navigieren


Es ist wahrscheinlich immer noch sinnvoll, darüber zu sprechen, dass sich auch ATtiny85-Mikrocontroller unterscheiden. Chips mit Markierungen vom Typ ATtiny85-20 sind in Geschäften am häufigsten und billiger, und ATtiny85-10 sind immer billiger. Aus Sicht der Herstellung des Stellungsreglers (und gemäß Datenblatt ) besteht der wichtigste Unterschied darin, dass der ATtiny85-20 im Spannungsbereich von 2,7 V bis 5,5 V und der ATtiny85-10 im Bereich von 1,8 V bis 5,5 V arbeitet. Jene. Die zweite ist unter dem Gesichtspunkt der vollsten Nutzung der Batteriekapazität viel vorzuziehen.

Der zweite Unterschied ist die Taktfrequenz von 20 MHz gegenüber 10 MHz. Obwohl dies für den Positionierer im Allgemeinen unwichtig ist: Er arbeitet mit 1 MHz und beschwert sich nicht über das Leben. Aber da ich mir gerade das erste geschnappt habe, das billiger geworden ist, habe ich nur ATtiny85-20.

Wenn es jemandem ein Rätsel ist, habe ich den Beschleunigungsmesser an den Controller angeschlossen, weil es am einfachsten ist, ihn (den Beschleunigungsmesser) im Schlafmodus des Positionierers auszuschalten. Andernfalls lecken wir ständig bis zu 350 μA (gemäß ADXL335-Datenblatt).

Er montierte alles mit einer an der Wand montierten Installation und verband die Elemente mit einem emaillierten 0,1-mm-Draht (markiert mit Überbrückungsdraht), ein Paar Spulen, von denen mir die guten Chinesen zusammen mit einer Lötstation gaben. Und was ich seit einem Jahr nicht mehr gewusst habe, wohin ich gehen soll. Es stellte sich ideal heraus: Der Draht ist mit einem 300C-Lötkolben mit einem herkömmlichen Kolophonium perfekt gerissen und ist praktisch genug, um sowohl den ATtiny85 als auch den Transistor im SOT23-Gehäuse zu löten.

Dies führt zu einer ziemlich nützlichen Landschaft :

. welche Komponenten waren - und eingestellt. Es ist sehr unrentabel, jeweils ein Stück in einer B & D-Boutique zu kaufen


Algorithmus und Code



Der grundlegende Algorithmus für die Arbeit des Positionierers lautet wie folgt:



Als Programmierumgebung habe ich das Arduino als keine Alternative gewählt, da es jetzt zumindest schlecht ist, aber ich bin nur damit vertraut. Nun, ich habe am Anfang Gestalt erwähnt - dies erklärt auch die Tatsache, warum ich nicht C ++ studiert habe, um einen Positionierer zu erstellen.

Was den Code betrifft, sollte ich einige Kommentare abgeben.

Aufgrund des Verwendungsmodells des Geräts (eingeschaltet und vergessen, bis es erinnert) wäre es äußerst wünschenswert, den täglichen Batteriewechsel zu vergessen. Und dafür müssen Sie ernsthaft Energie sparen, was sehr gut möglich ist, da im ATtiny85-Datenblatt angegeben ist, dass der Mindestverbrauch Zehntel eines Mikroamers beträgt. Ich muss sofort sagen - zu solchen Höhen bin ich nicht gestiegen (oder nicht gefallen?).

Hier habe ich wieder den einfachsten Weg gewählt. Nämlich - gegoogelt, was gebraucht wurde. Der erste ist der Code, mit dem ATtiny85 in den Tiefschlafmodus versetzt wird, indem der Watchdog-Timer aufwacht .

Gleichzeitig sank der Stromverbrauch von Milliampere auf Hunderte von Mikroampere. Es war schon schön, aber immer noch nicht schön genug.

Ich musste weiter suchen. Und dann stellte sich heraus, dass Schlaf ein Traum war und die Peripheriegeräte manuell ausgeschaltet werden mussten. Gleichzeitig wird der Löwenanteil der Energie auch im Schlafmodus vom ADC verzehrt. Hier steht es geschrieben .

Nachdem ich den ADC im Ruhezustand ausgeschaltet hatte, wurde das Netzteil des Positionierers so harmonisch, wie ich es überhaupt googeln konnte. Das heißt, wie ich oben geschrieben habe, beträgt der Mindestverbrauch beim Aufwachen während der Messung 4 μA - zehn oder Hunderte von Mikroampere, bei laufendem Vibromotor kann er 2 mA überschreiten.

Die Lebensfähigkeit dieser Codemischung kann durch die Tatsache geschätzt werden, dass der CR2032 seit einer Woche im Positionierer im Testmodus arbeitet, weit entfernt von der ersten Frische. Meistens natürlich im Standby-Modus, aber die aktive Zeit ist anständig. Mit einem Wort, es kommt einem realen Nutzungsmodell nahe.

In Bezug auf die Arbeit mit dem Beschleunigungsmesser. Tatsache ist, dass ich, soweit ich konnte, von absoluten Werten abstrahiert habe. Dafür gibt es mehrere Gründe. Erstens können Beschleunigungsmesser auf diese Weise geändert werden, ohne darüber nachzudenken, wie eine bestimmte Hardware funktioniert. Zweitens hatte ich, entschuldigen Sie die Tautologie, keine Garantie für Eisen, dass im Falle eines unvermeidlichen Spannungsabfalls während der Batterieentladung die Beschleunigungsmesserwerte, die mit der Verarbeitung des ADC im Mikrocontroller verbunden sind, nicht "schweben".

Schließlich werden die Einstellungen im Abschnitt zur Variablendeklaration platziert. So lobe ich mich selbst - denn um den Positionierer zu optimieren, müssen Sie nicht den gesamten Code ausgraben und sich mit schlechten Worten an mich erinnern, während Sie nach allen Fragmenten suchen, bei denen Sie die Werte ersetzen müssen.

Der Code wurde gemäß den allgemeinen Anweisungen über Arduino Mega auf ATtiny85 hochgeladen. Jene. zuerst heruntergeladen ATtiny Unterstützung für seine Version der Arduino - Umgebung hier .

Und wie üblich entpackte er den Inhalt des Archivs (winziges Verzeichnis mit allen Inhalten) in den Hardwareordner seines Arduino-Verzeichnisses:



Dann ging er in dieses Verzeichnis und erstellte gemäß den Anweisungen die Datei board.txt, in die er Prospective Boards.txt aus der vorhandenen Datei kopierte was ich brauchte - d.h. ATtiny 1 MHz Beschreibungen und für alle Fälle 8 MHz.

Hier ist board.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
 
###########################################################################
###########################################################################



Danach habe ich Arduino gestartet und sichergestellt, dass das erforderliche ATtiny im Service-Board-Menü angezeigt wird: Ich habe



Arduino Mega 2560 angeschlossen (und natürlich das richtige Board ausgewählt), daraus die Arduino ISP-Skizze



anhand der Beispiele geschrieben: Dann habe ich ATtiny mit Mega verbunden, geführt von Mega 2560 Pinout und Anweisungen aus der Arduino ISP-Skizze:

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


Natürlich habe ich ATtiny an Strom und Masse angeschlossen, in meinem Fall wurden beide Leitungen mit dem Programmierer geteilt, d. H. Mega 2560, obwohl wir alle verstehen, dass das notwendige Minimum der Summe die SPI-, Reset- und Erdungsleitungen sind.

Und als alles fertig war, schrieb der Bootloader zuerst (nicht zu vergessen, das ATtiny85-Board zu wählen):



Und nach ihm - eigentlich eine Skizze
// 
// 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);
}






Gehäuse


Von Anfang an hatte ich keine Illusionen darüber, dass der Fall von Grund auf neu gemacht werden muss. Die erste Idee, die ich schnell ablehnte, war, eine Schachtel mit mehreren geklebten Styroporplatten zu bekommen. Es wäre erbärmlich - na ja, wie ein Satzgehäuse einer Schweizer Uhr - und aufgrund der ausreichend hohen Festigkeit und Steifheit des Materials ziemlich zuverlässig.

Meine Leidenschaft ließ jedoch etwas nach, nachdem ich für die zweite Inkarnation von Eulampia einen Deckel aus dem angegebenen Polystyrol (nur 1,5 mm dick) geschnitten hatte . Es stellte sich als schwierig heraus - mit nur einem Teppichmesser aus Styropor herausgeschnitten.

Daher war ich sehr froh, als eine weitere Beleuchtung stattfand - Sie müssen Fimo nehmen, der leicht die gewünschte Form erhält, und dann backen, bis er fest ist. Genauer gesagt schien es mir so, weil ich ein wichtiges Detail nicht berücksichtigt habe: Ich habe, dass das Epoxid nicht aushärtet, dass der Fimo nicht besonders gut aushärtet. Aber das sind Texte.

Ich zersetzte die Komponenten auf kompakteste Weise, schätzte die Abmessungen des Körpers und fertigte eine Pappschalung der entsprechenden Form an, füllte sie mit Fimo. Dann schnitt er die notwendigen Löcher in eine noch weiche Masse und machte sich daran, gemäß den Anweisungen zu backen. Und dann für die gleiche Zeit, da der Ton nicht aushärten wollte.

Übrigens war es logisch, dass die Batterie ein Loch mit einem etwas größeren Durchmesser machte. Nachdem ich die Website der Bank of Russia studiert hatte, fand ich heraus, dass eine Münze von 10 Rubel für diese Rolle geeignet ist, die seit 2010 geprägt wurde, da ihr Durchmesser 22 mm beträgt. Nur ein Rand, damit der CR2032 normalerweise in das Batteriefach fällt, das ich mit einem Kontakt federbelastet habe, der vor langer Zeit aus einem anderen Batteriefach entfernt wurde.

Natürlich habe ich mir auch das Design des Batteriefachs ausgeliehen, da ich mir kaum etwas Besseres einfallen lassen kann, das die Kopfschmerzen beim Rückwärtsfahren beseitigt.

. so etwas dabei


. und so nachdem ich den bereits geklebten Körper zerlegen musste


Das heißt, alles ist ganz einfach: Ich habe das Bauteil angebracht, leicht nach unten gedrückt, entfernt - entlang der Kontur ausgeschnitten. Nun, plus Slots und Kanäle zum Posten. Was gut ist: Ein sehr kleiner Ton ging zum Positionierer. Natürlich habe ich die kleinste Packung mit 57 Stück gekauft und ich habe immer noch 50 Gramm dieses wertvollen Rohstoffs. Das ist das erste. Und das zweite: Um die Geometrie des noch plastischen Layouts nicht zu stören, können Sie es backen, ohne es vom Karton zu entfernen, da die erforderliche Temperatur 100 ° C - 110 ° C beträgt, d. H. weit weg von Papierfeuer.

Nachdem der Rahmen des Gehäuses irgendwie leicht gebacken war, wurden die Kanten mit einem Messer abgeschnitten. Und nachdem ich die Komponenten anprobiert hatte, stellte ich fest, dass dieser # $% & * # Ton nicht nur nicht so aushärtet, wie er sollte, sondern auch beim Backen „gebraten“ wird. Deshalb musste ich die Ausschnitte vorsichtig erweitern. Glücklicherweise war das resultierende Material kein Stein.

Das Problem der oberen und unteren Wände wurde mit Hilfe von Fragmenten einer Plastikkarte gelöst, die im Gegensatz zu einem halben Millimeter Polystyrol mit einer einfachen Schere perfekt geschnitten wird. Ich habe sofort die untere Wand (und auch die Oberseite, aber vergebens) aufgeklebt, aber am Ende habe ich mich anders verhalten als oben. Nämlich: Setzen Sie den Rahmen auf und verpacken Sie die resultierende Struktur sorgfältig in ein Schrumpfrohr. Der Vorteil dieses Ansatzes besteht darin, dass bei Bedarf alles zum Blinken leicht zerlegt und ebenso einfach wieder zusammengebaut werden kann.

. herzzerreißendes Schauspiel




Nun, der Blick - was ist los mit ihm? Wie auch immer, ich wollte einen Textilkoffer für den Positionierer anfertigen, da dies für das Gerät, das theoretisch ins Bett geht, am rationalsten ist. Und der Fall verbessert nur das Aussehen und die Tastempfindungen.

Übrigens empfehle ich keinen weißen Schrumpf, wenn Sie in meine Fußstapfen treten: elegant natürlich, aber es wird sehr schnell schmutzig.

Warum nicht auf einem 3D-Drucker drucken? Erstens habe ich es nicht. Und die Besitzer wissen es nicht. Zweitens weiß ich nicht, wie man Modelle zeichnet. Drittens müsste ich viel drucken, da ich diesen Rahmen zum ersten Mal 30 x 70 mm geplant habe und ihn dabei in etwas weniger als 30 mm Breite und etwa 65 mm Länge umgewandelt habe. Außerdem gelang es mir, in dem Ton, der noch keine Zeit zum Greifen hatte, die Kerbe für den Knopf zu durchschneiden, die ich zuerst vergessen hatte.

Und der Kunststoff jedes Mal neu drucken. Obwohl ich nicht argumentiere, wäre es viel cooler als meine Version der Redneck 3D-Modellierung.

Haftungsausschluss


Zunächst möchte ich sagen, dass der Positionierer nicht nur die geringste Beziehung zu Medizinprodukten hat, sondern auch zu Nahrungsergänzungsmitteln für ihn wie zum Mond. Dies ist ein Experiment. Dies ist eine Flucht vor Faulheit und Langeweile. Dies ist ein Versuch, so etwas mit eigenen Händen zu erfinden und zu tun.

Daher kann es natürlich nicht als Lebensretter oder ähnliches angesehen werden. Lustiger Begleiter, Assistent - ja. Und natürlich kann es absichtlich getäuscht werden, aber es ist möglich - nicht absichtlich. Vor allem, wenn es falsch ist, einen Befestigungsort zu wählen.

Um beispielsweise einen Schlaf auf dem Rücken zu verhindern, sollte der Positionierer nach dem Erfinden den Teil des Körpers fixieren, der eine sehr eindeutige Position einnimmt, wenn der Rest des Körpers genau diesen Rücken eingeschaltet hat. Und wenn Sie die Mobilität steuern, ist es besser, wenn sich der Positionierer am beweglichsten Teil des Körpers befindet, obwohl ich überprüft habe, ob er mit den aktuellen Einstellungen in der Stundentasche der Jeans gut zurechtkommt. Nun, wenn es um die Haltung geht, muss der Positionierer so repariert werden, dass er, wenn Sie krumm sind, an diesem sehr krummen Teil war.

Ansonsten keine Verwendung.

Ich bin damit einverstanden, dass es möglich wäre, einen anderen Controller und einen anderen Beschleunigungsmesser zu verwenden, es wäre möglich, mehr C ++ und mehr mit meinem eigenen Gehirn zu haben und ... Also verbiete ich nicht - mach es, probier es aus. Ich bin sicher, Sie werden Erfolg haben, besser als meiner.

Deshalb schreibe ich deshalb über Geek und nicht über Habré. Um sozusagen nicht das letztere zu gefährden, das eigentlich das erste ist.

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


All Articles