Skip to content

11. Open Source Hardware - From Fibers to Fabric

Research

Open Source Hardware week! I am super excited to work together as a team with Carolina, Asli and Michelle and become the ultimate Taskforce to take on hacking the Shopbot.

Going into this week,I am thinking about how this knowledge can be used in my sculptural practice. I am excited about how changing a machine function can create an interesting conversation around action and consequence. I have been looking at examples of artists who have used machine hacking to change the signifiers of these machines and convey poetic messages through the unexpected actions and interactions of machines:

Slacker by sculptor Holly Hendry was part of a show "The Dump is Full of Images" at the Yorkshire Sculpture Park. An investigation into mechanical imitation through a kinetic sculpture. Slacker is a machine in the shape of a body lying down, which slowly rotate a band of inlaid silicone around a set of paper press rollers to discuss material use and reuse as well as the bodies entwinement with machines.

Similarly, Sun Yuan and Peng Yu hack industrial machines such as robots, forklifts, vacuums and vortex cannons to create artworks that comment on the human condition. Their adaptions and reinventions of machines animate and personify the machines in a way that speak to human emotions.

Finally, Olafur Eliasson has done many investigations into drawing machines, investigating the relationship between input and output in hopes of making invisible phenomena such as music, movement, solar rays etc. visible through drawing.

Eliasson's Solar drawing observatory is powered primarily by the sun and by the movement of the planet. Two rows of glass spheres of various sizes are supported above a sheet of paper. The glass spheres act as lenses that focus the sunlight to burn marks onto the paper. As the position of the sun in the sky changes in relation to the glass spheres, the light travels across the paper.

moodboard

In Saltwater Drawing observatory canvases turn slowly on motors as salt water, mixed with pigments drips down onto the spinning surfaces. The wind causes the drawing utensil to move across the surface of the turning page.

moodboard

In Spatial Vibrations, Eliasson uses the sounds of string instruments to make two rods oscillate, converging with a pen that inscribes their rhythmic movement on a rotating piece of paper.

moodboard

From these examples I am excited to explore how machine building and hacking can be used to convey metaphor and draw attentions to actions and consequence.

Finally, another thing that interests me about this week is about how the embodied interactions with machines can be affected, bringing the tactile and the sensory back into machine use. I am excited about the possibilities created when craftspeople and artists have control in how the machine works so that things such as haptic interaction can be reinstilled.

This example of The SynLimb by Bertolt Meyer epitomises this adaption. Using his prosthetic to pick up and convert the electrode signals that are sent by the body to control the hand and use them to controlling his modular synthesizer. This completely changes the way the musical instrument is interacted with.

I am so excited by the possibilities this week will open up.

✙Documentation Workflow✙

This week we had to create:

Assignment Criteria: Week 8
  • Research and document existing fabrication methods, machines and industries , add references and sketches of the machine and the chosen process

  • Design and document the files of the machine, machine hack or tool and fabrication - assembly process

  • Document the schematic and the programming code (if any)

  • List the materials: electronics, materials amount other (references of the components)

  • Design, create and document a final outcome, a sample project of your process

  • Make a small video of the machine

  • Create an interface for controling your machine

Top Tip!!!
  1. Remember that you are in a spiralling design process, everything doesn't have to be pretty and perfect in the first iteration!
Inspiration!!!

⚂WHAT IS OPEN SOURCE HARDWARE?⚃

Open source hardware is an approach to hardware design aligned with the specifications of the open design movement, in which harware is created and licensed in such a way that it can be studied, modified, created, and distributed by anyone. Making all relevant information freely accessible and as a collective repository of knowledge

For this to be the case comprehensive and transparent documentation is key to the sharing of collective knowledge so that everything can be understood and replicated. Important features of open source hardware documentation are:

  • Licsence
  • A Project Overview
  • Assembly Instructions
  • Bill of Materials
  • Purchased Parts
  • Unique Parts
  • Source Files and Exported Files
  • Software
  • Reviews and Rebuilds

Finally, projects must be uploaded on to a publically accessible platform such as:

With our project we will aim to document comprehensively and share our developments, failures and rebuilds in line with a open source design approach.

☕︎PROJECT OVERVIEW: HACKING THE CNC MILLING MACHINE☕︎

This week we would be building on knowledge co-created at the Waag Futurelab and by past Fabricademy students. We would be Hacking the Shopbot.

moodboard

The Shopbot is our CNC milling machine, a subtractive manufacteuring machine that uses a cutting tool mounted on a rotating spindle. It operates via Shopbot code and a 3 axes co-ordinate system to mill away solid materials such as wood, plastic and metal in complex patterns and geometries.

The Shopbot has been used as part of a ongoing project at Waag called Tracks4Crafts. This is a Horizon Europe funded project exploring the idea of Craftsmanship 2.0. The project questions how technology can be placed in the hands of the craftsman to amplify and preserve their knowledge.

