“SPILL” - Final Project Documentation

View this post on Instagram

A post shared by lù does stuff (@lu.does.stuff)

sips tea Inspired by the Finnish folklore “harakointi” - the act of revealing a woman’s genitals to a target as supernatural magic to protect or curse, SPILL intends to spill the tea on a vaginal topic: menstruation. This kinetic installation demonstrates simplified menstrual cycles using tea wares and a tampon. The mechanism is controlled by anonymous data on menstrual cycle lengths from a healthcare research project in 2012.

Menstruation is the regular discharge of blood and mucosal tissue from the inner lining of the uterus through the vagina. Despite being a common (and significant) biological process, it is often a taboo topic. Stigmas and myths surrounding menstruation remains even until nowadays. For example, advertisement of period products uses blue liquid to represent blood, many girls and women are not allowed to be in the kitchen or attend ritual practices during their menstruation, and some languages adopt “euphemisms” for menstruation.

With this work, let’s spill some tea, blood, or truth about menstrual cycles. Let’s talk about it – our experiences, knowledge, myths, and more.

Image of the exhibited piece

Concept & Goals

SPILL is a kinetic installation that represents menstrual cycles mechanically with a set of tea wares.

As mentioned during the concept presentation, I wish to learn more the following three aspects through this course project:

  1. Mechanism - to communicate or feedback through physical motions (instead of screen display);
  2. Sensors - to understand more about Temperature and Humidity Sensor (AHT20) or Magnetometer (TLV493D);
  3. Material - to include something soft, such as muscle wire, fabric, or paper.

Considering these goals, I went on an “objet trouvé” hunt at recycling centres over one weekend. On this trip, I found some metal cups in similar styles with different sizes. When I placed a tall and narrow cup with two shorter and rounder ones together, this composition interestingly reminded me of a human uterus with two ovaries.

Apart from the anatomical resemblance, the similarity between a tampon and teabag also enabled me to envision a kinetic uterus with tea wares. I often joke about how tampons can be regarded as “anti-teabags.” Both tampon and teabag consist of a string and a pack of soft material, both are typically sold in a box with individual compact package for one time use, and both are immersed in liquid. However, they function in opposite ways – a teabag infuses while a tampon absorbs. Thus, I decided to construct a simulation of menstrual cycles using the cups found in the recycling centre.

Exhibited piece, tampon in the cup


Below is the initial sketch of the project concept - a kinetic sculpture that mimics mentruation cycles with a set of cups, a teaspoon, a plate, and a tampon: Sketch of the final project idea

The final working code (version December 2023) can be found in the Working Code section later on this page.

In this early sketch, I envisioned a structure that hangs the two small cups (as the ovaries) and the one long cup (as the uterus) on top of the white porcelain cup and the red glass tea plate. After around 28 counts, one of the ovaries tilted and then the uterus will flip over. A tampon will thus drop down and dip into the porcelain cup, which will be filled with red liquid.

Compared to this draft, there have been a few modifications in the final structure. For example, I replaced the red liquid with red glitters because the glitters will not change the mass of tampon much, the movement of the string will thus be consistent throughout the exhibition. Moreover, when the metalic tea spoon hits on the cups (either metalic or porcelain) or the glass plate, the sound effects are interesting. Thus, instead of tilting the “ovary” cups, I decided to place 14mm stainless steel valve balls. Thus, when the servo motor pulls the string, the ball will roll and hits the cup like a bell.

Nevertheless, I divided the parts with different priorities for me to plan the implementation process:

  • HIGH
    • Essential to prototype the concept – the looping movement of the tampon from the cup on top to the cup below; also, the tampon should land inside the porcelain cup and return to the cup above almost in every cycle;
    • Robust – magnetic sensor near the spool to control the rolling of strings;
    • Features for debugging (during the implementation) - the serial output, led matrix animations, and a push button to control the looping mechanism during the testing phase.
  • MID
    • Parts that complete the narrative – the movement of the “ovaries”, the usage of actual menstrual cycle length data, etc.
  • LOW
    • Ideas that emerged later during the implementation, such as the form development of the overall structure, ways to communicate the cycle lengths to the audience, and some possible interactivity.

Based on these priorities, I focused on the essential and the personally more challenging parts during the at first (e.g., the moving mechanism and the CAD for clamps). Afterwards, I tried to accomplish the rest features (e.g., small cups movements, magnetic sensor to stop, and the sculpting of moldable plastic) on the last few days.

Exhibited piece, the porcelain cup with the pink blob

Project Specification (for December, 2023)

Frame dimension (approximately): 62 x 42.5 x 56 (cm)

Material used:
3D-printed parts
Working code (for December 2023)
#include <Servo.h>
#include <Tlv493d.h>
#include "Arduino_LED_Matrix.h"

