Tuesday, May 17, 2011

RFM12B with Arduino

I've tried to get this very cheap radio modem working with Arduino. So far, no success, but I still got something working. I'll write a little bit about what I've done so that someone smarter than me will get it right. I managed to connect the board to Arduino using the SPI interface. I also managed to get the software working but couldn't get any data through the modem. Anyway, here's how you connect the RFM12B to Duemilanove or similar 168/328 boards.

1. Download the demo code and RF12.h Arduino library from here http://jeelabs.org/2009/02/10/rfm12b-library-for-arduino/

2. Download and install ports.h library from here http://jeelabs.net/projects/cafe/wiki/Ports

3. Upload the code to Arduino and connect the modem using SPI. The SPI bus uses pins 11 (SDI), 12 (SDO), and 13 (SCK). Also connect the pins 10 (SEL), 2 (IRQ) and 3.3V pin to (VDD) and ground to (GND). Use this datasheet to find correct pins on the RFM12B.

4. Open serial monitor and see the main menu where you can select your modem's frequency, node, etc.

Thursday, April 28, 2011

The Sentry Bot Code

Today I started to write the code for my robot. First I did just a simple move forward --> avoid obstacle --> move forward again type of thing. Next thing is to find out if it works :) And if it works, it's easy to move on to next phases.

#include <Servo.h>

Servo us_servo;
Servo vas;
Servo oik;

int temp = 0;
// Pins for ultra URM37 V3.2
int ultraData = 11;
int ultraTrigger = 10;
int ultraEnable = 9;
int ultraPower = 12;

int readUltra(){
  int ultraValue = 0;
  int timecount = 0;
  int val = 0;

  // Wake up and get ready for sensing
   pinMode(ultraPower, OUTPUT);
  digitalWrite(ultraPower, HIGH);  // Set to HIGH to provide 5V power
  pinMode(ultraEnable, OUTPUT);
  digitalWrite(ultraEnable, HIGH); // Set Enable Pin to HIGH
  pinMode(ultraTrigger, OUTPUT);   // Switch signalpin to output
  pinMode(ultraData,INPUT);
  delay(200); //Give sensor some time to start up --Added By crystal  from Singapo, Thanks Crystal.


  /* Send high-low-high pulse to activate the trigger pulse of the sensor
  * -------------------------------------------------------------------
  */
  digitalWrite(ultraTrigger, HIGH); // Send High pulse
  delayMicroseconds(500);
  digitalWrite(ultraTrigger, LOW); // Send low pulse
  delayMicroseconds(200);
  digitalWrite(ultraTrigger, HIGH); // Send High pulse
  delayMicroseconds(200);


  /* Listening for echo pulse
  * -------------------------------------------------------------------
  */
  // Loop until pin reads a high value
  do{
       val = digitalRead(ultraData);
       //Serial.println("BBB");
     }while(val == HIGH);
  // Loop until pin reads a high value
  do{
     val = digitalRead(ultraData);
     timecount ++;            // Count echo pulse time
     delayMicroseconds(50);
     }while(val == LOW);
    ultraValue = timecount; // Append echo pulse time to ultraValue

// Turn the lights out when you leave...
  digitalWrite(ultraTrigger,LOW);
  digitalWrite(ultraEnable,LOW);
  digitalWrite(ultraPower,LOW);

  return ultraValue;
}

void setup(){

  Serial.begin(9600);
   pinMode(ledPin, OUTPUT);
   pinMode(ledPin2, OUTPUT);
   vas.attach(7); // left motor to pin 7
   oik.attach(8); // right motor to pin 8
   us_servo.attach(9) // Ultrasonic sweeper servo to pin 9
}
void loop(){
  int pos = 0;
 
  vas.write(110); // slowly forward
  oik.write(110);
 
   for(pos = 50; pos < 130; pos += 1){
     us_servo.write(pos);
     temp = readUltra();
     if (temp < 30)
       break;
     delay(10);                       // waits 10ms for the servo to reach the position
   }
   for(pos = 130; pos>=51; pos-=1){                               
      us_servo.write(pos);              // tell servo to go to position in variable 'pos'
      temp = readUltra();
      if (temp < 30)
        break;
      delay(10);                       // waits 10ms for the servo to reach the position
    }
  if (temp < 30){
    vas.write(90); // stop movement
    oik.write(90);
    for(int i=0;i<10;i++){ // wait 500ms and check if the obstacle is still there
      temp = readUltra();
      delay(50);
    }
  }
  do {
    temp = readUltra();
    vas.write(80); // turn left
    oik.write(100);
    delay(10);
  }
  while (temp < 50) // thereshold to move forward again
  Serial.println(temp); // for debugging
}

Wednesday, April 20, 2011

URM37 with Arduino

