Shop OBEX P1 Docs P2 Docs Learn Events
Need help, program won't work — Parallax Forums

Need help, program won't work

Hi everyone, I am relatively new to this. I have the activity bot and I wrote a program to be used with the 2-axis joystick. I have an automated driving program that I would like to run in one cog, then, when I turn on the xbee transmitter, it will allow me to take over the robot and drive. Once I turn off the xbee transmitter, I want the robot to once again resume or restart the driving cog.

So far the program works to a point. When I turn on the robot, it starts with the automated driving sequence which will repeat indefinitely. I can then choose to turn on the xbee transmitter, and the cog_end function shuts down the driving cog, and then I can drive the robot however I wish. But when I turn off the transmitter, how do I get it to re-initiate the automatic driving sequence? I have tried plugging in the cog_run function in numerous places and it just won't do it. It seems like once I enter into the While(1) xbee loop, that's it, I can't get out. Please help! I am pulling my hair out after hours of trying to make it work hahaha

Here is the code below:


#include "simpletools.h" // Include libraries
#include "fdserial.h"
#include "abdrive.h"
#include "wavplayer.h"
#include "servo.h"
#include "ping.h"

fdserial *xbee;
int yep;
int turn;
void driving();
int main() // Main function

{

xbee = fdserial_open(9, 8, 0, 9600 ); // Begin the serial connection ( this is why we
// needed the jumper cables connected to pins 8 and 9 )
char data; // Create the variable that will be used to hold

int *cog = cog_run(driving, 128);

while (1) // Repeat this forever or until loss of power
{
data = fdserial_rxChar( xbee ); // Set data to the data received from the XBee board

if ( data == 'f' ) // If the data incoming is telling the robot to move forward
{
cog_end(cog);
drive_speed( -300, -300 ); // Move forward at 1/2 speed
}

else if ( data == 'b' ) // If the data incoming is telling the robot to move backward
{
cog_end(cog);
drive_speed( 50, 50 ); // Move backward at 1/2 speed
}

else if ( data == 'l' ) // If the data incoming is telling the root to turn left
{
cog_end(cog);
drive_speed( -100, 0 ); // Turn left in a spin turn at 1/2 speed
}

else if ( data == 'r' ) // If the data incoming is telling the robot to turn right
{
cog_end(cog);
drive_speed( 0, -100 ); // Turn right in a spin turn at 1/2 speed
}

else if ( data == 's' ) // If the data incoming is telling the robot to stop
{
cog_end(cog);
drive_speed( 0, 0 ); // Stop
}
}
}



void driving()
{
while(1)
{
yep = rand() %3;
if(yep == 0)
{
drive_speed(-100, -100);
pause(1000);
drive_speed(-64, -30);
pause(500);
drive_speed(64, -64);
pause(2000);
drive_speed(-50, -50);
pause(300);
drive_speed(50, 50);
pause(300);
drive_speed(-64, 64);
pause(2000);
drive_speed(64, 30);
pause(500);
drive_speed(100, 100);
pause(1000);
drive_speed(100, -100);
pause(3000);
drive_speed(-50, -50);
pause(500);
drive_speed(64, 0);
pause(700);
drive_speed(0, 64);
pause(700);
drive_speed(-50, -50);
pause(1000);
drive_speed(50, 50);
pause(1000);
drive_speed(0, -64);
pause(700);
drive_speed(-64, 0);
pause(700);
drive_speed(50, 50);
pause(500);
drive_speed(-100, 100);
pause(3000);
}
if(yep == 1)
{
drive_speed(-10, -30);
pause(1000);
drive_speed(0, 0);
pause(500);
drive_speed(-15, -15);
pause(1000);
drive_speed(-30, -30);
pause(300);
drive_speed(0, 0);
pause(4000);
drive_speed(30, 30);
pause(300);
drive_speed(15, 15);
pause(1000);
drive_speed(0, 0);
pause(500);
drive_speed(10, 30);
pause(1000);
drive_speed(-30, -10);
pause(1000);
drive_speed(0, 0);
pause(500);
drive_speed(-15, -15);
pause(1000);
drive_speed(-30, -30);
pause(300);
drive_speed(0, 0);
pause(4000);
drive_speed(30, 30);
pause(300);
drive_speed(15, 15);
pause(1000);
drive_speed(0, 0);
pause(500);
drive_speed(30, 10);
pause(1000);
}

if(yep == 2)
{
drive_speed(-10, 10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(1200);
pause(2000);
pause(500);
drive_speed(10,10);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
pause(3000);
drive_speed(10, -10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(2000);
pause(1000);
drive_speed(-10,-10);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
pause(670);
drive_speed(15, 5);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
pause(3000);
drive_speed(-10, 10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(1200);
pause(2000);
pause(500);
drive_speed(-15,-5);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
pause(3000);
drive_speed(5, 15);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
pause(500);
drive_speed(-5,-15);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
pause(3000);
drive_speed(10, -10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(1200);
pause(2000);
pause(3000);
drive_speed(10, -10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(1200);
pause(2000);
pause(3000);
drive_speed(-10, 10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(1200);
pause(2000);
pause(500);
drive_speed(10,10);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
pause(3000);
drive_speed(10, -10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(1200);
pause(2000);
pause(3000);
drive_speed(10, -10);
pause(750);
pause(3000);
pause(890);
pause(1679);
pause(3800);
drive_speed(0,0);
pause(1200);
pause(2000);
pause(1000);
drive_speed(-10,-10);
pause(2000);
pause(1000);
drive_speed(0,0);
pause(750);
}
}
}

Comments

  • Add a timer in the main while loop, reset when you get xbee dats. When timeout, start your automatic cog again
  • Thank you so much for the help! I have spent some time trying to learn about timers and I feel that it is out of my league in terms of understanding at my current beginner skill level. I will keep trying though.


    Please take a look at what I did below and help me to understand why this will not work. The program loads fine, and the robot drives. When I hit backwards, it initiates the automated sequence, but when I press forward the cog does not end. So even though I can drive, the motion keeps getting interrupted by the simultaneous running of the cog. Does what am I saying make sense?

    In other words, I made an int cog, then put cog_run under the "b" value and cog_end under the "f" value. The cog starts fine when I hit backwards, but won't END when I hit forward. What gives??

    See below..



    #include "simpletools.h"
    #include "fdserial.h"
    #include "abdrive.h"
    #include "wavplayer.h"
    #include "servo.h"
    #include "ping.h"

    fdserial *xbee;
    int yep;
    int turn;
    int cog;
    void driving();

    int main()
    {
    xbee = fdserial_open(9, 8, 0, 9600 );
    char data;

    while (1)
    {
    data = fdserial_rxChar( xbee );

    if ( data == 'f' )
    {
    cog_end(cog);
    drive_speed( -300, -300 );
    }

    else if ( data == 'b' )
    {
    int *cog = cog_run(driving, 128);
    }

    else if ( data == 'l' )
    {
    drive_speed( -100, 0 );
    }

    else if ( data == 'r' )
    {
    drive_speed( 0, -100 );
    }

    else if ( data == 's' )
    {
    drive_speed( 0, 0 );
    }
    }
    }



    void driving()
    {
    while(1)
    {
    yep = rand() %3;
    if(yep == 0)
    {
    drive_speed(-100, -100);
    pause(1000);
    drive_speed(-64, -30);
    pause(500);
    drive_speed(64, -64);
    pause(2000);
    drive_speed(-50, -50);
    pause(300);
    drive_speed(50, 50);
    pause(300);
    drive_speed(-64, 64);
    pause(2000);
    drive_speed(64, 30);
    pause(500);
    drive_speed(100, 100);
    pause(1000);
    drive_speed(100, -100);
    pause(3000);
    drive_speed(-50, -50);
    pause(500);
    drive_speed(64, 0);
    pause(700);
    drive_speed(0, 64);
    pause(700);
    drive_speed(-50, -50);
    pause(1000);
    drive_speed(50, 50);
    pause(1000);
    drive_speed(0, -64);
    pause(700);
    drive_speed(-64, 0);
    pause(700);
    drive_speed(50, 50);
    pause(500);
    drive_speed(-100, 100);
    pause(3000);
    }
    if(yep == 1)
    {
    drive_speed(-10, -30);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(-15, -15);
    pause(1000);
    drive_speed(-30, -30);
    pause(300);
    drive_speed(0, 0);
    pause(4000);
    drive_speed(30, 30);
    pause(300);
    drive_speed(15, 15);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(10, 30);
    pause(1000);
    drive_speed(-30, -10);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(-15, -15);
    pause(1000);
    drive_speed(-30, -30);
    pause(300);
    drive_speed(0, 0);
    pause(4000);
    drive_speed(30, 30);
    pause(300);
    drive_speed(15, 15);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(30, 10);
    pause(1000);
    }

    if(yep == 2)
    {
    drive_speed(-10, 10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(500);
    drive_speed(10,10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(2000);
    pause(1000);
    drive_speed(-10,-10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(670);
    drive_speed(15, 5);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(-10, 10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(500);
    drive_speed(-15,-5);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(5, 15);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(500);
    drive_speed(-5,-15);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(3000);
    drive_speed(-10, 10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(500);
    drive_speed(10,10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(1000);
    drive_speed(-10,-10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    }
    }
    }

  • Instead of starting and stopping a cog each time you switch driving modes, just start the cog and use a global variable as a flag. When on auto set the flag to one value (either 1 or 0) that tells the program to ignore XBee driving commands. When using the Xbee set the flag to the other value that tells the auto drive to be ignored.

    The link below shows how I did something like that.

    forums.parallax.com/discussion/161769/activitybot-sirc-control-whiskers

    The program drives the activitybot using a Sony remote. But if it hits something the function whisker (which is running all the time in its own cog) sets a flag (bumpflg) to 1 which tells the main cog to ignore any remote control commands while the whisker code is controlling the bot. When bumpflg is set to 0 the code below lets the remote control.
    if( ! bumpflg) drive_ramp(Lspd, Rspd);  // execute drive comnd, whiskers not cntrling movement
    

    Hope this helps
    Tom
  • Hi Tom, thank you so much. I just spent several hours looking at your code (amazing!) and I tried to incorporate the global variable as a flag. Unfortunately it still isn't working. Basically, the robot will begin its automatic drive sequence. When turn on the xbee controller, it will accept commands, but the motion is herky jerky because the automated drive sequence is still sending drive commands underneath the xbee commands (does the make sense?) The Xbee is not telling the board to ignore the drive sequence. My brain is fried, I cannot figure this out any further. I've attached my code below and I tried to best adapt your code to mine. It still isn't working :( Thank you so much for any help whatsoever. Thanks!


    #include "simpletools.h"
    #include "fdserial.h"
    #include "abdrive.h"
    #include "wavplayer.h"
    #include "servo.h"
    #include "ping.h"

    fdserial *xbee;
    int yep;
    int turn;
    int *cogremote;
    volatile int bumpflg;
    void remote();
    int Lspd, Rspd = 0;

    int main()
    {
    bumpflg = 0;
    cogremote = cog_run(remote, 100);

    while(1)
    {
    yep = rand() %3;
    if(yep == 0)
    {
    drive_speed(-100, -100);
    pause(1000);
    drive_speed(-64, -30);
    pause(500);
    drive_speed(64, -64);
    pause(2000);
    drive_speed(-50, -50);
    pause(300);
    drive_speed(50, 50);
    pause(300);
    drive_speed(-64, 64);
    pause(2000);
    drive_speed(64, 30);
    pause(500);
    drive_speed(100, 100);
    pause(1000);
    drive_speed(100, -100);
    pause(3000);
    drive_speed(-50, -50);
    pause(500);
    drive_speed(64, 0);
    pause(700);
    drive_speed(0, 64);
    pause(700);
    drive_speed(-50, -50);
    pause(1000);
    drive_speed(50, 50);
    pause(1000);
    drive_speed(0, -64);
    pause(700);
    drive_speed(-64, 0);
    pause(700);
    drive_speed(50, 50);
    pause(500);
    drive_speed(-100, 100);
    pause(3000);
    }
    if(yep == 1)
    {
    drive_speed(-10, -30);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(-15, -15);
    pause(1000);
    drive_speed(-30, -30);
    pause(300);
    drive_speed(0, 0);
    pause(4000);
    drive_speed(30, 30);
    pause(300);
    drive_speed(15, 15);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(10, 30);
    pause(1000);
    drive_speed(-30, -10);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(-15, -15);
    pause(1000);
    drive_speed(-30, -30);
    pause(300);
    drive_speed(0, 0);
    pause(4000);
    drive_speed(30, 30);
    pause(300);
    drive_speed(15, 15);
    pause(1000);
    drive_speed(0, 0);
    pause(500);
    drive_speed(30, 10);
    pause(1000);
    }

    if(yep == 2)
    {
    drive_speed(-10, 10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(500);
    drive_speed(10,10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(2000);
    pause(1000);
    drive_speed(-10,-10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(670);
    drive_speed(15, 5);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(-10, 10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(500);
    drive_speed(-15,-5);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(5, 15);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(500);
    drive_speed(-5,-15);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(3000);
    drive_speed(-10, 10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(500);
    drive_speed(10,10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(3000);
    drive_speed(10, -10);
    pause(750);
    pause(3000);
    pause(890);
    pause(1679);
    pause(3800);
    drive_speed(0,0);
    pause(1200);
    pause(2000);
    pause(1000);
    drive_speed(-10,-10);
    pause(2000);
    pause(1000);
    drive_speed(0,0);
    pause(750);
    }
    if( ! bumpflg) drive_ramp(Lspd, Rspd);
    }
    }






    void remote()
    {
    xbee = fdserial_open(9, 8, 0, 9600 );
    char data;
    bumpflg = 1;
    while (1)
    {
    if(! input (data = fdserial_rxChar( xbee )));
    bumpflg = 1;
    if ( data == 'f' )
    {

    drive_speed( -300, -300 );
    }

    else if ( data == 'b' )
    {
    drive_speed( 50, 50 );
    }

    else if ( data == 'l' )
    {
    drive_speed( -100, 0 );
    }

    else if ( data == 'r' )
    {
    drive_speed( 0, -100 );
    }

    else if ( data == 's' )
    {
    drive_speed( 0, 0 );
    }
    bumpflg = 0;
    }
    }



  • When posting your code, use [ code ] and [ /code ] around it (but without the spaces), and it'll keep the indenting and formatting. (You can also just click the 'C' button on the little button bar, too. That makes it easier to read the code, which makes it easier for people to help you. :)
  • Ok cool, thanks so much. Sorry for doing that, I understand it makes the code that much harder to decipher. Conceptually, all I am trying to do is tell the robot "please perform the pre-determined driving pattern. If, at any point, you start getting commands from XBEE to drive around, ignore the pre-determined pattern and allow the user to remote control you. Then if you stop getting commands from XBEE, restart the predetermined drive sequence again".

    Unfortunately, despite my greatest efforts and the help of Tom, I am unable to do this. Either the predetermined driving program keeps running and when I try to remote control the movement is all herky jerky because the wheels are getting simultaneous commands from the drive program and my remote. Alternatively, I can initiate the drive program and when the xbee turns on, it will end the drive program, but then it will not restart after I turn off the xbee. :(

    I feel like this should not be very difficult, and it probably isn't to someone who knows what they are doing. Unfortunately, I am not such a person :)

    -Deepak
  • One of things I noticed is that in the remote function you set the drive speed, but don't give it any time to run before you set bumpflg to 0. Try to put a pause after each assignment of drive_speed.

    I have a couple of questions.
    1. How do you get an "s" in the remote function?
    2. Why do you have so many "pause" functions between changes in drive speed in the main program? Can't you just use one?

    Tom

  • Hi Tom, thanks so much. So the way I think XBEE is working, is that when it gets a value such as "f", it will enact drive_speed(100, 100) for as long as it is receiving that value. This keeps the robot very responsive. The moment I let go of forward on the joystick the robot stops. If I do as you suggest and put in a pause function after each drive_speed command in the remote function, then when I hit forward on the remote, the robot will move forward for the length of time that I set the pause for. In other words, if I put pause(1000); after the drive_speed command, the robot will move forward for 1 second before listening to the next command. So you can't really steer properly then.

    You are right, there only needs to be one pause between changes. I had previously had multiple servo movements which I deleted and I wanted to keep the timing of the total pauses the same to preserve the drive pattern. That is the only reason.

    The "s" in the remote function was from the joystick activity bot tutorial on the parallax website that I uploaded onto my joystick propeller board.


    I am pasting code below. I have trimmed it down to the basic problem.

    Using the code below, when I turn on the robot, it initiates the drive cog. This sets it into a pattern of turning round and round in a circle. When I turn on the xbee propeller board, the robot stops (because I have cog_end under the "s" function which simultaneously tells the robot to have drive_speed(0, 0) AND also tells it to end the driving cog). Now, how do I get the driving cog to start back up again when I turn off the xbee board? I'm not sure the bumpflg method will work, but that is probably because I am not understanding things correctly. Thank you so much and sorry to keep posting all this code stuff!
    #include "simpletools.h"                      
    #include "fdserial.h"
    #include "abdrive.h"
    #include "wavplayer.h"
    #include "servo.h"
    #include "ping.h"
    
    fdserial *xbee;
    void driving();
    
    int main() 
    {
    xbee = fdserial_open(9, 8, 0, 9600 );      
    char data;                                 
    cog_run(driving, 128);
    
      while (1)                                 
      {
        data = fdserial_rxChar( xbee );           
     
        if ( data == 'f' )                        
        {
          drive_speed( -300, -300 );                  
        }
        else if ( data == 'b' )                 
        {
         drive_speed(-100, -100);
          }    
        else if ( data == 'l' )                   
        {
          drive_speed( -100, 0 );                   
        }
        else if ( data == 'r' )                   
        {
          drive_speed( 0, -100 );                   
        }
        
        else if ( data == 's' )                   
        {
          cog_end(driving);
          drive_speed( 0, 0 );                   
        }
      }
    }
    
    void driving()
    {
    while(1)
    {
    drive_speed(-100, 100);
    }
    }
    

  • JasonDorieJasonDorie Posts: 1,930
    edited 2016-02-25 07:57
    I think part of the problem here is that you have no idea when the XBee is turned off. You can get the 's' character, but that's not telling you it's disabled.

    Independent of that, there's a version of the serial character receive function that will check to see if a character is available, but it doesn't block waiting for one, so you can check to see if there is one, and if not, do your "non-xbee" code. I'd set it up like this:
    int main() 
    {
    xbee = fdserial_open(9, 8, 0, 9600 );      
    char data;                                 
    cog_run(driving, 128);
    
      while (1)                                 
      {
        int newChar = fdserial_rxCheck( xbee );
        if( newChar != -1 ) {
          data = newChar;  // This only happens when an actual character is received
          if ( data == 'f' ) {
            drive_speed( -300, -300 );                  
          }
          else if ( data == 'b' ) {
           drive_speed(-100, -100);
            }    
          else if ( data == 'l' ) {
            drive_speed( -100, 0 );                   
          }
          else if ( data == 'r' ) {
            drive_speed( 0, -100 );                   
          }
          else if ( data == 's' )                   
          {
            drive_speed( 0, 0 );                   
          }
        }
        else  // happens if no new data was received
        {
          drive_speed( -100, 100 );  // do the default thing
        }
      }
    }
    

    Doing that saves you running another cog.

    I believe there's a pin on the XBee that will tell you if you have a connection or not - you could use that to decide whether or not to use the last xbee command or the "default behavior", like this: (note, I don't know which pin this would be for you, so you'll need to adapt that part)
    int main() 
    {
    xbee = fdserial_open(9, 8, 0, 9600 );      
    char data;                                 
    cog_run(driving, 128);
    
      while (1)                                 
      {
        int xbee_status_pin = INA & (1<<15);  // this assumes it's pin 15 on the Prop
    
        if( xbee_status_pin > 0 )  // assumes the pin high means it's connected
        {
          int newChar = fdserial_rxCheck( xbee );
          if( newChar != -1 ) {
            data = newChar;  // This only happens when an actual character is received
          }
    
          if ( data == 'f' ) {
            drive_speed( -300, -300 );                  
          }
          else if ( data == 'b' ) {
           drive_speed(-100, -100);
            }    
          else if ( data == 'l' ) {
            drive_speed( -100, 0 );                   
          }
          else if ( data == 'r' ) {
            drive_speed( 0, -100 );                   
          }
          else if ( data == 's' )                   
          {
            drive_speed( 0, 0 );                   
          }
        }
        else  // happens if xbee_status_pin == 0
        {
          drive_speed( -100, 100 );  // do the default thing
        }
      }
    }
    

    Is that what you're trying to accomplish?
  • twm47099twm47099 Posts: 867
    edited 2016-02-26 18:26
    I took your earlier code, and deleted most of the steps in the main program between the if "yep" statements just to make the code more compact and easier to show in this post. If you take my suggestions below, you will have to add back your steps in main so the bot will move randomly as you wanted.

    I then make some suggested changes.
    I suggest using the joystick "s" value as the trigger to turn control from the joystick back to the random function, at least until you get the bot to work accepting commands from the XBee.

    The modified code is shown below:

    In the code you posted there was no closing "}" for main. I think that may have been a typo when copying the code to the post. When I am writing code with a lot of bracketed sections I will usually comment the ending } for sections that have a lot of code between starting and ending brackets. When I'm done & it works, I can remove the comments.

    I don't think that you need Lspd & Rspd since you are putting the speed numbers into the drive speed command. I used them and the "drive_ramp(Lspd, Rspd)" command because I was adding speed each time the remote called for a change. (although Lspd & Rspd may still be useful; see my last comments about conflicts.)

    In your original remote() function, at the end you had a statement "bumpflg = 0". That was executed every time you went through the while loop. So the program set a speed from the XBee, but at the end of the loop gave back control to Rand. Moving the statement up just below the drive_speed(0,0) as I show should allow the XBee to remain in control until an "s" is sent. When "s" is sent, the bot should stop and control will be given back to Rand (you might want to add a small pause before setting bumpflg =1 0 so it will transition smoother).

    One problem I see is that in main() since there are so many statements and long pauses between the "if(! bumpflg)" and the end of the loop, I think there will still be conflict between rand and the joystick. For example lets say that rand is executing yep = 1, there will be almost 20 seconds of drive movement controlled by yep = 1 before XBee can have exclusive control. You would either have to add a delay in remote (check bumpflg) and have the main program set bumpflg = 1 at the end of each loop to give Xbee a chance to take control. There is probably a better way to check that if for example you used arrays of drive and pause commands and just used a while loop for each one, something like:
    if yep = 1
    {
      x = 0;
      while(x < numsteps[yep] && !bumpflg)   
      {
        drive_speed(Lspd[yep, x], Rspd[yep, x]);
        y = 0:
        while(y<10 && !bumpflg)
        {
          pause(delay[yep, x]);
          y++;
        }
        x++;
       }
    
    
    There would still be some conflicts due to the length of the pauses, but if you make each pause 1/10 what it is now the while "y" loop shown above would minimize the time for a possible conflict.
    You would have to load the arrays in the variable declarations, but it would also make the code easier to read and modify.

    EDIT: Since the code above uses "if yep = 1", you don't need 2 dimensional arrays which I try to avoid when loading them in declarations. Just use Lspd_1[x], Rspd_1[x] and delay_1[x] for yep = 1, and Lspd_2[x] etc. for yep = 2 etc.

    hope this helps or at least gives you some other ideas.,
    Tom
    #include "simpletools.h"
    #include "fdserial.h"
    #include "abdrive.h"
    #include "wavplayer.h"
    #include "servo.h"
    #include "ping.h"
    
    fdserial *xbee;
    int yep;
    int turn;
    int *cogremote;
    volatile int bumpflg;
    void remote();
    int Lspd, Rspd = 0;
    
    int main()
    {
     bumpflg = 0;		
     cogremote = cog_run(remote, 100);
    
     while(1)
     {
    
    if(! bumpflg)		// if zero then rand controls   *** add this line
    {				//  *** add this line
    
      yep = rand() %3;
      if(yep == 0)
     {
      drive_speed(-100, -100);
      pause(1000);
     }
    
     if(yep == 1)
    {
     drive_speed(-10, -30);
     pause(1000); 
    }
    
    if(yep == 2)
    {
    drive_speed(-10, 10);
    pause(750); }
    if( ! bumpflg) drive_ramp(Lspd, Rspd);     // *** delete this ***
    }
    
    }   // end !bumpflg      //  *** add this line  ***
    }	// end while
    //  need one more }    // end main    *** add the } ***
    
    
    void remote()		// try using “s” to say XBee not controlling just to see if it works
                                       // if not “s” set bmpflg = 1 so XBee controls
    {
    xbee = fdserial_open(9, 8, 0, 9600 );
    char data;
    while (1)
    {
    if(! input (data = fdserial_rxChar( xbee )));   //*** delete ***
    data = fdserial_rxChar( xbee);         // rx_Char waits until a char is received *** add this line ***
    bumpflg = 1;    
    
    if ( data == 'f' )
    {
    drive_speed( -300, -300 );
    }
    
    else if ( data == 'b' )
    {
    drive_speed( 50, 50 );
    }
    
    else if ( data == 'l' )
    {
    drive_speed( -100, 0 );
    }
    
    else if ( data == 'r' )
    {
    drive_speed( 0, -100 );
    }
    
    else if ( data == 's' )
    {
    drive_speed( 0, 0 );
    }			*** // delete this line ***
    bumpflg = 0;
    }                               // *** add this line ***
    }
    }
    
    
    
  • Wow, thank you both so much! I am really grateful!

    Jason, thank you so much. I completely agree, I do not know how to symbolize or monitor when the xbee is OFF. The program needs to be able to detect if XBEE off then do some other action. I looked up online and also checked my wiring. It appears that I have the xbee DO going to Pin 9, and the DI going to Pin 8 on the robot. The same is true on the transmitter side.

    Using your second program, I plugged in the number 8 where you had put 15, and I ran the program. The robot does correctly receive data and drives beautifully. But once again, when I turn off the xbee, it does not resort back to drive_speed(100, -100). It just sits still. If I turn Xbee back on, it again begins to follow my commands. I still am unable to get it to start a different action once xbee is off.

    Tom, thank you so much! I am still too novice to really understand what is happening in the program you wrote. When I plug it in, the robot will drive correctly. However, in the default "s" position (when the joystick is in the neutral position), the robot moves very herky jerky. Once I implement forward, backwards, left or right, it drives perfectly. But in the default stop position it is clearly receiving conflicting commands or something. However, when I turn off the xbee it does resume the automatic driving sequence which is cool!

    I will keep playing around, but admit that I am out of my league. I feel that this is very close, and yet I am so far away hahahaha

    Thank you both so much for the help. Any other suggestions you have would be greatly appreciated, but I understand if you have devoted as much time as you can tolerate to this. Thanks again!

    -Deepak
  • twm47099twm47099 Posts: 867
    edited 2016-02-28 01:24
    Maybe the problem with "s" is that I thought that it would be used to transfer control to the automatic mode. If it is not, just delete the "bumpflg = 0"

    But that makes another problem. The auto mode doesn't turn on until "bumpflg =0".

    If you can I'd suggest adding 2 buttons (tact switches) to the board with the joystick. The tutorials show how to wire them up. Use 1 to turn on auto mode and the other to turn on joystick mode. When a button is pressed have the Xbee send the data to the board on the robot and just have one set bumpflg =0 and the other bumpflg = 1.

    Another way is to use a sequence of joystick motions to = transfer back to auto and another sequence to restart using the joystick . For example, b, f, b (or some sequence you wouldn't use when driving). You would have a variable, let's call it "offnum". It would start =0. In the part of the code where "b" is run, you would check its value. If 1, reset it to 0. Otherwise you would add 1 to it. If it then equaled 3, you would set drive_speed(0,0), offnum =0, and bumpflg = 0. In "f" if offnum = 1, you would add another 1 to it. If anything else, just reset offnum =0.

    You might have to play with the code to get the details to work. But the issue is how to send a use-auto / use-joystick code from the joystick board to the robot.

    Another way is to use a timer like roscoe suggested. But I'm not sure how to do that.
    Tom
  • Guys, I can't believe it but it worked! Tom, I ended up using your program. Rather than use the "s" I put it in "b". I also added a servo cog, ping, and lights. It's freakin awesome! The thing looks like it is alive! When you get too close to an object it will sound one of three sounds at random!

    Instead of "s", I put it under "b". So now, I turn on the robot, it engages in the automatic drive program. When I turn on xbee, the robot stops, but mildly twitches until full control is given over to xbee (like you said Tom). Once full control is given over, the robot drives forward, and turns left and right without interruption. If I hit backwards "b", the automatic drive program is again engaged. So if I hit backwards while simultaneously turning off xbee, the robot will go back to it's automatic program!

    I am going to add a tact switch like you suggested, so that I can restore the reverse function and drive in all four directions. Then when I want to go to automatic driving, I can hit the tact button and take it from there.

    One quick question, there is not enough room on the breadboard for two tact buttons and the joystick. Any suggestions?

    Thank you Tom and Jason, I really really appreciate the help. This thing is so awesome now, definitely could never have done this by myself!
    #include "simpletools.h"
    #include "fdserial.h"
    #include "abdrive.h"
    #include "wavplayer.h"
    #include "servo.h"
    #include "ping.h"
    
    fdserial *xbee;
    int yep;
    int voice;
    int *cogremote;
    volatile int bumpflg;
    void remote();
    void servo();
    void eyes();
    void lights();
    
    int main()
    {
     bumpflg = 0;		
    cogremote = cog_run(remote, 100);
    cog_run(servo, 100);
    cog_run(eyes, 100);
    cog_run(lights, 100);
    
     while(1)
     {
    if(! bumpflg)		// if zero then rand controls   *** add this line
    {	
    yep = rand() %3;
     if(yep == 0)
     {
     drive_speed(-100, -100);
     pause(1000);
     drive_speed(-64, -30);
     pause(500);
     drive_speed(64, -64);
     pause(2000);
     drive_speed(-50, -50);
     pause(300);
     drive_speed(50, 50);
     pause(300);
     drive_speed(-64, 64);
     pause(2000);
     drive_speed(64, 30);
     pause(500);
     drive_speed(100, 100);
     pause(1000);
     drive_speed(100, -100);
     pause(3000);
     drive_speed(-50, -50);
     pause(500);
     drive_speed(64, 0);
     pause(700);
     drive_speed(0, 64);
     pause(700);
     drive_speed(-50, -50);
     pause(1000);
     drive_speed(50, 50);
     pause(1000);
     drive_speed(0, -64);
     pause(700);
     drive_speed(-64, 0);
     pause(700);
     drive_speed(50, 50);
     pause(500);
     drive_speed(-100, 100);
     pause(3000);
     }
     if(yep == 1)
     {
     drive_speed(-10, -30);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(-15, -15);
     pause(1000);
     drive_speed(-30, -30);
     pause(300);
     drive_speed(0, 0);
     pause(4000);
     drive_speed(30, 30);
     pause(300);
     drive_speed(15, 15);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(10, 30);
     pause(1000);
     drive_speed(-30, -10);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(-15, -15);
     pause(1000);
     drive_speed(-30, -30);
     pause(300);
     drive_speed(0, 0);
     pause(4000);
     drive_speed(30, 30);
     pause(300);
     drive_speed(15, 15);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(30, 10);
     pause(1000);
     }
    
     if(yep == 2)
     {
     drive_speed(-10, 10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(1200);
     pause(2000);
     pause(500);
     drive_speed(10,10);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
     pause(3000);
     drive_speed(10, -10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(2000);
     pause(1000);
     drive_speed(-10,-10);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
     pause(670);
     drive_speed(15, 5);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
     pause(3000);
     drive_speed(-10, 10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(1200);
     pause(2000);
     pause(500);
     drive_speed(-15,-5);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
     pause(3000);
     drive_speed(5, 15);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
     pause(500);
     drive_speed(-5,-15);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
     pause(3000);
     drive_speed(10, -10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(1200);
     pause(2000);
     pause(3000);
     drive_speed(10, -10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(1200);
     pause(2000);
     pause(3000);
     drive_speed(-10, 10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(1200);
     pause(2000);
     pause(500);
     drive_speed(10,10);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
     pause(3000);
     drive_speed(10, -10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(1200);
     pause(2000);
     pause(3000);
     drive_speed(10, -10);
     pause(750);
     pause(3000);
     pause(890);
     pause(1679);
     pause(3800);
     drive_speed(0,0);
     pause(1200);
     pause(2000);
     pause(1000);
     drive_speed(-10,-10);
     pause(2000);
     pause(1000);
     drive_speed(0,0);
     pause(750);
    }   // end !bumpflg      //  *** add this line  ***
    }	// end while
    }
    }
    
    void remote()		// try using “s” to say XBee not controlling just to see if it works
                                       // if not “s” set bmpflg = 1 so XBee controls
    {
    xbee = fdserial_open(9, 8, 0, 9600 );
    char data;
    while (1)
    {
    data = fdserial_rxChar( xbee);         // rx_Char waits until a char is received *** add this line ***
    bumpflg = 1;    
    
    if ( data == 'f' )
    {
    drive_speed(-300, -300);
    }
    else if ( data == 'b' )
    {
    drive_speed( 100, 100 );
    bumpflg = 0;
    }
    
    else if ( data == 'l' )
    {
    drive_speed( -100, 0 );
    }
    
    else if ( data == 'r' )
    {
    drive_speed( 0, -100 );
    }
    
    else if ( data == 's' )
    {
    drive_speed( 0, 0 );
    }                               // *** add this line ***
    }
    }
    
    
    void servo()
    {
      while(1)
    {
    servo_angle(16, 900); 
    pause(400);
    servo_angle(16, 750);
    pause(600);
    servo_angle(16, 450);
    pause(1000);
    servo_angle(16, 800);
    pause(400);
    servo_angle(16, 1100);
    pause(890);
    servo_angle(16, 1350);
    pause(300);
    servo_angle(16, 1800);
    pause(3000);
    servo_angle(16, 200); 
    pause(750);
    servo_angle(16, 0);
    pause(3000);
    servo_angle(16, 750); 
    pause(890);
    servo_angle(16, 1000);
    pause(1679);
    servo_angle(16, 1600);
    pause(3800);
    servo_angle(16, 650);
    pause(1200);
    servo_angle(16, 0);
    pause(2000);
    servo_angle(16, 900);
    pause(500);
    servo_angle(16, 1250);
    pause(2000);
    servo_angle(16, 1400);
    pause(1000);
    servo_angle(16, 1150);
    pause(750);
    servo_angle(16, 1800);
    pause(3000);
    servo_angle(16, 250); 
    pause(750);
    servo_angle(16, 0);
    pause(3000);
    servo_angle(16, 390); 
    pause(890);
    servo_angle(16, 970);
    pause(1679);
    servo_angle(16, 1800);
    pause(3800);
    servo_angle(16, 250);
    pause(1200);
    servo_angle(16, 310);
    pause(2000);
    servo_angle(16, 1250);
    pause(1000);
    servo_angle(16, 1500);
    pause(2000);
    servo_angle(16, 1800);
    pause(1000);
    servo_angle(16, 1340);
    pause(750);
    servo_angle(16, 1300);
    pause(670);
    servo_angle(16, 900);
    pause(2000);
    servo_angle(16, 750); 
    pause(1000);
    servo_angle(16, 450); 
    pause(750);
    servo_angle(16, 1300);
    pause(3000);
    servo_angle(16, 400); 
    pause(750);
    servo_angle(16, 0);
    pause(3000);
    servo_angle(16, 350); 
    pause(890);
    servo_angle(16, 1300);
    pause(1679);
    servo_angle(16, 1400);
    pause(3800);
    servo_angle(16, 970);
    pause(1200);
    servo_angle(16, 344);
    pause(2000);
    servo_angle(16, 0);
    pause(500);
    servo_angle(16, 250); 
    pause(2000);
    servo_angle(16, 450); 
    pause(1000);
    servo_angle(16, 250); 
    pause(750);
    servo_angle(16, 570);
    pause(3000);
    servo_angle(16, 900); 
    pause(2000);
    servo_angle(16, 250); 
    pause(1000);
    servo_angle(16, 1450);
    pause(750);
    servo_angle(16, 0);
    pause(500);
    servo_angle(16, 350); 
    pause(2000);
    servo_angle(16, 750);
    pause(1000);
    servo_angle(16, 1700); 
    pause(750);
    servo_angle(16, 1300);
    pause(3000);
    servo_angle(16, 1050); 
    pause(750);
    servo_angle(16, 0);
    pause(3000);
    servo_angle(16, 790); 
    pause(890);
    servo_angle(16, 270);
    pause(1679);
    servo_angle(16, 1800);
    pause(3800);
    servo_angle(16, 1250);
    pause(1200);
    servo_angle(16, 310);
    pause(2000);
    servo_angle(16, 300);
    pause(3000);
    servo_angle(16, 1250); 
    pause(750);
    servo_angle(16, 0);
    pause(3000);
    servo_angle(16, 390); 
    pause(890);
    servo_angle(16, 770);
    pause(1679);
    servo_angle(16, 1200);
    pause(3800);
    servo_angle(16, 650);
    pause(1200);
    servo_angle(16, 310);
    pause(2000);
    servo_angle(16, 1400);
    pause(3000);
    servo_angle(16, 1200); 
    pause(750);
    servo_angle(16, 100);
    pause(3000);
    servo_angle(16, 750); 
    pause(890);
    servo_angle(16, 1200);
    pause(1679);
    servo_angle(16, 1600);
    pause(3800);
    servo_angle(16, 450);
    pause(1200);
    servo_angle(16, 900);
    pause(2000);
    servo_angle(16, 1200);
    pause(500);
    servo_angle(16, 1000);
    pause(2000);
    servo_angle(16, 1400);
    pause(1000);
    servo_angle(16, 750);
    pause(750);
    servo_angle(16, 1800);
    pause(3000);
    servo_angle(16, 1200); 
    pause(750);
    servo_angle(16, 980);
    pause(3000);
    servo_angle(16, 550); 
    pause(890);
    servo_angle(16, 1800);
    pause(1679);
    servo_angle(16, 1400);
    pause(3800);
    servo_angle(16, 350);
    pause(1200);
    servo_angle(16, 0);
    pause(2000);
    servo_angle(16, 1800);
    pause(3000);
    servo_angle(16, 250); 
    pause(750);
    servo_angle(16, 0);
    pause(3000);
    servo_angle(16, 390); 
    pause(890);
    servo_angle(16, 970);
    pause(1679);
    servo_angle(16, 1800);
    pause(3800);
    servo_angle(16, 250);
    pause(1200);
    servo_angle(16, 310);
    pause(2000);
    servo_angle(16, 1250);
    pause(1000);
    servo_angle(16, 1500);
    pause(2000);
    servo_angle(16, 1800);
    pause(1000);
    servo_angle(16, 1340);
    pause(750);
    }
    }
    
    
    
    void eyes()
    {
        while(1)
      {
    freqout(4, 200, 0);
    while(ping_cm(17) >= 20) pause(5); 
    voice = rand() %3;
    if(voice == 0)
      {  
        freqout(4, 500, 2000);
    freqout(4, 500, 1000);
    freqout(4, 500, 3000);
      }    
    if(voice == 1)
      {  
        freqout(4, 500, 3000);
    freqout(4, 500, 1000);
    freqout(4, 500, 2000);
      }    
    if(voice == 2)
      {  
    freqout(4, 500, 467);
    freqout(4, 500, 2768);
    freqout(4, 500, 1324);
      }    
      while(ping_cm(17) < 20);
    }
    }
    
    void lights()
    {
      while(1)
      {
        high(5);
        pause(300);
        low(5); high(11);
        pause(1000);
       high(5);
        pause(200);
        low(11); low(5);
        pause(560);
        high(11);
        pause(300);
        low(11);
        pause(300);
        high(5); high(11);
        pause(1000);
        low(5); low(11);
        pause(200);
        high(11); high(5);
        pause(200);
    low(5); low(11);
        pause(200);
        high(11); high(5);
        pause(200);
    low(5); low(11);
        pause(200);
        high(11); high(5);
        pause(200);
    low(5); low(11);
        pause(200);
        high(11); high(5);
        pause(200);
    low(5); low(11);
        pause(200);
        high(11); high(5);
        pause(200);
        low(5); high(11);
        pause(1000);
       high(5);
        pause(300);
        low(5); high(11);
        pause(1000);
      }    
     }
    
  • Congratulations on modifying it so it works the way you want and for putting it all together.

    I'm not sure how to mount the tact switches. I didn't realize that the joystick was so large. One thing you can try is to get a piece of foamcore art board and a small breadboard. Cut the foam core large enough to fit both the Activity Board with the joystick and the small bread board. You can temporarily screw the ABoard to foam core and use a small piece of double backed foam tape to hold the small breadboard so you can remove them later. Otherwise make the board look good and mount it permanently. Then you can put the tact switches on the small breadboard and connect jumpers to the Activity Board pin connectors.

    I find that once I write a program and get it working, I keep "optimizing" it. Once you get everything working how you want you might want to use the looping method I suggested to get rid of the jittter when switching to joystick control. You might also be able to figure out a couple of modifications so that you don't have to turn off the joystick board, but just use the switches to switch from one mode to the other.

    I recommend cleaning up the comments so they reflect how the statement is actually working. That way when you look at or modify the program in the future they won't be confusing. (voice of experience)

    Enjoy,
    Tom
  • One of the suggestions here was a timer, which might be a good idea. If you make your joystick so it's *always* sending while it's connected, even if it's centered, then it's pretty easy for your bot to tell if it's connected, because it'll stop receiving commands if it isn't.

    Using my earlier version as a starting point, you'd modify it like this:
    int main() 
    {
    xbee = fdserial_open(9, 8, 0, 9600 );      
    char data;                                 
    cog_run(driving, 128);
    int commandTimer = 0;
    const int loopPause = 5;  // pause time constant for loop
    
      while (1)                                 
      {
        int newChar = fdserial_rxCheck( xbee );
        if( newChar != -1 ) {
    
          // set this to how long to wait, in ms until you go back to auto mode
          commandTimer = 500;  // wait 1/2 a second after the last command
    
          data = newChar;  // This only happens when an actual character is received
          if ( data == 'f' ) {
            drive_speed( -300, -300 );                  
          }
          else if ( data == 'b' ) {
           drive_speed(-100, -100);
            }    
          else if ( data == 'l' ) {
            drive_speed( -100, 0 );                   
          }
          else if ( data == 'r' ) {
            drive_speed( 0, -100 );                   
          }
          else if ( data == 's' )                   
          {
            drive_speed( 0, 0 );                   
          }
        }
        else  // happens if no new data was received
        {
          if( commandTimer > 0 )  {
            commandTimer -= loopPause ;  // subtract off how long we pause in each loop
          }
    
          // if we havent seen a command in a while, do the default behavior
          if( commandTimer <= 0 ) {
            drive_speed( -100, 100 );  // do the default thing
          }
        }
    
        pause(loopPause);  // delay so you can time stuff
      }
    }
    

    With this code, if your joystick always sends 's' when stopped, or 'f' when forward, etc, and sends even once every 10th of a second, the above code will respond like it does normally. As soon as you turn off the joystick and it stops sending, the commandTimer value will start counting down, and when it reaches zero, the auto/default thing takes over. The next time you get a new command (which will happen if you turn the xbee on again) the commandTimer resets and you get normal control again.
  • Thank you so much Jason! I will definitely try this next!

    I modified and tweaked the code. I added a tact switch as was suggested and the thing works freakin amazingly. I push the tact switch and simultaneously turn off xbee and the robot goes back to its autodrive function. That freed up the backwards button so now I can drive in all directions.

    Put in some random movements for the head servo and lights to add a little extra action. Code is below. Thank you both so much, I am very happy so far with how it is turning out! Also, how did you both learn this language so well? A lot of the commands you are using are not in the tutorials. If I am interested in learning more, do I need to take a class? Or is there some guide online I can learn from (such as command timer, newchar ! etc. etc.). Thanks again to both of you!

    Also, I have two pictures of the robot and joystick controller. Is there a way to attach those to a post?

    -Deepak

    #include "simpletools.h"
    #include "fdserial.h"
    #include "abdrive.h"
    #include "wavplayer.h"
    #include "servo.h"
    #include "ping.h"
    
    fdserial *xbee;
    int yep;
    int voice;
    int head;
    int bright;
    int *cogremote;
    volatile int bumpflg;
    void remote();
    void servo();
    void eyes();
    void lights();
    
    int main()
    {
     bumpflg = 0;		
    cogremote = cog_run(remote, 100);
    cog_run(servo, 100);
    cog_run(lights, 100);
    cog_run(eyes, 100);
     while(1)
     {
    if(! bumpflg)		
    {	
    yep = rand() %5;
     if(yep == 0)
     {
     drive_speed(-100, -100);
     pause(1000);
     drive_speed(-64, -30);
     pause(500);
     drive_speed(64, -64);
     pause(2000);
     drive_speed(-50, -50);
     pause(300);
     drive_speed(50, 50);
     pause(300);
     drive_speed(-64, 64);
     pause(2000);
     drive_speed(64, 30);
     pause(500);
     drive_speed(100, 100);
     pause(1000);
     drive_speed(100, -100);
     pause(3000);
     drive_speed(-50, -50);
     pause(500);
     drive_speed(64, 0);
     pause(700);
     drive_speed(0, 64);
     pause(700);
     drive_speed(-50, -50);
     pause(1000);
     drive_speed(50, 50);
     pause(1000);
     drive_speed(0, -64);
     pause(700);
     drive_speed(-64, 0);
     pause(700);
     drive_speed(50, 50);
     pause(500);
     drive_speed(-100, 100);
     pause(3000);
     }
     if(yep == 1)
     {
     drive_speed(-10, -30);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(-15, -15);
     pause(1000);
     drive_speed(-30, -30);
     pause(300);
     drive_speed(0, 0);
     pause(4000);
     drive_speed(30, 30);
     pause(300);
     drive_speed(15, 15);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(10, 30);
     pause(1000);
     drive_speed(-30, -10);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(-15, -15);
     pause(1000);
     drive_speed(-30, -30);
     pause(300);
     drive_speed(0, 0);
     pause(4000);
     drive_speed(30, 30);
     pause(300);
     drive_speed(15, 15);
     pause(1000);
     drive_speed(0, 0);
     pause(500);
     drive_speed(30, 10);
     pause(1000);
     }
    
     if(yep == 2)
     {
    drive_speed(-50, -30);
    pause(500);
    drive_speed(-20, 20);
    pause(400);
    drive_speed(20, -20);
    pause(400);
    drive_speed(50, 30);
    pause(500);
    drive_speed(0, 0);
    }  
     if(yep == 3)
     {
       drive_speed(-100, -100);
    pause(500);
    drive_speed(-100, 100);
    pause(1000);
    drive_speed(0, 0);
    pause(1000);
    drive_speed(100, -100);
    pause(1000);
    drive_speed(100, 100);
    pause(500);
    drive_speed(0, 0);
    pause(200);
    }	
    
    if(yep == 4)
    {
      drive_speed(30, 70);
    pause(500);
    drive_speed(70, 30);
    pause(500);
    drive_speed(-100, 100);
    pause(2000);
    drive_speed(100, -100);
    pause(2000);
    drive_speed(-70, -30);
    pause(500);
    drive_speed(-30, -70);
    pause(500);
    }
    }
    }
    }
    
    void remote()		
                                      
    {
    xbee = fdserial_open(9, 8, 0, 9600 );
    char data;
    while (1)
    {
    data = fdserial_rxChar( xbee);        
    bumpflg = 1;    
    
    if ( data == 'f' )
    {
    drive_speed(-300, -300);
    }
    if ( data == 'b' )
    {
      drive_speed(75, 75);
      }
    
    if ( data == 'l' )
    {
    drive_speed( -100, 0 );
    }
    
    if ( data == 'r' )
    {
    drive_speed( 0, -100 );
    }
    
    if ( data == 's' )
    {
    drive_speed( 0, 0 );
    }     
    
    if (data == 'a')
    {high(26);
    bumpflg = 0;
    }
    
    if (data == 'q')
    {
      low(26);
    }  
    }
    }
    
    
    void servo()
    {
      while(1)
    {
    head = rand() %5;
     if(head == 0)
     {
    servo_angle(16, 0); 
    pause(1000);
    servo_angle(16, 1800);
    pause(1000);
    servo_angle(16, 900);
    pause(1000);
    servo_angle(16, 1800); 
    pause(1000);
    servo_angle(16, 0);
    pause(1000);
    servo_angle(16, 900);
    pause(1000);
    }
    if(head == 1)
    {
    servo_angle(16, 243); 
    pause(400);
    servo_angle(16, 400);
    pause(500);
    servo_angle(16, 767);
    pause(1000);
    servo_angle(16, 1000); 
    pause(500);
    servo_angle(16, 900);
    pause(1000);
    }
    
    if(head == 2)
    {
    servo_angle(16, 1400); 
    pause(600);
    servo_angle(16, 400);
    pause(1000);
    servo_angle(16, 1800);
    pause(1000);
    servo_angle(16, 1000); 
    pause(500);
    servo_angle(16, 700);
    pause(345);
    }
    if(head == 3)
    {
      servo_angle(16, 986); 
    pause(345);
    servo_angle(16, 0);
    pause(1000);
    servo_angle(16, 240);
    pause(230);
    servo_angle(16, 500); 
    pause(500);
    servo_angle(16, 1800);
    pause(1300);
    }
    
    if(head == 4)
    {
      servo_angle(16, 900); 
    pause(3000);
    servo_angle(16, 760);
    pause(300);
    servo_angle(16, 200);
    pause(500);
    servo_angle(16, 1100); 
    pause(700);
    servo_angle(16, 1700);
    pause(1300);
    }
    }
    }
    
    void eyes()
    {
        while(1)
      {
    freqout(4, 200, 0);
    while(ping_cm(17) >= 20) pause(5); 
    voice = rand() %3;
    if(voice == 0)
      {  
        freqout(4, 500, 2000);
    freqout(4, 500, 1000);
    freqout(4, 500, 3000);
      }    
    if(voice == 1)
      {  
        freqout(4, 500, 3000);
    freqout(4, 500, 1000);
    freqout(4, 500, 2000);
      }    
    if(voice == 2)
      {  
    freqout(4, 500, 467);
    freqout(4, 500, 2768);
    freqout(4, 500, 1324);
      }    
      while(ping_cm(17) < 20);
    }
    }
    
    void lights()
    {
      while(1)
      {
    bright = rand() %4;
     if(bright == 0)
     {
       high(5);
    pause(200);
    high(11);
    pause(300);
    low(5); low(11);
    pause(200);
    high(11); high(5);
    pause(700);
    low(5); low(11);
    pause(200);
    high(11); high(5);
    pause(700);
    low(5); low(11);
    pause(200);
    high(11); high(5);
    pause(700);
    low(5); low(11);
    pause(200);
    high(11); high(5);
    pause(700);
    low(5); low(11);
    pause(200);
    high(11); high(5);
    pause(700);
    low(5); low(11);
    pause(200);
    high(11); high(5);
    pause(700);
    low(5); high(11);
    pause(200);
    high(5); low(11);
    pause(700);
    low(5); high(11);
    pause(200);
    high(5); low(11);
    pause(700);
    low(5); high(11);
    pause(200);
    high(5); low(11);
    pause(700);
    low(5); high(11);
    pause(200);
    high(5); low(11);
    pause(700);
    low(5); high(11);
    pause(200);
    high(5); low(11);
    pause(700);
    }
    
     if(bright == 1)
     {
    high(5); high(11);
    pause(200);
    low(11);
    pause(2000);
    low(5); high(11);
    pause(1000);
    high(5);
    pause(700);
    low(5); low(11);
    pause(2545);
    high(11);
    pause(900);
    low(11);
    pause(200);
    high(11); high(5);
    pause(3434);
    low(5); low(11);
    pause(2000);
    high(11); high(5);
    pause(700);
    low(5);
    pause(200);
    high(5);
    pause(700);
    }
    
    if(bright == 2)
    {
      low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    low(5); high(11);
    pause(100);
    low(11); high(5);
    pause(100);
    }
    
    if(bright == 3)
    {
      high(11), high(5);
    pause(300);
    low(5);
    pause(465);
    low(11);
    pause(156);
    high(5);
    pause(546);
    low(5);
    pause(300);
    high(11), high(5);
    pause(1000);
    low(11), high(5);
    pause(300);
    }
     }
     }
    

  • Here is the code for the joystick side and tact button. Again, if there is a way to post a photo that would be cool.
    /*
    Code for Activity Board Joystick Controller - Joystick-Controlled ActivityBot Project
    Author: Vale T
    */
    #include "simpletools.h"                      // Include simple tools
    #include "fdserial.h"
    #include "adcDCpropab.h"
    
    fdserial *xbee;                               //Initialize the full-duplex serial connection over XBee
    
    int main()
    {
      xbee = fdserial_open( 9, 8, 0, 9600 );      // Open the serial connection
      adc_init( 21, 20, 19, 18 );                 // Initialize the analogue connections for the joystick
      float lrV, udV;                             // Create 2 float values for incoming joystick values
      
      while ( 1 )
      {
        int button = input(3);
        print("button = %d/n", button);
        udV = adc_volts( 2 );                     // Get values from the joystick
        lrV = adc_volts( 3 );
       
        if ( udV < 1.00 )                         // If joystick going backward, send backward value
        {
          dprint( xbee, "b" );
        }
         
        if ( udV > 4.00 )                    // If joystick going forward, send forward value
        {
          dprint( xbee, "f" );
        }
         
        if ( udV < 4.00 && udV > 1.00 && lrV < 4.00 && lrV > 1.00 ) // If joystick is in center,
                                                                         // send stop value
        {
          dprint( xbee, "s" );
        }
         
        if ( lrV < 1.00 )                    // If joystick is going left, send left value
        {
          dprint( xbee, "l" );
        }
         
        if ( lrV > 4.00 )                    // If joysitck is going right, send right value
        {
          dprint( xbee, "r" );
        }
        
        if (button == 1)
        {
          dprint( xbee, "a" );
        } 
        
        if (button == 0)
        {
          dprint( xbee, "q" );
        }
                   
        pause( 50 );                              // Only need to check joystick values 20 times a second
      }
    }
    
  • When posting, just below the edit box is "attach a file" - click that, then "choose file", find the file on your computer and that should do it.

    As for how to get good, C/C++ has been around a long time. There are probably online courses, or local colleges that would teach programming classes. I learned C on my own, reading voraciously and experimenting to start with. Then I started working in video games and learned through the job. Read a lot of other people's code, troll places like CodeProject.com, and so on. It takes practice. Generally you learn best by doing, so you're going about it the right way so far. :)
  • I'm still learning C. There are some concepts that I think I understand, and then get confused (especially pointers).

    In the late 1970's and 1980's I did a lot of programming in BASIC, both as a hobby and at work. I had learned FORTRAN in college, but didn't use it much after that. In my hobby, I was also exposed a little to FORTH and C. I liked both of those languages because they were not wordy and had some neat capabilities. But I didn't have much of a chance to use them. Eventually, my home computer (Compucolor 2) died and couldn't be fixed or replaced, and I also changed jobs where I didn't do programming any more.

    Skip ahead 30 years

    A couple things happened a couple of years ago. I started using my Android tablet to make some photography programs in Forth, and got interested in programming again. Then I was searching the web to find a robot kit as a Christmas present for one of my nephews, and found Parallax. I bought him a BOE BOT, and bought myself an ActivityBot since I thought it would be a good way to learn C.

    I did the tutorials, and started combining different tutorials, like my program that uses the SIRC as a remote control combined with whiskers in a different cog to handle bumping into things. I also started reading the documentation in the SimpleIDE library folders, and that gave me ideas of commands I could use to improve my programs (shorten, speed-up, use less memory). The link to the current Simple library is here:

    https://propsideworkspace.googlecode.com/hg/Learn/Simple%20Libraries%20Index.html

    There is also the Propeller C library here for more advance features (but start with the SimpleIDE ones first).:

    https://sites.google.com/site/propellergcc/documentation/libraries/propeller-h-library

    As I read these forums, I came up with other ideas of things I wanted to do, such as use my android tablet to control the ActivityBot and sensors. That meant that I had to learn to read sensor data sheets, different C commands, and different Propeller features (like the counters).

    I also read other peoples code. That's how I originally learned BASIC - translating programs for other computers to my Compucolor 2.

    There are a lot of programs in Spin in the Propeller Tool Libraryfor different sensors. I had to learn Spin to be able to convert them to C. I still am trying to learn Spin. I bought the Propeller Education Kit Book (also available as free download) to help me learn Spin, and I found that I ended up converting the Spin programs in that book to C.

    You are essentially doing what I did with the tutorials - combining and changing things to do what you want. Keep it up and read up on C to see how to improve your programs. One thing I would suggest first is to try to use different types of loops to shorten your programs (for loops, while loops with incrementing the argument similar to what I suggested in an earlier post.) Just make sure you save the program that works.

    If you have an android device, I found the "C programming book" free ap below to be useful. It can be read to get an idea of the different C statements, and has a good reference. Note that there are many free C programming aps, just find one that is good for you.

    Tom

    amazon.com/OneForMe-Learn-C-Programming-Reference/dp/B009M4RGNY/ref=sr_1_14?s=mobile-apps&ie=UTF8&qid=1456850039&sr=1-14&keywords=c+programming+book

  • Thank you both so much!! I will definitely start perusing other people's code etc. and go from there. Thanks again! I've attached two photos of the robot/controller. I have been having a blast with this thing, so thanks, I am really grateful!

    -Deepak
    1224 x 918 - 379K
    1224 x 918 - 422K
  • Also, I forgot to mention, I installed the board and servo backwards. I did this deliberately so that the center of gravity is better balanced. Installed the normal way, the servo/ping device made the thing too front heavy, and any time there was a sudden direction change it would always slightly tip. Never flipped, but still annoying. This way, the robot is always solid, no matter how quick I make the direction change.

    Only thing one has to keep in mind is that to drive forward you need negative numbers, and to drive backwards you need positive numbers.
Sign In or Register to comment.