Single PIN input control multiple LED Logic

271 views
Skip to first unread message

Gabriel Tutoky

unread,
Apr 20, 2016, 6:38:00 AM4/20/16
to souliss
Hello, I am new in this group and also in souliss API, so first I want to thank the developers for very nice and usefull product!

I have idea for developing light control with arduino/soulis/android for our house in way, that single push button (connected to the single pin on arduino) will control multiple light logics. For example, I have two logics: LED1 and LED2 and single button connected to an pin. I want to recognize three actions with button: single click, long click and double click (two single clicks). My desired logic is following:
- signle click (on button pull) - toggle for LED1 
- long click (on button is hold longer than 1000ms) - toggle for LED2
- double click (on first button single click - toggle for LED1 and on second button signle click (in shorter time than 1500ms after first single click - toggle for LED2)

Summary, single click and long click will control logics LED1 and LED2, double click will invert ON/OFF state for both logics.


How is the best way to implement this logic with souliss? It is possible to do it with current souliss API or I need to implement new function in LocalIO for handling ? specially for double clicks?

Thank you very much!

Flavio P.

unread,
Apr 20, 2016, 7:15:38 AM4/20/16
to sou...@googlegroups.com

Welcome Gabriel!
You can start from bere:
https://github.com/souliss/souliss/wiki/SoulissAPI

DigInHold for example is the right choise for you. For double click i think you must add a function on your sketch.

Hope this help,

Flavio.

--
You received this message because you are subscribed to the Google Groups "souliss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to souliss+u...@googlegroups.com.
To post to this group, send email to sou...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/souliss/ae4ce40f-4f3f-4a3a-a8f9-c48f8e411497%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Gabriel Tutoky

unread,
Apr 20, 2016, 7:38:06 AM4/20/16
to souliss
Thanks Flavio,

I read all about Souliss API. My code is following:

// This identify the number of the LED logic
#define LED1          0
#define LED2          1

void setup()
{   
    Initialize();

    // Get the IP address from DHCP
    GetIPAddress();                          
    SetAsGateway(myvNet_dhcp);       // Set this node as gateway for SoulissApp  
    
    Set_SimpleLight(LED1);        // Define a simple LED light logic
    Set_SimpleLight(LED2);        // Define a simple LED light logic

    // We connect a pushbutton between 5V and pin2 with a pulldown resistor 
    // between pin2 and GND, the LED is connected to pin9 with a resistor to
    // limit the current amount
    pinMode(2, INPUT);                  // Hardware pulldown required
    
    pinMode(8, OUTPUT);                 // Power the LED
    pinMode(9, OUTPUT);                 // Power the LED
}

void loop()
{
    // Here we start to play
    EXECUTEFAST() {                     
        UPDATEFAST();   
        
        FAST_50ms() {   // We process the logic and relevant input and output every 50 milliseconds

            LowDigIn(2, Souliss_T1n_ToggleCmd, LED1);            // Use the pin2 as ON/OFF toggle command
            //DigInHold(2, Souliss_T1n_AutoCmd, Souliss_T1n_ToggleCmd, LED2);
            
            Logic_SimpleLight(LED1);                           // Drive the LED as per command
            Logic_SimpleLight(LED2);                           // Drive the LED as per command
            
            DigOut(8, Souliss_T1n_Coil, LED1);                // Use the pin9 to give power to the LED according to the logic
            DigOut(9, Souliss_T1n_Coil, LED2);                // Use the pin9 to give power to the LED according to the logic
        } 
              
        // Here we handle here the communication with Android, commands and notification
        // are automatically assigned to MYLEDLOGIC
        FAST_GatewayComms();                                        
    }

If I use LowDigIn or DigInHold separately, I can recognize single click or double click separately, but If I want recognize both actions it does not work.



Dňa streda, 20. apríla 2016 13:15:38 UTC+2 Flavio napísal(-a):

Gabriel Tutoky

unread,
Apr 20, 2016, 2:20:33 PM4/20/16
to souliss
Hi,

I solved my idea by adding new function. I updated LocalIO.cpp in following way:

I add three globals:
static unsigned long souliss_upTime;
static unsigned long souliss_lastTime;
static unsigned long souliss_lastUpTime;

and this function: 
/*!
Link an hardware pin to the shared memory map, active on rising edge
        or on long press hold.
Identify three actions: press, hold and double press. Each action can
        perform an command for separate slot.
*/
/**************************************************************************/
U8 Souliss_DigIn3Action(U8 pin, U8 value_signle, U8 value_long, U8 value_double, U8 *memory_map, U8 slot_sigle, U8 slot_long, U8 slot_double, U16 holdTime=1000, U16 doublePressTime=500)
{   
    int reading = dRead(pin);
    
    // measure time on button DOWN
    if(reading && (InPin[pin]==PINRESET))
    {
        InPin[pin] = PINSET;
        souliss_lastTime = souliss_time;
        souliss_time = millis();

        return MaCaco_NODATACHANGED;
    }
    // measure time on button UP
    else if (!reading && InPin[pin]==PINSET)
    {
        souliss_lastUpTime = souliss_upTime;
        souliss_upTime = millis();
    } 
    // reset time - third press will be single click again
    else if (!reading && InPin[pin]==PINRELEASED)
    {
        InPin[pin] = PINACTIVE;
        souliss_time = souliss_upTime = 0;
    } 
    // reset pin
    else if (!reading && InPin[pin]==PINACTIVE) 
    {
        InPin[pin] = PINRESET;
    }
    
    // HANDLING of BUTTON ACTIONS
    // single or double click
    if (!reading && InPin[pin]==PINSET) 
    {
        // double click
        if (abs(souliss_time - souliss_lastTime) < doublePressTime && 
            abs(souliss_upTime - souliss_lastUpTime) < doublePressTime)
        {
            InPin[pin] = PINRELEASED;
            if(memory_map) memory_map[MaCaco_IN_s + slot_double] = value_double;
            return value_double;

        // single click
        } else {
            InPin[pin] = PINACTIVE;
            if(memory_map) memory_map[MaCaco_IN_s + slot_sigle] = value_signle;
            return value_signle;
        }
    }
    // long click
    else if (reading && InPin[pin]==PINSET){
        if (abs(millis() - souliss_time) > holdTime) 
        {
            InPin[pin] = PINACTIVE;
            if(memory_map) memory_map[MaCaco_IN_s + slot_long] = value_long;
            return value_long;
        }
    }
    
    return MaCaco_NODATACHANGED;
}

Please consider that it is my first day with souliss :)




Dňa streda, 20. apríla 2016 13:38:06 UTC+2 Gabriel Tutoky napísal(-a):

Flavio P.

unread,
Apr 20, 2016, 5:56:00 PM4/20/16
to sou...@googlegroups.com

Juan Pinto

unread,
Apr 21, 2016, 3:49:31 PM4/21/16
to souliss
Good job Gabriel! this will be useful :P Thanks for sharing :)
 
