Shop OBEX P1 Docs P2 Docs Learn Events
autoAB_prj — Parallax Forums

autoAB_prj

RsadeikaRsadeika Posts: 3,837
edited 2013-11-14 15:43 in Learn with BlocklyProp
Since the other thread is getting a little long, I decided to start its own thread. Basically this is to see how close to autonomy the ActivityBot can get. The basic program below has, what I think, are the minimal support libs that will be necessary. And this is the first big hurdle: Code Size 27,052 bytes(31,044 Total). A brief observation follows.

Of course, so far the biggest use of RAM is the SD support code, I am starting to get the feeling that it may not be able to get any smaller, and I do not see a different solution at hand.

ABdrive, in order to work correctly, has to be run in its own cog, therefore limiting the possible use of XMMC mode. Maybe there is a way to code it so it does not prohibit XMMC mode use, I do not know.

I added <sys/rtc.h>, because the bot has to have a sense of time while it is operating, especially for any kind of data logging, and that would be a major operation or part of the autonomy. I also added the serial support libs, because a feature that I had in mind would be for the bot to contact the base station to get the "real time and date" to start its own internal clock.

I decided to go with a very small IR_remote segment, I think that is the most sensible way of starting the robot, and if the robot gets super smart, you can always press a button on the remote to start a return home procedure.

So, it sort of looks like this is doomed from the start, but some people might have some suggestions as to how to get around some of the problems I observed.

Ray

