Hello!
I have a [I think] capacitive sensing pad as a light switch in my bedroom. If you tap the pad, it switches the light. If you press your finger on the pad, it fades the light until minumum / maximum brightness, then reverses. If you release your finger, then press down again, it will begin fade in the opposite direction. If you switch the light off by tapping the pad lightly, then if you press the pad again, the light will turn on at the previous brightness (it remembers the brightness before you turned it off), and fade up / down. If that needs more explaination, I would be happy to provide it. I want to imitate that effect using a momentary push button and an LED for now, using Arduino. Here is the non-working code so far:
I am having trouble with the logic. I want this to happen: if the button is pressed and released quickly (200ms or so), switch the light, but remeber the ON brightness. If button is held down for longer than 200ms, fade up / down. If brightness reaches maximum / minimum while fading, reverse direction. If button is released, then held again, fade in reverse direction. It is essentially imitating my bedroom light switch. I would appreciate it if someone can shed some light on this.
Thanks!
The only way to do what you are trying to do is to remember whether the switch was also pressed last time, too.
If the switch is pressed, and was not last time, this is a new press.
If the switch is pressed, and was also pressed last time, the switch is still being pressed. If the switch is still being pressed, then you need to determine how long it has been pressed (by subtracting now from then, where then is when the transition to pressed occurred (see above)).
Without knowing the previous state of the switch, I can see no way to accomplish what you are trying to do.
It works okay now. Next, I will use capacitive sensing instead of a button. That should not be so hard.
One more question: how can I get rid of the delay(interval+1) line? That was to not trigger the if statement for PRESSED and UNPRESSED right after each other, causing the LED to turn right back off once it turned on. You can see some commented-out failed attempts in the code. Do you get what I mean?
One more question: how can I get rid of the delay(interval+1) line?
That delay is apparently to manage debouncing the switch. If the switch bounces for 201 milliseconds, you need a better switch. 20 milliseconds is a lot of bouncing.
It is more likely due to the software, especially this part:
if(millis() - prev > interval){
//...
Now, I exchange the button for CapSense foils. Here is the new code:
#include <CapSense.h>
#include <Streaming.h>
#define DEBUG 1
const byte led = 9;
const word interval = 200;
/*const byte sendPin = 4;
const byte recvPins[3] = {
2, 6, 8};*/
typedef enum{
TOUCHED, UNTOUCHED}
touch_state;
touch_state lastState = UNTOUCHED;
touch_state state;
unsigned long prev = 0;
byte ledVal = 0;
byte lastLedVal = 0;
int dir = 1;
boolean beenOff = false;
//boolean beenOn = false;
CapSense set1 = CapSense(4,2); // 10M resistor between pins 4 & 2, pin 2 is sensor pin, add a wire and or foil if desired
CapSense set2 = CapSense(4,6); // 10M resistor between pins 4 & 6, pin 6 is sensor pin, add a wire and or foil
CapSense set3 = CapSense(4,8); // 10M resistor between pins 4 & 8, pin 8 is sensor pin, add a wire and or foil
void setup(){
#if (DEBUG)
Serial.begin(9600);
#endif
pinMode(led, OUTPUT);
TCCR1B = TCCR1B & 0b11111000 | 0x04;
}
void loop(){
state = isTouched();
if(state != lastState){
if(state == TOUCHED){
prev = millis();
if(beenOff){
switchLED();
beenOff = false;
//beenOn = true;
delay(interval+1);
}
dir = -dir;
}
if(state == UNTOUCHED){
if(millis() - prev < interval){
lastLedVal = ledVal;
//if(!beenOn){
switchLED();
beenOff = true;
//}
}
}
lastState = state;
}
if(ledVal == 0) dir = 1;
else if (ledVal == 255) dir = -1;
if(state == TOUCHED && millis() - prev >= interval){
//beenOn = false;
ledVal += dir*5;
}
analogWrite(led, ledVal);
#if (DEBUG)
Serial << "state: " << state << ", lastState: " << lastState
<< ", ledVal: " << ledVal << ", lastLedVal: " << lastLedVal
<< ", dir: " << dir << endl;
#endif
}
void switchLED(){
if(ledVal > 0) ledVal = 0;
else ledVal = lastLedVal+5;
}
touch_state isTouched(){
unsigned long prev = millis();
long totals[3] = {
set1.capSense(30),
set2.capSense(30),
set3.capSense(30)
};
unsigned long finished = millis();
#if (DEBUG)
Serial << "CapSense time: " << (finished - prev) << ", ";
#endif
for (byte i = 0; i < 3; i++) if(totals[i] > 500) return TOUCHED;
return UNTOUCHED;
}
But there is a compiler error that I cannot figure out the source of:
sketch_jul15b:2: error: 'touch_state' does not name a type
sketch_jul15b.cpp: In function 'void loop()':
sketch_jul15b:31: error: 'isTouched' was not declared in this scope