My ActivityBot
Rsadeika
Posts: 3,837
I just recently received an ActivityBot, nice little kit. Also, "Good job" for the Learn Team. I put the kit together to the basic build point, no extras like the whiskers were added. I followed the Learn setup guide to calibrate the servos and such, plus I looked into their explanation for preliminary navigation, very good job. So far everything is working as expected.
Some general random thoughts, probably the next addition to the ActivityBot will probably be the XBee module. The cord puts some limits on functionality for the bot, but then you would need some kind of interactive program, with some scripting capability. Since I am temporarily using the included battery pack, that will probably to be changed to the Li-ion pack, but the problem with that is you have no way of knowing when your pack needs to be re-charged. I keep bringing that point up every time I get chance.
Below are a couple of very basic programs, for maybe a beginner, to do some basic turns. Try running them and see what the difference is, if any.
Ray
Some general random thoughts, probably the next addition to the ActivityBot will probably be the XBee module. The cord puts some limits on functionality for the bot, but then you would need some kind of interactive program, with some scripting capability. Since I am temporarily using the included battery pack, that will probably to be changed to the Li-ion pack, but the problem with that is you have no way of knowing when your pack needs to be re-charged. I keep bringing that point up every time I get chance.
Below are a couple of very basic programs, for maybe a beginner, to do some basic turns. Try running them and see what the difference is, if any.
Ray
/* turns1.c */ #include "simpletools.h" #include "abdrive.h" int main() { // Left turn 90 deg // LW RW drive_goto(-26,25); pause(1000); // Home position drive_goto(51,0); pause(1000); // Right turn 90 deg drive_goto(26,-25); pause(1000); // Home position drive_goto(-51,0); }
/* turns2.c */ #include "simpletools.h" #include "abdrive.h" int main() { // Left turn 90 deg // LW RW drive_goto(-26,25); pause(1000); // Home position drive_goto(26,-25); pause(1000); // Right turn 90 deg drive_goto(26,-25); pause(1000); // Home position drive_goto(-26,25); }
Comments
I just tried to do a spin2cpp conversion of the Tom Doyle IR_RemoteTest.spin program with no success. Going this route will probably take some time because it will need a complete rewrite in Spin, and then a functional conversion using spin2cpp. Maybe the Learn team has that C code already, so I am bringing it up here.
My thoughts on the IR remote set up is, probably a lot of the beginners have access to a remote control, and they could probably write a fairly simple program to use that setup. At least this way they can drive the ActivityBot around the room, or wherever they are located after they do the initial setup of the bot. Since the Activity board has a uSD, maybe an improvement to the program could be a way of loading some coded bot programs from the SD card, and have that run when selected via the remote control. Going this route you would probably have to create a bare minimum ActivityBot Programming Language (ABPL).
Ray
Maybe consider how you could use Phil's wireless XBee programming example with an ActivityBot, as the Activity Board design should support the necessary wiring. Using it with a Spin/ASM file is probably quite straight forward, but we will need to do some tool work to support it with the C compiler. I'll be sure that this improvement is on our internal planning agenda for the near future.
Andy has used the Simple IDE debug window with an XBee VCP on USB. This allows debug data to come back to the PC and should also be able to be used for wireless control through the debug window.
Ken Gracey
Some of you may remember Turtle graphics. That should be an easy control concept for a bot with no obstacles. Automatically overcoming obstacles would be interesting.
After looking at the spin2cpp conversion code, it looks like it could be quite a task to rewrite it to something that I think that I would need for an expanded functional program for manipulating the ActivityBot. Since the program starts up at least two cogs, that I know of, it will be difficult to figure out how to start up other cogs when necessary. But I guess it is better than nothing.
Ray
Ray
Ray
Each Cog has it's own data direction registers DIRA so the serial code print is using was set up in
Cog0 the main cog. My guess is print cannot control the tx pin in different Cogs.
Why not have each new Cog set a flag var indicating it is running and print that fact in the main line code
tom
Ray
For printing between cogs it will be necessary to lock the stream. For N ports, a lock would not be necessary, and would limit number of ports ability if it was added to libserial by default. The libfdserial code might benefit from a lock. I'm not sure if the standard printf provided by GCC locks the port or not.
If people look at libsimpletext.c (the test code for the library), they will find the different ways to use the simpletext library.
https://code.google.com/p/propsideworkspace/source/browse/Learn/Simple Libraries/Text Devices/libsimpletext/libsimpletext.c
The code at about line 110 shows how to close and reopen the simpletext console device.
The same idea can be applied to opening a new serial port or N ports on other pins.Currently fdserial can only open a port per COG, so it is limited to about 7 ports. The simple serial port can have as many ports as there are pin pairs (without locking).
The program works kind of weird, it looks like it is buffering the keypress of the remote control, I think. I looked at the code and cannot find the commands that need to be corrected. I am using the old Parallax black remote control, I have the IR on p2. The IR driver code is in the IR_Remote.c, if somebody wants to look at it to see if they can spot the problem, it would be a big help.
Ray
It works for most of us. Can we do a hangout so you can demo to me? Maybe on the weekend?
Ray
I moved on to adding the ping))), again the Learn tutorial is very helpful for doing this. I did find a problem with the instructions in the Learn 'Try this - roaming with ping)))'. In the program example it is missing: and drive_setRampSte p(10) should be:
Ray
Ah, I see the extra-spaces typo in the screencapture, thanks Ray, I'll fix it now. The screencap only shows the modified main (we usually don't give away the whole solution to the "Try This" sections, just show the changed area) but in this case I'll also add the int turn line.
Ray
It's definitely a tight squeeze, but I got the Li-on pack to fit and use the same screws and spacers as my PropBOE Bot. Just needs a little space where the corners of the battery circuit board touches the server mounts. A little wedging took place and one corner of the circuit board just started to bend a little as I tightened the screw. I made sure not to tighten the screw too much to avoid breaking the board.
dgately
Here's an ActivityBot SONY remote app.
http://forums.parallax.com/showthread.php/150260-ActivityBot-with-SONY-Remote
Hopefully it'll be a little less cumbersome to work with than the ported Spin object. The library is still preliminary. Please let me know if there's anything I can do to improve it, make it more useful, etc.
Thanks, Andy
Making one process the clearinghouse for other cog variable tends to make the coding a lot simpler because you can avoid stopping and restarting the serial terminal process in every cog. Here is an example where main is displaying shared variable activity within two other processes.
Andy
Below is a small test program, trying to get a good idea as to what is going on with the different libs. In the program when I press the CH_UP button, sometimes the wheels start turning real slow, and when I press the same button again, it seems to pick up some speed, not sure why, or how, that is occurring. After hitting the CH_UP button, then I started to hit the CH_DN button, instead of going backwards, it kept moving forward, but at a slower rate, at which time it eventually started to go backwards. So, using the same behavior, I decided to try to make the turns in an incremental way, not sure if that is working the way I expected.
Making the drive go faster and slower by pressing a button is a good idea, but it seems like it needs a transition point for changing direction and not speed. Not sure if you can achieve that level of control while using an IR remote, not conveniently anyway.
Next what I will do with the program below is have a new cog for IR control and a new cog for the abdrive stuff. Since I will be implementing an XBee cog which will have drive control commands, I figure multiple use of a particular function should be appropriate.
Ray
With your code, pressing and holding a button will ramp it toward a particular speed. If you let go of a button, it will hold that speed instead of slowing down. That's because there's no code that responds to when the ir_key function returns -1 after a timeout. The -1 indicates that it didn't get any messages (because you aren't holding down a key any more). You could press and hold the button for the opposite direction, but you will need to hold it long enough for it to complete the change; otherwise, it might just slow down some, like you observed.
If you want it to instead put on the breaks when you release a button, you can add the condition:
if(key == -1) drive_speed(0, 0);
The timeout for the ir_key is set to 50 ms with ir_tLimit(50). After the timeout (because you're not holding a button), it returns -1, the if(key == -1) drive_speed(0,0) statement would cause the loop to step the speed back down toward a speed of 0, 0.
Another way you could make it stop would be to treat the PWR button as a way of putting on the breaks. Instead of using drive_goto, use drive_rampStep.
if(key == PWR) drive_rampStep(0, 0).
If you use that instead of if(key == -1) drive_rampStep(0, 0), the ActivityBot will keep going at whatever speed you ramped it too, and you can press and hold the PWR key to put on the breaks. You can also press and hold a key in the opposite direction to slow it down. Keep holding, and it'stop briefly, and then reverse direction and start to speed up in that opposite direction.
The drive_rampStep function has turned out to be the best tool for sensor loops because it gets the wheels to a certain speed, but not to abruptly like drive_speed does. In contrast, drive_goto is just designed for fun with dead reckoning when getting started. It's not all that useful beyond that because it cannot be interrupted. I'm working on a drive_distance version that will run in another cog and monitor for if the calling function changed its mind about the distance.
That said, there is one really cool potential application for drive_goto with the TV remote. The application would wait for the remote handler to key in a list of distances, and the press a key to initiate the sequence. Then, it would go through all the maneuvers that were just keyed in.
Hope that helps, Andy
P.S. If you leave the bot position 1 when the wheels are supposed to be turning and then switch to 2, weird things can happen. Reason being, the control system thinks the wheels are supposed to be a long way away from where they are, and they go crazy trying to catch up. So, if you have been testing in position 1 and you want to switch to position 2, press and release the RST button to restart the program right after you switch to position 2. That'll put both its measured and actual distance back to zero.
1) Set and forget speed, breaks applied by pressing and holding power. Press and hold a different key for a second or so to fully change direction.
2) Apply breaks applied by letting go of a button for a while:
3) Full stop by just one press/release of PWR (not tested):
Ray
I tried working with drive_speed() to see if I could get more control, but I was running into problems when I tried too implement backward, left, and right control. I was trying to use a separate key for speed increase/decrease, maybe the lib itself should contain more drive command(s) control.
Ray
Ray
This reminds me of a problem I see when we take more than one TV remote controlled bot to a youth event. Two kids get remotes from different tables and take them to the same table. Then, they use them to control the same bot. One presses and holds the forward button. The other presses and holds the back up button. The bot understandably looks like it's having a seizure.
In the case of your code, we have two inputs, and allowing them to exert control over the bot at the same time can result in similar behavior. Several ways to handle this come to mind. First, if both inputs are coming in at the same time, the code could give one priority over the other. Another way to handle it would be to take the average of the two for robot control. A third way to handle it would be to lock out whatever input tries to interrupt the first input stream until that input stream is obviously done.
But, before we start on any of that, I'd like to make sure both our subsystems are good. We have working and tested TV remote code earlier in this thread. Could you please post some working and tested XBee control code (that controls through just the XBee?).
After we get those two pieces, let's talk about how we want to mediate control. On my end, I'll add locks to abdrive to prevent any timing issues, but locks still cannot prevent the spasmodic motions that result when two or more conflicting incoming commands are repeating themselves. That's where the mediation approach comes in: One could always have priority over the other, they could be averaged, or they could lock until the input data stops.
Andy
Ray
Here is the xbee control modified slightly. I'm hoping that if you also put the TV remote code into this format, we'll have an easier time merging the two and adding the arbitration code. In other words, modify your TV remote code so that it sets speedLeft and speedRight variables and lets the ab_nav function take care of calling the abdrive functions.
Andy
The one thing that I have noticed is, SimpleIDE reports: "Code Size 15,528 bytes (20,476 total)", and this is in CMM mode. Barely getting started and the available memory is starting to dwindle, fast. One option is using XMM, but this would be a major redesign of the existing program, not even sure if you could implement abdrive and still have IR_remote and XB_remote function as expected.
Ray
Also, I've noticed that it's possible to add a lot more code now that we've got the smaller footprint libraries for text messages, EEPROM, and other things. Support for terminal, text messages and etc. are already in the app, so it should only grow by small increments with each function. That's with the possible exception of SD, but if you stick with fread and fwrite, it will keep the increase in code size reasonable.