For Waag Futurelab's contribution Asli Aksan, Michelle Vossen and Cecilia Raspanti have been exploring the traditions of Painting on Textiles in the Netherlands. They have made significant innovations in hacking the labs machinery (Shopbot and Axidraw) towards creating different human and machine interactions. In this video, you can see a snapshot of the amazing things they have been working on, particularly the integration of haptic devices:

Last year the 2023-2024 Fabricademy cohort hacked the Shopbot during Open Source Hardware week for the first time. They experimented with interventions such as making servomotor and brush attachments, custom brush designs and developing a Shopbot code. You can see their project work here

Building upon the knowledge and momentum of our local instructors and fabricademy predecessors we jumped into brainstorming how we could contribute to the redesign of the Shopbot as a machine for painting on textiles. We began brainstorming...

♒︎BRAINSTORMING♒︎

moodboard

We decided pretty quickly that our main interest was creating a haptic control system. We were excited about the idea of creating sensors that could facilitate embodied and playful interaction with the machine. We imagined a system through which we could draw with the CNC in a similar way you could with the hand, sensitively and with a variety of movement and pressure.

We wanted to create a modular system where by different inputs (sensors) could be attached to the machine to create a variety of outputs e.g movement and shape of lines.

We concluded that we would need to make 2 machine interventions to achieve this:

  1. A Wireless Haptic Control System where haptic sensors would control different brush movements via servomotor and ESP NOW wireless communication.

  2. Adding a Dye Reservoir and Pump System to bring dye to the brush when triggered by a switch. This would allow a more streamline workflow where dye wouldn't have to be put on the brush manually.

We started by making a list of different haptic inputs and the outputs we would like them to control:

SENSOR INPUT OUTPUT
Sound Sensor Sound (Volume) * Controls Linear or Sweep Movement of Servo Motor.
Touch Slider Touch * Part of Slider touched controls angle of Sweep Servo Motor.
Stretch Sensor Stretch of Conductive Textile (Variable Resistance) * Controls linear movement of servo motor.
Proximity Sensor LDR Readings * Controls the Sweep or Linear movement of Servo Motor.
Potentiometer Varied Resistance * Controls the Linear movement of the servo motor.

We drew out our systems and worked out the electronic set ups that would be needed for our 2 interventions.

We planned to have two electronic set ups which would wirelessly communicate:

  1. The Sender setup: to which we could attach our different haptic sensors modularly. We designed this as a modular box.

  2. The Receiver set up: that would be attached to the water pump system and servo motors then mounted on the Shopbot's central support beam.

moodboard moodboard

⌤Task Management and Division of Labour⌤

Now that we had a plan we quickly developed a Gant chart style schedule of our time outlining what we wanted to achieve per iteration of our machine hack. We identified key tasks and divided them between the days we had.

We divided the tasks we identified based on our skills and interests:

  1. HAPTIC SENSOR CREATION: Issy and Carolina
  2. BRUSH DESIGN AND TESTING: Issy and Carolina
  3. DYE RESERVOIR SYSTEM MACHINE ATTACHMENT: Asli
  4. AIR VALVE CODE: Michelle
  5. WIRELESS, HAPTIC RECIEVER AND SENDER CODE AND ELECTRONICS: Michelle
  6. DESIGN SHOPBOT CODE: Asli
  7. MACHINE HEAD ATTACHMENT MODIFICATION AND MOUNTING PLATE DESIGN: Issy and Carolina
  8. MODULAR BOX DESIGN = Michelle
  9. PROJECT MANAGEMENT: Asli and Michelle

We also agreed to keep track of materials we used by creating a Bill of Materials for the unique and purchased parts required for our Machine hack. This would ensure that our documentation was thorough and easily repeatable. Find this below:

With all this clear- it was time to begin Hacking!

⏏︎INTERVENTION #1: WIRELESS HAPTIC CONTROL SYSTEM⏏︎

✿INPUTS✿

Myself and Carolina began by getting to work making the haptic devices that we would use to control movement of the brushes.

⚱︎STRETCH SENSORS⚱︎

For our Stretch Sensor we used what we had learnt in E-textiles and create a conductive knit sample made with the Knitting Machine. Carolina took this on as she has experience with the knitting machine and wanted to try using the punchcards to create an aesthetic design. She fed 2 colours of yarn and a conductive thread into the machine to make the sample.

The stretching and squeezeing of the conductive knit will change its resistance value. We can use these readings as input to our system which determine the up and down motion of a linear servo motor actuator attached to a brush.

moodboard

