Working with soft material as a base for digital user interface comes with the challenge to make as many electronic components flexible as possible. Therefore is is very helpful to refer to one of out past experiments with textile and use conductive thread – at least for doing some experiments.
inital experiment
Kneading silicone works best for some rapid experiments without pouring and messing up the studio 🙂 – This silicone gets fixed within seconds and comes with two components. It’s even possible to addon material to existing structures. This prototype is for the finger – with two touch inputs realized with conductive thread stiched through the silicone material. This works pretty well even when stiching through longer segments of the material. The thread can be then sealed with more silicone to avoid shortcuts.
code and tools
Using the ESP32 with integrated touch pins is the best choice for this experiment. Using the serial interface to send the touch data to Processing makes it possible to even visualize the output properly. I used the TURBOFLIP’S own touch helper for this – just insert it to your project.
#include <Arduino.h> #include <touch.h> aTouch touch1(T0); aTouch touch2(T1); aTouch touch3(T2); aTouch touch4(T3); aTouch touch5(T4); aTouch touch6(T5); aTouch touch7(T6); aTouch touch8(T7); aTouch touch9(T8); void setup() { Serial.begin(9600); Serial.println("0,0"); // initally send null to init // put your setup code here, to run once: } void loop() { touch1.readAndProcessInput(); touch2.readAndProcessInput(); touch3.readAndProcessInput(); touch4.readAndProcessInput(); touch5.readAndProcessInput(); touch6.readAndProcessInput(); touch7.readAndProcessInput(); touch8.readAndProcessInput(); touch9.readAndProcessInput(); // Serial.println(touch1.smoothed_val); // if (Serial.available()>0){ Serial.print(touch1.smoothed_val); Serial.print(","); Serial.print(touch2.smoothed_val); Serial.print(","); Serial.print(touch3.smoothed_val); Serial.print(","); Serial.print(touch4.smoothed_val); Serial.print(","); Serial.print(touch5.smoothed_val); Serial.print(","); Serial.print(touch6.smoothed_val); Serial.print(","); Serial.print(touch7.smoothed_val); Serial.print(","); Serial.print(touch8.smoothed_val); Serial.print(","); Serial.println(touch9.smoothed_val); //} delay(11); // put your main code here, to run repeatedly: }
// ---------------------------------- // ------- TRXYS TOUCH HELPERS ------ // ---------------------------------- // ( put this code PRIOR to your mainloop code or you will get nice errors :) ) // simple lerp helper function float return_lerp(float _s, int _target,int _time){ _s = _s + (( float(_target) - _s)/float(_time)); return _s; } class aTouch { private: bool prev_touch_state = false; byte pin; int smooth_time = 2; int trigger_threshold = 15; long ts = 0; public: int current_val = 0; int smoothed_val = 0; int diff_val = 0; bool is_triggered = false; bool on_pressed = false; bool on_released = false; bool is_holded = false; aTouch(byte pin) { this->pin = pin; } void readAndProcessInput() { // reset interaction states on_pressed = false; on_released = false; // directly read out values TWICE = BUGFIX for debouncing current_val = touchRead(pin); delayMicroseconds(10); current_val = touchRead(pin); //calculate smoothed input values smoothed_val = return_lerp(smoothed_val,current_val,smooth_time); // calc current differential sum of button diff_val = smoothed_val - current_val; // check if there is a noticable difference input values if( diff_val > trigger_threshold){ if(prev_touch_state == false){ is_triggered = true; prev_touch_state = is_triggered; on_pressed = true; ts = millis(); // set timestamp for hold routine } }else if( diff_val < trigger_threshold*-.4){ if(prev_touch_state == true){ is_triggered = false; prev_touch_state = is_triggered; on_released = true; } } // calculate timed holding function if( ts + 2500 < millis() && is_triggered){ is_holded = true; }else{ is_holded = false; } delayMicroseconds(2); } };
import processing.serial.*; Serial myPort; int t1_val = 0; int t2_val = 0; int t3_val = 0; int t4_val = 0; int t5_val = 0; int t6_val = 0; int t7_val = 0; int t8_val = 0; int t9_val = 0; void setup () { size(300,300); // window size noSmooth(); ellipseMode(CENTER); // List all the available serial ports //println(Serial.list()); String portName = Serial.list()[0]; myPort = new Serial(this,portName, 9600); myPort.bufferUntil('\n'); } void serialEvent (Serial myPort) { try { operateSerial(myPort); } catch(RuntimeException e) { e.printStackTrace(); } } float[] all_touch_vals = {0,0,0,0,0,0,0,0,0}; void operateSerial(Serial myport) { String portData = myport.readString(); String[] stringData = split(portData, ','); int[] values = int(stringData); t1_val = int(values[0]); all_touch_vals[0]=t1_val; t2_val = int(values[1]); all_touch_vals[1]=t2_val; t3_val = int(values[2]); all_touch_vals[2]=t3_val; t4_val = int(values[3]); all_touch_vals[3]=t4_val; t5_val = int(values[4]); all_touch_vals[4]=t5_val; t6_val = int(values[5]); all_touch_vals[5]=t6_val; t7_val = int(values[6]); all_touch_vals[6]=t7_val; t8_val = int(values[7]); all_touch_vals[7]=t8_val; t9_val = int(values[8]); all_touch_vals[8] = t9_val; } void draw(){ background(22); fill(255); textSize(8); for(int i=0;i<9;i++){ fill(222); float mappedh = map(all_touch_vals[i],0.,150.,0.,300.); // map the touchpin values around the height of the stage rect(i*30,0,20,mappedh); fill(122); text("T:"+i,i*30+4,10); } }