RemoteBot program
Rsadeika
Posts: 3,837
This is the start of the RemoteBot program, the first post contains a starting point with just the diluted RemoteBot.c code shown. I am showing the code so everybody can look at the statements that I have made, and if their are any objections, lets get it out of the way. From this point I will be putting everything into a zip file which will contain the use of SimpleIDE exclusively.
This is a working piece of code, and I notice that the code size, using CMM, is at 14,232 bytes. I am just getting started and I am at the half way point of memory available already, I guess code optimization starts now.
Ray
This is a working piece of code, and I notice that the code size, using CMM, is at 14,232 bytes. I am just getting started and I am at the half way point of memory available already, I guess code optimization starts now.
Ray
/** * @file RemoteBot.c * * * This is the main RemoteBot program start point. */ #include <propeller.h> #include <stdio.h> #include <stdlib.h> #include <sys/sd.h> #include <dirent.h> extern _Driver _SimpleSerialDriver; extern _Driver _FileDriver; _Driver *_driverlist[] = { &_SimpleSerialDriver, &_FileDriver, NULL }; char *FindChar(char *ptr, int val); FILE *stdoutfile; FILE *stdinfile; FILE *cmdinfile; void Help() { printf("Commands - help, quit, \n"); } char *SkipChar(char *ptr, int val) { while (*ptr) { if (*ptr != val) break; ptr++; } return ptr; } char *FindChar(char *ptr, int val) { while(*ptr) { if (*ptr == val) break; ptr++; } return ptr; } int tokenize(char *ptr, char *IOtokens[]) { int num = 0; while(*ptr) { ptr = SkipChar(ptr, ' '); if (*ptr == 0) break; if (ptr[0] == '>') { ptr++; if (ptr[0] == '>') { IOtokens[num++] = ">>"; ptr++; } else IOtokens[num++] = ">"; continue; } if (ptr[0] == '<') { ptr++; IOtokens[num++] = "<"; continue; } IOtokens[num++] = ptr; ptr = FindChar(ptr, ' '); if (*ptr) *ptr++ = 0; } return num; } int CheckRedirection(char **tokens, int num) { int i, j; for (i = 0; i < num-1; i++) { if (!strcmp(tokens[i], ">")) { if (!stdoutfile) { perror(tokens[i+1]); stdoutfile = stdout; return 0; } } else if (!strcmp(tokens[i], ">>")) { stdoutfile = fopen(tokens[i+1], "a"); if (!stdoutfile) { perror(tokens[i+1]); stdoutfile = stdout; return 0; } } else if (!strcmp(tokens[i], "<")) { stdinfile = fopen(tokens[i+1], "r"); if (!stdinfile) { perror(tokens[i+1]); stdinfile = stdin; return 0; } } else continue; for (j = 1 + 2; j < num; j++) tokens[j-2] = tokens[j]; i--; num -= 2; } return num; } /* This routine closes files that were open for redirection */ void CloseRedirection() { if (stdinfile != stdin) { fclose(stdinfile); stdinfile = stdin; } if (stdoutfile != stdout) { fclose(stdoutfile); stdoutfile = stdout; } } /** * Main program function. */ int main(void) { int num; char *IOtokens[10]; uint8_t IObuff[40]; stdinfile = stdin; stdoutfile = stdout; cmdinfile = stdin; waitcnt(CLKFREQ + CNT); printf("Start RemoteBot\n"); while(1) { if (cmdinfile == stdin) { printf(":"); fflush(stdout); gets(IObuff); } else if (!fgets(IObuff, 80, cmdinfile)) { cmdinfile = stdin; continue; } num = tokenize(IObuff, IOtokens); num = CheckRedirection(IOtokens, num); if (num == 0) continue; if (!strcmp(IOtokens[0], "help")) Help(); else if (!strcmp(IOtokens[0], "quit")) break; else { printf("Invalid command\n"); } CloseRedirection(); } printf("System Stop\n"); return 0; }
Comments
The stdio file functions and standard printf are pretty big. There should be enough space left to do many useful things in CMM. Of course it's always good to optimize for size where possible on Propeller. We can put PASM in to "ECOG" if necessary and save some space if there is enough PASM.
I look forward to following you on this project. I've been putting off doing my own PropBOE bot, but I have one with the tank tracks sitting on my desk and it is a little lonely sometimes. My grandson loves playing with the bot. There is some servo and ping code here somewhere on my PC that I've used. I'll see if I can find it. I do have some XBEE stuff I bought in the summer, but I have to find it LOL. I also have some Bluetooth modules for experimenting.
I've been taking classes, but now that they are over I have more time for focused projects like this.
--Steve
Since working with the PropBOE for a couple of days, some personal observations - the use of a dead load( as opposed to a spring load) uSD reader, on this board, is looking like it could be a real inconvenience. I have noticed that once you plug in the XBee module, fiddling around, inserting and extracting the uSD card will be a real test of your patience, and it might make a hot load of the uSD card, not feasible. I am already looking around for some rubber tipped needle nose pliers. Also for this project it would have been nice to have some built in IR, just like they have on the QuickStart HIB, I know you can not have everything on a single board. The other possible inconvenience, since I will have the li-ion boebot battery pack on board my boebot, how do you determine the charge status, via software, of the battery pack? I do not see a real solution for this, at this time. So, it looks like this project may have some very real limitations of usage. Now onto testing of the uSD reader.
Ray
I wonder if anybody is working on a diagnostic suite for the Propeller and related boards, so the next time a glitch shows up it could be narrowed down very quickly to find out if it is hardware or software related. I guess it would have to be done in PropGCC, I do not see Spin as a viable alternative for something like that. Maybe those tools are already available, but hidden somewhere on the forum.
Ray
On the RemoteBot I have 0,1, 2 commands that the base unit should respond to. 0 - Sends out "RemoteBot\n", 1 - Turns on an LED, 2 - Turns off the LED. On the RemoteBot program I am using a spin2cpp converted XBee.spin program, that seems to be working pretty good. On the base unit I thought I would try to develop a C utility that would control the XBee module. So, any help would be appreciated.
Thanks
Ray
Ray
Ray
Ray
As far as '\n' goes, different programs send different characters for enter. In the SimpleIDE, the terminal can be set to force using '\n' for enter instead of '\r'. I do not have xbee set up yet to test this. I'll have to turn my office upside down to find it
I also picked up an XBee PC module, which I tested with my personal terminal program, that worked without any problems. I will probably have to develop a specific terminal program so I can talk to the boebot, although the terminal program that I have will probably work for the short term.
The project for tomorrow will be to zero in the servo drives, and come up with some commands for making the boebot move back and forth. Anybody have any C code examples for doing this?
The other stuff that I got, Digital Wheel Encoder, a PING, and a Sensirion temp module, I think my boebot will be a working robot. Man am I going to need a lot of C code examples.
Ray
I want to get this XBee interaction sorted out before I start to zero in the servo drives.
I gave up on the pthread version, it was also having problems with the buffer, plus when I started up another pthread the program compiled but it crashed when I tried to use it. I guess I want to get something somewhat reliable to work with before I start driving the boebot around from a remote terminal.
Ray
A couple of things, I am not sure if the speed adjustment is working correctly, when I tried it, seemed like the speed was not being affected. The other thing, I can not figure out what kind of threading the program uses. When I run the program in CMM and LMM it works as expected, but when I tried it in XMMC, the program did not work. So, it seems that the program is not using pthreads, but what do I know.
Ray
Ray
From the header for example ....
Ray
There is no solution.
Pthreads is designed to be used for general computing purposes. You can not use waitcnt() with pthreads because it breaks scheduling since the thread will hog the processor. Even if pthreads was implemented using pre-emptive multi-tasking, pthreads would not be deterministic enough to run a servo.
So, you see, there is no timing deterministic solution using pthreads. However, one could use usleep() and test for CNT to be a certain value. However, there is no guarantee that you will end up with exactly the wait time that you want though, and it gets worse with more pthreads. So, it's better to do what's natural with Propeller.
This situation highlights what Propeller is all about: I.E. Separate COGs doing deterministic things.
Similar things can be done with timers in other MCUs but there is always the possibility of over-running the time allowed for a task (processor hogging) in that situation.
--Steve
I guess another explanation that I need is what the heck is this doing:
DIRA |= pinmask;
OUTA &= ~pinmask;
OUTA |= pinmask;
OUTA ^= pinmask;
Is this changing the value of pinmask? Since I have pinmask = 18, is it changing it to 0? I sort of figured out the use of waitcnt() as a method of doing pulse width modulation, I think, but the bitwise stuff is really got me stumped. Once I get the speed control issue resolved, I may try the encoder stuff that I bought.
Ray
Now I will be adding the code for the left wheel, and hopefully the program will run as expected.
Ray
Attached is a better version of my original program.
It provides a reasonable speed control. As is, the slowest speed is 10 percent of maximum. The speed control in the cog threads is much improved.
If you want to calibrate your servos, set variable StopNoPulse = 0 first.
I changed the command set a little and have added code to demonstrate a good way to do character at a time input.
Note that I moved the pin numbers to the PropBoeServos.c file. Also the API function botSpeed(int rate); has been added.
The new command set using the SimpleIDE terminal is:
Normal Keys
+ = increase speed by 10 percent
- = decrease speed by 10 percent (stops if speed goes to zero - change this if you like)
f = go forward
b = go back
l = turn left
r = turn right
L = spin left
R = spin right
s = stop
Keypad Keys (may behave differently with non SimpleIDE terminal)
up arrow = go forward
down arrow = go back
left arrow = turn left
right arrow = turn right
home = spin left
page up = spin right
end = stop
The biggest problem that I noticed was, when the robot starts, it is in a speed of 20, but the robot has a very significant pull to the left side. As you increase the speed the left pull lessens and at the speed of 70, in a short distance, it starts to run straight. I think that once it is run at full speed, probably a long distance run will be pretty much straight. I did not try any of the other commands like 'l', I do not know which way it will turn, or how it will turn left. Not sure how or where that left pull got introduced with the new program. Could it be something different with the HUB board?
The "new thing" is the use of dprintf(), is this a new addition to the PropGCC? What is the difference between printf() and dprintf()? Not sure why you would want to use dprintf(). I also noticed you are using the "no buffering" setting, which works nice, eliminates the use of hitting the enter key. This will work very nicely with my C# robot terminal program, will not have to double click the GUI buttons.
On a more general observation of using the PropBOE and the boebot, using C, I think the robot setup needs two boards. One board would run the servos and any other peripheral device(s) that need(s) a deterministic control, and uses the separate cog setup. The second board could be setup using threads, maximizing the use of flash RAM, for a much larger program, which would enable the robot to do much more stuff, and perhaps have a better chance of running in auto mode. And of course what would the code look like that would be necessary for communication between the two boards?
Ray
I'm looking at the bot from the front. HUB board is a generic Propeller+80MHz+32KB configuration.
I notice a slight pull on my bot. Servos may behave differently with different settings.
You could try calibrating your servos:
1) set StopNoPulse = 0 ... maybe that should be default but i was thinking not sending any pulse would save battery
2) rebuild and run
3) verify servos don't move
I used dprintf (which is a #define printf ... see propboe.h) so I could turn off printing with a one line change.
Printing will be turned off if you change propboe.h line 8 as follows:
#define dprintf // printf
We can use COG code for driving servos instead of LMM/CMM threads. Then you can use XMMC, etc....
I'm not really interested in adding another propeller to my bot, but serial ports are easiest to use.
Ray
The point I was trying to make is that the servos should be calibrated (adjust using parallax screwdriver phillips end in the hole) so that the servos don't move at all. Then they should behave much better. If the servos are not calibrated, they will never work the way they should. The BOE-BOT manual recommends following such directions.
I found my xbee stuff. Here is my main file. To use it, make a new project and add PropBoeServos.c. Don't define TEST.
This works pretty good. I added a C calibrate command incase you want to tinker with it - it will set StopNoPulse to 1 for other commands.
I'm off to buy a classical guitar now.
--Steve
Ray
I had the same problem with the servo adjustments and had to pull apart and reassemble the bot. The approach is generic, however I see your point about using software to fix it. Most likely it would be easy to add some commands to adjust a "trim" variable in the servo code.
However, I've also been considering another servo approach using one cog for both servos written in pasm. That would mean only two cogs in use for the same functionality.
My son and grandson are enjoying playing with the xbee controlled bot right now. When they are tired of it, i'll program more.
--Steve
http://www.newspycam.com/Mini_Wireless_WIFI_Portable_WIFI_IP_SPY_Camera_2b_Stand_26_Adaptor_for_Iphone_Ipad_26_Androids/p1090014_4988830.aspx
FORWARD FORWARD
Counterclockwise Clockwise
(CCW) (CW)
Left Side Right Side
Center
1.6ms(1600) Fast 1.5ms(1500) No Move 1.4ms(1400) Fast
. .
2.0ms(2000) 1.0ms(1000)
. .
2.8ms(2800) Slow .3ms(300) Slow
Rotation Rotation
Pulse increases 0ms(0) Stop Pulse decreases
I notice that this chart looks like Smile, but maybe somebody will get some use out of it.
I looked at it, looks very nice, waiting to see how that works out for you. I noticed Parallax sells a contraption for rotating a PING around, I wonder if that little CAM would fit on there instead of or with the PING. Not sure how I would go about adding video streaming to my C# robot terminal program.
Once I get the servos centered, and the wheel encoder mounted, I think I will look into maybe adding a compass. Taking a glance at the encoder docs, it looks like they cover using the EEPROM for storing some of the data that the encoder provides, I wonder if this would be a good time to start thinking about adding access to the uSD, in the program now?
Ray
The other thing that I noticed, on the PropBOE, are the servo pins, it seems that they are pretty flimsy, at least on the board that I have. I have my servo wires on p18 and p19, and I noticed that they were bent over, enough that it concerned me that something was not right. I did have to straighten them out with some needle nose pliers. Now I am not sure as to how reliable those pins are. I think I am going backwards with this project.
Ray