With our first Stretch sensor we used yarn that was much too thick. This meant that the sample didn't have good stretch and gave us a very narrow range of values. It would not work despite being ✰beautiful✰. Carolina made another using thinner yarn. This one was better and we managed to get movement when connected with the linear servo motor attachment. However, the range was quite unstable and small.

✠TOUCH SLIDER✠

We also wanted to make a touch slider using the felting of conductive fibres with wool we learnt in E textiles. I took the lead on this sensor.

moodboard

  • I carded lots of coloured wool and also some seperate samples of conductive fibres and wool.

  • I then used a felting kneedle to felt the wool into a striped pattern, introducing conductive fibres in certain sections.

  • I then created 7 touch pads with conductive fabric which Carolina kindly machined on to a piece of denim for me.

  • Then I soldered 7 jumper wires to the 7 pad which we would later bring together with ribbon wire.

  • The conductive fibres in the felted stripes line up with the conductive pads so when the felt was touched the touch pin received input.

  • Michelle made her code so that depending on which of the 7 touch pads were touched a different servo motor angle would be triggered. If two pads were touched at the same time, an angle between 2 angle values would be generated.

This is the result! We had some problems with the serial monitor being overwhelmed and freezing. This is not something we could necessarily fix easily for the first spiral but we were happy to see a shakey version of our intended output. Similarly, the connections were quite unstable on some touch pads and didn't always trigger motion:

⚜︎AUDIO SENSOR⚜︎

We also wanted to create a simple audio sensor. Using the Analog Read function to make the volume of sound input into the audio sensor control the length of the sweep motion triggered from the servo motor.

We remapped the threshold value to trigger servo output in line with the readings we were getting in the serial monitor so that their was a good resting value and that you would have to make a loud sound to trigger movement from the motor. However, we found that it was most responsive when the audio sensor was blown on or if you made very loud, abrupt sounds.

Carolina also made this adorable felted mouse to cover the sound sensor so that you would have a cute face to sing and scream into:

moodboard

⌿LDR PROXIMITY SENSOR⍀

We were in desperate need of some more stable sensors so we were able to make a LDR proximity sensor very quickly.

We simply embedded a LDR in a Soakball Sponge (used for water fights) as we thought this would add some interest to the interaction.

Then we added a ribbon wire connection to both ends so it could be easily connected into our modular electronic setup which was ready with a voltage divider, power and ground.

moodboard

⍣POTENTIOMETER⍣

We also had a potentiometer so were able to add a makeshift lever and mount for it. We connected ribbon wire to the Ground and Signal pin so it could also be easily connected into our modular system.

A potentiometer is a three-terminal resistor with a rotating contact that acts as an adjustable voltage divider. When two terminals are used it acts as a variable resistor. By moving our lever we can change the resistance value being inputted into our system.

⌔HAPTIC SENDER CODE AND ELECTRONIC SET UP⌔

Michelle worked on our wireless SENDING electronics set up. This was created to allow us to modularly connect our many sensors.We used the XiaoESP32s3 as we needed 7 Touch pins and Analog Pins for all our sensors. The Voltage divider with a 100k ohm resistor allows us to introduce our LDR sensor and stretch sensors modularly.

moodboard

⍼MODULAR SENDER ELECTRONICS BOX⍼

We knew that from our messy breadboard set up we would need to do some cable management and user interface design.

Michelle did an amazing job at designing and fabricating this modular box using MakerCase. The box simplified the user interface, labels the actions possible and maintains all possibilities for connecting sensors and changing outputs.

moodboard

moodboard

She used pin headers and connectors to allow us to create easy, labelled connection points for our different sensors:

  • A ANGLE connector- where our touch slider could be plugged in to control the angle of the sweep servo motor.
  • A PRESSURE connector- where we could connect our Stretch sensor, Audio snsor, LDR and Potentiometer to control the up and down movements of the servo motor (pressure of the brush on the paper).
  • A REVOLVE connector- where we could use our sensors to control the sweep or revolution motion of the servo motor.
  • A PUMP connector, where we could connect our digital switch to turn on and off the air pump and bring ink into our system. (MORE ON THIS LATER)

She incorperated a tidy hole for our power cable to enter the box and the rest of the electronics are neatly hidden away.

☣︎WIRELESS SENDER CODE☣︎

Here is the wireless code Michelle made so that the XIAOESP32S3 in our Sender set up could use ESP NOW to wirelessly communicate with the XiaoESP32C3 in our Receiver Set up. It outlines the Analog Read and Touch Read functions we need for our sensors.

#include <esp_now.h>
#include <WiFi.h>


int touchAngle;              // variable to store servo angle in for the touch input to revolution angle
int squeezeSensorPin1 = A9;  // Squeeze sensor pin > up/down
int soundSensorPin2 = A10;   // Sound sensor pin > sweep
int buttonPin = D6;
#define NUM_TOUCH_PINS 7

