
Concept
Portable d[r]oom is a wearable helmet that turns the passive habit of doom scrolling into a physical condition. Drawing on Walter Pichler’s TV Helmet (Portable Living Room) from 1967, which isolated its wearer inside a television shell and anticipated today’s tech-induced detachment, the project addresses the stillness on which modern media addiction depends. An acceleration sensor continuously reads the wearer’s movement and distinguishes walking from standing still. While the wearer keeps moving, the mask stays open and the real world remains visible. The moment they pause, servo motors lower the mask and an OLED screen takes over the field of view with looping animations. Portable d[r]oom thereby confronts the user with their own idle habits and pushes them to their logical end: stop for a second and the media consumes you, keep moving or lose the real world.
Schematic and Bill of Material


Code
#include “LIS3DHTR.h”
#include <Wire.h>
LIS3DHTR<TwoWire> LIS; //IIC
#define WIRE Wire
//oled
#include <Arduino.h>
#include <U8x8lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
U8X8_SSD1306_128X64_ALT0_HW_I2C u8x8(/* reset=*/U8X8_PIN_NONE); // both OLED same = showing same Data
//servo
#include <Servo.h>
Servo servo1;
Servo servo2;
int Servo_up = 90;
int Servo_down = 0;
// calculation moving & smoothing
float lastX, lastY, lastZ;
const int numReadings = 10;
float readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
float total = 0; // the running total
float average = 0; // average
bool wasMoving = false;
int animRow = 0; //where am i in animation
void setup() {
Serial.begin(115200);
for (int thisReading = 0; thisReading < numReadings; thisReading++) { // initialize all the readings to 0:
readings[thisReading] = 0;
}
//servo
servo1.attach(3);
servo2.attach(4);
servo1.write(Servo_down);
servo2.write(180 – Servo_down);
//ACCELEARATION
while (!Serial) {
};
LIS.begin(WIRE, 0x19);
delay(100);
LIS.setFullScaleRange(LIS3DHTR_RANGE_2G);
LIS.setOutputDataRate(LIS3DHTR_DATARATE_50HZ);
lastX = LIS.getAccelerationX();
lastY = LIS.getAccelerationY();
// lastZ = LIS.getAccelerationZ(); // not important
//OLED
u8x8.begin();
}
//oled – setup loop – animation
void pre(void) {
u8x8.clear();
u8x8.noInverse();
u8x8.setCursor(0, 1);
}
void loop() {
int i;
uint8_t c, r, d;
float x = LIS.getAccelerationX();
float y = LIS.getAccelerationY();
float diff = fabs(x – lastX) + fabs(y – lastY); //+ fabs(z – lastZ)
lastX = x;
lastY = y;
total = total – readings[readIndex];
readings[readIndex] = diff;
total = total + readings[readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0; // end -> to start
}
average = total / numReadings; // average
//condition
if ((average >= 0.09)) {
Serial.println(average);
Serial.println(“MOVE”);
servo1.write(Servo_up);
servo2.write(180 – Servo_up);
if (!wasMoving) { //clear once
u8x8.clear();
}
wasMoving = true;
animRow = 0;
delay(15);
} else {
float x = LIS.getAccelerationX();
float y = LIS.getAccelerationY();
Serial.println(average);
Serial.println(“STILL”);
servo1.write(Servo_down);
servo2.write(180 – Servo_down);
if (animRow == 0) { // start of animation
pre();
u8x8.setFont(u8x8_font_inb33_3x6_n);
animRow = 0;
}
if (animRow == 0) {
u8x8.drawString(0, -1, “66666”); // all columns 6
}
if (animRow == 10) {
u8x8.drawString(0, -1, “77777”); // all columns 7
}
animRow++;
if (animRow >= 20) {
animRow = 0; // loop forever
}
wasMoving = false;
}
delay(50); // delay in between reads
}
Prototype
We began by connecting the acceleration sensor to a single servo motor to measure the data range of walking and standing still, and used it to define the conditions in our code. From there, we added the remaining components one by one: a second servo, smoothing of the sensor data, and the OLED animations. In the code, we deliberately chose a reactive stop-and-go behaviour rather than a smoothed-out one, so that the mask responds immediately to every pause.


The next steps concern the sensor position and the screen. For data stability, the sensor is currently held in the hand. In a future version, it could be clamped to the body and work wirelessly, or the acceleration data could come directly from the wearer’s phone. The screen content should be linked to a personal profile, so the animations can be adjusted to each wearer’s own media habits.