Just two tips, you use value_signle and slot_sigle, I suggest you to change to value_single and slot_single, just for a nice reading ;)
 
I will test and let you know. Once were tested you can make a Pull request and for sure this will be added to the master.
 
Regards

Gabriel Tutoky

unread,
Apr 25, 2016, 2:54:44 AM4/25/16
to souliss
Hi Juan,

thank for your tip, I fixed variable names and also thank for your testing.

I modified function because I using multiple light logics for a single button action. See my array for definition buttons and lights:
int buttonLight[noButtons][4][noLights] = {
//   button pin   single click lights   long click lights   double click lights
    {{36},        {45},                 {43, 47},           {}},
    {{34},        {43},                 {},                 {47, 45}},
    {{48},        {47},                 {45},               {}},
};

and my modified function:
U8 Souliss_ButtonHandle(U8 pin, U8 value_single, U8 value_long, U8 value_double, U8 *memory_map, int slot_single[], int slot_long[], int slot_double[], U8 noSlots, U16 holdTime=1000, U16 doublePressTime=500)
{   
    int reading = !dRead(pin);
    
    // measure time on button DOWN
    if(reading && InPin[pin]==PINRESET)
    {
        InPin[pin] = PINSET;
        souliss_lastTime = souliss_time;
        souliss_time = millis();

        return MaCaco_NODATACHANGED;
    }
    // measure time on button UP
    else if (!reading && InPin[pin]==PINSET)
    {
        souliss_lastUpTime = souliss_upTime;
        souliss_upTime = millis();
    } 
    // reset time - third press will be single click again
    else if (!reading && InPin[pin]==PINRELEASED)
    {
        InPin[pin] = PINACTIVE;
        souliss_time = souliss_upTime = 0;
    } 
    // reset pin
    else if (!reading && InPin[pin]==PINACTIVE) 
    {
        InPin[pin] = PINRESET;
    }
    
    // HANDLING of BUTTON ACTIONS
    // single or double click
    if (!reading && InPin[pin]==PINSET) 
    {
        // double click
        if (abs(souliss_time - souliss_lastTime) < doublePressTime && 
            abs(souliss_upTime - souliss_lastUpTime) < doublePressTime)
        {
            InPin[pin] = PINRELEASED;
            if(memory_map) {
                for (int i = 0; i < noSlots; i++) {
                    memory_map[MaCaco_IN_s + slot_double[i]] = value_double;
                }
            }
            return value_double;

        // single click
        } else {
            InPin[pin] = PINACTIVE;
            if(memory_map) {
                for (int i = 0; i < noSlots; i++) {
                    memory_map[MaCaco_IN_s + slot_single[i]] = value_single;
                }
            }
            return value_single;
        }
    }
    // long click
    else if (reading && InPin[pin]==PINSET){
        if (abs(millis() - souliss_time) > holdTime) 
        {
            InPin[pin] = PINACTIVE;
            if(memory_map) {
                for (int i = 0; i < noSlots; i++) {
                    memory_map[MaCaco_IN_s + slot_long[i]] = value_long;
                }
            }
            return value_long;
        }
    }
    
    return MaCaco_NODATACHANGED;
}

