Shop OBEX P1 Docs P2 Docs Learn Events
SIRC C code and cog_run() — Parallax Forums

SIRC C code and cog_run()

Not sure what is going on, but the SIRC function starts to act weird, after I start using the remote, when SIRC is run in its own COG.

I have inserted fresh batteries in the early edition of the Parallax remote controller. I am also using the Parallax IR demodulator. The IR circuit is wired just like the example in the Learn site. When I first start the program and start using the remote control, all is working as expected. But it does not take to long before the remote control is having no effect, basically I am pressing the necessary button and it is not working. It seems to take effect after I have pressed the button a whole bunch of times. At one point I did add a pause(150) in the SIRC while loop, that made it even worse.

Now I did try using the same setup, but had it in the main function (SIRC control is not in a COG), and it seem to work as expected, even after an extended period of time of pressing the necessary buttons. I am using the original Activity Board, and I have it set in CMM mode.

I also ran a test with my QuickStart+HIB setup, it worked there as expected, both in COG and regular function. It seems that the remote is not suffering from sticky keys, since it works fine in non COG mode.

Did something change with the new cog_run() function? I am using the latest Windows 7 SimpleIDE version. If I get a chance I will have to try this out with Linux SimpleIDE, but I think that version does not have a SIRC library, IIRC.

The program is fairly long, when I looked through it, I did not find any blatant errors.

Ray
/*
  cr_ab.c
  
  This is the iRobot Create Control System
  using the Parallax Activity Board
  November 28, 2016
  
*/
#include "simpletools.h"
#include "simpletext.h"
#include "fdserial.h"
#include "sirc.h"

serial *xbee;
serial *create;

int highbyte,lowbyte;
float newbyte;

/* COGed Functions */
void irrem();
/*******************/

void menu();

/* Create control commands. */
int speed_right = 75;
int speed_left = 75;
int turn_left = 35;
int turn_right = 35;
int highbyte,lowbyte;
float newbyte;

void CRstop();
void CRfore();
void CRback();
void CRleft();
void CRrite();
void CRsafe();
void CRstart();

void BattChrg();
/*******************/
int main()
{
  // Add startup code here.
/*                     Rx  Tx     BAUD   */
  xbee = fdserial_open(11, 10, 0, 9600);
  pause(250);
  create = fdserial_open(12, 13, 0, 57600);
  pause(250);
  //fdserial_txChar(create,128);
  //pause(400);
  //fdserial_txChar(create,131);
  //pause(500);

  cog_run(irrem,128);

/* XBee intro message. */  
  writeStr(xbee,"iRobot Create Robot Control System.\n");
  menu();
  
  char inBuff[40];
 
  while(1)
  {
    // Add main loop code here.
    writeStr(xbee,">");
    readStr(xbee,inBuff,40);
    if(!strcmp(inBuff, "help")) menu();
    else if(!strcmp(inBuff, "crstop")) CRstop();
    else if(!strcmp(inBuff, "crfore")) CRfore();
    else if(!strcmp(inBuff, "crback")) CRback();
    else if(!strcmp(inBuff, "crrite")) CRrite();
    else if(!strcmp(inBuff, "crleft")) CRleft();
    else if(!strcmp(inBuff, "crsafe")) CRsafe();
    else if(!strcmp(inBuff, "crstart")) CRstart();
    else if(!strcmp(inBuff, "crcharge"))
    {
      BattChrg();
      writeFloat(xbee,newbyte/1000);
      writeStr(xbee," Create Volts\n");
    }      
    else
    {
      writeLine(xbee,"Invalid Command");
    }    
  }  
}

/* COGed functions */
void irrem()
{
  
  
  while(1)
  {

    if(sirc_button(14) == 21) CRstop();
    else if(sirc_button(14) == 29) CRsafe();
    else if(sirc_button(14) == 25) CRstart();
    else if(sirc_button(14) == 16) CRfore();
    else if(sirc_button(14) == 17) CRback();
    else if(sirc_button(14) == 18) CRrite();
    else if(sirc_button(14) == 19) CRleft();
    
  }  
}
/*********************************************/