int touchPins[NUM_TOUCH_PINS] = { T1, T2, T3, T4, T5, T6, T7 };
int touchThresholds[NUM_TOUCH_PINS] = { 90000, 177000, 197500, 136500, 142000, 191500, 141000 };
int mappedValues[13];  // Precompute the 13 values between 0 and 180

int sensorData1 = 0;
int sensorData2 = 0;

// Keeps track of the last pins touched
// so we know when buttons are 'released'
uint16_t lasttouched = 0;
uint16_t currtouched = 0;

// REPLACE WITH YOUR RECEIVER MAC Address: 64:e8:33:00:90:1c
uint8_t broadcastAddress[] = { 0x64, 0xe8, 0x33, 0x00, 0x90, 0x1c };

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
int id;  // must be unique for each sender board
int revolution;
int pressure;
int sweep;
int ink;
} struct_message;

// Create a struct_message called myData
struct_message myData;

esp_now_peer_info_t peerInfo;

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
Serial.print("\r\nLast Packet Send Status:\t");
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

void setup() {
// Init Serial Monitor
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);

// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
}

// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Transmitted packet
esp_now_register_send_cb(OnDataSent);

// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;

// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
}
}

void loop() {
touchAngle = getTouchAngle();  // Call the function to update touchAngle
if (touchAngle != -1) {
    Serial.println(touchAngle);  // Print the touchAngle to Serial Monitor
}



// sensorData1 = analogRead(squeezeSensorPin1);
// sensorData2 = analogRead(soundSensorPin2);

// Set values to send
myData.id = 1;           // board number in case there will be more boards sending later
myData.revolution = touchAngle;   // 0-180
myData.pressure = sensorData1;  // 0-4095
myData.sweep = sensorData2;  // 0-4095
myData.ink = digitalRead(buttonPin);  // 0-4095

Serial.println(touchAngle);
Serial.println(sensorData1);
Serial.println(sensorData2);
Serial.println(digitalRead(buttonPin));

// Send message via ESP-NOW
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *)&myData, sizeof(myData));

if (result == ESP_OK) {
    Serial.println("Sent with success");
} else {
    Serial.println("Error sending the data");
}
delay(100);
}


// determine if touch pins are touched and map to servo motor angle 0-180

int getTouchAngle() {
int activePin = -1;
int nextPin = -1;

// Check which pin(s) are touched
for (int i = 0; i < NUM_TOUCH_PINS; i++) {
    int touchValue = touchRead(touchPins[i]);
    if (touchValue > touchThresholds[i]) {
    if (activePin == -1) {
        activePin = i;
    } else {
        nextPin = i;
        break;  // We found two adjacent touches
    }
    }
}

if (activePin != -1) {
    if (nextPin != -1 && nextPin == activePin + 1) {
    // Calculate interpolated value between activePin and nextPin
    int interpolatedValue = map(activePin, 0, NUM_TOUCH_PINS - 1, 0, 180);
    int nextInterpolatedValue = map(nextPin, 0, NUM_TOUCH_PINS - 1, 0, 180);
    return (interpolatedValue + nextInterpolatedValue) / 2;
    } else {
    // Return mapped value for single touch
    return map(activePin, 0, NUM_TOUCH_PINS - 1, 0, 180);
    }
}

return -1;  // No touch detected
}

⚘OUTPUTS⚘

We were interested in affecting the output of our Shopbot drawing machine in 3 ways:

  1. with the Servo motor movement
  2. with the brushes
  3. with the Shopbot Code

⚙︎SERVO MOTORS ATTACHMENTS⚙︎

We had access to 2 servo motor attachments made by previous Fabricademy participants and the Tracks4Crafts project.

One of the 3D printed attachments adapted the movement of a fixed range Servo Motor into a Linear movement. The other was engineered to change the servo movement into either a sweeping motion or revolution. We only used the Sweep motion for this project but will explore the revolution in future spirals:

moodboard

The modularity of our electronics set up and code would allow us to change the servo motor attachment and use our sensors to control different kinds of movements.

❦SERVO MOTOR ATTACHMENT MOUNTING PLATE❦

One of the constraints of using the Shopbot, which is an exisiting machine used by everyone in the Fablab, is that we were not allowed to attach anything to the milling bit (Z axis) on the machine. This gave us an interesting challenge to overcome when working out how to attach our servo motor attachments to the machine.

We decided to remove the vaccum attachment and skirt from the Shopbot leaving a metal component that moved up and down with a butterfly nut. This component had two drill holes in it.

moodboard

Myself and Carolina got to work designing some mounting plates that would allow us to securly attatch our servo motor attachments via these holes.

This was our basic design. We created two sets of holes based on the measurements we took from the machine. One set of holes was for the mounting plate to be bolted to the machine and the other for the servo motor attachment to be bolted to the plate. Our linear servo motor attachment didn't have any screw holes so we planned to just hot glue gun it to the plate, hence the 2nd design only has one pair of holes.

