First John,
I realized last night during my bouts of insomnia that I was probably clear as mud. However, you will see from my comments to Woody that follow, that you will probably HAVE to learn how to do this yourself in order to get the Roboteq to do what YOU want it to do. What has been posted are "snippets" of code to do a specific thing, not complete programs. Some of these snippets will work as a simple script, but they will do only that one thing. In the end, you will need a program that does lots of things - check whether pulse or analog input is active, adjust output commands for pulse or analog depending on which is active, send just the motor values for the mode that is active. All of this has to be put into a program that is structured so that you can debug it if there are errors, so that you can modify it easily without re-writing the whole shooting match, and so that if you look at it a month later you can still tell what's happening. That's not an insignificant amount of work, and I don't think that you can really ask that someone else do it for you. Also, especially for readability, if you write it you will (hopefully) use a structure and add the comments you need to be able to later read it. If someone else writes it, even if that someone isn't prone to writing what's called "spaghetti code" (you can imagine what that means), it may forever be unintelligible to you so you'll have trouble maintaining it or modifying it. Your attitude, rather like that of the socially conditioned sixth grade girl who says "I can't do maths." just doesn't match with what all the rest of us know of your talents. You can and should, perhaps must, learn a bit of programming.
I tried to look on the web for a BASIC primer. There are some out there, but generally for much more complete BASICs than Roboteq's MicroBasic and with enough syntax differences that I didn't yet come across one that I think would lead you quickly to Roboteq scripting. A pretty simple one, if you can first forget about Roboteq in order to learn a bit of programming, is
http://www.gladlylearn.com/BlastOff.htm. Being stubborn, however, I'm going to repeat some of what I said yesterday again in a different way, starting from the question "What do we want a program to do?" and trying to put this in a Roboteq context. So ...
START HERE:
http://www.youtube.com/watch?v=9-liqdSlBd8 If you can follow this video, you CAN learn to write MicroBasic scripts for the Roboteq. If you can't follow this video, send back your middle school diploma.
NEXT:
What do we want a program to do? (As you tell everyone about your programming page - read the rest of this slowly enough and enough times so that every sentence makes sense.)
(1) take in some data. For the Roboteq that usually means reading one of the pre-defined Roboteq variables using GetValue. For example: GetValue (_CAI, 1) gets the analog internal command value for channel 1, which is usually motor 1.
(2) put that data somewhere so we can use it. We assign it to a variable who's name we hope we can remember. For example: vAnalogSpeed = GetValue (_CAI, 1) puts the number read from the Roboteq into a place called "vAnalogSpeed". Note that upper and lower case letters don't matter, but using mixed case can make stuff easier to read. I tend to start the names of my variables "v" as a reminder that this is a variable of my invention rather than one pre-defined in the programming language.
(3) do some calculations with those data. For numbers, Roboteq MicroBasic only knows integers, so it would think that 0.7 is 0, or 7.3 is 7. To fake real numbers, but use only integers, we have to go through some hoops. For example, if vAnalogSpeed is now 150 and we want it to be to 0.7 of this we can't do vAnalogSpeed = 0.7*vAnalogSpeed; the correct result is 105 but MicroBasic will give 0 because it thinks 0.7 is 0. So we first multiply by 70 to get 10500 and then divide by 100 to get 105: vAnalogSpeed = (vAnalogSpeed*70)/100. Notice the parentheses to make sure things get calculated in the right order; if we first did 70/100, the result would be 0.7 which MicroBasic will think is 0 and we're no better off than trying to use 0.7 directly.
There are also logical variables and arithmetic - these variables can only be TRUE or FALSE and the arithmetic we use compares things and decides whether the result is TRUE or FALSE.
(4) Make some decisions about what to do based on the input data or our calculated results. This is called BRANCHING and the most often used kind of branching is done with an IF construct. The simplest IF is just:
IF (something is true) 'this "something is true" is called a CONDITIONAL EXPRESSION. You don't have to remember terms like this except for the fact that you'll probably be reading them and it's useful to have some notion about what the writer is talking about.
THEN (do the following)
ENDIF
but you might also want to do something else if "something" is NOT true:
IF (something is true)
THEN (do the following)
ELSE
THEN (do this other following)
ENDIF
And part of the (do the following) might be doing another branch:
IF (something is true)
THEN
IF (another thing is true)
THEN (do the following)
ELSE THEN (do this)
ENDIF
ELSE THEN (do this other following)
ENDIF
One thing that's very hard to see here without indenting is that every IF has a corresponding ENDIF that tells the computer where that particular branch ends. If the IFs and ENDIFs don't match correctly, the program will either not compile (because it can't figure out what you intended) or will give unexpected results (because something was done at one decision point when it should have been done at a different one). With indenting, it's easy to see which ENDIF works for which IF.
Conditional expressions can be very simple, e.g. IF a>0, or can be pretty complex IF (a>0) AND (b<0) OR (c=0) and hard to follow. Simple conditionals usually mean complicated chains of IFs, complex conditionals shorten that chain. Long chains of IFs can be hard for a human to follow, but so can complex conditionals. Different programmers have different styles for doing something just as different writers have different styles for saying the same thing.
(5) Repeat the whole program, or some part of the program, over and over - this is called a LOOP and there are several different loop structures you can use. The simplest just uses:
LabelName: 'notice the : to tell MicroBasic that this is a label
.
. the lines that you want to repeat
.
.
GoTo LabelName
Simple, isn't it? There are only two things to add to help you use a label:/GoTo label loop. First, this loop will run for ever and ever and ever; unless there's something within it that can get you out it will never end. Second, and this applies to all loops, while it is running the computer can't do much of anything else, like the calculations that the rest of the Roboteq software has to do. So, one of the lines in here should be a Wait (xx milliseconds) to give the computer some time to do other things. If we're reading a joystick input, which we want to do pretty frequently, this might be Wait (20) - we'll read the joystick 50 times a second, if we're doing some kind of once-in-a-while thing, like sending some text to a computer screen, it might be Wait (2000). A millisecond is actually a lot of time for a modern computer, even a tiny one, and a 200 millisecond delay (for things that don't have to be "real time") is barely noticeable to a human, so that gives you an idea of what to use.
There are other kinds of LOOP structures and most of them automatically have some way to end the loop, so most programmers prefer these and some, me for example, avoid GoTo as much as possible because it's too easy to get yourself trapped in an endless loop. I'll just give an example of one, the WHILE loop:
WHILE (something is true)
.
.
. the things to do as long as "something" is true
.
.
.
ENDWHILE
This loop will not execute at all if "something" is FALSE to start with, and will exit as soon as it becomes FALSE.
As I said, there are lot's of other loop structures, e.g. FOR/NEXT, DO UNTIL/LOOP and others, but you'll learn about these later on. They're just all LOOPs.
(6) Do something with what you've calculated and/or decided You might want to PRINT something to a screen, or send a serial message, or make some fancy graph, but for controlling the RoboTeq you're mostly going to want to use SetCommand to tell the RoboTeq to do something. For example:
SetCommand (_G, 1, vSpeed) will tell the RoboTeq to make motor 1 go at vSpeed
or
SetCommand (_DSET, 2) to turn on digital output number 2
(7) Structure your program so that it is easy to read, easy to modify. There's a certain amount of art in this, and it means different things to different people, but basically we want to
put things we're likely to want to change up near the top
have a basic section that just gives an easily understood outline of what we're doing, but not the details
and separate sections that carry out those details
So, I might put a line like:
vMotorResistance = 100
near the top, because this is something that will be changed as we tune motor compensation for our particular motors
and I might create a variable
vMaxReverseSpeed = 70
near the top because, while I think 70% is good for reverse, I may find that I prefer 60% and I don't want to have to hunt through my program for that 70. I'll just use vMaxReverseSpeed instead of the number 70 in the routine for scaling speed and change this line at the top if I decide that 60 is better than 70.
I might have a main never-ending Label:/GoTo loop like this:
MainLoop:
GoSub FindInputMode
GoSub ScaleSpeed
GoSub MotorCompensation
Wait (20)
GoTo MainLoop
This just says that we're going to find out what input mode (pulse, analog, serial) is active, scale speed (for example, to 70% of max for speed in reverse) and that we're going to apply some motor compensation, but the details will be in a subroutines labelled FindInputMode, ScaleSpeed and MotorCompensation. The subroutine for ScaleSpeed would be anywhere below this and would then look like this (but would use CPI if FindInputMode found out that Pulse is in use):
ScaleSpeed: 'the : says that this is a label
'find out what speeds the two motors are set at:
vSpeed1 = GetValue (_CAI, 1)
vSpeed1 = GetValue (_CAI, 2)
IF (vSpeed1 < 0) AND (vSpeed2 < 0) 'the chair is being told to move backwards
THEN
vSpeed1 = (vSpeed1*vMaxReverseSpeed)/100
vSpeed2 = (vSpeed2*vMaxReverseSpeed)/100
ENDIF
SetCommand (_G, 1, vSpeed1) 'unchanged from original values if not moving or going forward, 70% of original value if going backwards
SetCommand (_G, 2, vSpeed2)
RETURN 'goes back to the next line in MainLoop
In other words, a label:RETURN is like a label:GoTo except that instead of going back to label, it goes back to the next line in the main program.
**********************************************************************************************************************************************
**********************************************************************************************************************************************
OK, that's basically what we want a computer to do, but we're dealing with a particular computer, the one that's in the Roboteq. So, the next thing to do is read Section 15 of the Roboteq manual until you thoroughly understand this, then read through, but don't by any means memorize, Section 16 to get an idea of what all the built in commands are.
Lastly, decide what you want YOUR program to do, break that down into pieces, write subroutines for those pieces, and then tie it together with a main loop that calls the subroutines. Start simple, don't expect to not make mistakes. If you get syntax wrong, you'll get a compile time error (which are often so cryptic that it takes a while to figure out what the error message means - and Roboteq did not include a list of error messages in the manual). If you get logic wrong, it will compile, but you will get an error when you try to run it. A run-time error may stop the program, set it into an unintended unending loop, or just give you strange results, like a motor turning the wrong way. Now you have to go back to your program and trouble shoot. Trouble shooting a program is really not unlike trouble shooting mechanical things, and you at least don't have to throw away a piece that you measure once and cut twice.
Comment out lines in the main loop (with a ') to see which one is causing the problem,
Comment out lines in the troublesome subroutine for the same reason
Set values to numbers you chose, e.g. vSpeed1 to 500 (half speed forward), rather than reading the RoboTeq calculated numbers, to see whether you've multiplied by 0 when you intended to multiply by 70/100 and so on
Add some PRINT statements to show some of the values on your computer screen to see if they're being calculated as you intended or just to know that you've actually entered a subroutine that you intended to enter. You might, for example, have screwed up an IF so that the call to that subroutine could never happen. Note: add a Wait(100) or more after every print to give time for info to get to your computer and give you time to read it.
YES YOU CAN!
Ciao,
Lenny
I've got to take a break from this now before I go into some nitty-gritty with Woody. Gee, this is rather like writing Genetics lectures, and though many think that Profs have it easy, it just ain't so.