This is my first post and first project with a particle device, so I’m quite new on this.
I’m trying to replicate/extend the code given in FamilyLamp project: Family Lamp - Github which I already have it working.
Now I would like to adapt it to my requirements. I would like to be able to detect long or short touch. I’m planning to use short touch to light all the led with white (to act like a normal lamp) and long touch to activate the connectivity feature.
I’m using the library CapTouch, and the function CapTouch::TouchEvent. I would have thought, that it would allow me to detect the second touch, but it always gives me NoTouch in the second attempt. I tried to activate the event state, but it seems the implementation of the event class is not completed.
So far I got this code (modifying the preamble of loop function of the original Familylamp), attached at the end of this post.
The idea of the code is to check if it’s touching, wait for one second, check again if it is touching. If it is still touching, it is a “long” touch, if not, it was a short one.
Any ideas or suggestions are very appreciated! Kind regards,
void loop() {
// begin default
//dayTracking();
//touchEvent = Touch.getEvent();
//if (touchEvent == CapTouch::TouchEvent) {
// whileTouching();
//}
//
//if (Time.now() - lastColorUpdate > decayTime && lampOn == 1) {
// if (Time.now() - lastDecayDelay >= decayDelay) {
// extinguish();
// lastDecayDelay = Time.now();
// }
// }
//end defult
// =========================================================================================================
// being test
dayTracking();
touchEvent = Touch.getEvent();
// touched
if (touchEvent == CapTouch::TouchEvent){ // if touching
Particle.publish("Touching!");
if (while_is_not_running==1){
//Particle.publish("waiting!");
delay(900);
}
if (while_is_not_running!=1){
//Particle.publish("not waiting!");
}
//Touched
touchEvent = Touch.getEvent();
Particle.publish("Second touch", String(touchEvent));
if (touchEvent == CapTouch::NoEvent){// we still touch it
Particle.publish("WhileTouching!");
whileTouching();
while_is_not_running = 0;
}
if (touchEvent == CapTouch::ReleaseEvent){ //we have released
// It is a short touch, so we intend to light on/off the leds in white.
//get leds brightness
Particle.publish("into led!");
while_is_not_running = 1;
//int led_is_on = strip.getBrightness();
uint32_t led_is_on = strip.getPixelColor(1);
Particle.publish("color of ",String((led_is_on)));
//LEDs are on
if (led_is_on != 0) {
//turning off
strip.clear();
strip.show();
Particle.publish("turning off!","data is off?");
}
//LEDs are off
if (led_is_on == 0) {
//turning on
for(int i = 0; i <= strip.numPixels(); i++) {
strip.setPixelColor(strip.numPixels() - i, 255, 255, 255);
}
strip.show();
Particle.publish("turning on!");
}
}
}
//resetting jumping delay variable
if (touchEvent != CapTouch::TouchEvent){
while_is_not_running = 1;
}
// To do the decay.
if (Time.now() - lastColorUpdate > decayTime && lampOn == 1) {
if (Time.now() - lastDecayDelay >= decayDelay) {
extinguish();
lastDecayDelay = Time.now();
}
}
// end test
// =========================================================================================================
// Special idle functions
//... More things
}
I haven’t followed the logic of your snippet completely, but since you do seem to get a touch and a release event, wouldn’t it be easier to just record the time of the touch event and on release calculate the time the sensor was touched and distinguish from that whether it was a short or a long touch?
Having delays block the code flow for extended periods (aka more than a few milliseconds) isn’t the best practice.
This problem would lend itself to a simple FSM approach.
You are right I might be over complicating the code. The thing is at beginning I was trying to execute the function whileTouching() at the same time that the touching. This was intended, because that function shows different colors until you stop to touch it. So the procedure “check how long is the touching > executing the functions” wasn’t exactly what I wanted. I hope I’m clear with my explanations.
At the end I gave up and I did it in another way. Long touch start to loop over the colors, until you touch it again and it stop in one color.
The code is attached later.
If I picture your intent correctly I'd still not see any reason for not going with my proposal.
If you have a touch and a release event then everything between the two can be considered holding. So a whileTouching logic would easily be implemented in a non blocking fashion just the same.
Your project gave me an idea for a project. Years ago, I could send and receive Morse code at a decent clip, and it would be fun to get that skill back. A fun Particle project would be to create firmware that could convert dots and dashes into characters, and vice versa. I could then have the program send me the contents of a Google doc and I could key it back and check accuracy both directions. Anyway, I wrote the snippet to capture the moment. I’m glad you found it useful. Perhaps … someday … I’ll find out if sending/receiving Morse code is like riding a bicycle.
I'm afraid I don't understand what you mean with "a non blocking fashion". Could you share a small snippet (don't need to be related to this project)? for me to understand easier. Sorry, English is not my first language and i didn't study computer science or similar, that's maybe why I have problems to understand you .
@Bear
I'm glad it brought you memories. Hopefully you will find the time!
The command “delay(5000)” command prevents the processor for doing ANYTHING for 5 full seconds. Since IOT devices only have a single processor, a “blocking” command like that can lead to a variety of problems.
A non-blocking alternative would be to:
compute “resumeTime” by adding 5000 to millis().
trigger action when millis() >= “resumeTime”.
A timer can also be used to trigger action in 5000ms … or to trigger action every 5000ms when the timer is running (between the timer.start() and timer.stop() commands).
I’m the original author of the Familamp code. You should be able to almost use the code as-is, with the addition of a counter that runs inside while (touchEvent != CapTouch::ReleaseEvent) {. The code inside that while loop continues indefinitely until the CapTouch library returns a release from the call to it at the end of the loop, touchEvent = Touch.getEvent();. The speed of the while loop varies based on the humidity and resistor used, but it loops quite a few times a second. The “sparkle” function (where other lamps begin to sparkle when you put your hand on the lamp) already does something similar: every 3 seconds, it sends a Particle.publish(). You could use that code as a template and do something similar if the loops occur for more than, say, 5 seconds.
It looks like you’re already making progress on your improvements by ripping CapTouch out, so if you can get it working that way, great. Getting a reasonable response from the panel was one of the more challenging aspects of the project and I wasn’t talented enough to write something from scratch, so more power to you.