We then lasercut these from 4mm plywood sheet. You can download the file for this here 4

moodboard

It took some trial and error to get the hole distances and diameter just right so that the mounting plate and servo motor attachmemts would sit flush but everntually we were able to bolt it all together using Hex brass spacers, screw, nuts and washers. I am really happy with the results of this hack:

moodboard

✓WIRELESS RECEIVER ELECTRONIC SET UP AND CODE✓

To connect to these motor movements with the haptic devices input we needed to create a wireless receiver electronic set up and code.

Michelle created a second set up using the XiaoESP3C3 and a relay. We were able to connect different servo pins depending on the servo motor attachment we wanted to use as they were all defined in the code. The relay, which is a electrically operated switch, opens and closes the circuits when it recieves signals from our Sender set up.

moodboard

Here is a video of the Linear Servo Motor working with the Potentiometer and the Sweep Servo motor working with the LDR Sensor. They are connected up and in action wirelessly communicating via ESP NOW through the SENDER/RECEIVER code and electronics set up:

Here is the receiver code Michelle wrote below:

#include <esp_now.h>
#include <WiFi.h>
#include <ESP32Servo.h>

// Up and down servo control
const int servoPin = 2;  // Define the pin connected to the servo

// Sweeping servo control
const int servoPin2 = 3;  // Define the pin connected to the servo

// Revolving servo control
const int servoPin3 = 4;  // Define the pin connected to the servo

const int waterpumpPin = 5;  // Define the pin connected to the water pump

Servo pressureServo;    // Create a servo object
Servo sweepServo;       // Create a servo object
Servo revolutionServo;  // Create a servo object
int angle;              // Variable to store the servo angle

int sensorData1;
int sensorData2;
int touchAngle;
int sweep;
int ink;

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
int id;  // must be unique for each sender board
int revolution;
int pressure;
int sweep;
int ink;
} struct_message;

// Create a struct_message called myData
struct_message myData;
struct_message boardsStruct[3];

// callback function that will be executed when data is received
void OnDataRecv(const esp_now_recv_info_t *recvInfo, const uint8_t *incomingData, int len) {
memcpy(&myData, incomingData, sizeof(myData));
// Serial.println(myData.revolution);


// Update the structures with the new incoming data
if (myData.id >= 1 && myData.id <= 3) {
    boardsStruct[myData.id - 1] = myData;

    // Serial.printf("revolution value: %s \n", boardsStruct[myData.id - 1].revolution);
    // Serial.printf("pressure value: %d \n", boardsStruct[myData.id - 1].pressure);
    // Serial.printf("sweep value: %d \n", boardsStruct[myData.id - 1].sweep);
    // Serial.println();
}
touchAngle = myData.revolution;
// Serial.println(myData.revolution);
sensorData1 = myData.pressure;
// Serial.println(myData.pressure);
sensorData2 = myData.sweep;
// Serial.println(myData.sweep);
ink = myData.ink;

if (myData.id == 1) {
    board1action();
} else if (myData.id == 2) {
    board2action();
}
}

void setup() {
// Allow allocation of all timers
ESP32PWM::allocateTimer(0);
ESP32PWM::allocateTimer(1);
ESP32PWM::allocateTimer(2);
ESP32PWM::allocateTimer(3);
pressureServo.setPeriodHertz(50);    // standard 50 hz servo
sweepServo.setPeriodHertz(50);       // standard 50 hz servo
revolutionServo.setPeriodHertz(50);  // standard 50 hz servo
pinMode(servoPin, OUTPUT);           // Set servo pin as output
pinMode(servoPin2, OUTPUT);          // Set servo pin as output
pinMode(servoPin3, OUTPUT);          // Set servo pin as output
pinMode(waterpumpPin, OUTPUT);       // Set servo pin as output

pressureServo.attach(servoPin);     // Attach the servo to its pin
sweepServo.attach(servoPin2);       // Attach the servo to its pin
revolutionServo.attach(servoPin3);  // Attach the servo to its pin
Serial.begin(115200);

// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);

// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
}

// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info
esp_now_register_recv_cb(esp_now_recv_cb_t(OnDataRecv));
}

void loop() {
board1action();
// Serial.println("test");
// // Set the angle of the servo
// Serial.println(" set to 10 ");
// pressureServo.write(10);  // Set the servo angle
// delay(2000);
// Serial.println(" set to 100 ");
// pressureServo.write(100);  // Set the servo angle
// delay(2000);

// Move the servo from 0 to 180 degrees
// for (int pos = 0; pos <= 180; pos += 1) {
//   pressureServo.write(pos);  // Move the servo to 'pos'
//   delay(15);           // Wait for 15ms for smooth movement (adjust if necessary)
// }

// // Move the servo from 180 back to 0 degrees
// for (int pos = 180; pos >= 0; pos -= 1) {
//   pressureServo.write(pos);  // Move the servo to 'pos'
//   delay(15);           // Wait for 15ms for smooth movement (adjust if necessary)
// }
}

