Remotely Hugging Documentation



Plan in the last month (23. 05. 2021 updated)

To Do Realization
Week 17: 5/16-22 First Prototype:
  • Valves PCB (power)
  • Communication
    1. 3D printers for tubings and valves connection
    2. Buy matched tubings and valves x7
Control bump and valves with step response sensor button
Week 18: 5/23-29 Second Prototype:
  • Self-evaluation
  • Output: Finish the sewing of T-shirt and vacuum bags
  • Input: Connect the tubings, valves, and pumps (add switch) to the hugging suit
  • Input: Test the pressure sensors or step response sensors with a model (PCBs might need)
  • Communication: Wireless (Wifi or Bluetooth) communications from sensors to valves
Realize the functions of hugging suit
Week 19: 5/30-6/5 Third Prototype:
  1. Fill up the misses in week 18<
  2. Improve it
  3. Make the third prototype
Fix and improve the second prototype
Week 20: 6/6-12
  • Buffer week
  • One minute Video
  • Summary slide
  • 6/9: Fab Academy presentation
  • 6/10: Digital Fabrication presentation
Presentation preparation for Fab Academy and Digital Fabrication
Week 21: 6/13-18 Buffer week -

Week 17: First Prototype

The details of how I realized the first prototype are documented in Week 15: Networking and Communications.




Hidden Pockets in T-shirt and jacket

Layout of the T-shirt and mannequin

T-Shirt with vacuum bags
Mannequin with step response sensors

Following the patterns I designed, I laser cut several plywood patterns to simplify later works on hidden pockets and welding the bags.

Tubing Plan


The first idea was to install an intake and an outlet two-way valve for each bag to control incoming and outgoing air to inflate and deflate the bags. But later this was changed to just one three-way valve when I got them from Adafruit.

Feeling Test of vacuum bags in a pocket

I can feel the inflation of the bag, but the pockets should be closer to the body and the clothing should be tighter. Later, I will improve it with a fitted jacket and belt to ensure the feeling of hugs.


Sewing Machines

sketch Coverstitch Sewing Machine, Global
For flexible edges or components on clothes, general purpose for use with light to medium-weight fabrics.
sketch Overlock Machine, YAMATO
Finish the edges of fabrics.
sketch Lockstitch Sewing Machine, Brother
The lockstitch machine sews only straight stitches.

Fix the fabrics with Needle


Hero Shot of Hidden Pockets

sketch T-shirt Front Side
sketch T-shirt Back Side
sketch Jacket Inside
Some details of pockets
sketch Short bands to guide the tubings
sketch Velcros to fix the pocket well
sketch Straight stitches to enhance the banding effect of arm bags

Vacuum Bags and 3D printed connectors

In Week 17: Wildcard week, I learned how to use an Ultrasonic Welding machine to weld(sew) the vacuum bags. So I made them according to the laser cut patterns which would fit my pockets perfectly. Further details can be found in Week17.

sketch Two chest bags and a belly bag for Front Side
sketch Three arm bags for Back Side

3D printed connectors for valves


I tried to model connectors with threads which fit my valves I went through several tutorials: 3D Printed Thread, Measuring Thread Pitch & Threads Per Inch, and Copy Threads from McMaster. All of these tutorials helped me to create the connectors with Fusion 360 and understand the different standards of screw better. Inch-to-NPT Male-Female Hex Thread Adapters with Through Hole was my reference for valve connectors.

sketch With different tests of threads, I found the best setting for my valves. And the shrink of filaments also needed to be considered.

3D printed connectors for vacuum bags


After I printed the connectors, they should have been put in a UV box for just 1–2 hours. But even after one day, they were still sticky, which didn’t happen in previous weeks. I googled the curing time for tough 1500 on the Formlab website. It needs to be exposed to UV light for 60 minutes and 70°C. Then I figured out that the location of the UV lightbox was close to a heater that was turned on in winter but was now switched off, so it took longer to cure. Then an idea came to mind: why not cook it? I tried steaming, baking, and boiling at 60°C. The result showed that boiling in 60°C water for 10 minutes was the best balance between hardening and the durable texture of my connectors.

