Controller Programming

We are trying to extend and retract a cylinder with a button push. We’ve already made it work well with two different buttons, but now we’re just trying to make the joystick more user-friendly. We have all programmed in C++ and Turing languages, and have tried to incorporate that type of logic in our programs, but have failed miserably. For example, logically one would think that “p1_sw_top = 1” means that the button is pressed, but we have found that it is actually “p1_sw_top = 0”. Does Basic not allow If statements inside other If statements?

This is part of the program, and we want to know what part doesn’t work. We have declared count1 and assigned a value of 1 to it at the beginning of the program, outside the main loop.

if p1_sw_top = 0 then turn:
if count1=1 then left:
relay1_fwd = 0
relay1_rev = 1
count1 = 2
left:
if count1=2 then right:
relay1_fwd = 1
relay1_rev = 0
count1 = 1
right:
turn:

Another example program that we have tried is :

'if ((p1_sw_top = 0) &~ (count1=2))then turn:
’ relay1_fwd = 1
’ relay1_rev = 0
’ count1 = 2
'turn:

'if (p1_sw_top = 0) & (count1 = 2) then turn1:
’ relay1_fwd = 1
’ relay1_rev = 0
’ count1 = 1
'turn1:

For some reason, the controller doesn’t wait for a button to be pressed, it just sees “count1 = 1,” and extends.

Any help and/or suggestions would be greatly appreciated.

Remember that p1_sw_top will be 1 the entire time the switch is pressed. So, if you hold it down for 1 second, the relay will change back and forth about 40 times. What I do is store a bit (i call it p1_sw_top_last) that stores the state of the button last cycle. When p1_sw_top &~ p1_sw_top_last , then the button has just been pressed, so perform actions. Try this out:

when declaring variables:

p1_sw_top_last VAR bit
p1_sw_top_last = 0

in the main loop:

if NOT (p1_sw_top &~ p1_sw_top_last) then skipThis1:
if relay1_rev then fwd1:
relay1_fwd = 0
relay1_rev = 1
goto skipthis
fwd1:
relay1_fwd = 1
relay1_rev = 0
skipThis1:
p1_sw_top_last = p1_sw_top

Im gonna be testing this out tomorrow, so I’m not sure if it works.

If I understand this correctly, you’re making a toggle switch out of a momentary switch (in this case, port 1’s thumb button)…

Just a few hours ago, while I was in the lab, I found out that I needed to make this functionality, and now that I’ve seen this, it seems a lot easier.

Thank you both (Joelster for posing the question, and Curtis for answering) very much.

if count1= 1 | p1_sw_top = 0 then do:
relay7_fwd = 1
goto loop:
do:

if count1= 0 | p1_sw_top = 0 then do2:
relay7_fwd = 0
goto loop:
do2:

if p1_sw_top = 0 then s:
loop:
if p1_sw_top = 1 then j:
goto red:
j:
goto loop:
red:
if count1 = 1 then yo:
count1=1
yo:
if count1 = 0 then yo2:
count1 = 0
yo2:
s:

This is our other flaw…think you can make it work??? please reply asap!!

*Originally posted by Joelster *
**
This is our other flaw…think you can make it work??? please reply asap!! **

Well I see A problem. Remember your switches, joysticks, etc are read with the serin command at the top of the main loop.

Once you get to your loop: label, you’re just going to sit there spinning forever since you never execute the serin command again.

Since I’m not sure what you’re trying to accomplish with this code, I hesitate to try rewriting it… but I’ll give it a try:p

It looks like maybe what you’re wanting to do is turn on a motor when the switch transitions from open to closed, and then turn off the motor the next time the switch transitions from open to closed. Here is what I would do for that:


'if switch just pressed, turn motor on/off
if prev_sw = 1 or p1_sw_top = 0 then dont_change_relay
  relay7_fwd = relay7_fwd ^ 1      ' XOR toggles the bit
dont_change_relay:

prev_sw = p1_sw_top                  ' Save switch state for next time

Wouldn’t it be easier to just use a toggle switch in the first place?

Here’s what we did:

As I understand it, solonoids can’t have constant current applied to ‘em. Now, we didn’t want to use the joystick controls since you can accidentaly hit them in the wrong time. And since we were too cool for momentary switches, we used toggle switches. So basically our code does it so all that you have to do is flip the switch and the solonoid is pulsed out or in and then off (this is just for double solonoids, btw). This way we can have a cool-lookin’ flip switch but no harm done to the solonoids.