void board1action() {
// Squeeze to pressure
if (sensorData1 > 1000) {
    int angle = map(sensorData1, 1000, 4095, 0, 180);  // 90-180 should be clockwise
    pressureServo.write(angle);                        // Set the servo angle
}
if (sensorData1 <= 1000) {
    pressureServo.write(0);  // Set the servo angle, this should stop it
}
Serial.print("Stretch to pressure: ");
Serial.println(sensorData1);
Serial.print("Sound to sweep: ");
Serial.println(sensorData2);
Serial.println(" ");
// Sound to sweep
// if (sensorData2 > 200) {
//   // Calculate sweep offset and speed
//   // int offset = map(sensorData2, 1000, 4095, 0, 90);    // Sweep offset from 0 to ±90
//   int sweepSpeed = map(sensorData2, 200, 4095, 100, 20);  // Faster sweep with higher sensorData2
//   int offset = 30;
//   // Sweep to 90 + offset
//   sweepServo.write(90 + offset);
//   delay(sweepSpeed);

//   // Sweep to 90 - offset
//   sweepServo.write(90 - offset);
//   delay(sweepSpeed);
// } else {
//   sweepServo.write(90);  // Return to center if sensorData2 is low
// }
sweep = map(sensorData2, 0, 4095, 0, 180);  // Faster sweep with higher sensorData2

Serial.println(sweep);
sweepServo.write(sweep);  // Return to center if sensorData2 is low

// Touch to revolution
revolutionServo.write(touchAngle);  // Set the servo angle

if (ink == 0) {
    digitalWrite(waterpumpPin, HIGH);
} else {
    digitalWrite(waterpumpPin, LOW);
}
delay(50);
}

// Not yet in use
void board2action() {
}

❂BRUSH DESIGN❂

The second output we designed was the brushes. Varying the brushes allowed us to explore the lines and textures the machine could paint with and which materials held the dye best.

First we had to design a brush holder that would fit into the collet on our servo motor attachments. It also had to have a specific diameter so that the plastic tubing that would carry the dye from the reservoir to the brush head could fit inside of it. Therefore, we designed the holders to have a 8mm inner diameter. We also added ribbing at the end of the holder to secure the brush heads but ended up using some glue too. We created various lengths so we could test which was best.

moodboard

Once we had the design just right, we 3D printed the brush holders in transparent PLA so that we could see what was going on inside. You can download the .stl file from the sketchfab link above.

With our holders ready, we had fun designing some brush heads. We tested out the lines with Ecoline, the ink we intended to use with out Shopbot. We used different pressures, strokes and motions and selected the brushes we wanted to use in the machine tests.

moodboard

It would be interesting to see how the shape and density of the brush head material would effect the way the ink reaches the brush, was absorbed by the material and how it spreads the dye across the paper/fabric.

⚗︎SHOPBOT CODE⚗︎

Asli took the lead for creating the Shopbot code.

Shopbot code is the programming language for the Shopbot. We use this language to tell the machine what to do or how to do something.**

Asli gave us a peak behind the hood and showed us an example code explaining that their basic structure is as follows:

  • Start Code: This runs before the actual print commences. This instructss the prep and calibration of the machine.
  • Body: Is the co-ordinates for the positions and pathways the machine will take.
  • End Code: * is the actions that need to be executed after the job has been completed, bring the machine to a shut down.

Asli worked from a Tartan style Grasshopper Definition Carolina created for computational coutre week. She created a file that would have intersecting vertical and horizontal lines that would create a pattern reminiscent of plaid. We thought it would be nice to have a very structured pattern for the machine to follow given the chaos and movement the haotic devices would introduce.

moodboard moodboard

You can download the grasshopper definition here 1 and you can find the Shopbot code below:

SHOPBOT CODE:

'----------------------------------------------------------------
'SHOPBOT ROUTER FILE IN MM
'GENERATED BY PARTWorks
'Minimum extent in X = 0.000 Minimum extent in Y = 0.000 Minimum extent in Z = -0.500
'Maximum extent in X = 830.000 Maximum extent in Y = 1550.000 Maximum extent in Z = 0.000
'Length of material in X = 830.000
'Length of material in Y = 1550.000
'Depth of material in Z = 0.500
'Home Position Information = Bottom Left Corner, Material Surface 
'Home X = 0.000000 Home Y = 0.000000 Home Z = 20.000000
'Rapid clearance gap or Safe Z = 6.000
'UNITS:MM
'
IF %(25)=0 THEN GOTO UNIT_ERROR 'check to see software is set to standard
SA                              'Set program to absolute coordinate mode
CN, 90
'New Path
'Toolpath Name = Profile 1
'Tool Name   = Fabribrush

