Big Problem With Trying to Control DC Motors with Pushbuttons
sv806
Posts: 14
I'm new to the basic stamp, my group is using it to control motors for a design project at school, we would appreciate any kind of help as we are in our last week and still cant get this program to work...
So the project is to control 2 motors. We want them to do several different sets of motions...like turn motor 1 on for 1.3 seconds and motor 2 on for .5 seconds. That would be an example of 1 procedure, out of many. We are using 2 H-Bridges which have 2 pins each to control Direction and Pulse Width. There are also 6 Switches which are being used as feedback to the Basic Stamp, so it knows which procedure to do next. There are 4 Push Buttons being used to also tell the Basic Stamp which code to do next. What we want the code to do is...if Inputs are High on the Pins 1 and 4 do (something). The following is only part of the code, the real code has a process for every 2 highs among each pushbutton and each Momentary Switch.
EDITED:Some people have asked for a clearer discription, here's a short clear version..."we are monitoring 10 switches, and when any two of them are high, do a specific code for those two being high. We want the code to always be ready though, always be checking to see which two are high and then immediately do (specific program for those two)."
THE PROBLEM: It just wont work, it might do one of the random procedures, but it wont do anything perfectly, the idea of reading highs on 2 inputs which send highs on 2 outputs sounds simple to me, I didn't think there would be so many problems.
Post Edited (sv806) : 4/25/2007 1:16:25 AM GMT
So the project is to control 2 motors. We want them to do several different sets of motions...like turn motor 1 on for 1.3 seconds and motor 2 on for .5 seconds. That would be an example of 1 procedure, out of many. We are using 2 H-Bridges which have 2 pins each to control Direction and Pulse Width. There are also 6 Switches which are being used as feedback to the Basic Stamp, so it knows which procedure to do next. There are 4 Push Buttons being used to also tell the Basic Stamp which code to do next. What we want the code to do is...if Inputs are High on the Pins 1 and 4 do (something). The following is only part of the code, the real code has a process for every 2 highs among each pushbutton and each Momentary Switch.
EDITED:Some people have asked for a clearer discription, here's a short clear version..."we are monitoring 10 switches, and when any two of them are high, do a specific code for those two being high. We want the code to always be ready though, always be checking to see which two are high and then immediately do (specific program for those two)."
THE PROBLEM: It just wont work, it might do one of the random procedures, but it wont do anything perfectly, the idea of reading highs on 2 inputs which send highs on 2 outputs sounds simple to me, I didn't think there would be so many problems.
' {$STAMP BS2} ' {$PBASIC 2.5} INPUT 0 'Pushbutton 1 INPUT 1 'Pushbutton 2 INPUT 2 'Pushbutton 3 INPUT 3 'Pushbutton 4 INPUT 4 'Momentary Switch 1 INPUT 5 'Momentary Switch 2 INPUT 6 'Momentary Switch 3 INPUT 7 'Momentary Switch 4 INPUT 8 'Momentary Switch 5 INPUT 9 'Momentary Switch 6 'Pin 10 Direction H-Bridge Vertical 'Pin 11 PWM H-Bridge Vertical 'Pin 14 Direction H-Brige Horizonral 'Pin 15 PWM H-Bridge Horizontal DO IF (IN0=1) THEN 'If Pin 1 receive a voltage do the following: HIGH 14 HIGH 15 PAUSE 375 LOW 15 LOW 10 HIGH 11 PAUSE 468 LOW 11 ENDIF IF (IN0=1) AND (IN4=1) THEN 'If Pins 0 and 4 receive a voltage do the following: HIGH 10 HIGH 11 PAUSE 937 LOW 11 ENDIF IF IN0=1 AND IN5=1 THEN 'If Pins 0 and 5 receive a voltage do the following: LOW 10 HIGH 11 PAUSE 468 LOW 11 LOW 14 HIGH 15 PAUSE 375 LOW 15 LOW 10 HIGH 11 PAUSE 468 LOW 11 ENDIF
Post Edited (sv806) : 4/25/2007 1:16:25 AM GMT
Comments
Give all of your "chores" a label: and use GOTO label:·when input cond. are met in main: scan.
I'm new and not very well versed in the language but I sometimes get it to work.
Hope I didn't confuse ya,
RC
·· if this or that GOTO 1
·· if this or that GOTO 2
·· and so on.....
·· GOTO main
It will continue to loop back to main: until one of the cond. is met, then it will GOTO whatever·label .
RC
And i assume we should add a "goto main:" after every procedure as well?
The HIGH and LOW commands automatically change the associated pins to OUTPUTS.
Yes, usually goto main after each chore unless the program specifies otherwise.
Good Luck, there are brilliant folks·in this forum·that can help you from here.
This is about my limit for now, I just hope I got this right.
Anyone PLEASE correct me if I'm wrong.
RC
You were right with monitoring 10 switches, and when any two of them are high, do a specific code for those two being high. We want the code to always be ready though, so the looping is important.
We were having problems with the code setting a pin to high and it not going back to low after the switch was let off...thats why I asked curious1 before about the necessity of having to set the inputs as inputs or outputs in the beginning of the program before the Main. I have attached what he has told me to do. There are six positions the motors take a solid rod to, the two motors are being used to control an x and y actuator individually...think about a manual car.
I also had trouble until I used pull down resistors on all of the buttons and switches on my project.
Without them, you never know what it will do next.
Your'e in good hands w/LSB
RC
curious1, thank you for letting me know about the pull-down resistors, i have researched them and they seem like an ideal item to integrate into my circuit, i have been using resistors...however, they these momentary switches (the 6) aren't only being used to send HIGHs to the Basic Stamp, they are also lighting up an LED when they are switched on...here is a schematic i made in PSpice. I have attached it to this post, and it might also help clear some things up, I am working on a bigger schematic for all the electronics right now, it should be done within the hour...
Ok, so with the DIRS set as:
DIRL = %00000000 'SET PINS 0-7 TO INPUT
DIRH = %11110000 'SET PINS 8-12 TO INPUT, 12-15 TO OUTPUT
Then we can write the switch pattern to a Word sized variable (we'll only be using 10 bits, but all the switches won't fit in a byte so...
Buttons VAR Word
Do
BUTTONS.LOWBYTE(0)=INS.LOWBYTE(0)
BUTTONS.LOWBYTE(1)=INS.LOWBYTE(1)
BUTTONS.LOWBYTE(2)=INS.LOWBYTE(2)
BUTTONS.LOWBYTE(3)=INS.LOWBYTE(3)
BUTTONS.LOWBYTE(4)=INS.LOWBYTE(4)
BUTTONS.LOWBYTE(5)=INS.LOWBYTE(5)
BUTTONS.LOWBYTE(6)=INS.LOWBYTE(6)
BUTTONS.LOWBYTE(7)=INS.LOWBYTE(7)
BUTTONS.HIGHBYTE(0)=INS.HIGHBYTE(0)
BUTTONS.HIGHBYTE(1)=INS.HIGHBYTE(1)
Loop
Now, BUTTONS always shows the pattern of our switch settings in the 10 LSBs (Use DEBUG BIN16 BUTTONS to see this), so we can look at any one switch with Buttons(LP)=1 (assuming switches are wired with pullups--they should read 0 unless pressed) or any group of switches with a bit comparison like:
IF BUTTONS= %00000000 00001001 then Gosub SHIFT_TO_FIRST 'Button 0 and 3 pressed
IF BUTTONS= %00000000 00000101 then Gosub SHIFT_TO_SECOND 'Button 0 and 2 pressed
This goes in the loop like:
Buttons VAR Word
Do
BUTTONS.LOWBYTE(0)=INS.LOWBYTE(0)
BUTTONS.LOWBYTE(1)=INS.LOWBYTE(1)
BUTTONS.LOWBYTE(2)=INS.LOWBYTE(2)
BUTTONS.LOWBYTE(3)=INS.LOWBYTE(3)
BUTTONS.LOWBYTE(4)=INS.LOWBYTE(4)
BUTTONS.LOWBYTE(5)=INS.LOWBYTE(5)
BUTTONS.LOWBYTE(6)=INS.LOWBYTE(6)
BUTTONS.LOWBYTE(7)=INS.LOWBYTE(7)
BUTTONS.HIGHBYTE(0)=INS.HIGHBYTE(0)
BUTTONS.HIGHBYTE(1)=INS.HIGHBYTE(1)
IF BUTTONS= %00000000 00001001 then Gosub SHIFT_TO_FIRST 'Button 0 and 3 pressed
IF BUTTONS= %00000000 00000101 then Gosub SHIFT_TO_SECOND 'Button 0 and 2 pressed
.
.
.
Loop
Each pattern then goes to a subroutine that moves your shifter to the proper position and then RETURNS to the loop to continue checking the buttons, or continues around the loop if no match is found.
Also, look at the Button Command, it shows how to wire the switches for pull up (if you’ve got a meter, check that the switch output is 0 unless the button is pressed) and how to debounce. Look at Gosub it explains a subroutine.
Oh, the reason we wrote the button values to a variable is so we could set the 4 MSBs to 0 without affecting the INS register. Use statements like: Buttons(15)=0 to do this before checking the pattern in the if statements.
IF BUTTONS= %00000000 00001001 'is this in order from pin 16 to pin 0, left to right?
and is this how it should look or at least the right order: ?
and when I check the syntax it shows me the attached image.
Post Edited (sv806) : 4/25/2007 5:07:45 AM GMT
1) Remove the Main: label, you don't need it.
2) The spaces in the binary values (%000...) are fore readability, take them out.
3) GOSUB works like goto, but returns to the line after the gosub when it hits the word RETURN. Each of your subroutines should end with RETURN lke:
SHIFT_TO_FIRST:
HIGH 14
HIGH 15
PAUSE 375
LOW 15
LOW 10
HIGH 11
PAUSE 468
LOW 11
RETURN '
SEND EXECUTION BACK TO THE LINE UNDER THE GOSUB THAT SENT IT.
4) 'is this in order from pin 16 to pin 0, left to right? Close-- pin 15 to 0
5) No endif needed if the whole statement is on one line.
What does this mean and why only 10?
BUTTONS.LOWBYTE(0)=INS.LOWBYTE(0)
BUTTONS.LOWBYTE(1)=INS.LOWBYTE(1)
BUTTONS.LOWBYTE(2)=INS.LOWBYTE(2)
BUTTONS.LOWBYTE(3)=INS.LOWBYTE(3)
BUTTONS.LOWBYTE(4)=INS.LOWBYTE(4)
BUTTONS.LOWBYTE(5)=INS.LOWBYTE(5)
BUTTONS.LOWBYTE(6)=INS.LOWBYTE(6)
BUTTONS.LOWBYTE(7)=INS.LOWBYTE(7)
BUTTONS.HIGHBYTE(0)=INS.HIGHBYTE(0)
BUTTONS.HIGHBYTE(1)=INS.HIGHBYTE(1)
BUTTONS.HIGHBYTE(2)=INS.HIGHBYTE(2)
??
IF BUTTONS= %00000100 00000101 THEN GOSUB SHIFT_TO_SECOND 'Button 10, 0 and 2 pressed.
your last post...you wrote button 10, 0, and 2
i think your code was set to 11, 0, and 2
or am i wrong?
and i assume it would work the same for a pattern for any single button to all 10?
also, the periods within "BUTTONS.HIGHBYTE(1)=INS.HIGHBYTE(1)" are they there so I can read it or do I need them there?
Ah, a trick question on the periods. The short answer is yes, you need them. there are ways around it, but they're there and work.
Post Edited (sv806) : 4/25/2007 5:40:53 AM GMT
If not, what happens? Think twice, describe it carefully first to yourself, then to the forum.
Did you check your switches, do they output 0 unless pressed?
Did you check your BUTTONS variable with DEBUG BIN16 BUTTONS ? Did you try something like:
DEBUG BIN16 BUTTONS,CR
IF BUTTONS=%0000000100000001 THEN DEBUG "--MATCH. SHOULD GOSUB MAIN",CR 'pin 0 and 8
To see if you're getting the Match that you expect?
Did read and then reread the Help file sections I suggested to see if you could solve the problem without help?
Do you have a teacher or advisor that can help without suffering the tedium of typing every word?
I understand that desperation can certainly steal the motivation work thoroughly and carefully, but NOTHING is more important in progamming than a methodical and logical approach. My advice comes from Martin C. Clarke's book The Martian Way: "Hurry, but don't rush."
BUTTONS=INS
Since INS is a WORD variable the statement HIGHBYTE with a bit modifier makes no sense as HIGHBYTE(0) is the same as HIGHBYTE with no modifier. The statement HIGHBYTE(1) would point to actually I am not sure.
After playing with the code I did find an anomaly that perhaps Parallax can address. The following code actually changes the variable on the right side of the equation. I assume this is because for example HIGHBYTE(1) modifier used with a word value is pointing outside the actual variable addressed. I put comments on the lines of code that modify the wrong variable but the code is invalid code, it compiles and runs because the syntax is correct but it sets up invalid pointers that overwrites your variable space. I don't have time to drill down to the specifics.
You also have gosub MAIN in two statements and no MAIN: lable in the program.
MAIN is typically not a name that is used for a subroutine as it is the MAIN entry point to a program. Not that it can't be used but it is typically not used as a subroutine name.
I used a variable PINVAR instead of the INS variable so I did not have to actually hold any pins high or low. Your code is not doing what you want it to do.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
Post Edited (metron9) : 4/25/2007 3:10:41 PM GMT
LSB, i ran the code, it is attached, and while i was using the debug bin16 statement, i was able to see what the bits were doing, and every time they did something that corresponds to an IF THEN statement, they did not do the subroutine...i do not know if its comparing it correctly or maybe there is a problem with it checking to see if the new 16bit is the same as any of the IF statements?
IF BUTTONS=%0000000100000001 THEN DEBUG "--MATCH. SHOULD GOSUB",CR 'pin 0 and 8
as I suggested last night?
Also, check your IFs that start with Pin 3-- the '1' is in the wrong place for the second button.
Just delete all this code
BUTTONS.LOWBYTE(0)=INS.LOWBYTE(0) 'pin0
BUTTONS.LOWBYTE(1)=INS.LOWBYTE(1) 'pin1
BUTTONS.LOWBYTE(2)=INS.LOWBYTE(2) 'pin2
BUTTONS.LOWBYTE(3)=INS.LOWBYTE(3) 'pin3
BUTTONS.LOWBYTE(4)=INS.LOWBYTE(4) 'pin4
BUTTONS.LOWBYTE(5)=INS.LOWBYTE(5) 'pin5
BUTTONS.LOWBYTE(6)=INS.LOWBYTE(6) 'pin6
BUTTONS.LOWBYTE(7)=INS.LOWBYTE(7) 'pin7
BUTTONS.HIGHBYTE(0)=INS.HIGHBYTE(0) 'pin8
BUTTONS.HIGHBYTE(1)=INS.HIGHBYTE(1) 'pin9
and replace it with this code
Buttons=INS
What I was trying to point out is HIGHBYTE(1) is a pointer that doesn't point to the buttons variable.
INS is a variable that has all of the pins bits set if the pin is high and zero if the pin is low so you just check these bits.
You don't even need the BUTTONS variable
You can say
IF INS=%0000000000001001 then do something
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
Of course you are right; reading INS directly is more efficient and shorter. My intent was to make the relationship between INS bits and switches more transparent and aid understanding (same reason I didn't suggest a loop to copy the bits into BUTTONS). BUTTONS, too, my be written to without consequence-- allowing one button to set many bits (I'm still not sure why it takes more buttons than there are gears). It also allows for comparing old and new patterns of presses --suggestions I did not make, but considered in writing the code.
Of more concern to me is that HIGHBYTE causes a problem; in testing the code I wired only two buttons and tried them in two positions each, it didn't occur to me that the high byte would respond any differently than the low byte. While I appreciate knowing this, it creates more questions than it answers. Perhaps this weekend I will have more time to test this, or perhaps Parallax staff will weigh in to clarify how I should use this correctly.
In any case, I appreciate your stepping in to correct my error and I hope that SV806 has not suffered for it.
As far as the HIGHBYTE and LOWBYTE usage with modifiers (0...x) I see it this way.
A word value BUTTONS VAR WORD for example only has 2 bytes.
HIGHBYTE and LOWBYTE so a modifier in either HIGHBYTE or LOWBYTE other than 0 as 0 is the same as no modifier has no meaning even though you can execute the code.
I find these modifiers to be easy to use and understand without adding the numerical index modifier to it. The documentation says:
as well as this
Now I have been programming in assembler for a long time and accessing parts of arrays in this manner is quite confusing.
It aslo gos on to read..
So it is confusing or can be to use these modifiers with array values (1...xxx). I don't think many programmers ever need to use them as there are so many other ways to access the bits, nibbles, and bytes via their own memory register names.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Think Inside the box first and if that doesn't work..
Re-arrange what's inside the box then...
Think outside the BOX!
Using the syntax BUTTONS.HIGHBYTE.BITX , x being whichever bit you are addressing works·with the previous code examples, what is the advantage of using the modifiers in this situation , and if used in other situations would it work if you declared it as 16 bit array before using it.
Jeff T.