This is our code - I’m feeling a bit blue, so lets do something cool and help people out =)


if (R_G_Piston_p3_s4 = R_G_Piston_Last) then NotReset:
if (R_G_Piston_Counter <= DELAY) then NotResetA:
	R_G_Piston_Last = R_G_Piston_p3_s4
	R_G_Piston_Counter = 0
	relay4_fwd = 0
	relay4_rev = 0
NotResetA:
NotReset:

if (R_G_Piston_p3_s4 = R_G_Piston_Last) then NotToggle:
if (R_G_Piston_Counter > Delay) then NotToggleA:
	R_G_Piston_Counter = R_G_Piston_Counter + 1 + delta_t
	if R_G_Piston_p3_s4 = 1 then Next8a:
		relay4_fwd = 0		
		relay4_rev = 1		
	next8a:
	if R_G_Piston_p3_s4 = 0 then Next8b:
		relay4_fwd = 1
		relay4_rev = 0
	Next8b:
NotToggleA:
NotToggle:

if (R_G_Piston_p3_s4 <> R_G_Piston_Last) then NotNeutral:
	R_G_Piston_Counter = 0
	R_G_Piston_Last = R_G_Piston_p3_s4
	relay4_fwd = 0
	relay4_rev = 0
NotNeutral:

Okay, so what does all that garbage mean? Good question. I don’t know =D

Let me start by telling you what everything is
R_G_Piston_p3_s4 - The piston switch (p3_s4 = port 3, switch 4, is either a 0 or a 1)
R_G_Piston_Last - The SWITCH’s position in the last cycle (either a 0 or a 1)
R_G_Piston_Counter - Basically a cycle-counter
Delay - The amount of cycles you want the relay (solonoid) to be pulsed before switching off - i.e. a few seconds, if even that
delta_t - since this is a cycle-driven loop, delta_t calculates how many packets (and so cycles) were missed and adds approproatly. Serves no purpose other than making timing more exact, but since its no longer than 1, 2 seconds, timing really isn’t important, so this is pretty much useless. But again, this is the hardcore way of solving your problem. If you wanna use delta_t, search for the explanation on this board. Otherwise, just leave it out.

Okay, so now how does that code transform into logic, you ask? Well heres the theory behind it.

  1. You flip the switch
  2. It recognizes the switch is in a different position it was last cycle
    2a. If the switch is 0, relay is set to go fwd, if the switch is 1, relay go rev
    2b. Adds one to the counter variable, leaves the Piston_Last variable as it is
  3. Repeat step 2, always adding one to the counter
  4. Everytime step 2 is repeated, it checks to see if the counter is greater than the delay. If so, then x number of cycles have passed and time to turn the relay off
  5. Once the counter is greater than the delay variable, the code sets Piston_Counter = 0 (resets it), sets relayx_fwd = 0 & relayx_rev = 0 (puts the relay into neutral), and sets Piston_Last = the current switch position
  6. Now when the loop repeats (new cycle), it sees that the last position is = to the current position, so it does nothing, until you flip the switch

Thats the logic, now apply the logic to the code. Yes the code is dirty alias-wise. No we don’t care =D Took my friend and I a few days to get this working all nice and happy, and yes, you could simplify it by using two momentary toggle switches, but we’re hardcore. And, best of all, now we can add those military-style switches to make uber-hardcore piston controls =)

Supplying constant power to a single solenoid is not a problem. It is the double solenoids which are only supposed to be “pulsed”. If you are using a single solenoid, and want, for example, the top button to toggle it, I have some simple code to do this. You push it once and release, it goes out and stays until you press the button again, and it retracts. Let me know if this is what you’re looking for.

*Originally posted by thedillybar *
**Supplying constant power to a single solenoid is not a problem. It is the double solenoids which are only supposed to be “pulsed”. **

yeah, this code is for the double solonoids. But are you sure that the single ones can have constant current applied to them? I could have sworn they’re not supposed to

I think you can provide constant power to them, we have been while operating our robot for about a week now. Constant power is the only way to keep the pneumatic in the outward state if the default is the retracted state.

We decided to use the single instead of the double because w/ the single we are always providing force in one direction or the other. When the pneumatic is in, it’s being held in. And when the pneumatic is out, it’s being held out.