Shop OBEX P1 Docs P2 Docs Learn Events
Draft: Make Your Own ActivityBot Programming Language — Parallax Forums

Draft: Make Your Own ActivityBot Programming Language

edited 2013-10-17 10:12 in Learn with BlocklyProp
Overview: This is a draft of a tutorial intended to spark some additional interest in more tutorials on the basics of string manipulation. The current plan is to link from this tutorial to some smaller ones that cover more string handling building blocks and fundamental concepts that go into this application. Since it’s intended to be a lighter introduction, certain file and string formalities were omitted from the example. The plan is also to address them in separate tutorials.

Make Your Own ActivityBot Programming Language

Up until now, we’ve been making programs in C language that make the ActivityBot perform various tasks. In this activity, you will experiment with a program that opens a file from the SD card that’s in another programming language. Let’s call it AB. The AB programming language has five commands, forward, backward, left, right, and end. Each command has a single argument, which is the distance the ActivityBot should travel in encoder ticks. Your C program will interpret and execute each AB command.

attachment.php?attachmentid=104431&d=1381978366

Circuit

We will not be using any sensor circuits here, just the SD card.
  • Insert your kit’s microSD card into your Propeller Activity Board’s SD socket.

Test Code

Start by downloading the application zip and then copy its folder into your ActivityBot tutorial folder.
  • Make sure you have the latest SimpleIDE software, Learn folder, and ActivityBot Library.
  • Download the ActivityBot Navigate with SD Code.
  • Unzip the folder, and copy its SD Navigation folder to …Documents\SimpleIDE\Learn\Examples\ActivityBot Tutorial.

The zip for this application contains a text file that you will copy to your SD card. After that, you will load a C application into the ActivityBot that will open the file, and fetch and execute its AB language commands. It also has a test ActivityBot library that takes somewhat less space than the ActivityBot 2013-09-03b currently available from learn.parallax.com.
  • Use your file browser to find and open navset.txt, and verify that it contains the program with the forward, left, right, backward, and end commands.
  • Close the text file.
  • In SimpleIDE, SimpleIDE’s Open Project button.
  • Open AB Interpreter from …Documents\SimpleIDE\Learn\Examples\ActivityBot Tutorial\SD Navigation.
  • Click Program and select File to SD Card.
  • Select NAVSET.TXT and click Open. This will load the file onto the SD card. You can also verify that it loaded correctly by checking the build status pane. If it isn’t already open, just click the Show Build Status button at the bottom of the SimpleIDE window.
  • Now for running the interpreter. Click Load EEPROM and Run.
  • Verify that your ActivityBot goes forward, then spins in place to the left, then to the right, then to the left again, and backs up to about where it started.

How it Works

i-box: To learn more about SD data storage and retrieval, go to http://learn.parallax.com/propeller-c-simple-devices/sd-card-data. For an introduction to strings, go here (future links).

After opening navset.txt, the application copies up to 512 bytes from the text file to a 512 byte buffer named str. Then, the strLength = strlen(str) function figures out how many bytes are in the string and copies it to the strLength variable. Before any modifications, there are about 90 characters in the navset.txt.

The first task inside the while(1) loop for parsing commands is to find the first printable character. There might be carriage returns or blank spaces leading up to the first character in the command. So, while(!isalpha(str)) i++ repeatedly checks each successive character in the str string until it finds an alphanumeric character, which is assumed to be the first character in the next command. sscan(&str, “%s”, cmdbuf copies the word (up to the next non alphanumeric character) into a smaller character array named cmdbuf. Then, the index of for the next character to check in str is updated with i += strlen(cmdbuf). Last, but far from least, if(!strcmp(cmdbuf, “end”)) break checks to see if the end command has been reached. If it has, the break command exits the while(1) loop.

/*
 AB Interpreter.c
*/

#include "simpletools.h"                     // Library includes
#include "abdrive.h"  

FILE *fp;                                    // File pointer for SD
char str[512];                               // File buffer

char cmdbuf[10];                             // Command buffer
char valbuf[4];                              // Text value buffer
int  val;                                    // Value

int main()                                   // Main function
{
  int DO = 22, CLK = 23;                     // SD I/O pins
  int DI = 24, CS = 25;
  sd_mount(DO, CLK, DI, CS);                 // Mount SD file system
  fp = fopen("navset.txt", "r");             // Open navset.txt

  fread(str, 1, 512, fp);                    // navset.txt -> str 
  int strLength = strlen(str);               // Count chars in str
  int i = 0;                                 // Declare index variable

  drive_speed(0, 0);                         // Speed starts at 0

  while(1)                                   // Loop through commands
  {
    // Parse command
    while(!isalpha(str[i])) i++;             // Find 1st command char
    sscan(&str[i], "%s", cmdbuf);            // Command -> buffer
    i += strlen(cmdbuf);                     // Idx up by command char count
    if(!strcmp(cmdbuf, "end")) break;        // If command is end, break

    // Parse distance argument
    while(!isdigit(str[i])) i++;             // Find 1st digit after command
    sscan(&str[i], "%s", valbuf);            // Value -> buffer
    i += strlen(valbuf);                     // Idx up by value char count
    val = atoi(valbuf);                      // Convert string to value

    // Execute command
    if(strcmp(cmdbuf, "forward") == 0)       // If forward
      drive_goto(val, val);                  // ...go forward by val
    else if(strcmp(cmdbuf, "backward") == 0) // If backward
      drive_goto(-val, -val);                // ... go backward by val
    else if(strcmp(cmdbuf, "left") == 0)     // If left
      drive_goto(-val, val);                 // ...go left by val
    else if(strcmp(cmdbuf, "right") == 0)    // If right
      drive_goto(val, -val);                 // ... go right by val
  }
  
  fclose(fp);                                // Close SD file
}


The distance argument is parsed using similar techniques. For example, the statement while(!isdigit(str)) i++ checks and rejects any character that’s not a digit. After it does find a digit, sscan(&str, “%s”, valbuf) copies the value to a smaller character array named valbuf. Again, the index of for the next character to check in str is updated, this time with i += strlen(valbuf). After figuring out the position of the next character to check in the str array, it’s time to convert the character representation of the distance argument to a value the program can use. That’s what val = atoi(valbuf) does. The term atoi is short for ascii to integer.

After parsing the command and distance arguments, all that’s left is to check what the command is and use the distance arguments accordingly. To figure out what command string was actually stored in cmdbuf, we use strcmp. This function returns a zero if two strings match, or nonzero if they do not. So, if(strcmp(cmdbuf, “forward”) == 0 drive_goto(val, val) checks to see if the contents of cmdbuf match the string “forward”. If it does, then it uses the distance argument stored in val and drive_goto to make the activitybot go the distance. If cmdbuf instead stored the string “backward”, the first if statement would not be true, but else if(strcmp(cmdbuf, "left") == 0)… would be true.

Did You Know?

Many of the functions used for files, strings, and characters come from the Standard C Libraries built into Propeller GCC. The simpletools library has #includes for them, so they do not need to be included at the top of AB Interpreter. Here is a list of standard libraries and the functions used:

  • stdio.h: fopen, fread
  • string.h: strcmp, strlen
  • ctype.h: isalpha, isdigit
  • stdlib.h: atoi

My favorite resource for looking up and reading the documentation on these functions is IBM’s C library reference:
http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frtref%2Fsc41560702.htm

Try this

Let’s try expanding the AB language with a couple new commands: pivotLeft and pivotRight. These commands will keep one wheel still while turning the other so that the ActivityBot “pivots” on one wheel.
  • Modify navset.txt so that it looks like this.
  • Save and load the modified file to your board’s SD card.

    forward = 64
    pivotLeft = 53
    pivotRight = 106
    forward = 64
    end

  • Modify navset.txt so that it looks like this, and use Load EEPROM and run to run the modified example.
  • Verify that the ActivityBot goes forward a wheel turn, pivots about a quarter turn to the left, then about a half turn to the right, then goes forward and stops.
    // Execute command
    if(strcmp(cmdbuf, "forward") == 0)
      drive_goto(val, val);
    else if(strcmp(cmdbuf, "backward") == 0)
      drive_goto(-val, -val);
    else if(strcmp(cmdbuf, "left") == 0)
      drive_goto(-val, val);
    else if(strcmp(cmdbuf, "right") == 0)
      drive_goto(val, -val);
    else if(strcmp(cmdbuf, "pivotLeft") == 0)  // <-- Add
      drive_goto(0, val);                       // <-- Add
    else if(strcmp(cmdbuf, "pivotRight") == 0) // <-- Add
      drive_goto(val, 0);                       // <-- Add

Your Turn

This program can also be modified to detect and handle line comments. For example, you could to place REM (for remark) at the beginning of the line that contained programmer’s notes. You could support this in the program by checking for the string, and then using while(str != ‘\n’ && str != ‘\r’) i++ to disregard all the characters to the end of the line.

Also consider that this current example limits the program size to 512 characters. Modifying the program to load the next 512 characters could be tricky. How would you approach it?

Comments

  • bomberbomber Posts: 297
    edited 2013-10-16 19:48
    Looks interesting so far...I haven't really dabbled around in C yet (waiting for MicroMedic contest rewards to get an ActivityBot), but I have attempted something similar in SPIN. Here's an idea to expand on this: modify some code (IR roaming, remote-control, etc) to write the code to a text file, and then be able to 'replay' the robot's movements! Cant wait to hear more progress on this topic!
  • jazzedjazzed Posts: 11,803
    edited 2013-10-17 10:12
    Looks great Andy.
Sign In or Register to comment.