PDA

View Full Version : Help with some Basic Stamp 2 programming for art project



Blake
05-13-2006, 05:02 AM
Hey, I'm a senior Sculpture undergrad at Cornell University, and I'm using some BASIC stamps in a few of my projects for my thesis. I was wondering if there was anyone who would be willing to provide me with some assistance in writing a few programs. I know the basics of pbasic but not a lot of complex language. I've been learning with the book, Physical Computing.

Here's what I'm doing:

I would like to control typewriters with solenoids. I have two typewriters typing different words on each. I have a bunch of solenoids arrayed with bicycle brake lines, so that they each punch one key, thus typing one character. The solenoids are activated by a motion detector. Thus if the motion detector sense motion, the solenoids might type out, "P" "R" "E" "S" "E" "N" "T" "," "<space>" and wait for the next detection. I need to write a program that takes into account the line length of the typewriter to occasionally press the "<return>" button. Also, I would like to incorporate another motion detector, that, when activated, interrupts the normal flow of the first detector, inserting a new word with other solenoids standing by.

So with the two typewriters, one might type "left, left, left, left" and the other might type "right, right, right, right" but then a third motion detector might insert the word "not" into it so that it becomes, "left, left, left, not, left, not, left, left, left" or "right, right, right, not, right" creating a new message when the viewer glances across both units.


I anticipate needing to know something about "counters" within the code to keep track of how many solenoids have activated.
If any of this sounds interesting, and you could help check my code or something, let me know.

thanks,
blake
bbf3@cornell.edu

Ryan Clarke
05-13-2006, 06:46 AM
Hi Blake,

We'd all be happy to take a look at your code as you go along.

Ryan

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Ryan Clarke
Parallax Tech Support

RClarke@Parallax.com (mailto:RClarke@Parallax.com)

Blake
05-13-2006, 12:59 PM
great! I'll try to have some more specific code ready in a day or two.

Blake
05-23-2006, 10:37 AM
hi everyone. sorry you haven't heard from me in a week or two. A friend of mine and fellow sculpture student died last saturday when his house burned down, and i've been coping with that for the past week. However, I am still making this sculpture and have now finished the hardware side of it.

a copy of my code is as follows:

' {$STAMP BS2}
' {$PBASIC 2.5}
INPUT 0
total VAR Word

sense:
IF IN0=1 THEN act:
GOTO sense:

act:
'r key
HIGH 1
PAUSE 300
LOW 1
'i key
HIGH 2
PAUSE 300
LOW 2
'g key
HIGH 3
PAUSE 300
LOW 3
'h key
HIGH 4
PAUSE 300
LOW 4
't key
HIGH 5
PAUSE 300
LOW 5
', key
HIGH 6
PAUSE 300
LOW 6
'<space> key
HIGH 7
PAUSE 300
LOW 7
total=total+7
IF total=65 THEN autoreturn:
GOTO sense:

autoreturn:
'<return>
HIGH 8
PAUSE 300
LOW 8
GOTO sense:
END

How does this seem?
I have trouble with the principle of switching between different sections of code using IF/THEN commands
At the end of the act: section, I am trying to have a variable count upwards each time the act: section is used, so that it will press return (go to the autoreturn: section) at 65 characters in length. Does anyone foresee any problems with this code?

Thanks ahead of time for your help,
I'm new at the world of PBASIC,

Blake
bbf3@cornell.edu (mailto:bbf3@cornell.edu)

Lee Harker
05-23-2006, 10:15 PM
Blake,
I see a couple things that would help your code. Since you are doing things that follow a pattern, you can use a loop to reduce your code to a few lines.

Example:
for keyloop = 1 to 7
high keyloop
pause 300
low keyloop
next

Also, if you add 7 to your total every time, it will never equal 65. You will want to pick a different number or use >= .
Another thing that would be useful is to make your return action a subroutine. That way you can use it from other places in your program.

Hope that helps.

Lee

