Textile prototype using touch input and direct visual feedback.
Both LED and Touch Helper Lib is needed for this in prior.
// ---------------------------------- // -------- BASIC HELPERS LED & TOUCH -------- // ---------------------------------- // basic lerp function float return_lerp(float _s, int _target, int _time) { _s = _s + (( float(_target) - _s) / float(_time)); return _s; } // -------------- // LED Object // ------------- class aLED { private: byte pin; long ts = 0; int led_mode = 0; //0 manual / 1:sinpulse / 2:fading public: int brightness = 0; // current brightness float fade_target = 0; // where to fade? int fade_speed = 4; float pulse_speed = .004; // speed of pulse when in pulsemode int pulse_amplitude = 125; aLED(byte pin) { this->pin = pin; init(); } void init() { pinMode(pin, OUTPUT); } void operateLED() { if (led_mode == 0) { // if in manual mode } else if (led_mode == 1) { // ----------- PULSE MODE brightness = int((sin(millis() * pulse_speed) + 1) * pulse_amplitude * .5); } else if (led_mode == 2) { // ----------- FADING MODE brightness = int(return_lerp(brightness, fade_target, fade_speed)); } analogWrite(pin, brightness); } void setMode(int _mode) { led_mode = _mode; } }; class aTouch { private: bool prev_touch_state = false; byte pin; int smooth_time = 2; int trigger_threshold = 8; 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); } }; // ---------------------------------- // -------- MAIN PROGRAM -------- // ---------------------------------- // setup the LED object aLED namewhatever(pin); aLED led1(19); aTouch touch1(2); aTouch touch2(4); bool holdmode = false; int hold_ticker = 0; bool has_record = false; float curr_pulsespeed = .1; void setup() { Serial.begin(9600); } void loop() { led1.operateLED(); //operate specific LED touch1.readAndProcessInput(); touch2.readAndProcessInput(); if( touch2.is_holded){ Serial.println("Touch2 hold very long"); holdmode = false; hold_ticker = 0; } if( touch1.is_holded){ Serial.println("Touch1 hold very long"); holdmode = true; } if(holdmode == false){ if( touch1.on_pressed){ led1.setMode(0); led1.brightness=255; led1.setMode(2); led1.fade_target=1; } }else{ // ------------------- // ------- IN HOLDMODE ----------- // ---------------------- hold_ticker++; led1.setMode(1); led1.pulse_speed=.00002*float(hold_ticker); led1.pulse_amplitude = int(.1*hold_ticker)+2; curr_pulsespeed =.00002*float(hold_ticker); has_record = true; } if( touch1.on_released){ if( hold_ticker == 0){ has_record = false; } if(has_record ){ led1.setMode(1); led1.pulse_speed = curr_pulsespeed*2.; led1.pulse_amplitude = 122; }else{ led1.setMode(0); led1.brightness=0; } holdmode = false; hold_ticker = 0; } delay(20); }