
Cleanse
2022digital sculpture for the global AR Pavillion at “wrong Biennale”
Portfolio2026
Two spools stand facing each other, bound by a single continuous thread.
One grows as the other diminishes, the same thread that constructs also consumes.
To be attached is to be made and unmade by proximity.
Scroll to transfer the thread
Arduino powered spinning machine

Two spools stand facing each other, bound by a single continuous thread. They spin in unison, one grows as the other diminishes, the same thread that constructs also consumes.
Together, they create a mechanical duet of dependency - neither can exist without the other, and neither can be whole.
By giving the thread a mechanical metabolism, the work exposes attachment not as stability but as a cyclical exchange. To be attached is to be made and unmade by proximity.
This machine continuously transfers yarn between two motorized spools while a vertically actuated guide precisely controls its placement. Through a programmed motion profile that varies speed across the travel path, the machine generates sculptural accumulations.






#include <AccelStepper.h>
#include <math.h>
// ====== MIDDLE MOTOR PINS ======
#define STEP_MITTE 4
#define DIR_MITTE 5
AccelStepper stepperMitte(AccelStepper::DRIVER, STEP_MITTE, DIR_MITTE);
// ====== RIGHT MOTOR PINS ======
#define STEP_RECHTS 2
#define DIR_RECHTS 3
#define ENABLE_RECHTS 8
AccelStepper stepperRechts(AccelStepper::DRIVER, STEP_RECHTS, DIR_RECHTS);
// ====== LEFT MOTOR PINS ======
#define STEP_LINKS 6
#define DIR_LINKS 7
#define ENABLE_LINKS 9
AccelStepper stepperLinks(AccelStepper::DRIVER, STEP_LINKS, DIR_LINKS);
// ====== CONTROL VARIABLES ======
bool paused = true; // start paused until 'r' is pressed
unsigned long lastMoveTime = 0; // timing for 5-second middle motor
const long moveAmount = 500; // middle motor steps per move
bool forward = true; // middle motor direction flag
long segmentStart = 0;
long segmentTarget = 0;
bool midPauseDone = false;
bool midPausing = false;
unsigned long midPauseStart = 0;
long segmentCenter = 0;
long basePosition = 0; // lowest allowed position
long baseOffset = 0; // shifts base upward in steps
// ====== MIDDLE MOTOR GAUSSIAN PROFILE ======
const float MITTE_MIN_SPEED = 20.0f;
const float MITTE_MAX_SPEED = 200.0f;
const float MITTE_MIN_ACCEL = 10.0f;
const float MITTE_MAX_ACCEL = 80.0f;
const float MITTE_SIGMA = 120.0f;
float gaussianFactor(float distance, float sigma) {
float x = distance / sigma;
float dip = expf(-0.5f * x * x);
return 1.0f - dip;
}
// ====== SIDE MOTOR CONSTANT SPEED ======
const int SPOOL_SPEED = 220; // SAME speed for left & right
int leftDir = -1;
int rightDir = 1;
void applySideMotorSpeeds() {
stepperLinks.setSpeed(leftDir * SPOOL_SPEED);
stepperRechts.setSpeed(rightDir * SPOOL_SPEED);
}
void setup() {
Serial.begin(115200);
while (!Serial) {}
// ---- ENABLE MOTORS ----
pinMode(ENABLE_LINKS, OUTPUT);
digitalWrite(ENABLE_LINKS, LOW);
pinMode(ENABLE_RECHTS, OUTPUT);
digitalWrite(ENABLE_RECHTS, LOW);
// ---- SET STEP/DIR LOW ----
pinMode(2, OUTPUT); digitalWrite(2, LOW);
pinMode(3, OUTPUT); digitalWrite(3, LOW);
pinMode(6, OUTPUT); digitalWrite(6, LOW);
pinMode(7, OUTPUT); digitalWrite(7, LOW);
// ---- MIDDLE MOTOR ----
stepperMitte.setMaxSpeed(MITTE_MAX_SPEED);
stepperMitte.setAcceleration(MITTE_MAX_ACCEL);
// ---- SIDE MOTORS ----
stepperLinks.setMaxSpeed(SPOOL_SPEED);
stepperLinks.setAcceleration(0);
stepperRechts.setMaxSpeed(SPOOL_SPEED);
stepperRechts.setAcceleration(0);
applySideMotorSpeeds();
basePosition = stepperMitte.currentPosition();
Serial.println("Send 'r' to START, 's' to STOP, 'x' to SWAP, 'u'/'d' to shift base");
}
void loop() {
// ---- SERIAL CONTROL ----
if (Serial.available()) {
char c = Serial.read();
if (c == 's') {
paused = true;
stepperMitte.stop();
stepperLinks.setSpeed(0);
stepperRechts.setSpeed(0);
Serial.println("Motors STOPPED");
}
if (c == 'r') {
paused = false;
applySideMotorSpeeds();
Serial.println("Motors RESUMED");
}
if (c == 'x') {
leftDir = -leftDir;
rightDir = -rightDir;
applySideMotorSpeeds();
Serial.println("Left/Right directions swapped");
}
if (c == 'u' || c == 'd') {
long delta = (c == 'u') ? 2000 : -2000;
baseOffset += delta;
if (baseOffset < 0) baseOffset = 0;
long newBase = basePosition + baseOffset;
stepperMitte.moveTo(newBase);
segmentStart = stepperMitte.currentPosition();
segmentTarget = newBase;
segmentCenter = newBase;
midPauseDone = true;
midPausing = false;
lastMoveTime = millis();
Serial.println("Base position shifted");
}
}
if (paused) return;
// ---- MIDDLE MOTOR EVERY 5 SECONDS ----
if (stepperMitte.distanceToGo() == 0 && millis() - lastMoveTime >= 5000) {
long target = forward
? basePosition + baseOffset + moveAmount
: basePosition + baseOffset;
stepperMitte.moveTo(target);
segmentStart = stepperMitte.currentPosition();
segmentTarget = target;
segmentCenter = basePosition + baseOffset + (moveAmount / 2);
midPauseDone = false;
midPausing = false;
forward = !forward;
lastMoveTime = millis();
}
// ---- MID-SEGMENT PAUSE ----
if (stepperMitte.distanceToGo() != 0 && !midPauseDone && !midPausing) {
long traveled = labs(stepperMitte.currentPosition() - segmentStart);
long total = labs(segmentTarget - segmentStart);
if (total > 0 && traveled >= total / 2) {
midPausing = true;
midPauseStart = millis();
}
}
if (midPausing) {
if (millis() - midPauseStart >= 3000) {
midPausing = false;
midPauseDone = true;
}
} else {
float distance = fabsf(stepperMitte.currentPosition() - segmentCenter);
float factor = gaussianFactor(distance, MITTE_SIGMA);
float targetSpeed = MITTE_MIN_SPEED + (MITTE_MAX_SPEED - MITTE_MIN_SPEED) * factor;
float targetAccel = MITTE_MIN_ACCEL + (MITTE_MAX_ACCEL - MITTE_MIN_ACCEL) * factor;
stepperMitte.setMaxSpeed(targetSpeed);
stepperMitte.setAcceleration(targetAccel);
stepperMitte.run();
}
// ---- RUN SIDE MOTORS ----
stepperLinks.runSpeed();
stepperRechts.runSpeed();
}
Materials and text to be supplied by the artist