SSteve
05-24-2006, 02:45 AM
Hi, Blake:

I've attached a program that uses a more generalized approach to typing words. It defines constants for each solenoid and builds words out of the constants. It then uses loops to type the words. Please note that the program compiles correctly, but I haven't been able to test it so there may be some logic errors.

The program I wrote will work for typing everything on one typewriter and uses all 16 I/O pins. You might run into the problem where using one pin per solenoid you are going to run out of I/O pins on the BS2 if you want to have three motion detectors and be able to type "left", "not", <comma>, <space> & <return> on one typewriter and "right", "not", <comma>, <space> & <return> on another. You might need to use a BS2p40 or maybe a Propeller.

When you want to post code of more than a couple lines, it's best to either attach it or use [*code] [/code*] tags (without the asterisks) around it. That way the spacing is maintained and it's much easier to read and use.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows

Blake
05-25-2006, 07:41 AM
Thanks for the good suggestions. SSteve, I don't understand how the "Thekey" command functions and what its purpose is. Previously in the code, you defined keys with the·DATA command, but here i don't see why it is named theKey.

READ wordAddr, theKey
·· DO WHILE (theKey <> 0)
····· HIGH theKey
····· PAUSE 300
····· LOW theKey
····· letterCount = letterCount + 1
····· WordAddr = wordAddr + 1
····· READ wordAddr, theKey

What does the <> mean?

SSteve
05-25-2006, 09:04 AM
"<>" means "not equal to".

theKey is a variable, not a command. I've stored the various words as sequences of values in EEPROM. Since the only way to access data stored in EEPROM is by reading it into a variable, I'm reading each value into theKey.

Here's how the Type_Word subroutine works:

The statement "READ wordAddr, theKey" reads the EEPROM data at the address wordAddr into the variable theKey. The HIGH, PAUSE, and LOW statements then set that pin high and low to type the key. letterCount is incremented then wordAddr is incremented. Now wordAddr points at the next address in EEPROM and that value is read into theKey and the loop starts again. When the value read into theKey is 0, the loop stops.

So to type "right, ", you set wordAddr equal to "word_right" and GOSUB Type_Word.

You can type any sequence of characters by creating a DATA statement that has a list of the characters you want followed by a zero. So to type "fortnight, " you'd have the line:


word_fortnight DATA key_f, key_o, key_r, key_t, key_n, key_i, key_g, key_h, key_t, key_comma, key_space, 0


and somewhere in the program you'd have:


wordAddr = word_fortnight 'Set wordAddr to point to the first byte in "fortnight, "
GOSUB Type_Word


I hope that explanation helps.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows

Blake
05-25-2006, 10:36 AM
thank you for the explanation Steve. I was confused as to how the variable "theKey" was assigned, but now i understand. Still, in your code where you have "WordAddr = wordAddr + 1", WordAddr should be equal to something like "key_r" or "key_space", etc. at any given time. Does saying "WordAddr + 1" simply move incrementally to the next data slot in the EEPROM and retrieve that value (for example, from "key_r" to "key_i"), or is it literally saying, for example, "key_r + 1"?

Again, thanks so much for the help,

Blake

SSteve
05-25-2006, 01:33 PM
Blake said...
Does saying "WordAddr + 1" simply move incrementally to the next data slot in the EEPROM and retrieve that value (for example, from "key_r" to "key_i"), or is it literally saying, for example, "key_r + 1"?

The former. WordAddr doesn't contain the values "key_r", "key_i", etc. It contains the address of those values. Say this is the way the BS2's memory winds up after the program is compiled:



Address Value
87 1 (key_r)
88 2 (key_i)
89 3 (key_g)
90 4 (key_h)
etc.



In this case word_right will have the value 87. The line "wordAddr = word_right" assigns the value 87 to the variable wordAddr. The line "READ wordAddr, theKey" assigns the value at location 87 to the variable theKey. So theKey gets the value 1. Then "wordAddr = wordAddr + 1" sets wordAddr to 88 and "READ wordAddr, theKey" assigns the value at location 88 to theKey. The loop stops when theKey is set to 0.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows

Blake
05-27-2006, 11:14 AM
Is this a problem?

How can I store a word value into the internal EEPROM?
The internal EEPROM of the BASIC Stamp module (used for both program and data storage) is organized and accessed in units of bytes only. Since a word value is actually two bytes it requires two consecutive memory locations to store it in EEPROM. You must break the word value into its lower and upper byte parts and use two WRITE commands to store the value, or two READ commands to retrieve it.

The following code demonstrates this for the BASIC Stamp 1 module:

W0 = 1250
WRITE 0, B0
WRITE 1, B1

The following code demonstrates this for the BASIC Stamp 2, 2e, 2sx, 2p24, 2p40, and the 2pe modules:
Temp VAR WORD
Temp = 1250
WRITE 0, Temp.LOWBYTE
WRITE 1, Temp.HIGHBYTE
also, i have attached the current updated program:

Blake
05-27-2006, 11:35 AM
oh no! the program needs four auxillary pins to cover all solenoids and sensors! How do you program these. It obviously isn't accepting "PIN 16, PIN 17, Etc."

?

Blake
05-27-2006, 11:42 AM
Okay, I added MAINIO to the beginning when i defined the first 16 pins (0-15) and then AUXIO for the last four (0-3). Will this work? Or do MAINIO's and AUXIO's need to be dispersed throughout the programming. Pins are never referred to directly within the program after defining constants, except by their new names. Is this okay?



Thanks,

Blake

Blake
05-27-2006, 11:55 AM
okay, hooked it up and downloaded the program, and nothing happened. crap@!

i think there may be something wrong with how i wired it. Its very simple though. Each pin is connected to the base of a tip120 darlington transistor. The collector is attached to a 24v·bus. the emitter goes to the positive end of a polarized solenoid. The·ground end of the solenoid goes to the ground. This seems logical right?

Thanks,
Blake

Post Edited (Blake) : 5/27/2006 4:05:08 AM GMT

Blake
05-27-2006, 12:16 PM
i have just done some reading in Physical Computing and there are two things i happened by chance to see. First, the ground·of the 2p40 and of the solenoids are separated. The 2p40 and three motion detectors are running on·their own 5V+ and ground, and the solenoids are hooked up to their own 24V+ and different·ground. Second, i do not have a snubber diode in my circuit at each tip120 darlington transistor. I assume these are the issues and that these are crucial to a functioning circuit. I will fix them tomorrow morning first thing.

Let me know if you have any other suggestions,
Blake

SSteve
05-27-2006, 12:51 PM
The trick is that you need to specify MAINIO or AUXIO before the statements that perform I/O, not before the pin definition.

I've modified your program. I guessed on the pins and I/O groups. I also had to make a couple assumptions, but you can change them if necessary. If you have trouble, let me know.

My assumptions:
1) "wrong" is typed on typewriter 2
2) "right" and "right is" are typed on typewriter 1

Here's how your detector logic works:
If detector_3 is on and detector_1 is on, "wrong. " gets typed.
If detector_2 is on and detector_3 is on, "right is, right, " gets typed.
If detector_2 is on and detector_3 is off, "right, " gets typed.

Is that the way you want it?

Keep in mind that the attached program compiles, but could still have logic errors. I'll have to leave the hardware hookup details to those with experience.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows

Blake
05-27-2006, 09:10 PM
You wrote:
Here's how your detector logic works:
If detector_3 is on and detector_1 is on, "wrong. " gets typed.
If detector_2 is on and detector_3 is on, "right is, right, " gets typed.
If detector_2 is on and detector_3 is off, "right, " gets typed.

Your assumptions are correct.
However, the detector logic is not.