sketch Right after boiling, cool them down with cold water

Laser cut the Rubber Washer

Find out the Air Leak

Inflation Test

Testing the feeling of inflation

Test the bag on the belly
Tighten the T-shirt with safe needles. The hugging feeling gets stronger
Test the arm feeling from the backside

Test with fit jacket, the feeling was stronger than a loose T-shirt
sketch Jacket with the tubing from hidden pockets.

Packaging with Bags and Belt

Pattern and layout of bags


After I laid out the pumps and valves, I measured how much fabric was needed and drew the patterns with some given tolerances for sewing and some additional space. Drawing the expanded view of the bags required some experience and skill. I was able to do it with the help from Sophia at Väre and Johanna from the sewing workshop.

Start Sewing

sketch Follow the patterns to cut the fabrics
sketch Small piece of fabric for the belt
sketch The belt matches with the bag perfectly

Hero Shots of Bags and Belt

sketch Front Side of Bag
sketch Back Side of Bag
sketch Wear it up

Mounting Station for Pumps, Valves, and PCB.

Hero Shot of Mounting Stations

sketch Pumps Side of Station
sketch Valves Side of Station
sketch Add tubings
sketch Add tubings
sketch Jacket + Vacuum Bags / Pumps + Valves + Tubings in Bags + Belt
sketch T-shirt + Sensors + Bags

Step Response Sensors in Silicone


I milled and 3D printed two molds to cast my sensors. I found that milling a wax mold was more efficient and accurate than printing a 3D-printed mold. Also, the surface of the wax mold was smoother, providing a better quality finish. The experience in Week 13: Molding and Casting, taught me that I should use talcum powder or flour before casting, which makes it easier to take off the silicone after it has cured.

sketch Add some flour

Cut the copper sheet with Vinyl Cutter
sketch First layer cast
sketch After the first layer has cured, attached the copper sheet and casted the second layer of silicone
sketch After the second layer has cured, attached the second copper sheet and casted the third layer
sketch It's done!

Testing the Step Response Sensor

The video clearly shows that even when my hand just hovered above the sensor, the sensor could still detect it. This oversensitivity led to the movement of hugs couldn’t be detected correctly. The issue and the solutions are explained more in the Challenges Section.

Hero Shots of Step Response Sensor


PCBs and ESP communication

Power Management Calculation


The power supply (adapter) can provide a total of 24.96 watts, which is only just sufficient for the power requirements of 6 pumps, 6 valves, and 2 attenuations. It was lucky that this did not lead to any problems in the final assembly. But if I had had more time to improve the final project, I would have preferred to build a safer, steadier, and higher power supplier.



In order for the mainboard and secondary boards to communicate wirelessly, I chose an ESP-Wroom-02D module as my microcontroller. I followed the instructions from Getting Started with ESP-WROOM-02.


Kickback Diodes, Pull-Down Resistors and Block the VCC of FTDI


Secondary Board


The difficulty of the secondary board was that ESP-WROOM-02D only has one analog read Pin. The solution that came to mind was to use an ESP-32 CAM that has more analog read pins; please see the pinout explanation in AI-Thinker Pinout Guide. But later I found a note said that: “ADC2 pins cannot be used when Wi-Fi is used. So, if you’re using Wi-Fi and you’re having trouble getting the data from an ADC2 GPIO, you may consider using an ADC1 GPIO instead, that should solve your problem.” But in the ESP-32 Cam breakout module, all the ADC1 GPIO were occupied by the camera.