// Constants
const int dirPin = 2;
const int stepPin = 3;
const int enPin = 4;
const int stepAmount = 200;
const int microSteps = 16; // 16 means 1/16, 32 means 1/32 etc.
const int servoPin = 9;
const int sideServoAPin = 8;
const int sideServoBPin = 7;
const int cycleLengths[] = {29,27,29,27,28,26,29,24,28,28,26,29,27,28,30,28,26,26,24,27,28,26,27,27,25,32,27,29,26,27,28,31,27,27,28,27,26,28,28,24,26,27,28,27,28};
int totalCycles = sizeof(cycleLengths) / sizeof(int); // calculate the number of elements in the array
const uint32_t happy[] = {
const uint32_t heart[] = {

// Variables
Servo myservo;  // create servo object to control a servo
Servo sideServoA;  // create servo object to control a servo
Servo sideServoB;  // create servo object to control a servo
ArduinoLEDMatrix matrix;

Tlv493d Tlv493dMagnetic3DSensor = Tlv493d(); // Tlv493d Opject

int installationState = 1;

int pos = 0;    // variable to store the servo position
int shakePos = 0; // variable to shake small cup
int cycleIndex = 0;
int staticRoll = 15;

void setup() {
  myservo.attach(servoPin);  // attaches the servo on pin 9 to the servo object

  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(enPin, OUTPUT);

  digitalWrite(dirPin, HIGH);
  digitalWrite(enPin, LOW);




void loop() {

  // int reading = digitalRead(btnPin);
  int rollCount = 0;

  while (installationState == 1) {

    Serial.print("cycle index:");

    // delay(cycleLengths[cycleIndex]*1000); // use the data from the array
    for (int i=0; i<cycleLengths[cycleIndex]; i++){


    // randomly move left or right
      for(shakePos = 0; shakePos <=30; shakePos+=1){
      for(shakePos = 30; shakePos <=0; shakePos-=1){
    } else{
      for(shakePos = 0; shakePos <=30; shakePos+=1){
      for(shakePos = 30; shakePos <=0; shakePos-=1){


    // flip the cup -> string drop
    for (pos = 90; pos <= 150; pos += 1) { // goes from 180 degrees to 0 degrees
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      //delay(15);                       // waits 15ms for the servo to reach the position


    // avoid the string
    for (pos = 150; pos >= 45; pos -= 1) { // goes from 180 degrees to 0 degrees
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(15);                       // waits 15ms for the servo to reach the position

    // roll up the strings
    while(abs(Tlv493dMagnetic3DSensor.getX())<0.65 && abs(Tlv493dMagnetic3DSensor.getY())<0.65 && abs(Tlv493dMagnetic3DSensor.getZ())<0.65){ // use magnet to detect the spoon position
      rollCount += 1;

      Serial.print("Roll count: ");



    // adjust the cup to tilt a bit
    for (pos = 45; pos <= 90; pos += 1) { // goes from 180 degrees to 0 degrees
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(15);                       // waits 15ms for the servo to reach the position


    // lower to the cup
    oneFullRotation(rollCount); // use magnet to detect the spoon position

    rollCount = 0;

    // turn the cup back
    for (pos = 90; pos >= 45; pos -= 1) { // goes from 0 degrees to 180 degrees
      // in steps of 1 degree
      myservo.write(pos);              // tell servo to go to position in variable 'pos'
      delay(5);                       // waits 15ms for the servo to reach the position

    // move to next cycle
    if (cycleIndex < totalCycles) {
      cycleIndex += 1;
    } else {
      cycleIndex = 0;





void oneStep() {
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(100); // speed
  digitalWrite(stepPin, LOW);

void oneFullRotation(int round) {
  for (int i = 0; i < stepAmount * microSteps * round; i++) {

Reflection and Plan for Future Iterations

There are a few shortcomings in this version of my installation can be addressed in my next iterations.

Especially for the spooling mechanism of the tea spoon and the tampon, as the objects rotate while ascending, the magnetometer sometimes may not be able to capture the readings immediately. When this situation happens, the spoon often gets stuck with the wooden frame. In addition, the string sometimes entangles on the spool, which leds to the inconsistency of the looping.

Moreover, the waiting time between menstruations may appear to be obscure to the audience. I think that certain signals to visualise/sonify the process may help the audience to understand more about the piece.

Here are some of my thoughts for future iterations

  • Robustness:
    • Revise the spool structure and the string length;
    • Reexamine the usage of magnetometer. Currently, I use 0.65 for either x/y/z direction as the threshold to stop the spooling, I can either stablise the tampon (and the spoon), or investigate more about the ways of working of magnetometer;
    • Design a self-calibration process;
    • Wiring.
  • Form:
    • Utilise the dimension from the current structure, such as the distance between the spool and the “uterus” cup, to further develope the form of the supporting frame;
    • Fully utilise the modalbe plastic to develope an organic (yet robotic) look of the installation.
  • Mechanism:
    • It is possible to use only one motor for the “ovaries” motions, so that the installation can be more efficient.
  • Interactivity:
    • Signals to the audience during the waiting time (either visual or audio);
    • Use the audience’s pulse or breathing (28 counts maybe?) as the duration instead of the online dataset.

Exhibited piece with the hand of Diana Lisitsa

(Exhibition) Afterthought

At the exhibition, I had an unexpectedly fun conversation or, at least, interaction with a toddler beside my work. According to her parent, this was the child’s “favourite” at that moment. Probably because the pedestal is low enough, even a toddler can closely observe the details. The parent accompanying this kid told me that the daughter was super excited about this work and dragged him over to see it together.

I started casually chatting with the child, found out that red (and violet) happened to be her favourite colours. When the stained tampon started moving, adults tend to find this robotic menstruation fun in a “quirky” manner, yet the toddler appreciated it as an animated glittery tea party - with her favourite colour even.

It is interesting to realise that connotations of certain objects are learnt from life experiences and cultural influences.

Research (for mechanism and visual representation)

1. Menstruation

2. Menstrual Cycle Data

Link to the Kaggle page Link to the original publication

In a simplified way, the column for “LengthofCycle” can be used as a timer to control the installation movement cycle.

In addition, this dataset contains in total 80 columns. Other data including “MeanBleedingIntensity”, “UnusualBleeding”, or “PhasesBleeding” can be used for future iterations of this project.

4. (!!!) Manipulating array in Arduino

To retrieve the size of an array is unexpectedly tricky in Arduino: Link to the tutorial on The Circuit Maker

5. 3D Files

Micro servo horn (Note: actually for SLA printers)

The End

Below is an imagined manuscript of a kinetic installation that represents menstrual cycles: Imagined manuscript of a a kinetic installation that represents menstrual cycles