/* Create commands */
void CRstop()
{
  fdserial_txChar(create,145);
  fdserial_txChar(create,0);
  fdserial_txChar(create,0);
  fdserial_txChar(create,0);
  fdserial_txChar(create,0);
}

void CRfore()
{
  fdserial_txChar(create,145);  
  fdserial_txChar(create,((speed_right)>>8)&0xFF);
  fdserial_txChar(create,((speed_right)&0xFF));
  fdserial_txChar(create,((speed_left)>>8)&0xFF);
  fdserial_txChar(create,((speed_left)&0xFF));
}

void CRback()
{
  fdserial_txChar(create,145);
  fdserial_txChar(create,((-speed_right)>>8)&0xFF);
  fdserial_txChar(create,((-speed_right)&0xFF));
  fdserial_txChar(create,((-speed_left)>>8)&0xFF);
  fdserial_txChar(create,((-speed_left)&0xFF));    
}

void CRleft()
{
  fdserial_txChar(create,145);  
  fdserial_txChar(create,((turn_right)>>8)&0xFF);
  fdserial_txChar(create,((turn_right)&0xFF));
  fdserial_txChar(create,((-turn_left)>>8)&0xFF);
  fdserial_txChar(create,((-turn_left)&0xFF));
}

void CRrite()
{
  fdserial_txChar(create,145);  
  fdserial_txChar(create,((-turn_right)>>8)&0xFF);
  fdserial_txChar(create,((-turn_right)&0xFF));
  fdserial_txChar(create,((turn_left)>>8)&0xFF);
  fdserial_txChar(create,((turn_left)&0xFF));
}

void CRsafe()
{
  fdserial_txChar(create,128);
  pause(400);
  fdserial_txChar(create,131);  
}

void CRstart()
{
  fdserial_txChar(create,128);
}        

void BattChrg()
{
  fdserial_txChar(create,142);
  fdserial_txChar(create,22);
  highbyte = fdserial_rxChar(create);
  pause(50);
  lowbyte = fdserial_rxChar(create);
  newbyte = ((highbyte << 8) + lowbyte);
}  
/*********************************************/


void menu()
{
  writeStr(xbee,"Menu -  help,   \n");
  writeStr(xbee,"crcharge, crstop, crfore, crback, crleft, crrite \n");
  writeStr(xbee,"crsafe, crstart, \n");
}  