Just when I was frustrated, another idea came to mind. I could add another microcontroller (Attiny1614) that only serves for analog read and later send the data through a Serial Port to ESP-WROOM-02D which communicates with the mainboard via Wifi. And it worked! But to ensure the TX and RX communication wouldn’t interfere with each other, Matti advised me to add a switch for each channel. So whenever I program or debug with FTDI I can switch off the TX and RX in between two boards and switch it on when I want them to communicate.


Hero Shots of PCBs

sketch Main Board

If you watch the video carefully, you will notice that the vacuum bag was inflated and deflated gradually.
sketch Secondary Board, Attiny1614 + ESP-WROOM-02D
sketch Power with AA Battery and its holders

Networking Wifi AccessPoint and HTTP Client


In the concept, I used ESP on the mainboard as a Wifi AccessPoint and ESP on the secondary as an HTTP Client that can send an HTTP request to change the status of the mainboard. On the secondary board, Attiny1614 would collect the analog data from step response sensors and send the command to ESP on secondary to determine which valves and pumps should be turned on or off.

Important Code on Attiny1614 of Secondary

The code was modified from Week12: Input Devices and Button Press was described in Week15: Networking and Communications. I will skip the repeated code and focus on the code created for the final project.

#define Sensor1_RX 10 //  PA3 of the ATtiny1614
#define Sensor2_RX 9  //  PA2 of the ATtiny1614
#define Sensor3_RX 8  //  PA1 of the ATtiny1614

long timeBegin = 0;
long timeDelta = 100;
long Sensor1_Result_Begin = 0;
long Sensor1_Result_End = 0;
long Sensor2_Result_Begin = 0;
long Sensor2_Result_End = 0;
long Sensor1_Thresh = 200;
long Sensor2_Thresh = 300;

int sample = 100;
int Sensor1_Avr=0;
int Sensor2_Avr=0;

Define the pins to control the valves and pumps. Set timeBegin and timeDelta to read the analog data every 100 milliseconds. And set sample to collect 100 times of data whenever the program begins.