I bought this great ultrasonic sensor made by DFrobot. The only problem is that it's not so easy to control with arduino. It needs a wake-up signal and communicates via PWM pulse. The great thing is, it has an integrated temp sensor for more accurate ultrasonic readings and a servo controller. The servo movement is operated by the wake-up signal width. Clever.

Probably the best thing for me is that it's cheap. It's like 2/3 the price of a parallax equivalent, except that this has integrated atmega8, temp sensor, etc.

Example codes for Arduino can be found from http://www.yerobot.com/forum/index.php?topic=3.0

Spiderbot coding

This time I did something completely different. I've always wanted to do a spiderbot but it needs so many servos that it's quite expensive. Here's a simple 4-legger code I wrote as a basic frame for a spiderbot I might do in the future. It can only go forward but with a method for every leg, it can easily be coded to do anything.

#include <Servo.h>

Servo legtakaoik;
Servo legtakavas;
Servo legetuoik;
Servo legetuvas;
Servo legtakaoikup;
Servo legtakavasup;
Servo legetuoikup;
Servo legetuvasup;
int eteen;
boolean jalka;

void setup()
{
  legtakaoik.attach(9);
  legtakavas.attach(10);
  legetuoik.attach(8);
  legetuvas.attach(7);
  legtakaoikup.attach(6);
  legtakavasup.attach(5);
  legetuoikup.attach(4);
  legetuvasup.attach(3);
}
void loop() {
  etuvas(90, false); // all servos to 90 degrees = center
  etuoik(90, false); // false = leg down, true = leg up
  takavas(90, false);
  takaoik(90, false);
  delay(200);
  eteen=10; // For testing only. Move forward 10 steps.
  delay(4000);
  for (int i=0;i<eteen;i++) // go forward
  {
    if (i=0) { // first step
      etuvas(120, true);  // move servo 120 degrees
      takaoik(120, true);
      delay(200);
    }
    else {
      etuoik(60, false);
      takavas(60, false);
      delay(360);
      etuvas(120, true);
      takaoik(120, true);
      delay(360);
    }


    etuoik(120, true);
    takavas(120, true);
    delay(360);
    etuvas(60, false);
    takaoik(60, false);
    delay(360);
  }
}
void etuvas(int i, boolean jalka) { // front left foot
  legetuvas.write(i);
  if (jalka == true)
    legetuvasup.write(180);
  else
    legetuvasup.write(0);
}
void etuoik(int i, boolean jalka) { // front right foot
  legetuoik.write(i);
   if (jalka == true)
    legetuoikup.write(180);
   else
     legetuoikup.write(0);
}
void takavas(int i, boolean jalka) { // rear left foot
  legtakavas.write(i);
   if (jalka == true)
    legtakavasup.write(180);
   else
     legtakavasup.write(0);
}
void takaoik(int i, boolean jalka) { // rear right foot
  legtakaoik.write(i);
   if (jalka == true)
    legtakaoikup.write(180);
   else
     legtakaoikup.write(0);
}

Monday, April 18, 2011

Change of plans

When giving a second thought to the navigation system, a line-follower type of approach seemed to be just too oldskool. It also had a lot of problems, like the fact that the whole navigation system would stop working if a piece of paper drops on the floor and hides the line. The IR-array bar in front of the robot is also very inconvienient as it can easily hit objects on the floor due to very low ground clearance.

Instead, I'm planning on implementing an RFID based system. Current RFID readers can read a tag from 10-15cm distance, which is great for ground clearance. Also, it doesn't need visual contact with the tag, so it couldn't care less about debris on the floor. It works like this: My robot has an RFID reader on bottom of it and the destined path is marked with RFID tags on the floor. Each RFID tag is coded with the information where the robot can find the next tag. Just like orienteering. The information would be at least the angle the robot needs to turn to get straight to the next tag. The angle is calculated from imaginary lines from the previous tag to the next tag. The robot controls it's movements with gyroscope to meet the specific angle the tag is giving. I know this is a bit problematic, so I still need to figure out how the robot calibrates itself. It could be multiple RFID readers, special calibration tags or some sort of INS (Inertial Navigation System).

I'm also very interested to hear feedback or suggestions, so feel free to comment :)

Tuesday, April 12, 2011

Old chassis testing

I found this old video in which the robot is in radio-controlled mode. It has quite a lot of torque/speed so I think I need to limit it a bit to be safe in public environments. Also, the tracks are only for outdoors as they do a lot of scratches for example, to asphalt.

Designing the sensors

Today I did a simple drawing about how the robot would interact with it's environment. I'll probably add some more sensors later, but to get it moving, it only needs two. IR-array to follow the line and an ultrasonic sensor to make sure it doens't kill anyone.

To remove the need of multiple ultrasonic sensors, I'll put one on top of a servo. The servo will do regular panning to make sure the way ahead is clear of obstacles. I need another one on the back if the robot goes on reverse, but right now I try to focus on just going forward.