Lag din egen ASMR-dings for å redusere stress

Dette innlegget handler om et preventivt stresstiltak, i form av en ASMR-stimuleringsenhet, som hjelper kroppen til å følge en mer naturlig rytme. Den har formen til en potteplante, og avgir blant annet fuglekvitter og bekkelyder. Eksempelkode er skrevet i Arguino IDE (C++)

Thor Nydal

14 feb 2022

Verden endrer seg med økende frekvens, og den frekvensen økonomien opererer på i dag er, sett fra et historisk/evolusjonsmessig perspektiv, unormal. Effektene av dette må vi mennesker til syvende og sist betale for, gjennom et overstimulert nervesystem, samt følgeeffekter dette kan ha på kroppens andre systemer og funksjoner. 

Det finnes flere forebyggende og mitigerende metoder for å håndtere stress. Vanlige metoder for å få løst opp i stramme muskler, få ut stresshormoner og for å berike kroppen med ny luft, er ofte fysisk aktivitet, men som et lite labbprosjekt har jeg funnet på en mer uvanlig, men forebyggende tiltak mot stress.

Bakgrunnen for initiativet er en økt bevissthet knyttet til hvordan det urbane og økonomisk orienterte samfunn ofte bryter med natur og harmoni. Dermed oppstod ideer om hvordan kompensere litt for dette.

Stimuler for ro 

Dette innlegget handler nemlig om et forebyggende tiltak, i form av en Autonom sensorisk meridianrespons (ASMR)-stimuleringsenhet, som hjelper kroppen til å følge en mer naturlig rytme ved bruk av en potteplante, naturlyder og kode skrevet i Arduino IDE. 

Autonom sensorisk meridianrespons (ASMR) er en opplevelse karakterisert som en statisk-lignende, eller prikkende, følelse mot hud, som typisk starter i hodebunnen for så å bevege seg ned mot nakke og øvre ryggrad. Kilde: Wikipedia.

Ved å for eksempel gi dine ører lyden av harmonisk natur, og en fin liten potteplante i øyesyn, så vil dette kunne bidra til å holde det parasympatiske nervesystemet dominant.

Etter koronapandemien har ASMR blitt et veletablert fenomen i populærkulturen. Det kan kanskje skyldes at flere har måttet tilbringe mer tid innenfor hjemmets fire vegger, og ikke har fått gå ut og oppleve naturen prakt.

Min ASMR-enhet

Funksjonelt består altså enheten av en visuell komponent form av en fin liten potteplante (kunstig riktig nok), og av en naturlyd som korresponderer til gitt kalenderdag og tid på dagen. Denne versjonen er basert på store statiske lydklipp.

Kort fortalt så fungerer enheten slik at når man kobler den til, så er det første du må gjøre å åpne en laptop eller mobil med WiFi-tilkobling til det nettet du ønsker å koble til. Skriv så inn en IP-adresse i nettleseren og tast inn WiFi-brukernavn + passord og lagre. Når dette er gjort vil enheten koble seg til WiFi-nettet samt hente dato og klokkeslett og forberede en avspilling som passer døgnrytmen. Naturlyd kommer så ut i høyttaleren.

Tekniske detaljer

Enheten jeg har laget er basert på en NodeMCU/ESP8266. Denne er så koblet til en liten høyttaler med god kvalitet, gjennom en seriell MP3-modul. Det er en forholdsvis rimelig dings. Koden er skrevet i C++ in Arduino IDE, men man kan også skrive kode for den gjennom en egen Python platform.

Jeg brukte en ordinær USB-plugg som kan kobles til en vanlig mobillader, og enheten benytter altså 5V-driftsspenning. En MP3-modul er koblet til gjennom det serielle grensesnittet til microkontrolleren, f.eks. D0 & D1 til MP3-modulens TX og RX. 

Driver til MP3-modulen jeg har brukt kan man finne her: https://github.com/ArtronShop/OPEN-SMART-RedMP3

Forbedringer 

Ettersom at MP3-modulen støtter avspilling av flere strømmer samtidig, ser jeg på mulighet for avspilling av flere avslappende naturlyder, for eksempel bekker eller dyr, for å kunne gi flere opplevelser og kombinasjon for hver dag som går. 

 