Comments

  • Came across another interesting problem with the program, I tried to place the XBee functionality in its own COG. Did not work as expected.

    When the COG started up, on the remote terminal, all It was doing was the curser was jumping all over the screen. I got the impression that maybe the readStr() command was not working the way it is supposed too, in the while loop. I am starting to wonder if even, in CMM mode, starting a new COG is being treated like a pthread within SimpleIDE (PropGCC), if that makes any sense.

    Not sure as to why I am starting to run into all these problems using SimpleIDE. Previously, a few years back, I do not recall having this many problems.

    Ray
  • I've launched multiple cogs in my own code in CMM or LMM modes with no issues, so I can attest that it works as expected. That said, there are a few things to know about it, and how it interacts with GCC and the optimizer.

    - Variables that are used in multiple threads / cogs will very probably need to be marked as volatile. The optimizer in GCC will do things like load a variable from hub ram into a cog register and repeatedly use it from there because it's faster. If you have two different cogs / threads interacting with a variable, marking the variable as volatile makes sure that each time the variable is used, it is loaded from / written to memory so that other threads using it will see the most recent changes.

    - launching a cog in C/C++ has different stack space requirements than launching one in Spin. I believe the minimum stack size is 40 longs just for interpreter working space (you should double check this, as it's from memory). I typically use 64 longs as my stack.

    - I haven't used cog_run() myself, but use cogstart, like this: cogstart( &EntryFunction, Param, stackAddress, stackSizeInBytes );
  • I also just noticed that you're calling the CR*() functions from both your main loop *and* from your cog thread, which means you could potentially be trying to use the same fdserial object from two threads at the same time. This will not work without some kind of mechanism to prevent simultaneous access, or they'll be fighting over the same variables and all kinds of weird things can happen.
  • Do you have any insight as to what that mechanism might be, to prevent simultaneous access?

    At the moment I am just using one or the other, mostly the IR remote for testing. But eventually I will probably be using both, XBee and IR.

    The new cog_run() command requires a stack space amount, I have been using 128, and also had it up too 256, made no difference in functionality.

    I just did a test using the switch loop instead of the 'if' 'else if' loop, made no difference, the SIRC COG starting acting up.

    Ray
  • I made some changes to the program, but I am still getting some flaky activity with the SIRC.

    The one thing that I just noticed, was that the Create has a docking station, which I think sends out some of its own IR signals, not sure if this is having an effect on the IR demodulator that I am using. Since the robot just went red (need a charge), after it charges, I will have to try blocking the IR mechanism on the docking station, and see if this makes a difference.

    Ray
    /*
      cr_ab.c
      
      This is the iRobot Create Control System
      using the Parallax Activity Board
      November 28, 2016
      
    */
    #include "simpletools.h"
    #include "simpletext.h"
    #include "fdserial.h"
    #include "sirc.h"
    
    serial *xbee;
    serial *create;
    
    static volatile int highbyte,lowbyte;
    static volatile float newbyte;
    
    /* COGed Functions */
    void irrem();
    //void cogbe();
    /*******************/
    
    void menu();
    
    /* Create control commands. */
    static volatile int speed_right = 75;
    static volatile int speed_left = 75;
    static volatile int turn_left = 35;
    static volatile int turn_right = 35;
    static volatile int highbyte,lowbyte;
    static volatile float newbyte;
    
    void CRstop();
    void CRfore();
    void CRback();
    void CRleft();
    void CRrite();
    void CRsafe();
    void CRstart();
    
    void BattChrg();
    /*******************/
    int main()
    {
      // Add startup code here.
    /*                     Rx  Tx     BAUD   */
      xbee = fdserial_open(11, 10, 0, 9600);
      pause(250);
      create = fdserial_open(12, 13, 0, 57600);
      pause(250);
      //fdserial_txChar(create,128);
      //pause(400);
      //fdserial_txChar(create,131);
      //pause(500);
    
    
      cog_run(irrem,128);
    
    /* XBee intro message. */  
      writeStr(xbee,"iRobot Create Robot Control System.\n");
      menu();
      
      char inBuff[40];
     
      while(1)
      {
        // Add main loop code here.
        writeStr(xbee,">");
        readStr(xbee,inBuff,40);
        if(!strcmp(inBuff, "help")) menu();
        else if(!strcmp(inBuff, "crstop")) CRstop();
        else if(!strcmp(inBuff, "crfore")) CRfore();
        else if(!strcmp(inBuff, "crback")) CRback();
        else if(!strcmp(inBuff, "crrite")) CRrite();
        else if(!strcmp(inBuff, "crleft")) CRleft();
        else if(!strcmp(inBuff, "crsafe")) CRsafe();
        else if(!strcmp(inBuff, "crstart")) CRstart();
        else if(!strcmp(inBuff, "crcharge"))
        {
          BattChrg();
          writeFloat(xbee,newbyte/1000);
          writeStr(xbee," Create Volts\n");
        }      
        else
        {
          writeLine(xbee,"Invalid Command");
        }    
      }  
    }
    
    /* COGed functions */
    void irrem()
    {
      
      int button = 0;  
      while(1)
      {
    
    //    if(sirc_button(14) == 21) CRstop();
    //    if(sirc_button(14) == 26) CRsafe();
    //    if(sirc_button(14) == 27) CRstart();
    //    if(sirc_button(14) == 16) CRfore();
    //    if(sirc_button(14) == 17) CRback();
    //    if(sirc_button(14) == 18) CRrite();
    //    if(sirc_button(14) == 19) CRleft();
        button = sirc_button(14);
        if(button < 100)
        {
        switch(button)
        {
          case 21:    // Pwr
            CRstop();  
            break;
          case 27:    // << 
            CRsafe();
            break;
          case 26:    // > 
            CRstart();
            break;
          case 16:    // Ch+ 
            CRfore();
            break;
          case 17:    // Ch- 
            CRback();
            break;
          case 18:    // Vol+
            CRrite();
            break;
          case 19:
            CRleft(); // Vol-
            break;
          
          //default: CRstop();
        }
        }    
        button = 0;      
      }  
    }
     
    /*********************************************/
    
    /* Create commands */
    void CRstop()
    {
      fdserial_txChar(create,145);
      fdserial_txChar(create,0);
      fdserial_txChar(create,0);
      fdserial_txChar(create,0);
      fdserial_txChar(create,0);
    }
    
    void CRfore()
    {
      fdserial_txChar(create,145);  
      fdserial_txChar(create,((speed_right)>>8)&0xFF);
      fdserial_txChar(create,((speed_right)&0xFF));
      fdserial_txChar(create,((speed_left)>>8)&0xFF);
      fdserial_txChar(create,((speed_left)&0xFF));
    }
    
    void CRback()
    {
      fdserial_txChar(create,145);
      fdserial_txChar(create,((-speed_right)>>8)&0xFF);
      fdserial_txChar(create,((-speed_right)&0xFF));
      fdserial_txChar(create,((-speed_left)>>8)&0xFF);
      fdserial_txChar(create,((-speed_left)&0xFF));    
    }
    
    void CRleft()
    {
      fdserial_txChar(create,145);  
      fdserial_txChar(create,((turn_right)>>8)&0xFF);
      fdserial_txChar(create,((turn_right)&0xFF));
      fdserial_txChar(create,((-turn_left)>>8)&0xFF);
      fdserial_txChar(create,((-turn_left)&0xFF));
    }
    
    void CRrite()
    {
      fdserial_txChar(create,145);  
      fdserial_txChar(create,((-turn_right)>>8)&0xFF);
      fdserial_txChar(create,((-turn_right)&0xFF));
      fdserial_txChar(create,((turn_left)>>8)&0xFF);
      fdserial_txChar(create,((turn_left)&0xFF));
    }
    
    void CRsafe()
    {
      fdserial_txChar(create,128);
      pause(400);
      fdserial_txChar(create,132);  
    }
    
    void CRstart()
    {
      fdserial_txChar(create,128);
    }        
    
    void BattChrg()
    {
      fdserial_txChar(create,142);
      fdserial_txChar(create,22);
      highbyte = fdserial_rxChar(create);
      pause(50);
      lowbyte = fdserial_rxChar(create);
      newbyte = ((highbyte << 8) + lowbyte);
    }  
    /*********************************************/
    
    
    void menu()
    {
      writeStr(xbee,"Menu -  help,   \n");
      writeStr(xbee,"crcharge, crstop, crfore, crback, crleft, crrite \n");
      writeStr(xbee,"crsafe, crstart, \n");
    }  
    
  • For locking, the Prop has built in lock objects which you can acquire and release. I'm not sure how that works exactly (never used it) but it should do what you need. You essentially have a lock object associated with a single-use object (like a serial port). In order to ensure you are the only one using the object at any given moment, you acquire the lock first. Only one thread / cog can have it at a time, and you have to release it when you're done so other threads can use it.
  • Ah yes, the locking mechanism. I remember using it when I was doing some programs with the Hackable Badge. Will have to dig that up and see if it will work here.

    So, the robot got charged up, I blocked the IR on the docking station, and the program seems to be working as expected. This creates a new problem, how do I block out the signals from the docking station or have my program and IR demodulator disregard the signals from the docking station? I was hoping to be able to use the Create IR and the docking station IR for a custom docking program.

    Well at least I found the SIRC problem, I hope.

    Ray
Sign In or Register to comment.