Clothing for furniture
Humans get dressed. Every day, we choose what to wear based on where we are going, what we are doing, and how we feel. Our clothing helps us adapt to environments, meet expectations, and express identity.
What if furniture could do the same?
A simple welded steel chair is getting dressed:
Drag an outfit onto the chair, or tap it.
Outfits tried: 0 of 3
Each outfit can be slipped on or off with ease and be stored on a regular hanger, right alongside human clothes. All garments are made from discarded clothing and deadstock fabrics - materials originally intended for human bodies, carrying memories of dressing, utility, and style, now reimagined for a chair. By changing its clothes, the chair shifts its role, its mood, and the atmosphere of the room it inhabits.








Double layered lenticular weaving with dyed weft threads
Depression can change you in many ways. It affects various aspects of the senses, including the perception of colour. Research has shown that individuals suffering from depression often perceive colours as less vibrant and more muted. Luckily this change in perception is not irreversible, people who won their battle with the illness often report seeing the world shine in its „true colours“ again.
„Feeling Blue-ish“ aims to visualise this phenomenon and encourage people to view the world through different eyes. The double-layered textile is woven in stripes of two alternating images. The pleats create a lenticular effect, changing the visibility of the images depending on the viewer‘s perspective - signifying the shift in perception that is imperative to recovery.












Inspired by knitting machine programming glitches, the collection of knitted textiles blends the organic softness of yarns with fragmented aesthetics of distortion. Each piece creates a sense of movement and visual disruption. Together, they aim to evoke a contrast between the traditional usage of knitting and modern interferance.








Textile Mechanisms

Defence is a primal instinct that connects all living beings. It manifests itself in strategies developed through evolution, that are essential for survival. These strategies vary greatly, ranging from passive camouflage to visual deterrence, escape or active combat.
Humans, too, are constantly faced with the challenge of finding an appropriate defence strategy in the face of conflicts or attacks. It is crucial for success to be able to react both passively and actively.
“Protective Patterns" depicts this duality. Textile mechanisms that can switch ad hoc between two different states. In the drastic changes of their surface structure, they can embody both defensive and offensive capabilities. Thus, they become extensions of the body, communicating on a textile basis.

Handmade Paper out of recycled cotton and jeans




digital sculpture for the global AR Pavillion at “wrong Biennale”

Silicone and silver foil on organza

Biography, education, exhibitions and CV: to be supplied by the artist.