Shop OBEX P1 Docs P2 Docs Learn Events
My ActivityBot - Page 2 — Parallax Forums

My ActivityBot

2

Comments

  • jazzedjazzed Posts: 11,803
    edited 2013-09-19 11:27
    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.

    Very good advice that all Propeller C users should follow. People who have too much experience to use the libraries can ignore this and make their own hole ;)
  • David BetzDavid Betz Posts: 14,516
    edited 2013-09-19 13:38
    jazzed wrote: »
    Very good advice that all Propeller C users should follow. People who have too much experience to use the libraries can ignore this and make their own hole ;)
    Or they can buy the Propeller Memory Card so they can use one of the XMM modes. :-)
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-09-19 14:29
    In the program below I am trying to add a command(s) startroam/stoproam, in XB_remote, which I am having some trouble figuring out how to do it properly. I want to be able to start/stop in XB_remote, and then add something to the IR_remote to do the same thing. In the global_Roam() cog, I can start the roam function with the startroam command, but the stoproam command is not working, not sure why. Any ideas?

    Ray
    ///////////////////////////////////////////////////////////////////////////////
    /*
     * abpl.c
     *
     * The ActivityBot program.
     * 
    */
    #include "simpletools.h"
    #include "abdrive.h"
    #include "simpletext.h"
    #include "ping.h"
    #include "fdserial.h"
    #include "sonyremote.h"
    
    
    
    volatile unsigned int IRpin = 9;
    
    //static volatile char xbInBuf[40];
    static volatile int xbCog;
    static volatile int speedLeft, speedRight;
    static volatile int roamcmd;
    
    
    serial *xbee;
    
    
    unsigned int IRstack[40 + 50];
    unsigned int XBstack[40 + 50];
    unsigned int abstack[40 + 50];
    unsigned int roamstack[40 + 50];
    
    // Function prototype
    void IR_remote(void *par);
    void XB_remote(void *par);
    void ab_nav(void *par);
    
    void global_Roam(void *par);
    
    
    ///////////////////////////////////////////////////////////////////////////////
    int main()
    {
      // Add startup code here.
      char inBuff[40];
    //  int getBuff;
      char getBuff;
    
      pause(300);
      print("The ActivityBot\r");
    
      int ircog = cogstart(&IR_remote, NULL, IRstack, sizeof(IRstack));
      pause(500);
      int xbcog = cogstart(&XB_remote, NULL, XBstack, sizeof(XBstack));
      pause(500);
      int abcog = cogstart(&ab_nav, NULL, abstack, sizeof(abstack));
      pause(500);
      int roamcog = cogstart(&global_Roam, NULL, roamstack, sizeof(roamstack));
      pause(500);
     
      while(1)
      {
        putChar('#');
        getBuff = getStr(inBuff,40);
        if(!strcmp(getBuff,"quit")) break;
        else
        {
          putLine("Invalid Command!");
        }
        
    //    pause(400);    
      }
      putLine("Program Stopped!");  
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* IR remote control */
    void IR_remote(void *par)
    {
      int key;
      ir_tLimit(50);
    
      while(1)
      {
        key = ir_key(IRpin);
        if(key == PWR)
        {
          speedLeft = 0;
          speedRight = 0;
        }
        if(key == CH_UP)  // CH_UP -> Forward
        {
          speedLeft = 32;
          speedRight = 32;
        }
        if(key == CH_DN)  // CH_DN -> Backward
        {
          speedLeft = -32;
          speedRight = -32;
        }
        if(key == VOL_UP)  // VOL_UP -> Right
        {
          speedLeft = 16;
          speedRight = 0;
        }
        if(key == VOL_DN)  // VOL_DN -> Left
        {
          speedLeft = 0;
          speedRight = 16;
        } 
    //    pause(50);  
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* XB remote control */
    void XB_remote(void *par)
    {
    
      char inBuff[40];
    
    
    /*                     Rx  Tx mode BAUD */
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(500);
      writeStr(xbee,"XBremote started.\n");
    
      while(1)
      {
        writeStr(xbee,"> ");
        readStr(xbee, inBuff, 40);
        if(!strcmp(inBuff,"onled"))
        {
          high(26);
        }
        else if(!strcmp(inBuff,"offled"))
        {
          low(26);
        }
        else if(!strcmp(inBuff,"gostop"))
        {
          speedLeft = 0;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"gofore"))
        {
          speedLeft = 32;
          speedRight = 32;
        }
        else if(!strcmp(inBuff,"goback"))
        {
          speedLeft = -32;
          speedRight = -32;
        }
        else if(!strcmp(inBuff,"goright"))
        {
          speedLeft = 16;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"goleft"))
        {
          speedLeft = 0;
          speedRight = 16;
        }
        else if(!strcmp(inBuff,"startroam"))
        {
          roamcmd = 1;
        }
        else if(!strcmp(inBuff,"stoproam"))
        {
          roamcmd = 0;
        }
        else
        {
          writeLine(xbee,"Invalid Command!");
        }    
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    void ab_nav(void *par)
    {
      int speedLeftOld  = speedLeft;
      int speedRightOld = speedRight;
      while(1)
      {
        if(speedLeftOld != speedLeft || speedRightOld != speedRight)
        {
          drive_speed(speedLeft, speedRight);
          speedLeftOld = speedLeft;
          speedRightOld = speedRight;
        } 
        pause(20);
      }
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    
    void global_Roam(void *par)
    {
      int turn;
      roamcmd = 0;
      while(1)
      {
    //    if(roamcmd == 1)
        while(roamcmd != 0)
        {
          speedLeft = 32;
          speedRight = 32;
    //    while(ping_cm(8) >= 20) pause(5);
    
    //    turn = rand() % 2;
    //    if(turn == 1)
    
    //    {
    //      speedLeft = 16;
    //      speedRight = -16;
    //    }
    //    else
    //    {
    
    //      speedLeft = -16;
    //      speedRight = 16;
    //    }
    
    //    while(ping_cm(8) < 20);
        }
    //    else
    //    {
    //      roamcmd = 0;
    //      high(27);
    //      pause(500);
    //      low(27);
    //      pause(500);
    //    }
      }
     
    }
    
    
  • edited 2013-09-20 10:52
    Hi Ray,

    I'd recommend removing the global_roam and just take care of it in ab_nav. Here is some (not tested) code that shows the general idea of an approach that I think will work.

    <<edit>> This code is not helpful, please disregard. <</edit>>
    void ab_nav(void *par)
    {
      int speedLeftOld  = speedLeft;
      int speedRightOld = speedRight;
    
      while(1)
      {
        if(roamcmd == 1)
        {
          int turn;
          while(roamcmd == 1)
          {
            speedLeft = 32;
            speedRight = 32;
            while(ping_cm(8) >= 20) pause(5);
    
            turn = rand() % 2;
            if(turn == 1)
            {
            speedLeft = 16;
            speedRight = -16;
            }
            else
            {
            speedLeft = -16;
            speedRight = 16;
            }
            while(ping_cm(8) < 20);
          }
        }
        else if(roamcmd == 0)
        {
          if(speedLeftOld != speedLeft || speedRightOld != speedRight)
          {
            drive_speed(speedLeft, speedRight);
            speedLeftOld = speedLeft;
            speedRightOld = speedRight;
          } 
        }
        pause(20);
      }
    }
    

    Andy
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-09-20 14:09
    Below I added in the code that Andy provided, unfortunately it is not working as expected. This morning I was working on this problem, and the code that I came up with was very similar to the snippet that Andy has, except I was still using global_roam. The code below works as expected UNTIL you activate roamcmd, then the program locks up and none of the keys on the remote respond. I sort of think that something weird is occurring with the use of "while(ping_cm(8) >= 20) pause(5);". I am not certain if there is something different with the ping_cm() or if it is the way it is used within a while(). I even tried to come up with something that did not use a while() loop and used an if loop with a ping_cm(), it seemed like the ping))) was not responding, the green LED was not flashing.

    In the program, the XB_remote, I use the startroam and stoproam commands. In the IR_remote I use the ENTER to startroam, and MUTE to stoproam. Thinking about the remote controller, as I mentioned earlier I have the old Parallax black model, and the model that Parallax sells now, the 3-function model, has fewer function keys that are available. To avoid confusion for anybody that is using the program, I will try to use only the keys that are available on the newest model, so maybe adding the number keys to the header file might be appropriate, at least that way I can use the ONE and ZERO keys for roam.

    Ray
    ///////////////////////////////////////////////////////////////////////////////
    /*
     * abpl.c
     *
     * The ActivityBot program.
     * 
    */
    #include "simpletools.h"
    #include "abdrive.h"
    #include "simpletext.h"
    #include "ping.h"
    #include "fdserial.h"
    #include "sonyremote.h"
    
    
    
    volatile unsigned int IRpin = 9;
    
    //static volatile char xbInBuf[40];
    static volatile int xbCog;
    static volatile int speedLeft, speedRight;
    static volatile int roamcmd;
    
    
    serial *xbee;
    
    
    unsigned int IRstack[40 + 50];
    unsigned int XBstack[40 + 50];
    unsigned int abstack[40 + 50];
    unsigned int roamstack[40 + 50];
    
    // Function prototype
    void IR_remote(void *par);
    void XB_remote(void *par);
    void ab_nav(void *par);
    
    //void global_Roam(void *par);
    
    
    ///////////////////////////////////////////////////////////////////////////////
    int main()
    {
      // Add startup code here.
      char inBuff[40];
    //  int getBuff;
      char getBuff;
    
      pause(300);
      print("The ActivityBot\r");
    
      int ircog = cogstart(&IR_remote, NULL, IRstack, sizeof(IRstack));
      pause(500);
      int xbcog = cogstart(&XB_remote, NULL, XBstack, sizeof(XBstack));
      pause(500);
      int abcog = cogstart(&ab_nav, NULL, abstack, sizeof(abstack));
      pause(500);
    
     
      while(1)
      {
        putChar('#');
        getBuff = getStr(inBuff,40);
        if(!strcmp(getBuff,"quit")) break;
        else
        {
          putLine("Invalid Command!");
        }
        
    //    pause(400);    
      }
      putLine("Program Stopped!");  
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* IR remote control */
    void IR_remote(void *par)
    {
      int key;
      ir_tLimit(50);
    
      while(1)
      {
        key = ir_key(IRpin);
        if(key == PWR)
        {
          speedLeft = 0;
          speedRight = 0;
        }
        if(key == CH_UP)  // CH_UP -> Forward
        {
          speedLeft = 32;
          speedRight = 32;
        }
        if(key == CH_DN)  // CH_DN -> Backward
        {
          speedLeft = -32;
          speedRight = -32;
        }
        if(key == VOL_UP)  // VOL_UP -> Right
        {
          speedLeft = 16;
          speedRight = 0;
        }
        if(key == VOL_DN)  // VOL_DN -> Left
        {
          speedLeft = 0;
          speedRight = 16;
        }
        if(key == ENTER)  // ENTER -> Start roam
        {
          roamcmd = 1;
        }
        if(key == MUTE)  // MUTE -> Stop roam
        {
          roamcmd = 0;
        } 
    //    pause(50);  
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* XB remote control */
    void XB_remote(void *par)
    {
    
      char inBuff[40];
    
    
    /*                     Rx  Tx mode BAUD */
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(500);
      writeStr(xbee,"XBremote started.\n");
    
      while(1)
      {
        writeStr(xbee,"> ");
        readStr(xbee, inBuff, 40);
        if(!strcmp(inBuff,"onled"))
        {
          high(26);
        }
        else if(!strcmp(inBuff,"offled"))
        {
          low(26);
        }
        else if(!strcmp(inBuff,"gostop"))
        {
          speedLeft = 0;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"gofore"))
        {
          speedLeft = 32;
          speedRight = 32;
        }
        else if(!strcmp(inBuff,"goback"))
        {
          speedLeft = -32;
          speedRight = -32;
        }
        else if(!strcmp(inBuff,"goright"))
        {
          speedLeft = 16;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"goleft"))
        {
          speedLeft = 0;
          speedRight = 16;
        }
        else if(!strcmp(inBuff,"startroam"))
        {
          roamcmd = 1;
        }
        else if(!strcmp(inBuff,"stoproam"))
        {
          roamcmd = 0;
        }
        else
        {
          writeLine(xbee,"Invalid Command!");
        }    
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    void ab_nav(void *par)
    {
    /*  int speedLeftOld  = speedLeft;
      int speedRightOld = speedRight;
      while(1)
      {
        if(speedLeftOld != speedLeft || speedRightOld != speedRight)
        {
          drive_speed(speedLeft, speedRight);
          speedLeftOld = speedLeft;
          speedRightOld = speedRight;
        } 
        pause(20);
      } */
      int speedLeftOld  = speedLeft;
      int speedRightOld = speedRight;
    
      while(1)
      {
        if(roamcmd == 1)
        {
          int turn;
          while(roamcmd == 1)
          {
            speedLeft = 32;
            speedRight = 32;
            while(ping_cm(8) >= 20) pause(5);
    
            turn = rand() % 2;
            if(turn == 1)
            {
            speedLeft = 16;
            speedRight = -16;
            }
            else
            {
            speedLeft = -16;
            speedRight = 16;
            }
            while(ping_cm(8) < 20);
          }
        }
        else if(roamcmd == 0)
        {
          if(speedLeftOld != speedLeft || speedRightOld != speedRight)
          {
            drive_speed(speedLeft, speedRight);
            speedLeftOld = speedLeft;
            speedRightOld = speedRight;
          } 
        }
        pause(20);
      }
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    
    
    
  • edited 2013-09-20 15:21
    Hi Ray,

    Sorry for the bad advice today. I went back to your post #34 and applied a little debugging. Result is below, and I think it's working they way you intend now. Debugging code is still in main.

    Andy

    ///////////////////////////////////////////////////////////////////////////////
    /*
     * abpl.c
     *
     * The ActivityBot program.
     * 
    */
    #include "simpletools.h"
    #include "abdrive.h"
    #include "simpletext.h"
    #include "ping.h"
    #include "fdserial.h"
    #include "sonyremote.h"
    
    
    
    volatile unsigned int IRpin = 9;
    
    //static volatile char xbInBuf[40];
    static volatile int xbCog;
    static volatile int speedLeft, speedRight;
    static volatile int roamcmd;
    
    
    serial *xbee;
    
    
    unsigned int IRstack[40 + 50];
    unsigned int XBstack[40 + 50];
    unsigned int abstack[40 + 50];
    unsigned int roamstack[40 + 50];
    
    // Function prototype
    void IR_remote(void *par);
    void XB_remote(void *par);
    void ab_nav(void *par);
    
    void global_Roam(void *par);
    
    
    ///////////////////////////////////////////////////////////////////////////////
    int main()
    {
      // Add startup code here.
      char inBuff[40];
    //  int getBuff;
      char getBuff;
    
      pause(300);
      print("The ActivityBot\r");
    
      int ircog = cogstart(&IR_remote, NULL, IRstack, sizeof(IRstack));
      pause(500);
      int xbcog = cogstart(&XB_remote, NULL, XBstack, sizeof(XBstack));
      pause(500);
      int abcog = cogstart(&ab_nav, NULL, abstack, sizeof(abstack));
      pause(500);
      int roamcog = cogstart(&global_Roam, NULL, roamstack, sizeof(roamstack));
      pause(500);
    
    
     
      int roamcmdOld = roamcmd;
      int speedLold2 = speedLeft;
      int speedRold2 = speedRight;
      while(1)
      {
        if(roamcmdOld != roamcmd)
        {
          print("roamcmd = %d\n", roamcmd);
          roamcmdOld = roamcmd;
        }
        if(speedLold2 != speedLeft || speedRold2 != speedRight)
        {
          print("speedLeft = %d, speedRight = %d\n", speedLeft, speedRight);
          speedLold2 = speedLeft;
          speedRold2 = speedRight;
        }
      }
    
    
    
      while(1)
      {
        putChar('#');
        getBuff = getStr(inBuff,40);
        if(!strcmp(getBuff,"quit")) break;
        else
        {
          putLine("Invalid Command!");
        }
        
    //    pause(400);    
      }
      putLine("Program Stopped!");  
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* IR remote control */
    void IR_remote(void *par)
    {
      int key;
      ir_tLimit(50);
    
      while(1)
      {
        key = ir_key(IRpin);
        if(key == PWR)
        {
          speedLeft = 0;
          speedRight = 0;
        }
        if(key == CH_UP)  // CH_UP -> Forward
        {
          speedLeft = 32;
          speedRight = 32;
        }
        if(key == CH_DN)  // CH_DN -> Backward
        {
          speedLeft = -32;
          speedRight = -32;
        }
        if(key == VOL_UP)  // VOL_UP -> Right
        {
          speedLeft = 16;
          speedRight = 0;
        }
        if(key == VOL_DN)  // VOL_DN -> Left
        {
          speedLeft = 0;
          speedRight = 16;
        } 
    //    pause(50);  
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* XB remote control */
    void XB_remote(void *par)
    {
    
      char inBuff[40];
    
    
    /*                     Rx  Tx mode BAUD */
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(500);
      writeStr(xbee,"XBremote started.\n");
    
      while(1)
      {
        writeStr(xbee,"> ");
        readStr(xbee, inBuff, 40);
        if(!strcmp(inBuff,"onled"))
        {
          high(26);
        }
        else if(!strcmp(inBuff,"offled"))
        {
          low(26);
        }
        else if(!strcmp(inBuff,"gostop"))
        {
          speedLeft = 0;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"gofore"))
        {
          speedLeft = 32;
          speedRight = 32;
        }
        else if(!strcmp(inBuff,"goback"))
        {
          speedLeft = -32;
          speedRight = -32;
        }
        else if(!strcmp(inBuff,"goright"))
        {
          speedLeft = 16;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"goleft"))
        {
          speedLeft = 0;
          speedRight = 16;
        }
        else if(!strcmp(inBuff,"startroam"))
        {
          roamcmd = 1;
        }
        else if(!strcmp(inBuff,"stoproam"))
        {
          roamcmd = 0;
          speedLeft = 0;
          speedRight = 0;
        }
        else
        {
          writeLine(xbee,"Invalid Command!");
        }    
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    void ab_nav(void *par)
    {
      int speedLeftOld  = speedLeft;
      int speedRightOld = speedRight;
      while(1)
      {
        if(speedLeftOld != speedLeft || speedRightOld != speedRight)
        {
          drive_speed(speedLeft, speedRight);
          speedLeftOld = speedLeft;
          speedRightOld = speedRight;
        } 
        pause(20);
      }
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    
    void global_Roam(void *par)
    {
      int turn;
      roamcmd = 0;
      while(1)
      {
        if(roamcmd == 1)
        {
          speedLeft = 32;
          speedRight = 32;
          pause(100);
          while(ping_cm(8) >= 20)
          {
            pause(5);
            if(roamcmd == 0) break;
          }
          if(roamcmd == 0) continue;
    
          turn = rand() % 2;
          if(turn == 1)
    
          {
            speedLeft = 16;
            speedRight = -16;
          }
          else
          {
            speedLeft = -16;
            speedRight = 16;
          }
          while(ping_cm(8) < 20);
          {
            pause(5);
            if(roamcmd == 0) break;
          }
        }
        else
        {
          high(27);
          pause(500);
          low(27);
          pause(500);
        }
      } 
    }
    
  • edited 2013-09-20 16:14
    I'm moving this to the Learn forum.
  • NWCCTVNWCCTV Posts: 3,629
    edited 2013-09-20 18:50
    Since the HB-25's are controlled just like servos, can this code be used with the Wild Thumper as it stands or would it need to be modified at all?
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-09-21 05:05
    I had a little fright this morning, went to the usual place to find My ActivityBot, and it read "Moved ...". I figured oh well, lets move on. But, it is now in the Learn forum, maybe this is where it should of originated.

    I had a chance to to run the latest iteration, of the program, and the servos did not run when when given the command. I like the diagnostic feature that Andy added, which showed which commands were issued and the values, but no servo action. So I tried a couple of my earlier programs which were IR_remote specific, no servo action. I ended up doing an abcalibrate, which the servos did turn and it looks like the program finished successfully. So now the only thing left to do, is pull all the devices off, and start from scratch to see if I can isolate the culprit responsible for this new headache. Maybe the ActivityBot needs a set of diagnostic tools, so maybe the problem can be found without having to remove all the devices, I will be thinking about that this morning while I try to debug the problem. Hopefully this will not take to long, but...

    Ray
  • edited 2013-09-21 08:16
    Hi Ray,

    Sorry for having caused you a fright. It's a fun project, and I could imagine some classroom situations where they might want to operate the ActivityBot this way. So, I moved it here from Propeller GCC Beta, and had the redirect persist for four days so that anybody following could get to the new location.

    I just re-tested the code in post 37. It's working fine on my copy of your ActivityBot with both xbee, TV remote, and roaming. I also tested with/whithout the programming cable connected. All-good. I'd recommend checking all the possible culprits, batteries, XBee USB connection, etc.

    Andy
  • edited 2013-09-21 08:53
    Hi NWCCTV,

    If you change #include "abdrive" to #include "servodiffdrive.h", you'll be close to working. Then, just a few steps.

    1) Add an s to all instances of drive_speed. In other words, change drive_speed(speedLeft, speedRight) to drive_speeds(speedLeft, speedRight).

    2) Add a drive pins call with your left and right HB25 signal pins (they must be different) as the first thing statement in the main function

    3) Add drive_speeds(0, 0) as the second statement.

    Example, assuming Assuming you have the HB25 controlling the left wheel connected to P12 and the one controlling the right connected to P13, add these two functions to the start of the main function:

    drive_pins(12, 13);
    drive_speeds(0, 0);

    There is also the power sequence thing with the HB25s. The code in post 37 is using print, which has a built-in pause when the program starts. It's in the 0.7 second neighborhood. Hopefully the Thumper has a switch to add power to the HB25s after the program has been running for a second or two.

    Andy

    P.S. The abdrive library is a completely different animal. It's a servo control + encoder feedback library that also relies on an interpolation table that was created during a calibration step near the beginning of the ActivityBot tutorials.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-09-21 12:52
    I finally got it working, I just copy and pasted the listing that Andy had posted. Evidently my original program picked up an error in my code and did not work as expected. So far so good.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-09-24 05:35
    In the program below I added a volts cog, and when you run the program that part works, but the abdrive is no longer functioning. I think I just ran out of COGS! It would be nice if the compiler would give a warning like - "exceeded eight cogs", or something along those lines. So I guess I need a new programming strategy, how can I minimize the amount of cog use? I still wanted to add a softRTC, which uses a cog, and the use of the uSD card, plus whatever.

    I know that there is threading that is available, but I would need that to work within a cog, then maybe I could put complimentary functions in one cog, and have it working with a threads strategy. I am fairly certain that that is not available, I think? I guess at this point the ActivityBot has overwhelmed the programming language.

    I also think that I just might have to make a fork, have one program that is XBee centric, and one that is IR_remote centric, but I have the feeling that I might just run out of cogs or memory, in this case the cogs came first. Anybody have any suggestions?

    Ray
    ///////////////////////////////////////////////////////////////////////////////
    /*
     * abpl.c
     *
     * The ActivityBot program.
     * 
    */
    #include "simpletools.h"
    #include "abdrive.h"
    #include "simpletext.h"
    #include "ping.h"
    #include "fdserial.h"
    #include "sonyremote.h"
    #include "adcDCpropab.h"
    
    volatile unsigned int IRpin = 9;
    
    //static volatile char xbInBuf[40];
    static volatile int xbCog;
    static volatile int speedLeft, speedRight;
    static volatile int roamcmd;
    static volatile int voltscmd;
    
    
    serial *xbee;
    
    
    unsigned int IRstack[40 + 50];
    unsigned int XBstack[40 + 50];
    unsigned int abstack[40 + 50];
    unsigned int roamstack[40 + 50];
    unsigned int voltstack[40 + 50];
    
    // Function prototype
    void IR_remote(void *par);
    void XB_remote(void *par);
    void ab_nav(void *par);
    void ab_volts(void *par);
    
    void global_Roam(void *par);
    
    
    ///////////////////////////////////////////////////////////////////////////////
    int main()
    {
      // Add startup code here.
      char inBuff[40];
    //  int getBuff;
      char getBuff;
    
      pause(300);
      print("The ActivityBot\r");
    
      int ircog = cogstart(&IR_remote, NULL, IRstack, sizeof(IRstack));
      pause(500);
      int xbcog = cogstart(&XB_remote, NULL, XBstack, sizeof(XBstack));
      pause(500);
      int abcog = cogstart(&ab_nav, NULL, abstack, sizeof(abstack));
      pause(500);
      int roamcog = cogstart(&global_Roam, NULL, roamstack, sizeof(roamstack));
      pause(500);
      int voltcog = cogstart(&ab_volts, NULL, voltstack, sizeof(voltstack));
      pause(500);
    
      int roamcmdOld = roamcmd;
      int speedLold2 = speedLeft;
      int speedRold2 = speedRight;
      while(1)
      {
        if(roamcmdOld != roamcmd)
        {
          print("roamcmd = %d\n", roamcmd);
          roamcmdOld = roamcmd;
        }
        if(speedLold2 != speedLeft || speedRold2 != speedRight)
        {
          print("speedLeft = %d, speedRight = %d\n", speedLeft, speedRight);
          speedLold2 = speedLeft;
          speedRold2 = speedRight;
        }
      } 
    
    
    
    /*  while(1)
      {
        putChar('#');
        getBuff = getStr(inBuff,40);
        if(!strcmp(getBuff,"quit")) break;
        else
        {
          putLine("Invalid Command!");
        }
        
    //    pause(400);    
      }
      putLine("Program Stopped!"); */ 
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* IR remote control */
    void IR_remote(void *par)
    {
      int key;
      ir_tLimit(50);
    
      while(1)
      {
        key = ir_key(IRpin);
        if(key == PWR)
        {
          speedLeft = 0;
          speedRight = 0;
        }
        if(key == CH_UP)  // CH_UP -> Forward
        {
          speedLeft = 32;
          speedRight = 32;
        }
        if(key == CH_DN)  // CH_DN -> Backward
        {
          speedLeft = -32;
          speedRight = -32;
        }
        if(key == VOL_UP)  // VOL_UP -> Right
        {
          speedLeft = 16;
          speedRight = 0;
        }
        if(key == VOL_DN)  // VOL_DN -> Left
        {
          speedLeft = 0;
          speedRight = 16;
        }
        if(key == ENTER)
        {
          roamcmd = 1;
        }
        if(key == MUTE)
        {
          roamcmd = 0;
          speedLeft = 0;
          speedRight = 0;
        } 
    //    pause(50);  
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* XB remote control */
    void XB_remote(void *par)
    {
    
      char inBuff[40];
    
    
    /*                     Rx  Tx mode BAUD */
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(500);
      writeStr(xbee,"XBremote started.\n");
    
      while(1)
      {
        writeStr(xbee,"> ");
        readStr(xbee, inBuff, 40);
        if(!strcmp(inBuff,"onled"))
        {
          high(26);
        }
        else if(!strcmp(inBuff,"offled"))
        {
          low(26);
        }
        else if(!strcmp(inBuff,"gostop"))
        {
          speedLeft = 0;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"gofore"))
        {
          speedLeft = 32;
          speedRight = 32;
        }
        else if(!strcmp(inBuff,"goback"))
        {
          speedLeft = -32;
          speedRight = -32;
        }
        else if(!strcmp(inBuff,"goright"))
        {
          speedLeft = 16;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"goleft"))
        {
          speedLeft = 0;
          speedRight = 16;
        }
        else if(!strcmp(inBuff,"startroam"))
        {
          roamcmd = 1;
        }
        else if(!strcmp(inBuff,"stoproam"))
        {
          roamcmd = 0;
          speedLeft = 0;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"battery"))
        {
          writeFloat(xbee,voltscmd);
          writeLine(xbee," Volts");
        }
        else
        {
          writeLine(xbee,"Invalid Command!");
        }    
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    void ab_nav(void *par)
    {
      int speedLeftOld  = speedLeft;
      int speedRightOld = speedRight;
      while(1)
      {
        if(speedLeftOld != speedLeft || speedRightOld != speedRight)
        {
          drive_speed(speedLeft, speedRight);
          speedLeftOld = speedLeft;
          speedRightOld = speedRight;
        } 
        pause(20);
      }
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    
    void global_Roam(void *par)
    {
      int turn;
      roamcmd = 0;
      while(1)
      {
        if(roamcmd == 1)
        {
          speedLeft = 32;
          speedRight = 32;
          pause(100);
          while(ping_cm(8) >= 20)
          {
            pause(5);
            if(roamcmd == 0) break;
          }
          if(roamcmd == 0) continue;
    
          turn = rand() % 2;
          if(turn == 1)
    
          {
            speedLeft = 16;
            speedRight = -16;
          }
          else
          {
            speedLeft = -16;
            speedRight = 16;
          }
          while(ping_cm(8) < 20);
          {
            pause(5);
            if(roamcmd == 0) break;
          }
        }
        else
        {
          high(27);
          pause(500);
          low(27);
          pause(500);
        }
      } 
    }
    ///////////////////////////////////////////////////////////////////////////////
    
    void ab_volts(void *par)
    {
      adc_init(21,20,19,18);
      float v3;
    
      while(1)
      {
        v3 = adc_volts(3);
        v3 = v3*2;
        voltscmd = v3;
    
        if(v3 <= 6.0)
        {
          high(26);
          pause(500);
          low(26);
          pause(500);
        }
        pause(100);
      }
    }
    
    
  • tdlivingstdlivings Posts: 437
    edited 2013-09-24 07:27
    Ray
    If you print the values returned by cogstart you can see what cog your at.

    Tom
  • edited 2013-09-24 07:38
    Hi Ray,

    The work you are currently doing in five separate cogs can be done in a single cog, and it's not going to require threading. The cogs on my hit list are: IR_remote, XB_remote, ab_nav, global_Roam, and ab_volts. I'm confident that they can put them all in a single loop that:

    (1) Checks the remote and either get a message or lets it time out
    (2) Checks the serial buffer, and either take action or move on if nothing there
    (3) Checks the volts
    (4) Update the wheel speeds if they changed

    If the code enters a roaming loop, have that loop take a break to go back and perform steps 1 - 4 periodically.

    Andy
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-09-24 08:48
    On a separate issue, will the ActivityBot wheels and encoders be sold as a separate purchase? Since I have a BOEBOT, I would like to outfit it with the new wheels, I am thinking ActivityBot swarming.

    Ray
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2013-09-24 09:01
    Rsadeika wrote: »
    On a separate issue, will the ActivityBot wheels and encoders be sold as a separate purchase? Since I have a BOEBOT, I would like to outfit it with the new wheels, I am thinking ActivityBot swarming.

    Ray

    Yes, we are working on making various ActivityBot parts and sub-kits available on our website as we do for the Boe-Bot robot. We always aim to help educators maintain their "fleets" with a balance of affordability and convenience. I will reply here as items are added.
  • edited 2013-09-24 16:22
    Hi again Ray,

    Here is your first set of hints on cleaning up cog usage. This is assuming you start with the code in post #37.

    Start by replacing that block of cogstarts in main with this.
      while(1)
      {
        key = IR_remote(9);
        //xbcmd = XB_remote();
        //if(xbcmd == 1) global_Roam();
        ab_nav();
      }
    

    You will need to update your forward declarations and function prototypes to play nice with the modified calls in the above while loop.

    IR_remote (and all the other functions) have while(1) loops in them, which is fine if they launch into cogs. But now, we want to call each one and have it return.

    First focus on updating the code so that it works with just the IR_remote and ab_nav calls.

    In IR_remote, remove the while(1) { from near the start, and remove the corresponding closing brace } from later in the function. That should allow it to check the IR and return if there's no incoming message.

    inside ab_nav, remove the int speedLeftOld = speedLeft and int speedRightOld = speedRight that come before the if block. Then, make global declarations that initialize to zero for speedLeft, speedLeftOld, speedRight, and speedRightOld. Last, but not least, remove the while(1) { and the corresponding closing brace }.

    That should get you pretty close to functioning with IR and ab_nav. It'll probably take some more debugging though. Since your terminal debug code will be temporarily disabled by all this, use the P26 and P27 LEDs to tell you where you are in the code (turn on in one spot, off in another, etc).

    Andy
  • edited 2013-09-24 16:26
    P.S. The reason this is all doable is because the two critical processes (servos+encoders and Xbee) are the only two things that really need to run in other cogs. Since they are running in other cogs, your main loop can just go through and check for messages from the TV remote, then from the XBee. If messages did come in, ab_nav can be called to update the sevo speeds (in a set it and forget it fashion).
  • edited 2013-09-26 10:10
    Hi Ray,

    I see that you started working on this in a different thread with a different approach, and it looks good so far.

    So that we don't leave anybody who might follow this thread hanging, here is a modified version of the code from post #37 that incorporates all those extra cogs for IR remote, XBee, and navigation decisions into a single cog.
    #include "simpletools.h"
    #include "abdrive.h"
    #include "simpletext.h"
    #include "ping.h"
    #include "fdserial.h"
    #include "sonyremote.h"
    
    
    volatile unsigned int IRpin = 9;
    
    //static volatile char xbInBuf[40];
    static volatile int xbCog;
    static volatile int speedLeft = 0;
    static volatile int speedRight = 0;
    static volatile int roamcmd;
    static volatile int speedLeftOld = 0;
    static volatile int speedRightOld = 0;
    
    
    serial *xbee;
    
    // Function prototype
    int IR_remote(int irPin);
    int XB_remote(void);
    void ab_nav(void);
    void global_Roam(void);
    
    
    ///////////////////////////////////////////////////////////////////////////////
    int main()
    {
      // Add startup code here.
      char inBuff[40];
    //  int getBuff;
      char getBuff;
    
      pause(300);
      print("The ActivityBot\r");
    
    /*                     Rx  Tx mode BAUD */
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(500);
      writeStr(xbee,"XBremote started.\n");
      writeStr(xbee,"> ");
    
      int roamcmdOld = roamcmd;
      int speedLold2 = speedLeft;
      int speedRold2 = speedRight;
    
      int key = -1, xbcmd = -1;
    
      low(26);
    
      while(1)
      {
        key = IR_remote(9);
        xbcmd = XB_remote();
        if(xbcmd == 1) global_Roam();
        ab_nav();
      }
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* IR remote control */
    int IR_remote(int irPin)
    {
      //toggle(26);
      int key;
      ir_tLimit(50);
    
      key = ir_key(irPin);
      if(key == PWR)
      {
        speedLeft = 0;
        speedRight = 0;
      }
      if(key == CH_UP)  // CH_UP -> Forward
      {
        speedLeft = 32;
        speedRight = 32;
      }
      if(key == CH_DN)  // CH_DN -> Backward
      {
        speedLeft = -32;
        speedRight = -32;
      }
      if(key == VOL_UP)  // VOL_UP -> Right
      {
        speedLeft = 16;
        speedRight = 0;
      }
      if(key == VOL_DN)  // VOL_DN -> Left
      {
        speedLeft = 0;
        speedRight = 16;
      }
      //pause(100);
      //toggle(26);
      //pause(100);
      return key; 
    }
    ///////////////////////////////////////////////////////////////////////////////
    /* XB remote control */
    int XB_remote()
    {
      high(27);
      char inBuff[40];
      int retval = 0;
    
      if(fdserial_rxReady(xbee))
      {    
        readStr(xbee, inBuff, 40);
        writeStr(xbee,"> ");
        if(!strcmp(inBuff,"onled"))
        {
          high(26);
        }
        else if(!strcmp(inBuff,"offled"))
        {
          low(26);
        }
        else if(!strcmp(inBuff,"gostop"))
        {
          speedLeft = 0;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"gofore"))
        {
          speedLeft = 32;
          speedRight = 32;
        }
        else if(!strcmp(inBuff,"goback"))
        {
          speedLeft = -32;
          speedRight = -32;
        }
        else if(!strcmp(inBuff,"goright"))
        {
          speedLeft = 16;
          speedRight = 0;
        }
        else if(!strcmp(inBuff,"goleft"))
        {
          speedLeft = 0;
          speedRight = 16;
        }
        else if(!strcmp(inBuff,"startroam"))
        {
          retval = 1;
        }
        else if(!strcmp(inBuff,"stoproam"))
        {
          retval = 2;
          speedLeft = 0;
          speedRight = 0;
        }
        else
        {
          writeLine(xbee,"Invalid Command!");
          retval = -1;
        }   
      }
    
      low(26);
      return retval; 
    }
    ///////////////////////////////////////////////////////////////////////////////
    void ab_nav(void)
    {
      if(speedLeftOld != speedLeft || speedRightOld != speedRight)
      {
        drive_speed(speedLeft, speedRight);
        speedLeftOld = speedLeft;
        speedRightOld = speedRight;
      } 
      pause(20);
    }
    
    ///////////////////////////////////////////////////////////////////////////////
    
    void global_Roam(void)
    {
      int turn;
      roamcmd = 0;
      while(1)
      {
        if(XB_remote() == 2)
          return;
        else
        {
          speedLeft = 32;
          speedRight = 32;
          ab_nav();
          pause(100);
          while(ping_cm(8) >= 20)
          {
            pause(5);
            if(XB_remote() == 2) return;
          }
          if(XB_remote() == 2) return;
    
          turn = rand() % 2;
          if(turn == 1)
    
          {
            speedLeft = 16;
            speedRight = -16;
          }
          else
          {
            speedLeft = -16;
            speedRight = 16;
          }
          ab_nav();
          while(ping_cm(8) < 20);
          {
            pause(5);
            if(XB_remote() == 2) return;
          }
        }
      } 
    }
    
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-09-26 11:55
    Yes, the other thread that I started, I want to keep it strictly IR_remote. I figure there might be some people that do not have an XBee module just yet, and with the new IR library that you will have, anybody will be able to use just about any remote that they have available.

    Now that I have looked at how you handled everything without using any cogstart commands, I will be modifying the other, IR_remote specific program slightly. I was having some difficulty trying to do a roam scenario, now that I have seen how you did it here, it all becomes obvious, of course.

    I still have hope of doing an "all but the kitchen sink" ActivityBot program, but in the mean time, the small programs should suffice.

    Ray
  • Steph LindsaySteph Lindsay Posts: 767
    edited 2013-10-04 09:55
    Yes, we are working on making various ActivityBot parts and sub-kits available on our website as we do for the Boe-Bot robot. We always aim to help educators maintain their "fleets" with a balance of affordability and convenience. I will reply here as items are added.

    The ActivityBot Refresher Pack and the Encoder Wheel and Tire are now available in the Parallax web store. Andy is redesigning the Encoder Bracket to make it less sensitive to minor variations in mounting position, loose screws, and so forth. Once that is done the ActivityBot Encoder Kits will also be available separately.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-10-29 05:06
    For the last couple of weeks I have been investigating and choosing a platform for developing a GUI control program for the ActivityBot with XBee control. I decided to go with Python 3 and Tkinter as the GUI feature. I have installed, on my Windows computer Python 3, and PySerial, I also have the same setup on my RPi computer. I wanted to make sure that the program is workable on both computers, and it is, with one program line change, that deals with the COM port selection. The program is very, very, very crude; it basically has eight buttons which control the ActivityBot movements. As I learn more about Python/Tkinter I will fancy up the program.

    I tested the new ActivityBot program, which Andy made available, with the IR_remote and my GUI control program, and everything seems to be working as expected. I did notice when I started the roam feature, the ActivityBot got caught up on a wall edge, and did not know how to handle it, it just kept rubbing on the wall corner until I had to intervene. I guess the roam function needs some refinement.

    I did not try the new log feature because there is no convenient way of looking at the log file on the uSD card. I guess the ActivityBot needs a stand alone card reader/editor so you can conveniently view and edit the log file. Then I guess I could add some more buttons to my GUI program that would start some scripted ActivityBot program runs.

    Now I am thinking about adding the softRTC feature, if there is enough RAM space, with the AcitityBot Control Program running on the big computer, maybe there could be a button that loads up the ActivityBot with the real time/date. That could give the log feature some more useful data to work with.

    I am still thinking about how to make communication between two AcitityBots a very simple and painless feature. I guess I could go the XBee route, but my knowledge about XBee is still very limited. Besides, that would probably be overloading the AcitivityBot, it only has so much RAM space to work with. And I only have one ActivityBot to work with, so maybe this will be done at a later date.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-10-31 12:18
    In the zip file below, it contains two programs, one Python3 GUI program, and an accompanying PropGCC program. This is a proof of concept, and a project feasibility study. In my previous post, I mentioned that I wanted to try some data logging with a time stamp, and have the Activity Board do the heavy lifting. Well, after playing around with that idea, I decided to have the Propeller do the thing that it does best, and have the PC do the heavy lifting.

    The Python GUI program basically has some buttons that does onLED/offLED and a method for data logging that activity. This of course is done with the XBee module that is attached. The PropGCC program basically does the onLED/offLED when requested by the GUI program, and also has an XBee module on board. All very straight forward, and not to overly complicated.

    This is to be used on a Windows computer that has Python3, and PySerial installed, I also use Geany as the IDE for the Python program. And of course you need an Activity or PropBOE board, in my case, I am using a PropBOE board, I am starting to run short on Activity Boards.

    The next thing that I will do is put the Python GUI program on my RPi, and see if it works as expected. After that, the next thing to do is too try out a scripting program that will be written on the PC, using a handy text editor, and then have the GUI program feed it to the PropBOE to see if in fact it can follow instructions. After I get that to work then I will move the PropGCC program to the ActivityBot and start implementing the concepts that I have just tested out. Hopefully the first thing will be is to have the ActivityBot controlled with an IR_remote and have the steps data logged with the GUI program, with much more to follow...

    If somebody wants to test this out on there system, to see what kind of bugs pop up, I would find that to be a big help for stamping out the bugs before the program(s) get out of hand.

    Ray
  • jazzedjazzed Posts: 11,803
    edited 2013-10-31 21:07
    Hi Ray,

    Where is the serial.py module?

    Added:
    Well apparently it has to be installed as part of pySerial. I tried installing that, but it complained that my Python3.3 is not in the registry.
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-01 02:22
    Since I did not think that anybody was going to take more interest, I did not add any additional information. It took me a couple of tries to get the Python 3 installed on my Windows computer, I think you have to use the 32 bit version of Python 3 too make it all work correctly. The zip file contains the PySerial that I am using, the other files were to big to be included in the zip.

    Yesterday I tried running my Py GUI program on the RPi and it ran into some problems, so the port between different OSs is not as smooth as it is talked about. But, I guess it is better than starting from scratch with each new OS.

    Now that some of the concepts are starting to look very positive, I am really starting to think about moving to PyQt4 for the GUI stuff. But first I have to collect a lot of information and manuals about the language implementation and all the examples that I can find.

    My first gut feeling about this Python GUI and the Propeller combination is very positive, especially when using the XBee as the middleman. Now I am envisioning a Python GUI control program that would be able to gain gathered data from multiple XBee attached devices like ActivityBots, and whatever else you can prepare on an Activity or PropBOE board.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-02 05:51
    This is the next step in My ActivityBot program, the POC of running a script file on the ActivityBot. The below zip contains the very, very, very basic PyGUI program, the PropGCC program, and a test script file(testrun.txt). All very basic proto style programs to prove that an idea is feasible.

    For the PyGUI part, it just has three buttons, one of the buttons is to run the script program. The "testrun.txt" file, which has a test script format, should reside in the same folder that the PyGUI program resides in.

    The PropGCC program has a script interpreter program, very limited, just to show that it does work. Now it is time to start working on the "Big" PropGCC program, that is, adding the code necessary to run an ActivityBot from the PyGUI terminal. The main emphasis will probably be on the data logging and scripting aspect, with great consideration to the scripting code. I just use the "brute force" method, I am not that good of a programmer to come up with clever ways of coding. That is why, in the interpreter part, I just use the standard "if" and "else if" loops, I suppose there are better ways to do this. But I will leave that up to the fresh young minds to do a better job.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-02 11:44
    Below is a functional ActivityBot Control Program done with the PyGUI program. This program just has the basic buttons for the ActivityBot control, which include the 'Roam/Stop Roam' function. I tested the program on my Windows PC, and on my RPi computer, and it is working as expected.

    What is not on this version is the IR_remote control, data logging, or the script programming for the ActivityBot. Those will take some thought as to how too make that work properly. I want to make sure I get a good functioning data logging system that works with the IR_remote control.

    As I was searching the web today I came across a program called py2exe, but unfortunately it only works with Python 2.7 as the highest level. Since I need something that works with Python 3.2.2, I am out of luck for providing a simple PyGUI.exe program. That is one downside for Python programming on the Windows PC, for Python 3.x you need to install the complete Python program.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-04 06:02
    Attached is the program that has a functional running of scripts, also included is an example text file, runprog.txt. The commands gofore and goback use inch values, and gorite, goleft use degree values. the text file should only contain a command per line, so you would have something like:
    '
    gofore
    10
    ::

    '
    So this script file would be interpreted as go foward 10 inches. Make sure that you hit the return button after the '::'.

    I did a test run of this program on my RPi computer, and it ran as expected. Now comes the hard part, creating a sensible data logging segment for the pyAB_prj program.

    Ray
  • RsadeikaRsadeika Posts: 3,837
    edited 2013-11-05 09:36
    Well, I just ran into a problem with my scripting program, I guess the XBee has some sort of buffer size limit, and I seem to be hitting that before my script file has completed. When I run some short script programs, the ActivityBot responds as expected, when I use a program that is larger, then it stops without completing the full run. Anybody have any suggestions to how this should be resolved? I am very sure that I do not know what the next step should be.

    Ray
Sign In or Register to comment.