I see one small bug in this function. Time variables are using commonly for all buttons and if in the same time (less difference than doublePressTime) are two different buttons pressed (single click), it will be handled as double click for a button which was pressed as second. And moreover if during button long click will be pressed another button, handling of first button will be canceled. Solution is to using time variables array - separe times for each pin, but it rapidly increase used memory in arduino.

Gabriel



Dňa štvrtok, 21. apríla 2016 21:49:31 UTC+2 Juan Pinto napísal(-a):

Di Maio, Dario

unread,
Apr 25, 2016, 3:39:02 AM4/25/16
to sou...@googlegroups.com

Hi Gabriel,

you may try otherwise with a stop flag. Till your timer is used for a button the stop flag is set, so that the other buttons will not work.

So in that case, you have to press again but you will not disturb the first pressed one.

Otherwise the option is to keep this function at user level and not framework one, because at framework level we are obliged to keep a timer for each possible button. At user level you set the number of timers based on your needs.

An other option is to write the function as class, so that each instance of the class has its timer. So if you have two inputs, the class is initialized twice and you have separate timers without have to foreseen timers for all the pins.

Dario.

From Mobile.

Gabriele Ribichini

unread,
Apr 28, 2016, 11:03:25 AM4/28/16
to souliss
Ciao Gabriel,
I think Souliss_DigInHoldSteps does exactly what you were looking for.
Sorry if I am a little late.

I am using such function in my apartment to increase light intensity.
Holding the button lights are turned on one by one.

BR
- gabriele

Gabriele Ribichini

unread,
Apr 28, 2016, 4:17:02 PM4/28/16
to souliss
BTW 
the mentioned code from the main branch has been just rewritten for a better usability in daily life.
the new code should be integrated in branch 720_rc with this pull request

BR
- gab

guyc

unread,
Aug 16, 2016, 4:12:43 PM8/16/16
to souliss


I'm looking for a similar function to control 2 different slots with one push button, but cannot find any function usable. DigInHoldSteps seems the only function at the moment to control different slots.

What I need :
short puls : control slot X
long puls or double puls  : control slot y.

Di Maio, Dario

unread,
Aug 18, 2016, 2:41:30 AM8/18/16
to sou...@googlegroups.com

Use DigInHold on an empty slot, if(DigInHold(...)==value1) mInput(slotX)=...; else if(DigInHold(...)==value2) mInput(slotY)=...;

Dario.

From Mobile.

--
You received this message because you are subscribed to the Google Groups "souliss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to souliss+unsubscribe@googlegroups.com.

