Looping a function one time through;

I am running into a bit of a snag with declaring functions within conditionals. I’ll explain after the code:

`function poll()
{

values += changes;
if (values == 100) {
   changes = changes-1;

} else if (values == 0) {
changes = changes+1;
}

led8.write(values/256.0);
imp.wakeup(0.01, poll);

}

function buttonStateChanged() {
// read the current state
local state = button.read();
// send it to the agent

if(state==1){
  poll();
}

}`

so, when a button is HIGH, I want to go through the function. Problem I am encountering is the function seems to progressively cycle (loop) faster every time the condition is met until the function is overloaded. how would I reset the function ?

This is because you ALWAYS do an imp.wakeup at the end of poll. Every time poll is run, it will call itself back 10ms later.

Every time your buttonStateChanged() calls poll, it sets of another set of imp.wakeups.

The first time poll() is called, it will continue forever calling itself every 10ms
The second time poll() is called, it adds another callback, effectively calling it every 5ms
The third time poll() is called, it adds yet another callback, effectively calling it every 3.3ms

…and so on.

I think you want this:

`

function poll()
{
values += changes;

// Change direction when we get to the end
if (values == 100) {
   changes = -1;

}

led8.write(values/256.0);

// Only call back if values isn’t zero; as we enter first time with values=0 and changes=1, by the time we get here values=1 and won’t get back to zero until we go all the way to 100 and back again
if (values != 0) imp.wakeup(0.01, poll);
}

function buttonStateChanged() {
// read the current state
local state = button.read();
// send it to the agent

if(state==1){
   // Single loop up and down
  values=0; changes=1;
  poll();
}

}`

Hey Hugo,

somewhat. The issue now is the loop executes one time though when the button is high; I want it to continuously loop else other condition is met.

So you want it to pulse only when the button is high?

In that case change the:

if (values != 0) imp.wakeup(0.01, poll);

to…

if (button.read() == 1) imp.wakeup(0.01, poll);

…this means the animation of the LED only happens whilst the button is held. When it’s released, the imp.wakeup is no longer called and so the loop terminates.

Seems to be the exact same issue; here is my implementation:

`//////MAIN//////////
imp.setpowersave(true);

imp1state <- 0;
imp2state <- 0;
imp3state <- 0;

led9 <- hardware.pin9;
led8 <- hardware.pin7;
led7 <- hardware.pin5;
led9.configure(PWM_OUT, 0.02, 0.0);
led8.configure(PWM_OUT, 0.02, 0.0)
led7.configure(PWM_OUT, 0.02, 0.0);
values <- 0;
changes <- 1;
imp.configure(“touchstone1”, [], []);
// assign hardware.pin9 to a variable to make things more clear
button <- hardware.pin2;

function poll()
{

  local state = button.read();
  
values += changes;

// Change direction when we get to the end
if (values == 100) {
   changes = -1;

}

led8.write(values/256.0);

// Only call back if values isn’t zero; as we enter first time with values=0 and changes=1, by the time we get here values=1 and won’t get back to zero until we go all the way to 100 and back again
//if (values != 0) imp.wakeup(0.01, poll);

if (button.read()==1) imp.wakeup(0.01, poll);

}

/*
function buttonStateChanged() {
// read the current state
//local state = button.read();

 server.log(imp1state);
 send it to the agent
agent.send("touchstone1", state);

}
*/

function setLed(value) {

if (value ==2){
imp2state = 7;

} 

else if (value==20){
    
    imp2state=0;
}


   if (value ==3){
imp3state = 8;

} 

else if (value==30)
{
    imp3state=0;
}
    

server.log("IMP 2 = "+ imp2state)
    server.log("IMP 3 = "+ imp3state)

if (imp2state == 7 && imp3state==0) {

}
if(imp2state==0 && imp3state==0){

led9.write(0);
led8.write(0);
led7.write(0);

}

if (imp3state == 8 && imp2state==0) {
led9.write(1);
led8.write(0);
led7.write(1);
}

if(imp2state==7 && imp3state==8){

 led9.write(1);
    led8.write(0.01);
    led7.write(1);  

}

}

// setup a handler for setLed message from the agent
agent.on(“setLed”, setLed);

// configure the button
button.configure(DIGITAL_IN_PULLDOWN, poll);
`

Erm, now you’re just calling poll every time there’s a button state change. This, again, will cause multiple callbacks to be fired on every switch bounce.

It really seems you’re trying to run before you can walk here with general programming concepts… :frowning:

Well, I implemented your suggested code; I’m not certain where I am contradicting your example in my implementation, but some clarification would be great.

The original question still stands; how to trigger a function when the button is pressed. Implemented your suggestion, which pointed to achieving this, yet similar results are occurring.

You are triggering a function when the button is pressed. The problem is, you’re triggering it multiple times, because a button press will “bounce” due to the mechanical nature of buttons.

Search the forums for button debounce to find some examples of how to deal with this.

I am aware of how to debounce a button; This seems to be a different suggestion from your earlier approach?

The code before still applies - just don’t call my poll() function on spurious switch bounces. If you call it just once per event then it will function correctly. You have hooked it directly to the pin change handler, which will have a lot of bouncing.