Tuesday, November 30, 2010

First Robot

After some time, I've built a first completely wireless robot.
It uses a wireless XBee connection to send the commands.
It will move for 4 seconds and then stop for 4 seconds before moving 4 seconds and so on.

Here is a video:

The code is very basic, it uses the UART example provided with the XMOS development environment.

This is the code that receives the data sent by an Arduino with XBee module on top.

void rxByte (in port RXD, chanend c){
 unsigned byte;
 unsigned time;
 char val;

 // Wait for start bit
 RXD when pinseq (0) :> void @ time;
 time += BIT_TIME / 2;

 // Input data bits
 for (int i = 0; i < 8; i++) {
  time += BIT_TIME;
  RXD @ time :> >> byte;
 }

 // Input stop bit
 time += BIT_TIME;
 RXD @ time :> void;

 // Send received character to listener to perform associated action
 c <: val;
}
This is the code that sends the data.   
void setup()
{
  Serial.begin(9600);
}

void loop()
{
  Serial.print('H');
  delay(1000);
  Serial.print('L');
  delay(1000);
}

Tuesday, November 16, 2010

Presentation and Preliminary study

Below are the preliminary study and corresponding presentation. In these documents you can find a description of the project and how all components will be handled.

Workshop 1

Preliminary Study Multicore Embedded Robot

Saturday, November 13, 2010

Simon Says

In this first tutorial, I will explain how to create a basic and easy to implement version of the Simon Says game.
For this tutorial, an XMOS embedded device (XC-1A but it should also work on an XC-1) and an LCD screen will be used.
The command will appear on the screen as a letter and that letter corresponds to one of the buttons on the board.
The player starts with one command or character on the screen and will continue untill a predetermined value is reached or if the player enters a wrong command. This value is stored in the `cmdleft` value
The commands are stored in a variable named `cmd`. New commands consist of 2 bits to be able to use the 4 buttons. These 2 bits are appended to the previous command list.
Each time a command is added, the whole sequence is displayed on the screen and the corresponding button led flashes.

void simon(chanend tc){
 int count = 0;
 unsigned long cmd = 0x0;

 timer tmr;
 unsigned t;
 int cmdLeft = 5; // holds the value of the amount of commands have to be given to finish the game

 bled <: 0;

 tmr :> t;
 srand(t);

 while(cmdLeft > 0){
  cmd = addNewCommand(cmd);
  flashLed(cmd, ++count, tc);
  bled <: 0xff;
  tmr :> t;
  tmr when timerafter(t+FLASH_PERIOD) :> void;
  bled <: 0;
  ClearScreen(tc);
  cmdLeft--;
  if (buttonCheck(cmd, count, tc)){
   if (cmdLeft == 0)
    WinGame(tc);
  }
  else {
   LoseGame(tc);
   break;}
  ClearScreen(tc);
 };
}

 
The procedure that displays the commands (flashLed) and the one that checks the input (buttonCheck) the user gives are very similar. They basically reverse the command sequence and loop over this sequence 2 bits at a time. The 2 last bits are removed and either send it to the led to flash or check if the user presses the correct button. Below is the code for flashing the leds in the correct order. The code to check the user input can be found in the complete source code at the end of this post. Because the code that checks the user input is so similar, it has been left out here.
// flash the leds in the sequence of commands already given
void flashLed(unsigned long cmd, int count, chanend tc){
 int curr;
 timer tmr;
 unsigned t;
 cmd = rev(cmd, count);

 while(count > 0){
  curr = cmd - ((cmd >> 2) << 2);
  switch(curr){
  case 0:  // button A
   tc <: 'A';
   bled <: 1;
   break;
  case 1:  // button B
   tc <: 'B';
   bled <: 2;
   break;
  case 2:  // button C
   tc <: 'C';
   bled <: 4;
   break;
  case 3:  // button D
   tc <: 'D';
   bled <: 8;
   break;
  }
  cmd >>= 2;
  tmr :> t;
  tmr when timerafter(t+FLASH_PERIOD) :> void;
  bled <: 0;
  tmr :> t;
  tmr when timerafter(t+(FLASH_PERIOD/2)) :> void;
  count--;
 }
}

Because of the way the commands are stored, before the commands can be shown or checked, they must be reversed forst using a special reverse function that keeps the order of eacht 2 bits. For example, the sequence 11/01/10/11/11/01 becomes 01/11/11/10/01/11.
unsigned long rev2(unsigned long x, int count){
 unsigned long newx = 0;

 for(int c = count; c > 0; c--){
  newx = appendNbit(newx, lastNbit(x, 2), 2);
  x >>= 2;
 }

 return newx;
} 
The last procedure that will be discussed is the dispText procedure. This procedure uses a channel to receive text. This text is either a certain character to print on the screen or an internal command that has an extra effect on the game. For example, if the '&'-symbol is sent using the channel, the text `Congratulations, you won!` will appear on the screen.
// listen for character on the tc-channel and print it or perform action
void dispText(chanend tc){
 char c;
 int count = 0;
 while(1){
  tc :> c;
  if(count > 16){ // after 16 characters or newline character
   lcd_cmd(0x80 | 0x40); // move cursor to second line
   count = 0;}
  else
   switch(c){
   case '&':
    lcd_clear();
    lcd_text("Congratulations, you won!");
    return;
   case'*':
    lcd_clear();
    lcd_text("Sorry, you lose!");
    return;
   case '!':
    count = 0;
    lcd_clear();
    break;
   default:
    lcd_data(c);
    count++;
    break;
   }
 }
}

Here is a video of how it should look when you compile the code and run it on the device. The first part of the video shows a game that is won by the player. In the second part, the player makes a mistake and the game ends displaying a message.
Here you can find the complete source code of this small example. This includes all the other, trivial procedures that aren't described here and the library to display text on the screen.