Comments

  • SRLMSRLM Posts: 5,045
    edited 2013-11-09 18:52
    Sounds pretty big for what you have. First off, I'd make sure that -gc-sections is set (along with -ffunction-sections and -fdata-sections to make it most effective). I think SimpleIDE does this by default, but I don't know. That should save a few KB.

    Next, I would step through your code and make sure that you're not using redundant libraries. The most common is with serial. I'd make sure that you have only one serial section, and it's used wherever you need it. No printf for sure. I see from your main autoAB_prj.c file that you're using a number of different serial drivers. You'll need to pick one and stick with it. Printf is nice and handy (especially with the %s type modifiers), but it's pretty big. It should go. You'll need to make sure that none of the libraries use printf either, otherwise that will pull it in.

    For a rough comparison, I have a project that uses SD, I2C, and serial that is ~24KB. It's all about trimming the fat: finding redundancies and unused code, and cutting it out.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-10 04:29
    Thanks SRLM for looking at the code. Your comments should be greatly appreciated by the beginners, or new C programmers.

    The first point I want to make, I tried to set up the program in simple view, just like some of the new people are being instructed at the Learn site. This is probably an exercise in, what exactly can you do while using simple view, along with the simple libraries.

    The one thing that SRLM noticed was that I used printf(), the reason that I used it was that if I use, the normally used print(), in this case, I get a compile error - "...hub overflow." This is the first time that I have seen that error, I guess that means that it has exceeded the 32K limit, but I thought that I would see that with the use of printf(). So, I am not sure if that is a bug, or just something weird that is occurring.

    Doing some more thinking about what is to be accomplished, maybe this exercise should start by not using any libraries at all, and developing specific functions to accomplish what would be necessary to achieve the outlined program. Having said that, maybe the Learn site should get into teaching how to create drivers, starting with the servos and how to keep the two wheels functional at all times during a call during the program. Maybe then approach a good understanding and use of the encoders, then move on to the other things like serial I/O, the ping, the remote, other things on the Activity Board, ..., etc. I know "Hello, World" is a good first glance of C, but we are using this to work with the Activity Board.

    Now back to my outlined program, if I strip out all of the header files, what exactly could I accomplish?

    Ray
  • SRLMSRLM Posts: 5,045
    edited 2013-11-10 04:50
    The point isn't so much to get rid of everything and do it all from scratch. You'd just have to recreate most of it anyway*. It's to cut away duplication. If you have both printf and fullduplexserial then you have two sets of code to do the same thing (serial). The challenge is to go through what you have and take away the redundancy.

    * And recreating code is just throwing away all the development effort that has been put into what you have already. It's helpful if you want to learn how to write a particular object, but otherwise think carefully before you write it yourself.

    On a particular note about printf: I've noticed a large decrease in size if you don't use the % modifiers.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-10 08:24
    As suggested, I started code optimizing by removing the fdserial header and the associated library, and low and behold there was no difference in the program code size. But the strangest thing is that I am still using:
      xbee = fdserial_open(7, 6, 0, 9600);
    
    and everything still works. I thought by using just the libsimpletext you would be forced to use simpleterm_open(), which is what I cannot use. The documentation only covers simpleterm_open(), plus how and when to use it. So, here is another strange thing that is happening.

    At this point I am not sure what else you could remove, short of possible redundant code in the actual libraries themselves. If you are going to do that, isn't that basically starting from scratch? Am I missing something completely obvious to everybody else?

    Ray
  • jazzedjazzed Posts: 11,803
    edited 2013-11-10 08:34
    Rsadeika wrote: »
    I thought by using just the libsimpletext you would be forced to use simpleterm_open(), which is what I cannot use. The documentation only covers simpleterm_open(), plus how and when to use it. So, here is another strange thing that is happening.
    The simpletext library functions include simpleterm, but will support any compatible driver. The fdserial library simply "extends" simpletext. Extends in this case means you get simpletext functions plus the special fdserial functions.
  • SRLMSRLM Posts: 5,045
    edited 2013-11-10 15:05
    To be pedantic, I suggested that you get rid of printf. But whatever the case may be, you have to get rid of the object from your entire project, not just your top level file. This means anywhere it is called you have to substitute something else (or not do it). That's why removing printf might be easier: I suspect that it's only in a few places, and can be removed without any negative effect.

    And even if you have to modify the library to fit your needs it's still much less work then "starting from scratch".
  • jazzedjazzed Posts: 11,803
    edited 2013-11-10 15:36
    SRLM wrote: »
    To be pedantic, I suggested that you get rid of printf. But whatever the case may be, you have to get rid of the object from your entire project, not just your top level file.
    #include "simpletext.h"
    #define printf print
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-10 16:19
    I was only using the printf() to verify that the <sys/rtc.h> was in fact alive and well, it will be removed once I have that part working the way I want. While I was checking things out I did notice that when I remove the the lines that refer to the SD, then the plain print() version would work without showing a compile error. But even without using the printf() it is not showing that much of a return of RAM.

    I did notice that another large code grabber is the <sys/rtc.h> itself, maybe I should look into some kind of function that would act like small clock, but do not know how well the date part would work. This still looks to me like you have to grab the smallest code segments of these different functions like rtc, SD, and others. Not so sure that this is going to work out like I was hoping.

    Ray
  • SRLMSRLM Posts: 5,045
    edited 2013-11-10 16:43
    jazzed wrote: »
    #include "simpletext.h"
    #define printf print

    Wouldn't that only work for the current compilation unit? I'd think that you would need to use -D on the compile line to get it "global".
  • jazzedjazzed Posts: 11,803
    edited 2013-11-10 17:16
    Ya -Dprintf=print is probably better.


    Ray,

    One of the big hogs when using SD or other filesystem support is fprintf ... which is just like printf.
    Replace fprintf with sprint(buffer, "something %d", number); and fwrite(buffer ...) more or less.

    BTW, regardless of fprintf in SD stuff, the SD Card drivers in CMM will eat about 8KB of memory.
    Converting SD card spin to C is not much better and you lose functionality.

    What kind of an RTC do you have?
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-11 03:58
    What kind of an RTC do you have?
    I don't, I for got to add the soft part, meaning softRTC. Yesterday I was thinking about having a function, maybe a port of the Spin clock program that is available, and have something along those lines to get away from using <sys/rtc.h>, but even a new function would have to run in its own cog, so...

    I think that the beginning of this thread is going to be used as, documenting the real limits of the ActivityBot functionality, in other words, what do have to work with. The key item, as I see it is the SD, so I might as well just deal with the fact that there is only 22K of actual code space to work in, I averaged up because that functionality will probably grow in code size, slightly I hope. Some key items that are missing, a compass, a horn, fancy bracket for the ping, and a real RTC. Not only do we have code restraints, we also have to deal with the breadboard, that also has a fixed space limit.

    The horn is not to much of a problem, there is now a bracket that can be used for attaching it to the frame, no breadboard incursion, same goes for the ping bracket. The horn would become very useful as a locating device, there might be a time when it gets under your bed and it is not moving. For the ping in its current state, a fixed position it really puts some limits on the full potential of ping.

    The compass is essential because it would add another bit of important data to the navigation aspect, a sense of real direction. This could add to resolving the issue of the stall pattern, the bot wheels are turning but the bot is not moving. I will have to look into the compass, in terms of communication, is it I2C or serial, or something else.

    The RTC has a similar concern, I2C or ... The other concern is where does it get located on the breadboard, very limited space. A big concern could be if it is I2C, there is no buss, so you have to give up a couple of pins for that purpose, plus some support electronics.

    Now I have to look into how to resolve the issues just described, but I think the bot autonomy could be achieved, in a very limited way.

    Ray
  • jazzedjazzed Posts: 11,803
    edited 2013-11-11 08:43
    Rsadeika wrote: »
    I don't, I for got to add the soft part, meaning softRTC.
    The main issue is with using the asctime() and other time library functions. Underneath asctime() uses printf variants.

    It shouldn't be too hard to make a simple library that does things like getHours(time), etc.... Want to help define that?
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-11 12:29
    Want to help define that?
    I will have to give that some thought as to what I think I need. At the moment, my thinking is, probably something simple like getHours(time) which returns an integer value, 1 - 23. And maybe something like getDay(date) which returns an integer value 1 - 31. Since this will be used for data logging purposes, specifically naming files and folders, I hope the SD program can do folders. A folder naming could be 111113, and a file convention could be 152230_0.log, assuming the SD can do more than 7.3 format. Still not sure about all that.

    Today I was looking at the global_Roam() function to see how that will be changed to be the core or central method for doing the mapping(navigation). I am still missing a key component, how do I get or figure out distance traveled as input from the encoder? The way that I am seeing this is, once the global_Roam starts, it will probably check to see if the SD card has a folder for the day, if not create one. Then it will create a file with a time stamp(161113_0.log) which will data log the movements for a particular run. The log file would probably contain a ping reading, a compass heading, a time stamp for start of bot movement, a time stamp for any derivation from the true course, or straight line, and of course a time stamp if the bot stops or pauses.

    This is just an overview of a concept, probably I am missing something. I know that somewhere along the line the bot will have to make decisions based on comparison of data that has already been obtained, so the contents of the files will have to make some sort of comparison sense, I think, or is this overly ambitious for the ActivityBot?

    Ray
  • jazzedjazzed Posts: 11,803
    edited 2013-11-11 13:15
    Not sure about overly ambitious :) More HUB memory would be nice, but that ain't gonna happen any time soon.

    There must be a way to convert encoder ticks to distance. Nikos mentioned something about using the encoder as an odometer in another thread.

    As far as RTC goes, I was thinking of using get/set for date-time attributes, and get/set time for fake RTC updates.

    Functions get/set for seconds, minutes, hours, ampm, month, monthday, yearday, year could be used to set seconds since the computing epoch.

    The actual fake RTC is already implemented in propeller-gcc. We may need rtc_open/close or start/stop functions to simplify things.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-12 04:01
    This time/date business could be a thread all of its own, never the less, what I plan on is, sort of an init procedure at the time you power on the ActivityBot. The procedure would be, start up the SD, get the fdserial going, and then the time/date function. This function will only work if it can make a connection to a program on the PC via XBee to download the real time/date values. Now, of course, I will have to find out the specific details, like what kind of variables have to be worked with, will the PC have to manipulate the variables to something <sys/rtc> expects, and so forth. Since this would be an important part of the program, I think I will have an init error function which basically show a solid flashing of the LEDs meaning, you have to do a fresh power on of the ActivityBot.

    Since I am not making any headway on the encoder part, I think I will try to implement some thing on this auto load of the time/date. Not sure if I will just do a simple Python script or try to add the functionality to the existing pyGUI program that I have. Maybe at the same time have a limited use of the global_Roam function to create some files on the SD and log the time/date. This might give me an idea as to how much code would be necessary for this small job.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-13 05:40
    I have been experimenting with a function that is supposed to take in some values and set the <sys/rtc>, but the time/date that it is showing is not the correct date. Some time ago jazzed provided me with a program to basically set the <sys/rtc>, what I did was I pulled out the code lines that I thought would be the simplest form to achieve this, not working as expected.

    The actual goal of init_td() function will be, convert an incoming data variable, via XBee, which will be in the form of, now.strftime(" %m-%d-%y %H:%M:%S\n") , so the function can set the clock.

    Anybody have any insight as to what I got wrong here?

    Ray
    void init_td(void)
    {
      struct timeval tv;
      struct tm t;
      char *endp;
      char year = "2013", mon = "11", mday = "13", hour = "6", min = "13", sec = "30";
    
      t.tm_isdst = 0;
      t.tm_year = strtol(year, &endp, 10);
      t.tm_mon = strtol(mon, &endp, 10);
      t.tm_mday = strtol(mday, &endp, 10);
      t.tm_hour = strtol(hour, &endp, 10);
      t.tm_min = strtol(min, &endp, 10);
      t.tm_sec = strtol(sec, &endp, 10);
    
      tv.tv_sec = mktime(&t);
      settimeofday(&tv, 0);
    
    }
    
  • SRLMSRLM Posts: 5,045
    edited 2013-11-13 05:48
    This won't work:
    char year = "2013", mon = "11", mday = "13", hour = "6", min = "13", sec = "30";
    

    You should try this:
    char [b]*[/b] year = "2013", mon = "11", mday = "13", hour = "6", min = "13", sec = "30";
    

    Edit: See jazzed's answer below.
  • jazzedjazzed Posts: 11,803
    edited 2013-11-14 09:11
    SRLM wrote: »
    This won't work:
    char year = "2013", mon = "11", mday = "13", hour = "6", min = "13", sec = "30";
    

    You should try this:
    char [B]*[/B] year = "2013", mon = "11", mday = "13", hour = "6", min = "13", sec = "30";
    
    Niether will work. The comma operator in C is very bad ... even in for statements.

    I recommend breaking the comma habit even if you've been doing it for 30 years because some intern could come along and mess it up by adding ', ampm = "AM";'.

    If you must use it, it would be this.
    char [B]*[/B]year = "2013", *mon = "11", *mday = "13", *hour = "06", *min = "13", *sec = "30";
    
    Using '*hour = "06";' makes it possible to reuse the variable, but it is not a recommended method.

    Below is the preferred method for many reasons including, easy to get right, and less source control conflicts. Using const forces not using the variables as storage which could otherwise cause problems.
    const char [B]*[/B]year = "2013";
    const char *mon = "11";
    const char *mday = "13";
    const char *hour = "6";
    const char *min = "13";
    const char *sec = "30";
    
  • SRLMSRLM Posts: 5,045
    edited 2013-11-14 15:43
    Thanks for the correction.

    There's a good discussion of this on SO: http://stackoverflow.com/questions/2704167/type-declaration-pointer-asterisk-position
Sign In or Register to comment.