&PWSafeZ = 6.000
&PWZorigin = Material Surface
&PWMaterial = 0.500
'&ToolName = "Fabribrush"
&Tool =1                    'Jog Z axis to safe height
C9
TR,18000
C6                   'Return tool to home in x and y
PAUSE 2
'
MS,60,50
JZ,20.000000
J2,0.000000,0.000000
M3,0,0,15
M3,42.5,50,15
M3,42.5,50,-0.01
M3,342.5,50,-0.01
M3,342.5,50,15
M3,42.5,65,15
M3,42.5,65,-0.01
M3,342.5,65,-0.01
M3,342.5,65,15
M3,42.5,80,15
M3,42.5,80,-0.01
M3,342.5,80,-0.01
M3,342.5,80,15
M3,42.5,95,15
M3,42.5,95,-0.01
M3,342.5,95,-0.01
M3,342.5,95,15
M3,42.5,125,15
M3,42.5,125,-0.01
M3,342.5,125,-0.01
M3,342.5,125,15
M3,42.5,140,15
M3,42.5,140,-0.01
M3,342.5,140,-0.01
M3,342.5,140,15
M3,42.5,155,15
M3,42.5,155,-0.01
M3,342.5,155,-0.01
M3,342.5,155,15
M3,42.5,185,15
M3,42.5,185,-0.01
M3,342.5,185,-0.01
M3,342.5,185,15
M3,42.5,200,15
M3,42.5,200,-0.01
M3,342.5,200,-0.01
M3,342.5,200,15
M3,42.5,230,15
M3,42.5,230,-0.01
M3,342.5,230,-0.01
M3,342.5,230,15
M3,42.5,245,15
M3,42.5,245,-0.01
M3,342.5,245,-0.01
M3,342.5,245,15
M3,42.5,260,15
M3,42.5,260,-0.01
M3,342.5,260,-0.01
M3,342.5,260,15
M3,50,42.5,15
M3,50,42.5,-0.01
M3,50,267.5,-0.01
M3,50,267.5,15
M3,65,42.5,15
M3,65,42.5,-0.01
M3,65,267.5,-0.01
M3,65,267.5,15
M3,80,42.5,15
M3,80,42.5,-0.01
M3,80,267.5,-0.01
M3,80,267.5,15
M3,95,42.5,15
M3,95,42.5,-0.01
M3,95,267.5,-0.01
M3,95,267.5,15
M3,125,42.5,15
M3,125,42.5,-0.01
M3,125,267.5,-0.01
M3,125,267.5,15
M3,140,42.5,15
M3,140,42.5,-0.01
M3,140,267.5,-0.01
M3,140,267.5,15
M3,155,42.5,15
M3,155,42.5,-0.01
M3,155,267.5,-0.01
M3,155,267.5,15
M3,185,42.5,15
M3,185,42.5,-0.01
M3,185,267.5,-0.01
M3,185,267.5,15
M3,200,42.5,15
M3,200,42.5,-0.01
M3,200,267.5,-0.01
M3,200,267.5,15
M3,230,42.5,15
M3,230,42.5,-0.01
M3,230,267.5,-0.01
M3,230,267.5,15
M3,245,42.5,15
M3,245,42.5,-0.01
M3,245,267.5,-0.01
M3,245,267.5,15
M3,260,42.5,15
M3,260,42.5,-0.01
M3,260,267.5,-0.01
M3,260,267.5,15
M3,275,42.5,15
M3,275,42.5,-0.01
M3,275,267.5,-0.01
M3,275,267.5,15
M3,305,42.5,15
M3,305,42.5,-0.01
M3,305,267.5,-0.01
M3,305,267.5,15
M3,320,42.5,15
M3,320,42.5,-0.01
M3,320,267.5,-0.01
M3,320,267.5,15
M3,335,42.5,15
M3,335,42.5,-0.01
M3,335,267.5,-0.01
M3,335,267.5,15
JZ,20.000000
J2,0.000000,0.000000
'
'Turning router OFF
C7
END
'
'
UNIT_ERROR:
CN, 91                            'Run file explaining unit error
END

INTERVENTION 2: DYE RESERVOIR ATTACHMENT AND WATER PUMP SYSTEM

WATER PUMP SYSTEM

Our second machine intervention was working on a Dye Reservoir and Water pump system that would use a 12 V Water pump to bring dye from a container to the brush head. This is a development on last years machine hack where the paint was applied manually to the brush head. This way the entire system could be controlled wirelessly from our sensor and switch station.