Kode

 #include <Time.h>  
 #include <Timezone.h>  
 #include <ESP8266WiFi.h>  
 #include <ESP8266WebServer.h>  
 #include <EEPROM.h>
 #include <NTPClient.h>  
 #include <WiFiUdp.h>  
 #include <SoftwareSerial.h>  
 #include <RedMP3.h>
 #define RX 5//RX of NodeMCU  
 #define TX 4//TX of NodeMCU  

 MP3 mp3(RX,TX);  
 WiFiUDP ntpUDP;  
 NTPClient timeClient(ntpUDP);  
 // Central European Time (Frankfurt, Paris)  
 TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120};   // Central European Summer Time  
 TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60};    // Central European Standard Time  
 Timezone CE(CEST, CET);  
 const int MINUTE = 60000;  
 const int8_t WINTER = 1;  
 const int8_t SPRING = 2;  
 const int8_t SUMMER = 3;  
 const int8_t AUTUMN = 4;  
 const int8_t GONG = 5;  
 int8_t volume = 0x11;//0~0x1e (30 adjustable level) 0x1a  
 struct tm *ptm;  
 unsigned long epochTime;  
 int month_;  
 int hour_;  
 int minute_;   

 int i = 0;  
 int statusCode;  
 String st;  
 String content;

 //Function Decalration  
 bool testWifi(void);  
 void launchWeb(void);  
 void setupAP(void);

 //Establishing Local server at port 80 whenever required  
 ESP8266WebServer server(80);  

 void setup() {  
  Serial.begin(115200); //Initialising if(DEBUG)Serial Monitor  
  Serial.println();  
  Serial.println("Kobler fra wifi");  
  WiFi.disconnect();  
  EEPROM.begin(512); //Initialasing EEPROM  
  delay(10);  
  pinMode(LED_BUILTIN, OUTPUT);  
  Serial.println();  
  Serial.println();  
  Serial.println("Starter opp");  
  //---------------------------------------- Read eeprom for ssid and pass  
  Serial.println("Leser EEPROM ssid");  
  String esid;  

  for (int i = 0; i < 32; ++i)  
  {  
   esid += char(EEPROM.read(i));  
  }  
  Serial.println();  
  Serial.print("SSID: ");  
  Serial.println(esid);  
  Serial.println("Leser EEPROM passord");  
  String epass = "";  

  for (int i = 32; i < 96; ++i)  
  {  
   epass += char(EEPROM.read(i));  
  }  
  WiFi.begin(esid.c_str(), epass.c_str());  

  if (testWifi())
  {  
   Serial.println("Tilkoblet.");  
   delay(500);//Requires 500ms to wait for the MP3 module to initialize  
   timeClient.begin();  
   delay(500);  
   timeClient.update();  
   epochTime = timeClient.getEpochTime();  
   return;  
  }  
  else  
  {  
   Serial.println("Slår på Wifi HotSpot");  
   launchWeb();  
   setupAP();// Setup HotSpot  
  }  
  Serial.println();  
  Serial.println("Ventar.");  
  
  while ((WiFi.status() != WL_CONNECTED)) {  
   Serial.print(".");  
   delay(100);  
   server.handleClient();  
  }  
 }  
  
 void loop() {  
  time_t lokaltid = getLocalTime(CE, timeClient.getEpochTime());  
  ptm = gmtime(&lokaltid);  
  month_ = ptm->tm_mon+1;  
  hour_ = ptm->tm_hour;  
  minute_ = ptm->tm_min;  
  if (hour_ == 0 && minute_ == 0) { // start   
   if (month_ < = 3) {  
    mp3.playWithFileName(WINTER,1);  
   } else if (month_ <= 6) {  
    mp3.playWithFileName(SPRING,1);  
   } else if (month_ <= 9) {  
    mp3.playWithFileName(SUMMER,1);  
   } else if (month_ <= 12) {  
    mp3.playWithFileName(AUTUMN,1);  
   }  
  }  
  mp3.playWithFileName(4,1);  
  Serial.println(".");  
  delay(MINUTE); // refresh every 1 minute  
 }  
 
 //----------------------------------------------- Fuctions used for WiFi credentials saving and connecting to it which you do not need to change  
 bool testWifi(void) {  
  int c = 0;  
  Serial.println("Venter på at Wifi skal koble seg til");  
  while ( c < 100 ) {  
   if (WiFi.status() == WL_CONNECTED)  
   {  
    return true;  
   }  
   Serial.print("*");  
   digitalWrite(LED_BUILTIN, HIGH);  
   delay(250);  
   digitalWrite(LED_BUILTIN, LOW);  
   delay(250);  
   c++;  
  }  
  Serial.println("");  
  Serial.println("Tilkobling feilet, åpner AP");  
  return false;  
 }  
 
 void launchWeb() {  
  Serial.println("");  
  if (WiFi.status() == WL_CONNECTED)  
   Serial.println("WiFi tilkoblet");  
  Serial.print("Lokal IP: ");  
  Serial.println(WiFi.localIP());  
  Serial.print("SoftAP IP: ");  
  Serial.println(WiFi.softAPIP());  
  createWebServer();  
  // Start the server  
  server.begin();  
  Serial.println("Server startet");  
 }  

 void setupAP(void) {  
  WiFi.mode(WIFI_STA);  
  WiFi.disconnect();  
  delay(100);  
  int n = WiFi.scanNetworks();  
  Serial.println("scanning ferdig");  
  if (n == 0)  
   Serial.println("fant ingen nettverk");  
  else  
  {  
   Serial.print(n);  
   Serial.println(" nettverk funnet");  
   for (int i = 0; i < n; ++i)  
   {  
    // Print SSID and RSSI for each network found  
    Serial.print(i + 1);  
    Serial.print(": ");  
    Serial.print(WiFi.SSID(i));  
    Serial.print(" (");  
    Serial.print(WiFi.RSSI(i));  
    Serial.print(")");  
    Serial.println((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*");  
    delay(10);  
   }  
  }  
  Serial.println("");  
  st = "<ol>";  
  for (int i = 0; i < n; ++i)  
  {  
   // Print SSID and RSSI for each network found  
   st += "<li>";  
   st += WiFi.SSID(i);  
   st += " (";  
   st += WiFi.RSSI(i);  
   st += ")";  
   st += (WiFi.encryptionType(i) == ENC_TYPE_NONE) ? " " : "*";  
   st += "</li>";  
  }  
  st += "</ol>";  
  delay(100);  
  WiFi.softAP("naturlyd", "");  
  Serial.println("Initializing_softap_for_wifi credentials_modification");  
  launchWeb();  
  Serial.println("over");  
 }  

 void createWebServer() {  
  {  
   server.on("/", []() {  
    IPAddress ip = WiFi.softAPIP();  
    String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);  
    content = "<!DOCTYPE HTML><html>Sett opp WiFi for naturlyd opplegg:";  
    content += "<form action=\"/scan\" method=\"POST\"><input type=\"submit\" value=\"scan\"></form>";  
    content += ipStr;  
    content += "<p>";  
    content += st;  
    content += "</p><form method='get' action='setting'><label>SSID: </label><input name='ssid' length=32><input name='pass' length=64><input type='submit'></form>";  
    content += "</html>";  
    server.send(200, "text/html", content);  
   });  
   server.on("/scan", []() {  
    //setupAP();  
    IPAddress ip = WiFi.softAPIP();  
    String ipStr = String(ip[0]) + '.' + String(ip[1]) + '.' + String(ip[2]) + '.' + String(ip[3]);  
    content = "<!DOCTYPE HTML><html>gå tilbake";  
    server.send(200, "text/html", content);  
   });  
   server.on("/setting", []() {  
    String qsid = server.arg("ssid");  
    String qpass = server.arg("pass");  
    if (qsid.length() > 0 && qpass.length() > 0) {  
     Serial.println("sletter eeprom");  
     for (int i = 0; i < 96; ++i) {  
      EEPROM.write(i, 0);  
     }  
     Serial.println(qsid);  
     Serial.println("");  
     Serial.println(qpass);  
     Serial.println("");  
     Serial.println("skriver eeprom ssid:");  
     for (int i = 0; i < qsid.length(); ++i)  
     {  
      EEPROM.write(i, qsid[i]);  
      Serial.print("Skreiv: ");  
      Serial.println(qsid[i]);  
     }  
     Serial.println("skriver eeprom passord:");  
     for (int i = 0; i < qpass.length(); ++i)  
     {  
      EEPROM.write(32 + i, qpass[i]);  
      Serial.print("Wrote: ");  
      Serial.println(qpass[i]);  
     }  
     EEPROM.commit();  
     content = "{\"Success\":\"skrev til eeprom... reset enhet for å koble til wifi\"}";  
     statusCode = 200;  
     ESP.reset();  
    } else {  
     content = "{\"Error\":\"404 not found\"}";  
     statusCode = 404;  
     Serial.println("Sender 404");  
    }  
    server.sendHeader("Access-Control-Allow-Origin", "*");  
    server.send(statusCode, "application/json", content);  
   });  
  }  
 }  
 /**  
  *   
  * TimeZone related help functions  
  *   
  */  
 time_t getLocalTime(Timezone tz, time_t utc) {  
   char buf[40];  
   char m[4];  // temporary storage for month string (DateStrings.cpp uses shared buffer)  
   TimeChangeRule *tcr;    // pointer to the time change rule, use to get the TZ abbrev  
   return tz.toLocal(utc, &tcr);  
 }  

 

Innlegg skrevet av

Thor Nydal
Utvikler