Single Click On/Off Using the Trigger in EasyC

I’ve posted a few pictures of my senior project, and before my presentation I’ve been working with Easy C to get the cathodes that are attached to my robot to light up and stay lit after a single click of the left trigger. I then wanted the cathodes to turn off once the trigger was clicked again. The cathodes are connected to the RC using a Spike Relay. I have been using EasyC to program my robot. I do not have the laptop that is used for programing with me but I believe my current code is:

if(p1_sw_trig && n == 0)
{
OItoRelay(1,1,1,1);
n = 1;
}

if(p1_sw_trig && n == 1)
{
n = 0;
}

This turns the light on with a single button click, but the cathodes do not always turn off with the next click. I was wondering if anyone knew how to make this work, rather than have it work half the time or using two buttons to turn it on and off. Thanks in advance!

-Ira

I’ve never written C where && means both values are equal to the value on the right of the ==. I’ve always done it if (p1_sw_trig == 0 && n == 0)…

Maybe try that?

This how we did a click on click off


    if(CLAW_BUTTON == 1 && claw_toggle_state == 0)       // Code to handle toggle
    {
        CLAW_OPEN = !CLAW_OPEN;
        CLAW_CLOSED = !CLAW_CLOSED;
    }

    claw_toggle_state = CLAW_BUTTON;

Since the value of a trigger is already essentially a boolean you can just use it as itself, no == needed. So what he has is the same thing as (p1_sw_trig == 1 && n == 0)

Yep, I have the variable p1_sw_trig set when the trigger is pressed.

I dunno if this is causing the problem, but I’d put in a little time delay before it can switch states, because, as coded, if you held the trigger down too long the system would ‘flicker’ between the two states.

I have no experience with WPIlib, so I do not know if this could be the issue, but you don’t set the relay to zero in your second if statement, so I would think it might just stay at that value set earlier. Again, I have no experience with WPIlib, so I don’t know if this could be the issue.

It has been a few months since I’ve done computer programming, so from what I’m getting now, if the button is pressed and the claw_toggle_state = 0, and CLAW_OPEN and CLAW_CLOSED becomes not what it’s previous state was. The claw_toggle_state then becomes 1 when it is pressed.

This means in my code I should have:


if(p1_sw_trig && cathode_toggle_state == 0)
{
    OItoRelay(1,1,1,1);
}

cathode_toggle_state = p1_sw_trig;

I think that should be right, but feel free to correct me.

I was thinking that was the problem, as I tried using a counter for every button press and it still didn’t work all the time. I’ll try putting in a little bit of a time delay during the second if statement and see what happens.

I also tried setting the relay to zero in the second statement, and the results were not too good. I don’t remember the exact response though. This current code does work, but I am missing a step in turning it back off. It does turn off on some presses, but sometimes it does not for a few or many clicks.

You don’t really want to toggle the state of the lights when the trigger is active. You want to toggle when the trigger becomes active. You need to keep track of whether or not the trigger is pressed, and only do the toggle action when it is pressed now, but was not pressed last time.

The code bear24rw posted is a good example of how to do it.

I’m still very much a beginner at programming for a robot, and haven’t really coded anything in the last few months. If it is at all possible, can someone give a breakdown of the code that Bear24rw posted. I just want to make sure that I understand what is going on, as I am still a bit fuzzy. Thanks to everyone who’s helped me so far!

When I need to do something like this I write the program so that it waits until the first cycle after I let go of the button to toggle it. This way it is like:

if (pressed)
{
     if (not pressed)
     toggle;
}

This is how we do it, although we have since developed and function call method that is a little more sophisticated than this sample. But this sample does work.

static unsigned char p1_sw_trig_prev = 0;

if ((p1_sw_trig == 1) && (p1_sw_trig_prev  == 0))
    relay1_fwd = !relay1_fwd;

p1_sw_trig_prev = p1_sw_trig;

So what is all of this and what does it mean…

  1. We define a static variable to hold the contents of the state of the button to be compared with on the next pass through the program loop.

  2. We say if the trigger is being pressed and was previously in a released state then change the state of relay1_fwd. But if not don’t do anything.

  3. The relay1_fwd = !relay1_fwd statement causes relay1_fwd to change states. If relay1_fwd initially was zero, it becomes 1 and vice versa.

  4. We then save the state of the trigger in our static variable to use in the comparison next time through.

What will happen now is every time you pull the trigger and release it will case the relay1_fwd to toggle between on and off.

What you are accomplishing here is making your trigger into a toggle switch of sorts. Click once it’s on, Click again it’s off, click again it’s on, click again it’s off and so on…

I hope this helps you to understand better what is happening.

Thank you very much for the full breakdown! I’m pretty sure I can do this now. Thanks to everyone for all their help and I’ll post about my results once I get the code loaded on the robot.

Ok, I got the code to work, bit it took a little bit of tweaking. It may be how I set it up though. Either way, I’m able to have the cathodes toggle on and off with the trigger. This is the code I used:


if(p1_sw_trig && toggle_state == 0)
{
   toggle = !toggle;
}

delay(100);

toggle_state = p1_sw_trig;

if(toggle == 1)
{
   OItoRelay(1,1,1,1)
}

For some reason, without the delay, the program would have the light stay on only when the trigger was held, then not do anything on the second click. On the third click however, the cathodes would stay on after the trigger was pressed. I think it has to do with the amount of time you hold the button down, but I’m not entirely sure. If someone does have an answer to that, it would be greatly apprciated to know for future projects. And again, thank you to all who contributed to this! Doing beginners programming on a computer is a bit different than programming for a real world object.

Even though I’m not a C programmer, I’ve done this with my TI-89 before when making a program…

It would be something like this I guess


//NOTE: THIS IS NOT C CODING AT ALL AND IF YOU USE THIS, YOU WILL GET ERRORS!!!
define lastvalue //lastvalue can be any variable
 define cathodespike //this would be replaced by the particular spike you will have set to control your cathode

do:
if lastvalue==(not equal)p1_sw_trig and p1_sw_trig=1 cathodespike=1 then
   cathodespike=0
   lastvalue = 1
endif
if lastvalue==(not equal)p1_sw_trig and p1_sw_trig=1 and cathodespike=0 then
cathodespike=1
lastvalue = 1
endif
lastvalue = p1_sw_trig
loop

With this code, there is no delay and no chance of the light blinking on and off if the trigger is held in a closed state.

It is my belief that the syntax of your IF statement when compiled is causing the comparisons at execution time to be something like this…

IF (1 && 0 == 0)
IF (0 && 0 == 0)
IF (0 && 1 == 0)
IF (1 && 1 == 0)

Instead of what you really want which is more like this
IF (0 = 1) && (0 = 0) False
IF (1 = 1) && (0 = 0) True
IF (0 = 1) && (1 = 0) False
IF (1 = 1) && (1 = 0) False

Try this syntax instead and take out the delay and see what happens.
if((p1_sw_trig == 1 ) && (toggle_state == 0))