Asli and Michelle tool the lead on this part of our machine hack.

Asli created a mouting plate for the dye reservoir (a squeeze bottle) and air pump so it could be attached to the Shopbots central support beam. She designed the file on Rhino using the measurements of the parts and the machine. It also leaves space for the Receiver Electronics set up to be secured to the plate also. She laser cut her file2 from Multiplex wood. This was then put together using press fit and secured to the machine using velcro.

moodboard

The results were really well considered and held everything securely as it was very important that nothing could move or spill on the electronic set up or the Shopbot's sacrificial layer.

moodboard

Asli even 3D printed corks from TPU for the squeeze bottle reservoir. The larger cork was to close the refilling hole when it wasn't in use and the second plug was for an air release hole that was added to stop pressure building up inside the squeeze bottle. You can download the g code file for these here 3

⍨DIGITAL SWITCH⍨

Michelle focused on creating the electronics for the water pump using a 12V power supply and a Relay to convert input from a digital switch into the pumping (and not pumping) of the dye through the system.

We needed to create a digital switch to turn on and off our water pump system which would bring ink via our repositories into plastic tubing and then into our brush attachments when the switch was connected.

Myself and Carolina got to work on the button. We sandwiched a thick piece of foam with holes cut into it between 2 pieces of conductive fabric. All these layers were enclosed in a neoprene button and sewn together with tabs from each piece of conductive fabric sticking out for us to connect our alligator clips.

We had some trouble with the readings and ensuring there were no resting connections but eventually we got it to work and integrate into our system:

moodboard

MACHINE PREPARATION

With all the components of our machine hack made and tested it was time to run our first test with Iteration #1 of our Shopbot Hack (lovingly named FEFE after fatal error!).

First we had to prepare the machine. As the Shopbot is a working machine in our Fab Lab it was important that all of our interventions were reversible and didn't leave any mess or damage on the machine.

moodboard

To protect the sacrificial layer on the machine bed we carefully covered everything with plastic bags, making sure to tape it down well.

We then placed a peice of Acrylic sheet as a work surface that would make extra sure that no dye seeped through the plastic and caused damage.

Finally, we prepared our painting surface by stretching our paper taunt with tape, ensuring we had a couple layers of paper below to absorb any excess dye.

We ensured our brush attachment was at the correct height to touch the paper when the Z axis was calibrated and we filled our dye repositories with a solution of Ecoline and Water, replacing the corks after.

⌯ITERATION #1⌯

For our first iteration we did not test our haptic devices. We simply wanted to see how the dye reservoir and water pump system would function whilst the machine was in operation and to see if the Shopbot code moved smoothly and created a clear pattern with the brush.

moodboard

Video made by Carolina V=Berião

REFLECTIONS

As you can see there were some adjustments that needed to be made!

The shopbot code was perfect, the pattern came out very nice and all our hardware held up very securly.

Unfortunately we had the following problems:

  1. The dye was much too watery and the colour was not very visible. This was not well absorbed by the paper we used for this test.
  2. The water pump system was very leaky and the excess dye was interfering with our drawing and making everything wet!
  3. We were worried about the security of our plastic tubing and squeezy bottle after a small explosion during testing.

In responses to these issues we had a troubleshooting session and devised these solutions.

  1. We mixed a more concentrated mixture of Ecoline and swapped the paper for Cotton Fabric, again taped taunt over a stack of paper.

  2. We discovered through trial and error testing (see below) that the water pump system would cease leaking when the dye reservoir was lower in height than the discharge point (the brush). Infact we witnessed the dye being sucked back in slightly and holding tight.

Rather than create a completely new mounting plate, Asli laser cut an additional piece of Multiplex wood to attach to the bottom of the exisiting plate, giving us enough room to attach the Dye Reservoir significantly lower than the water pump and the discharge point from the brush head. We saw clearly that this efficiently resolved our leaky system!

  1. We used zip ties to secure all major connections, especially where the tubing connects to the pump and reservoir.

❥ITERATION #2❥

For our second Iteration we did a quick test run with out the haptic sensors to ensure that all our adjustments were working as they should.

moodboard

Despite a pretty big splodge from when we got too excited and hit the pump button a bit hard, the system worked perfectly and we were sooooo happy and proud of ourselves!

We decided to be brave girls and do the big bad test with the ✩Haptic Devices✩. We connected up the LDR and the Sweep Servo Motor Attachment with a Wire Sponge brush head that would be able to make the most of the sweeping movements.

moodboard

The results were amazing and I am obsessed with this chaotic little machine we created! There was so much joy and playfulness created whilst we interacted with it and in my opinion the resulting textile is BEAUTIFUL.

I can't wait to do more tests with FEFE and see what else she is capable of.

For more fun from this week, check out Carolina's Site couldn't have asked for a better team!

Fabrication files