Help with "ClickButton.h"

The code below shows my work to date. As a newbie I have worked hard on this. I have a Radio Control receiver attached to the arduino and it works 7 relays on demand. All well and good. Now I want to put in a routine, and the only way to trigger this from the RC is to make a double click response.

I have added the “ClickButton.h" and the sample code which is all I want to so far. I have attached the Led to measure success or not.

https://code.google.com/p/clickbutton/wiki/Usage

The major difference here is that I am not using a click button, but an algorithm based on ‘double clicking’ the transmitter. I am not getting any joy from this at all. I am sure this is where the issue lies.. Is there an obvious problem?

#include <PinChangeInt.h>
#include "ClickButton.h"

#include <Servo.h>


#define BALLAST_IN_PIN 2
#define KNOB_IN_PIN 3
#define AUX_IN_PIN 4
#define HYDRO_IN_PIN 5


#define HYDRO_OUT_PIN 13

int PISTON_DIVE_PIN = 6;
int PISTON_SURFACE_PIN = 7;
int PUMP_DIVE_PIN = 8;
int PUMP_SURFACE_PIN = 9;
int TRIM_TO_BOW_PIN = 10;
int TRIM_TO_STERN_PIN = 11;
int WATER_GUN_PIN = 12;
int buttonPin1;

// the LED
const int ledPin = A2;
int ledState = 0;

// the Button
//int buttonPin1;
ClickButton button1(buttonPin1, LOW, CLICKBTN_PULLUP);

// Arbitrary LED function 
int LEDfunction = 0;



// individual timing gaps for the following functions.
//first switches
const unsigned long PISTON_DIVE_PINinterval = 1000;
const unsigned long PISTON_SURFACE_PINinterval = 1000;
const unsigned long PUMP_DIVE_PINinterval = 1000;
const unsigned long PUMP_SURFACE_PINinterval = 1000;
const unsigned long TRIM_TO_BOW_PINinterval = 1000;
const unsigned long TRIM_TO_STERN_PINinterval = 1000;
const unsigned long WATER_GUN_PINinterval = 1000;



unsigned long PISTON_DIVE_PINtimer;
unsigned long PISTON_SURFACE_PINtimer;
unsigned long PUMP_DIVE_PINtimer;
unsigned long PUMP_SURFACE_PINtimer;
unsigned long TRIM_TO_BOW_PINtimer;
unsigned long TRIM_TO_STERN_PINtimer;
unsigned long WATER_GUN_PINtimer;



Servo servoBallast;
Servo servoKnob;
Servo servoAux;
Servo servoHydro;

// These bit flags are set in bUpdateFlagsShared to indicate which
// channels have new signals
#define BALLAST_FLAG 1
#define KNOB_FLAG 2
#define AUX_FLAG 4
#define HYDRO_FLAG 5

//double click routine
#define diveclick1
#define diveclick2
#define diveroutine

// holds the update flags defined above
volatile uint8_t bUpdateFlagsShared;


volatile uint16_t unBallastInShared;
volatile uint16_t unKnobInShared;
volatile uint16_t unAuxInShared;
volatile uint16_t unHydroInShared;



uint32_t ulBallastStart;
uint32_t ulKnobStart;
uint32_t ulAuxStart;
uint32_t ulHydroStart;


void setup()


{
 
Serial.begin(9600);

 
servoHydro.attach(HYDRO_OUT_PIN);

{
  
  button1.debounceTime   = 20;   // Debounce timer in ms
  button1.multiclickTime = 250;  // Time limit for multi clicks
  button1.longClickTime  = 1000; // time until "held-down clicks" register
}

pinMode(PISTON_DIVE_PIN, OUTPUT);
pinMode(PISTON_SURFACE_PIN, OUTPUT);
pinMode(PUMP_DIVE_PIN, OUTPUT);
pinMode(PUMP_SURFACE_PIN, OUTPUT);
pinMode(TRIM_TO_BOW_PIN, OUTPUT);
pinMode(TRIM_TO_STERN_PIN, OUTPUT);
pinMode(WATER_GUN_PIN, OUTPUT);
pinMode(ledPin, OUTPUT);

// timer for functions
PISTON_DIVE_PINtimer = millis ();
PISTON_SURFACE_PINtimer = millis ();
PUMP_DIVE_PINtimer = millis ();
PUMP_SURFACE_PINtimer = millis ();
TRIM_TO_BOW_PINtimer = millis ();
TRIM_TO_STERN_PINtimer = millis ();
WATER_GUN_PINtimer = millis ();

(PISTON_DIVE_PIN, HIGH);
(PISTON_SURFACE_PIN, HIGH);
(PUMP_DIVE_PIN, HIGH);
(PUMP_SURFACE_PIN, HIGH);
(TRIM_TO_BOW_PIN, HIGH);
(TRIM_TO_STERN_PIN, HIGH);
(WATER_GUN_PIN, HIGH);
(buttonPin1, HIGH);

  
PCintPort::attachInterrupt(BALLAST_IN_PIN, calcBallast,CHANGE);
PCintPort::attachInterrupt(KNOB_IN_PIN, calcKnob,CHANGE);
PCintPort::attachInterrupt(AUX_IN_PIN, calcAux,CHANGE);
PCintPort::attachInterrupt(HYDRO_IN_PIN, calcHydro,CHANGE);
}