Typewriter 2 operates independently of Typewriter 1 and uses only 1 detector, which is detector_3. If detector_3 = 1, then the typewriter should type "wrong,_", regardless of any other detectors.

Typewriter 1 should type "right,_" if detector_2 is on and detector_1 is off. If detector_1 is on, regardless of detector_2, typewriter 1 (on the left side) should type "right_is,_".

SSteve
05-28-2006, 01:04 AM
Blake said...
Typewriter 2 operates independently of Typewriter 1 and uses only 1 detector, which is detector_3. If detector_3 = 1, then the typewriter should type "wrong,_", regardless of any other detectors.

Typewriter 1 should type "right,_" if detector_2 is on and detector_1 is off. If detector_1 is on, regardless of detector_2, typewriter 1 (on the left side) should type "right_is,_".

Ok. I've made those changes in the attached program. I removed the detector tests from Type_Wrong and Type_Right and added a Type_Right_Is subroutine. All the testing is now in the main program loop. The Type_XXX subroutines simply type the appropriate word.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows

Blake
05-28-2006, 06:45 AM
I have finally worked out the kinks in the hardware!!! Now it is possible to test whether this program works. Its getting down to the line, my commencement ceremony is tomorrow at 9AM eastern, and my show is on Monday at 8AM eastern. I'm going to try and get this thing working at least by Monday. Thanks for all of your help thus far, I would have gotten nowhere on my own.

Thus far, with the current program, the right-side typewriter types "rog._" when the right hand detector (detector_3) senses movement. The left-side typewriter thus far does nothing no matter what. Additionally, when it gets to the end of a line, it does hit return, and move to the next line. It's awesome to watch even just at this phase.

I've tested everything with other simpler programs however, and all solenoids trigger correctly, so i think we have dealt with most hardware issues and are down to software.


Post Edited (Blake) : 5/27/2006 10:49:57 PM GMT

SSteve
05-28-2006, 11:33 AM
Tackle everything one element at a time. First make sure the interface to all the solenoids is working. Here's a simple program that will repeatedly type "rights<space><comma><return>" on one typewriter and "wrong<space><period><return>" on the other. Change pin assignments at the top of the program if necessary. If you need to change the I/O group for a pin, make that change in the DATA statement. Once this program works, transfer those changes to the original program.

As far as the detectors, it would be great if you could hook up LEDs to Aux I/O pins 4-6. Then you could run a loop like this:


AUXIO
DO
out4 = in1
out5 = in2
out6 = in3
LOOP



Then you could confirm that your detectors are working. If you can have a computer hooked up at the same time as the detectors, you could do something like this:


AUXIO
DO
DEBUG HOME, "Sensor 1 = ", BIN1 IN1, "Sensor 2 = ", BIN1 IN2, "Sensor 3 = ", BIN1 IN3
PAUSE 100
LOOP



You also need to look at the timing of when the detectors are read. Right now, the program first looks at detector 3. If it's active, "wrong. " gets typed. Then the program looks at detector 1. Is detector 1 still going to be active at that point? If not, you need to create three variables to store the detector values at the beginning of the loop like this:



'Variable section
detector1State VAR BIT
detector2State VAR BIT
detector3State VAR BIT

'Main program loop
DO
AUXIO
detector1State = detector_1
detector2State = detector_2
detector3State = detector_3
IF detector3State = 1 THEN
GOSUB Type_Wrong
ENDIF
IF detector1State = 1 THEN
GOSUB Type_Right_Is
ELSEIF detector2State = 1 THEN
GOSUB Type_Right
ENDIF
LOOP



Hopefully this will be enough to get you going. Good luck!

(If you do make any changes to the program, be sure to post your current version if you need any further help.)

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows

SSteve
05-29-2006, 09:44 AM
I just realized there's a big problem with my programs. They use zero as a stop value, but zero is a valid pin value. (I was thinking about zero-terminated strings when I wrote the program.) I changed the stop value to $FF and have attached corrected programs.

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows