What if your laptop was alive? If it had a heartbeat? Would you engage with it differently? See it as more than just a device? This project aims to find out.
Table of Contents
The Idea
The idea for ‘living laptop’ was born when I was anxiously feeling my laptop’s temperature after a certain piece of software had stopped responding. One of my fellow students asked me: “Are you checking for a pulse?” And I thought, why not? That would give me a better indication of how much it is struggling compared to analysing the noise that the fans are making. I wanted to experiment with physicalising the CPU load of my laptop in another way than just showing percentages in my taskbar. Thus the idea of equipping my laptop with a pulsating vein was born. (I know that technically it’s an artery because it pulsates; something which veins don’t do.)
Setup
A python script on my laptop takes the current CPU, converts it to a time interval in between heartbeats, and sends this value over serial to an Arduino, which uses it to drive a pump. The pump inflates the vein on my laptop. The most difficult aspect of this project was getting the vein to work, and getting my python script to talk to the Arduino powering the pump. The code isn’t perfect yet, but good enough that I can simulate my laptop actually having a heartbeat. I’m not sure yet how to keep the heartbeat going regularly, as the serialEvent() is an interrupt, and so every 10 seconds, when my laptop sends a new value over serial, the vein skips a beat.
The vein is located on the left side of the laptop, fabricated in matte black to match the style of my Lenovo Thinkpad. I experimented with different vein locations, some of which also yield continuous haptic feedback, such as placing the vein underneath the palm of the hand. This almost feels like a real vein throbbing, but the delicacy of the prototype prompted me to move the vein to a location where my hands do not interact with it frequently. This makes the throbbing more of a visual cue, while I can also easily reach out with my left hand to check the laptop’s pulse.
The vein was fabricated from a black nitrile glove and a vein model printed in PLA. This vein was coated in vaseline and the glove was glued around the vein using superglue. The vaseline prevents the nitrile from sticking to the PLA model so it can be removed later on. The nitrile can be glued surprisingly easily.
Findings
Because the vein is located to the side of the keyboard, and thus not in direct contact with my hands all the time, the heartbeat feedback from the laptop is not direct. Instead, the current setup forces me to actively feel the pulse to get an idea of how the laptop is doing. This does not differ substantially from how I regularly interact with my laptop, frequently feeling how hot it is or listening to the fan speed to gauge whether it is struggling with a task. When feeling the pulse, however, the feedback is much more salient than temperature or fan noise.
Lessons Learnt
- Perform the calculations on the processor that has the most computing power.
- Don’t forget to take progression pictures!
- Don’t be afraid to experiment with fabrication methods, even if people tell you that it’s not possible. I was told that no way would superglue stick to nitrile, but on the glove I got it worked wonders.
Code
Arduino Code
/* Code by Katrien van Riet - July 2022
With special thanks to Jan Rouvroye and Eden Chiang for helping me getting
python to communicate with Arduino
*/
#include <MedianFilter.h>
const int ledPin = 11;
const int filterSize = 10;
const int initialFilterValue = 1000;
int bpm; // Beats per minute
int beatTime = 100; // Time on per beat (calculate this!) [ms]
const int motorPin = 3;
unsigned long prevTime;
unsigned long currentTime;
long timeInterval; // In millis
long serialValue;
boolean isBeatOn = false;
MedianFilter timeIntervalFilter(filterSize, initialFilterValue);
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
pinMode(motorPin, OUTPUT);
digitalWrite(ledPin, LOW);
bpm = 60; // Initial bpm when serial data is unavailable
timeInterval = 60000 / bpm;
prevTime = millis();
}
void loop() {
currentTime = millis();
if (currentTime - prevTime > timeInterval) {
isBeatOn = true;
prevTime = currentTime;
}
if (isBeatOn && (currentTime - prevTime) > beatTime) {
isBeatOn = false;
}
if (isBeatOn) {
analogWrite(motorPin, 255);
}
else {
analogWrite(motorPin, 0);
}
}
void serialEvent() {
serialValue = Serial.readString().toInt();
timeIntervalFilter.in(serialValue);
timeInterval = timeIntervalFilter.out();
}
Python code
import psutil
import serial
import time
delayTime = 10 # In seconds
myPort = serial.Serial('COM7', 115200, timeout=0.1)
def write_to_serial(x):
myPort.write(bytes(x,'utf-8'))
time.sleep(delayTime)
value = myPort.readline()
return value
while True:
data = round(psutil.cpu_percent(delayTime))
timeInterval = 2 * data + 50
print(round(60000 / timeInterval))
value = write_to_serial(str(round (60000 / timeInterval)))