long normalize(int sensor_RX){
  long sum=0;
  long avr=0;
  for(long i = 0 ; i < sample ; i++)
    sum = sum + tx_rx(sensor_RX);
  avr = sum/sample;
  return avr;
void setup() {
  Sensor1_Avr = normalize(Sensor1_RX);
  Sensor2_Avr = normalize(Sensor2_RX);

The purpose of the normalize function is to calculate the average data of each sensor in the start of sensors.

void loop() {
  long Sensor1_Result = (tx_rx(Sensor1_RX)-Sensor1_Avr);
  long Sensor2_Result = (tx_rx(Sensor2_RX)-Sensor2_Avr);
  long timeCurrent = millis();
  if (timeBegin + timeDelta < timeCurrent) {
    // This here is run only after each timeDelta 
    Sensor1_Result_End = Sensor1_Result;
    if (Sensor1_Result_End - Sensor1_Result_Begin > Sensor1_Thresh) {
      sendMessage(Sensor1_Address,B0001); //on
    if (Sensor1_Result_Begin - Sensor1_Result_End > Sensor1_Thresh) {
      sendMessage(Sensor1_Address,B0000); //off

    // Reset value
    Sensor1_Result_Begin = Sensor1_Result_End;

    // This here is run only after each timeDelta 
    Sensor2_Result_End = Sensor2_Result;
    if (Sensor2_Result_End - Sensor2_Result_Begin > Sensor2_Thresh) {
      sendMessage(Sensor2_Address,B0001); //on
    if (Sensor2_Result_Begin - Sensor2_Result_End > Sensor2_Thresh) {
      sendMessage(Sensor2_Address,B0000); //off

    // Reset value
    Sensor2_Result_Begin = Sensor2_Result_End;

    // Reset timer
    timeBegin = timeCurrent;

This part of the code is detecting if the changes of the data are bigger than the sensor thresholds which were observed from the Serial Plotter of the raw data.

Important Code on ESP of Secondary (HTTP Client)

Parts of the code were modified from the DCMotor Driver described in Week15: Networking and Communications and the template of ESP8266 Basic Http Client. I will skip the repeated code and focus on the code created for final project.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>

ESP8266WiFiMulti WiFiMulti;

To use the HTTP Client function, we have to include the above libraries.

void setup() {
  WiFiMulti.addAP("ESPap", "thereisnospoon");

ESPap will become the Wifi name, and "thereisnospoon" will be the Wifi passwords.

void loop() {
  if (( == WL_CONNECTED))
    WiFiClient client;
    HTTPClient http;
    if (Serial.available() > 0)

      if (address == B0000) // sensor1
        if (command == B0001) //sensor1_ON
          Serial.print("Turn ValveFront on...\n");
          if (http.begin(client, "")) {
            int httpCode = http.GET();
            if (httpCode > 0) {
              Serial.printf("[HTTP] GET... code: %d\n", httpCode);
              if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
                String payload = http.getString();
            } else
              Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
          } else
            Serial.printf("[HTTP} Unable to connect\n");
          Serial.print("Turn Pump on...\n");
        if (command == B0000) //sensor1_OFF
          Serial.print("Turn ValveFront off...\n");

          Serial.print("Turn Pump off...\n");

      if (address == B0001) // sensor2
        if (command == B0001) //sensor2_ON

          Serial.print("Turn Pump on...\n");

        if (command == B0000) //sensor2_OFF

          Serial.print("Turn Pump off...\n");


In the loop, there are two conditions for each valve, on and off, according to the address. Whenever the valve is activated, the pumps are turned on as well. All of them will send a HTTP request: "" to the access point (mainboard).

Important Code on ESP of Main Board (Wifi Accesspoint)

Part of the code was modified from the DCMotor Driver described in Week15: Networking and Communications and the template of ESP8266 Wifi Accesspoint. I will skip the repeated code and focus on the code created for the final project.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#define pump 5 
#define valve1 14

#ifndef APSSID
#define APSSID "ESPap"
#define APPSK  "thereisnospoon"


Include the libraries that we need for the Wifi Server and define the pins for pumps and valves. Also define the passwords for this Access Point.

void handleRoot() {
  server.send(200, "text/html", "<h1>You are connected</h1>");

void handlePumpOn() {
  digitalWrite(pump, HIGH); 
  server.send(200, "text/html", "Pump is on!");
void handlePumpOff() {
  digitalWrite(pump, LOW); 
  server.send(200, "text/html", "Pump is off!");

void handleValveFrontOn() {
  digitalWrite(valve1, HIGH); 
  digitalWrite(valve2, HIGH); 
  digitalWrite(valve3, HIGH); 
  server.send(200, "text/html", "Valves Front are ON...");

void handleValveFrontOff() {
  digitalWrite(valve1, LOW); 
  digitalWrite(valve2, LOW); 
  digitalWrite(valve3, LOW); 
  server.send(200, "text/html", "Valves Front are off...");

void handleValveBackOn() {
  digitalWrite(valve4, HIGH); 
  digitalWrite(valve5, HIGH); 
  digitalWrite(valve6, HIGH); 
  server.send(200, "text/html", "Valves Back are ON...");

void handleValveBackOff() {
  digitalWrite(valve4, LOW); 
  digitalWrite(valve5, LOW); 
  digitalWrite(valve6, LOW); 
  server.send(200, "text/html", "Valves Back are off...");

Here is the function for each status of valves and pumps, we will use them for the HTTP requests.

void setup() {
  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  server.on("/", handleRoot);
  server.on("/pump/on", handlePumpOn);
  server.on("/pump/off", handlePumpOff);
  server.on("/valveFront/on", handleValveFrontOn);
  server.on("/valveFront/off", handleValveFrontOff);
  server.on("/valveBack/on", handleValveBackOn);
  server.on("/valveBack/off", handleValveBackOff);
  Serial.println("HTTP server started");

void loop() {

Instead of running the functions in the loop, we should set it up in setup. And that’s it!

Hero Shots and Final Project Test

Hugging Simulation
Back Side Pumping
Front Side Pumping


  1. This was my first time to sew something. It was really challenging for me. But after the final project, sewing pockets, bags, and belts are no more a problem for me!

  2. FLA took a long time to cure


    !!Solution: Cook it. I tried steaming, baking, and boiling at 60°C. The results showed that boiling in 60°C water for 10 minutes was the best balance between hardening and the durable texture of my connectors.

    ??Reason: I figured out that the location of the UV lightbox was close to a heater that was turned on in winter but was now switched off, so it took longer to cure.

  3. Air leak of vacuum bags

    !!Solution: Instead of epoxy glue, I used rubber washers to fill up male and female connectors.

    ??Reason: Becasue epoxy glue hardens after drying

  4. T-shirt was too loose to feel the hug

    The original idea was to use a T-shirt as the main design for all the vacuum bags; however, in the testing section, I found that the T-shirt was too loose to hug me. So I switched to a fitted jacket with a belt, which could provide me a stronger and more realistic feeling of hugs.

  5. The old valves are giant and inefficient


    The left one is the old valve from Amazon; the right one is a new valve from Adafruit

    Name Voltage Current Power Comsumption Tubes Where to buy
    Left Solenoid Valve 12V 0.52A 6.24 watts 2 Amazon
    Right Air Valve 6V 0.3A 1.8 watts 3 Adafruit

    After installing the new valves, I could optimize the usage of packaging space and reduce the power consumption and current in total. But I had to block one of the connectors on the vacuum bags to ensure they can be inflated without air leaking.


    With the leftovers from rubber washers, it could block the connectors perfectly.

  6. Multiple Step Response sensors would affect each other


    !! Solution: In the end, I only used two sensors to represent the front and back valves to minimize the noise that might happen during the hugging. The improvement that could be made in the future is to shorten the cables from sensors to PCBs, in other words, give each sensor a microcontroller. Only use the digital signals to travel around the clothes to avoid the noise and achieve communication between the boards.

    ?? Reason: Because of the characteristics of the step response, I found that not only the copper sheets but also the cables themselves are part of the sensors, which means not only when I touched but also when my hand hovered over the cable the sensor would react.

  7. Wrong direction of Diode Schottky

    ?? Reason: Because of the wrong direction of the kickback diodes, the power-on LEDs couldn’t be lighted correctly.

    !! Solution: Change the direction of it: the cathode of diodes should be connected to the positive side of the voltage source (VCC).

  8. The code couldn’t be uploaded to ESP-WROOM-02D

    sketch The uploading status was stuck at Connecting forever...
    sketch Debugging with connecting IO15 to GND
    sketch Finally, I am able to upload the program

    ?? Reason and !! Solution: I was struggling with this part for a whole week. Finally, with help from Matti, I learned that the importance of adding a pull-down resistor, which could pull down (set to ground) the IO15 while it was flashing.


    To cut a long story short, I used IO15 as one of the digital outputs to N-Mosfet to control the on and off of a valve. However, according to default, it has to be either connected to the ground or a pull-down resistor while flashing. In my case, I connected IO15 to a Mosfet. The pin is unconnected from either a defined HIGH or LOW condition, it has the potential to “float” between 0V and +5V (Vcc) allowing the pin to self–bias at any voltage level whether that represents a HIGH or a LOW condition.

    sketch Fix with pull-down resistors (12kΩ), which should be higher than 10 kΩ

    The mainboard works!
  9. The airflow volume of one of DP0125 or DP0140 was too low; therefore it took approximately 30 seconds to pump all the bags up

!! Solution: Parallelize the pumps. I found a tutorial on YouTube that introduced me how to parallelize the pumps. It works quite similarly to parallelizing the current in electronics.



The Final Project zip file 1 and Final Project zip file 2 includes:

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.