To post to this group, send email to sou...@googlegroups.com.

guyc

unread,
Aug 20, 2016, 6:13:34 AM8/20/16
to souliss
I have tried to do it with 'DigInHold' but this instruction refers to the same slot.
my test :

if(DigInHold(22)==1), mInput(eethoek_A1)=Souliss_T1n_ToggleCmd); else if(DigInHold(22)==2) mInput(B_leeslamp)=Souliss_T1n_ToggleCmd);

I receive the error message: digInHold needs 4 arguments, only 1 given.

Did I soemthing wrong ?

thanks

Op donderdag 18 augustus 2016 08:41:30 UTC+2 schreef Dario Di Maio:

Use DigInHold on an empty slot, if(DigInHold(...)==value1) mInput(slotX)=...; else if(DigInHold(...)==value2) mInput(slotY)=...;

Dario.

From Mobile.

On 16 Aug 2016 22:12, "'guyc' via souliss" <sou...@googlegroups.com> wrote:


I'm looking for a similar function to control 2 different slots with one push button, but cannot find any function usable. DigInHoldSteps seems the only function at the moment to control different slots.

What I need :
short puls : control slot X
long puls or double puls  : control slot y.

--
You received this message because you are subscribed to the Google Groups "souliss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to souliss+u...@googlegroups.com.

guyc

unread,
Aug 20, 2016, 9:05:02 AM8/20/16
to souliss
I have made something as a new function that maybe can be incorporated in the localIO.cpp.

U8 Souliss_DigInHoldDouble_Helper(U8 pin, U8 pin_value, U8 *memory_map, U8 firstSlot, U8 secondSlot, U16 step_duration)
{
  if( pin_value == PINRESET ) // unpressed button
  {
    InPin[pin] = PINRESET;
    return MaCaco_NODATACHANGED;
  }

  // if here the button is pressed
  if( InPin[pin] == PINRESET ) // it was unpressed before
  {
    InPin[pin] = PINSET;
    time = millis();                // Record time
    // this is the first cycle detecting the button press: current input=1, previous input=0

    // toggle the first slot light

      if(memory_map[MaCaco_OUT_s + firstSlot] == Souliss_T1n_OnCoil)  memory_map[MaCaco_IN_s + firstSlot] = Souliss_T1n_OffCmd;
       else if (memory_map[MaCaco_OUT_s + firstSlot] == Souliss_T1n_OffCoil)  memory_map[MaCaco_IN_s + firstSlot] = Souliss_T1n_OnCmd;
        return MaCaco_DATACHANGED;
         
    }
 
   

  }
  else if( InPin[pin]==PINACTIVE && (abs(millis()-time) > step_duration) )
  {
  

  // if here the button is pressed
  if( InPin[pin] == PINRESET ) // it was unpressed before
  {
    InPin[pin] = PINSET;
    time = millis();                // Record time
    // this is the first cycle detecting the button press: current input=1, previous input=0

    // toggle the second slot light

      if(memory_map[MaCaco_OUT_s + secondSlot] == Souliss_T1n_OnCoil)  memory_map[MaCaco_IN_s + secondSlot] = Souliss_T1n_OffCmd;
       else if (memory_map[MaCaco_OUT_s + secondSlot] == Souliss_T1n_OffCoil)  memory_map[MaCaco_IN_s + secondSlot] = Souliss_T1n_OnCmd;
        return MaCaco_DATACHANGED;
         
    }
   
    return MaCaco_STATUS;
  }

  return MaCaco_NODATACHANGED;
}

U8 Souliss_DigInHoldDouble(U8 pin, U8 *memory_map, U8 firstSlot, U8 secondSlot, U16 step_duration)
{
  return Souliss_DigInHoldDouble_Helper(pin, dRead(pin), memory_map, firstSlot, secondSlot, step_duration);
}

U8 Souliss_LowDigInHoldDouble(U8 pin, U8 *memory_map, U8 firstSlot, U8 secondSlot, U16 step_duration)
{
  return Souliss_DigInHoldDouble_Helper(pin, !dRead(pin), memory_map, firstSlot, secondSlot, step_duration);
}

Reply all
Reply to author
Forward
0 new messages