void loop()
{
  
static uint16_t unBallastIn;
static uint16_t unKnobIn;
static uint16_t unAuxIn;
static uint16_t unHydroIn;

  // local copy of update flags
static uint8_t bUpdateFlags;

  //Serial.println(unBallastIn 
  //Serial.println(unKnobIn);
  //Serial.println(unAuxIn); 
  //Serial.println(unHydroIn); 
  Serial.println(buttonPin1); 
  
  
  
  //click parameters  which need work
  
  if (unBallastIn > 1800)  
{ 
digitalWrite(buttonPin1, LOW);
}         
  else if (unBallastIn < 1800) 
{
digitalWrite(buttonPin1, HIGH);
}
  
  {
  // Update button state
  button1.Update();

  // Save click codes in LEDfunction, as click codes are reset at next Update()
  if (button1.clicks != 0) LEDfunction = button1.clicks;
  

  // Simply toggle LED on single clicks
  // (Cant use LEDfunction like the others here,
  //  as it would toggle on and off all the time)
  if(button1.clicks == 1) ledState = !ledState;

  // blink faster if double clicked
  if(LEDfunction == 2) ledState = (millis()/500)%2;

  // blink even faster if triple clicked
  if(LEDfunction == 3) ledState = (millis()/200)%2;

  // slow blink (must hold down button. 1 second long blinks)
  if(LEDfunction == -1) ledState = (millis()/1000)%2;

  // slower blink (must hold down button. 2 second loong blinks)
  if(LEDfunction == -2) ledState = (millis()/2000)%2;

  // even slower blink (must hold down button. 3 second looong blinks)
  if(LEDfunction == -3) ledState = (millis()/3000)%2;


  // update the LED
  digitalWrite(ledPin,ledState);
}
  
  
  //PISTON PARAMETERS for realy action
  

if (unBallastIn > 1800)
  {
    if ( (millis () - PISTON_DIVE_PINtimer) >= PISTON_DIVE_PINinterval)          
    digitalWrite(PISTON_DIVE_PIN, LOW);     
  }
    else if (unBallastIn < 1800)
  {
    digitalWrite(PISTON_DIVE_PIN, HIGH);
    PISTON_DIVE_PINtimer = millis ();  
  }
  
  
 if (unBallastIn < 1300)
  {
    if ( (millis () - PISTON_SURFACE_PINtimer) >= PISTON_SURFACE_PINinterval)    
    digitalWrite(PISTON_SURFACE_PIN, LOW);
  }
    else if (unBallastIn > 1300)
  {
   digitalWrite(PISTON_SURFACE_PIN, HIGH);
   PISTON_SURFACE_PINtimer = millis ();  
  }

//etc, cut the rest out
int buttonPin1;

No initializer provided, so the value defaults to 0.

ClickButton button1(buttonPin1, LOW, CLICKBTN_PULLUP);

So, you are connecting the button to one of the hardware serial pins.

Better get rid of this

Serial.begin(9600);

then.

{
  
  button1.debounceTime   = 20;   // Debounce timer in ms
  button1.multiclickTime = 250;  // Time limit for multi clicks
  button1.longClickTime  = 1000; // time until "held-down clicks" register
}

Why is this stuff in curly braces?

What is this crap?

(PISTON_DIVE_PIN, HIGH);
(PISTON_SURFACE_PIN, HIGH);
(PUMP_DIVE_PIN, HIGH);
(PUMP_SURFACE_PIN, HIGH);
(TRIM_TO_BOW_PIN, HIGH);
(TRIM_TO_STERN_PIN, HIGH);
(WATER_GUN_PIN, HIGH);
(buttonPin1, HIGH);

Do you have a clue what the comma operator does? What you are doing here makes no sense.

  {
  // Update button state
  button1.Update();

More useless curly braces...

The major difference here is that I am not using a click button, but an algorithm based on 'double clicking' the transmitter.

Then, I don't understand how you think this is going to work.

Which pins is the RC receiver connected to?

Hi

Thanks for your time! I don't want to let you go..

You are a bit brutal with a newbie, but.. firstly all this works very well.. (I couldn't put all the code in obviously due to the character limit)

I am confused when to write low and 0 and high and 1 etc. I just test till it works. I will get rid of the extra curleys. I just copy them in.

The radio comes in on

#define BALLAST_IN_PIN 2
#define KNOB_IN_PIN 3
#define AUX_IN_PIN 4
#define HYDRO_IN_PIN 5

The ballast channel is the one I want to be able to 'double click' in one direction to get the subroutine to start. Thus my attempt here

if (unBallastIn > 1800)
{
digitalWrite(buttonPin1, LOW);
}
else if (unBallastIn < 1800)
{
digitalWrite(buttonPin1, HIGH);
}

By clicking it >1800 twice quickly I want to trigger the routine. Thus my attempted use of button.h. This IS the issue; I don't have a button, I have a transmitter firing over 1800 twice. Can this be done, and if not what would you suggest.

John

By clicking it >1800 twice quickly I want to trigger the routine. Thus my attempted use of button.h. This IS the issue; I don't have a button, I have a transmitter firing over 1800 twice. Can this be done, and if not what would you suggest.

What, exactly, does "quickly" mean? How would YOU determine that two "clicks" were discrete events vs. a "double click"?

It seems to me that you'd want to record when an event (a "click") occurs. When an event occurs, you would also determine how long it had been since the last event (of the same kind).

So, if a "click" happens at 27183465 and another one happens at 32630763, there is no way that you'd consider that a "double click".

But, if a "click" happens at 27183465 and another one happens at 27183535, you might consider that a "double click". That's a difference of 70 milliseconds, which might be reasonable for a "double click". Or, it might not.

What you'd have to do is experiment, printing the time that events occurred, and then determining the appropriate interval that means "double click" to you.

Where do those numbers come from? From millis(), of course.

Exactly. I will need to experiment once it is working and I will adjust the parameters. The problem is that the code is not working as it is. There must be a glitch somewhere in it. I am hoping someone can help me so I can get to base one and then start adjusting.

I have looked at the code in your first post and even if all of the comments that @PaulS has made were corrected I can't make any sense of it. This is probably because so much depends on the code in the libraries.

For example where does the variable unBallastIn get updated and what does it represent? (But that is only a small example of my lack of understanding).

One way would be for you to explain in some detail how your are using the two libraries (I am familiar enough with the Servo library).

More useful, I suspect, (for you and for us) would be for you to write a very simple program that receives the inputs and just displays debug info on the Serial Monitor while you figure out how to do it.

In either case it would be a great help if you provide a plain-language explanation of how your program is intended to work as I am much too lazy to try to reverse-engineer it.

Are you sure that those 3 libraries are compatible with each other?

...R

OK.

I have left off the rest of the sketch because the forum won't accept it's length. The sketch is to control the functions of a model submarine. So far it works perfectly well with all its problems. I have two channels Servo servoBallast; and Servo servoKnob;that are driving eight relays very nicely, depending on where the arm is. ie trim tab one way, and the pump is pumping water. Centre it, and put the arm full travel, and the piston is withdrawing. All working perfectly.
By adding clickbutton.h everything still works. All I want to do is turn a function 'on' using a double click.What I will do is strip down the basic idea to just one channel, and one double click and re enter the problem. That may help.
Cheers
John

By adding clickbutton.h everything still works.

Perhaps you need to add EthernetClient.h, too.

Clickbutton is the WRONG way to do what you want. It deals with mechanical switches connected to digital pins. That is NOT what you have, is it?

Johnredearth:
I have left off the rest of the sketch because the forum won't accept it's length. The sketch is to control the functions of a model submarine. So far it works perfectly well with all its problems. I have two channels Servo servoBallast; and Servo servoKnob;that are driving eight relays very nicely, depending on where the arm is. ie trim tab one way, and the pump is pumping water. Centre it, and put the arm full travel, and the piston is withdrawing. All working perfectly.
By adding clickbutton.h everything still works. All I want to do is turn a function 'on' using a double click.What I will do is strip down the basic idea to just one channel, and one double click and re enter the problem. That may help.

The shorthand version of this seems to me to be "I won't explain the code that works but please help with the stuff that doesn't"

Without a good understanding of how the working parts work I can't begin to think about what the problem might be.

...R

Hi

What I want to do:

I have a scratch built submarine:

This is a fun vid about the boat taken with a camera on another boat. UBoat Pond Patrol - YouTube

I want to throw out the current system and control the, at least, 8 relays off two channels, for ballast, piston, trim tanks etc. The current sketch does this however I want to automate the diving and surfacing routines. I also want to add a pressure sensor to the bow and for example only start the ‘pump out’ when the boat has breached the surface.

So the long hand message is that your comment is really rude. I would have posted the whole sketch but the forum won’t allow that many characters. I said that at the beginning. I am not trying to pay electronic hide and seek. Can I attach it somehow or send directly to your email?

I was introduced to Arduino 4 weeks ago and have done bloody well. Anyway, with this sketch I have replicated the current control of the sub, and now want to automate a dive and surface routine using the ballast, piston and trim tanks. The only way to do this practically is to click the dive control lever to one side twice quickly. A ‘double click’ if you will. If anyone can make a recommendation about this could best be done please let me know.

Cheers John

Johnredearth:
So the long hand message is that your comment is really rude. I would have posted the whole sketch but the forum won’t allow that many characters.

You can post the entire program as an attachment to your post. If the Forum still won't accept .ino files change it to a .txt file.

My original request to you was

One way would be for you to explain in some detail how your are using the two libraries (I am familiar enough with the Servo library).

and

In either case it would be a great help if you provide a plain-language explanation of how your program is intended to work

As far as I could see you did not respond to either of these questions - hence my comment.

The description of your project is also very useful, but an explanation of the code is also needed.

...R

OK back to it.

Would be happy to attach something, but how?? I can't find any indication of how that can occur. I have reread 'before posting' etc etc. no idea.

Cheers

John

Would be happy to attach something, but how?

When you click on Reply, a new reply window is created (Quick reply is useless!). Just below that window is a link "Attachments and other options". I'm sure you can figure it out from there.

But, ClickButton.h is NEVER going to work for you, so the sooner you get over your fixation on using it, the sooner you'll make progress.

HI

I have in fact given up and been trying to write my own. That is not on here though

buttonsketch.txt (13.9 KB)

Johnredearth:
I have in fact given up and been trying to write my own. That is not on here though

When you have the new version post it and I will look at it.

...R

This is the basic stuff I have that works and fires the relays with 1 second delay. The dleay for my purposes is fine and I want to make the double click within 250, then maybe shorten the delay for the relays.

My attempts to code from scratch for double click are a mess. I need to create a function such that one short 'stab' of the radio turns on a function, which only lasts for a short time. I need to have the second stab do the same, but only works if the first is high, also for short time. If both functions are on simultaneously then the diveroutine can be triggered which will remain 'on' until that routine is finished.

I have created two functions and attached led's to them so that I can see what is happening. I also created a third which I thought was necessary but now can see it may not be. I thought if I exaggerate the time periods to being quite long first, then I can slow everything down to within 250 or so by experiment to get the double click.

I also cannot have the first triggered if the second is on and etc. It all seems simple but I have spent hours trying to get this right. I think some assistance would get me over this hurdle and I can just get on with the next step, but I can see I am confusing matters.

So there we are. The one I am sending does not have button click on it.

doubleclickattempt.txt (13.9 KB)

Posting a boat load of commented out code is annoying. The code obviously isn't being executed, so it contributes nothing to what you are doing/what problems you might be having. Delete it!

// timer for functions
PISTON_DIVE_PINtimer = millis ();
PISTON_SURFACE_PINtimer = millis ();
PUMP_DIVE_PINtimer = millis ();
PUMP_SURFACE_PINtimer = millis ();
TRIM_TO_BOW_PINtimer = millis ();
TRIM_TO_STERN_PINtimer = millis ();
WATER_GUN_PINtimer = millis ();
DIVECLICKONEAtimer = millis ();
DIVECLICKONEBtimer = millis ();
DIVECLICKTWOtimer = millis ();
LATCH1timer = millis ();
DIVECLICKONEtimer = millis ();

These are NOT timers. They are times. No R!

(PISTON_DIVE_PIN, HIGH);
(PISTON_SURFACE_PIN, HIGH);
(PUMP_DIVE_PIN, HIGH);
(PUMP_SURFACE_PIN, HIGH);
(TRIM_TO_BOW_PIN, HIGH);
(TRIM_TO_STERN_PIN, HIGH);
(WATER_GUN_PIN, HIGH);
(LATCH1, 0);
(DIVECLICKONE, LOW);

Useless ass crap. Get rid of this crap unless you have one damned good reason for it being here. If you do, there damned well needs to be some comments that explain WHY!

  if (LATCH1, HIGH)

Another stupid misuse of the comma operator. If it is NOT a misuse of the comma operator, and it certainly looks like it is, then there MUST be some comments that explain why you are doing something that LOOKS stupid.

In general, your code is severely under-commented and poorly indented. There is no excuse for either one. Comments take little time to write, and Tools + Auto Format will fix the crappy indenting in nothing flat.

Hi

attaching again

doubleclickattempt.txt (13.9 KB)

Sorry but I can't make sense of your code without the explanations I requested in Reply #5 and repeated in Reply #10

...R

Hi

attaching again

Without fixing a damned thing. I'm done trying to help.