Biribot

Simple Biribot "avoiding obstacles" program


Biribot_walk01 is a simple program, completely documented. Biribot_walk02 is a more elaborated, version with an improved estrategy

To summarize,the most used and simple way to design an avoiding obstacle "walk" program is

#define TIME_A                500
#define TIME_B           1000
#define MIN_DISTANCE           10.0
float Read_position();    // Prototype
..................

void loop()
{
    float pos;   
    Move(FORWARD);
    do
    {
       pos = Read_Positicion();
    } while( pos< MIN_DISTANCE );
   
    // Do something, for example

    Move(REVERSE);
    delay( TIME_A );
    Turn( LEFT );
    DELAY( TIME_B );
}

we won't be awarded for a program like this, yet it works!

I have tried to give a bit of "roll", or "swing" to Biri's program, as you can see in the video. Biri tries to find out the normal direction to an obstacle, then he gets closer to it slowly, moves backwards and turns right for a second

The main disadvantage of Biri is the fact that he is an open loop system, This means that we don't have any way of feedback to guarantee that the systems gets the state we tried to command. For example we would like to tell Biri something like

int angle = 45;  //To rotate 45 degrees
..............
Turn( LEFT, angle );

but we need some kind of response (feedback) from Biri to know the actual degree he has rotated, so we should implement an angle-sensor. Another simple reason to implement a feedback line in Biribot's circuit is a command like

Move(FORWARD);

Biri will start both servos to go forward, but surely they wont move the same speed ( due to friction forces on wheels, gears, different internal coils in each motor ..) and Biri will desviate left or right on his way. We may tune Biri to move forward adding/substracting an offset to one motor, i.e

move( letfmotor , speed);
move( rightmotor , speed - OFFSET );

with OFFSET a constant to be defined empirically. But the question now is... Will be OFFSET the same for the whole range of speed? In other words, if we tune the value of OFFSET (i.e. 23 ) for speed = 40, we can't guarantee that this value will be fine for a new speed of 70, and Biri should move straightforward for speed = 40, but not at a speed = 70. If we go one step ahead, we could calibrate different pairs [ OFFSET , speed ] and store them in EEPROM ( We have 1Kbyte in our ATMEGA328P ) to load later the one according to Biri's selected speed, but this is artificial

Finally, and open loop system is controlled mainly in two different ways, that is

-   Using well calibrated subsystems and
-   Using  time based subprocesses adjusting each one

As a result, we could code

#define 15_DEGREES_DELAY         250     // Values are invented
#define 30_DEGREES_DELAY         475
#define 45_DEGREES_DELAY         700
#define 90_DEGREES_DELAY       1250

Turn( LEFT );
delay( 45_DEGREES_DELAY );

to turn Biri the desired angle

Josele

 


 

Simple library to move Biribot

 

Here you are a simple video showing the basis to move Biribot. Attached is the code, very simple and ( I hope ) clear.

To simplify, we have two similar low level functions, which control both motors, called lm_move() and rm_move(). Here we have the code ( nothing new ). Note that speed is added/ substracted to the center position of each servo, as long as both motors move in opposite directions

/*
    lm_move()
   
    Move Left Motor
   
      pars:
        where: { FORWARD , REVERSE , STOP }
        speed : { 0 , V_MAX  }
*/
void lm_move( int where , int speed )
{
  if( (speed > V_MAX) || (speed < V_MIN) )
    return;

  switch( where )
  {
    case FORWARD:
      lm.write(LM_CENTER+speed);
      break;
    case REVERSE:
      lm.write(LM_CENTER-speed);
      break;
    case STOP:
    default:
      lm.write(LM_CENTER);
  }
}

/*
    rm_move()

    Move Right Motor
   
      pars:
        where: { FORWARD , REVERSE , STOP }
        speed : { 0 , V_MAX  }
*/
void rm_move( int where , int speed )
{
  if( (speed > V_MAX) || (speed < V_MIN) )
    return;

  switch( where )
  {
    case FORWARD:
      rm.write(RM_CENTER-speed);
      break;
    case REVERSE:
      rm.write(RM_CENTER+speed);
      break;
    case STOP:
    default:
      rm.write(RM_CENTER);
  }
}

Now is simple to code functions like Move(), Rotate() or Turn(). We can find them in the attached file Drivetrain_test.zip. For example, the code for Turn() - that moves only one motor - is

/*
    Turn()
   
    Turn Biribot moving only one motor FORWARD/REVERSE
   
      pars:
        where: { LEFT_FW , LEFT_RV , RIGHT_FW , RIGHT_RV }     ( FW: FORWARD , RV: REVERSE )
        speed : { 0 , V_MAX  }
*/
void Turn( int where , int speed )
{
  switch( where )
  {
    case LEFT_FW:
      lm_move( FORWARD , speed);
      rm_move( STOP , speed);
      break;
    case LEFT_RV:
      lm_move( REVERSE , speed);
      rm_move( STOP , speed);
      break;

    case RIGHT_FW:
      lm_move( STOP , speed);
      rm_move( FORWARD , speed);
      break;
    case RIGHT_RV:
      lm_move( STOP , speed);
      rm_move( REVERSE , speed);
      break;
    default:
      return;
  }
}

Finally, we have extra functions like Engine_start(), that attaches both servos, Engine_stop() -detaches - or Neutral(), that moves both servos to their central position. This last function will be used frequently, since each call to lm_move()/rm_move() start a servo continuosly in time

In our next steps we will a simple loop for Biribot to run and avoid obstacles not the standard and easy way. Then, we will give feedback to Biribot, which is now an open loop control system. And ( why not ? ) we will add some IR "home made" sensors to Biri

Modifying the servos

 

The original Biribot used a L293N to drive the servos. I have to admit that I didn't know the recipe that Ossippee gave to me. Here you have the link

https://www.robotshop.com/letsmakerobots/how-modify-micro-servo-continuous-rotation

The code in the link was a bit strange to me, as long as I'm not expert in Picaxe ( To be honest I don't know a word haha! ). So I went to an example in Arduino IDE, that is sweep...

The standard code in Arduino for a servo is

#include <Servo.h>
................
Servo myservo;  // create servo object to control a servo
................

void loop()

{

   for(pos = 0; pos <= 180; pos += 1)
   {                                
       myservo.write(pos);             
       delay(15);
   }  

}

So we should expect the servo to stop if we code

myservo.write(90);

This is nearly true. In fact I had to adjust my servos to 84 and 87 to stop completely the gears ( no sound, no move ). Then we can use PWM and write() to move the motors. So,

myservo.write(80);   moves the servo one way, slowly, and

myservo.write(0);    moves it the same way, faster. And

myservo.write(95);  moves slowly the servo the other way, and

myservo.write(180); moves the servo the maximun speed

Here you have a simple program, that is the skeleton of my code

/*
    Servo test
   
    Hardware: Connect a modiffied servo to pin 10

    Notes: to get the exact number for CENTER ( in my servo was 84 )
   
    a) Remove the first PAUSE_2;
    b) Type FOREVER;
    c) Starting with 90, try different numbers until the servo is totally stopped
     
    d) Then, rechange FOREVER; with PAUSE_2;
*/
  

#define FOREVER  for(;;)
#define PAUSE_2    delay(2000)
 
#define SERVO_PIN      10               
 
#define CENTER            84      //The position that gets stopped. It should be 90  

#define V_ACT              50      // Simple speed to test the servo

#include <Servo.h>
Servo myservo; 

void setup()
{
  myservo.attach(SERVO_PIN);  // attaches the servo on pin 9 to the servo object
}


void loop()
{
  // Go neutral position
  myservo.write(CENTER);
  PAUSE_2;
 
  //Move one direction
  myservo.write(CENTER - V_ACT);
  PAUSE_2;

  // Go neutral position
  myservo.write(CENTER);
  PAUSE_2;

  //Move opposite direction
  myservo.write(CENTER + V_ACT);
  PAUSE_2;
}

With this in mind we are ready to build a basic library of functions for Biribot to ...

  • Move
  • Turn
  • Rotate
  • Change direction

 

Assembling Biribot

 

Biribot is very easy to assemble. You only need some cyanoacrylate glue ( Loctite, Super Glue 3 ) for the front arms and battery pack.

I have redesigned the front arms to be printed in two parts instead of one, and the results are better. Here you may see it

...

You can see a rubber band connecting both wheels to simulate chains. You can connect them with 2 bands, or just one and use rubber rings for a better friction.

You can also see a mini breadboard with the HC-SR04 ultrasonic sensor  and servos connected. 

 

Biribot design

 

Full view of Biribot in OpenScad

I have uploaded all the files to print Biribot. You may find both .stl and .scad files. I have to translate some file (I think one .scad), cause the originals were made in my mother tongue, Spanish ( next I will do it in English haha ! )

Notes:

a)   You may see something like this at the beguinning of most of files

//To test the module uncomment the next line
//Rear_wheel2();

so its easy to render the files, just deleting the 2 slashes ("/") and pressing F5. Have fun!

b)   In params.scad there is a variable, called resolution ( the last one in the file), involved in each cylinder() function, i.e.

cylinder(r=fr_wheel_diam/2,h=fr_height,$fn=resolution);

you may set it to resolution = 50; instead of its original value (resolution = 100)  to speed up rendering.

c)   One extra advice. Take care to render full_view.scad. It will take a long time to render. This file ( the picture above ) is just to see all the pieces together, to "dance" around Biribot. I think the result is nice, and it took me more than a while hehe!

d)   I will add a readme.txt file, but Im think everything is simple

Well, it's ok now. I have tasks to be done, like videos ( I will stay at my mum's a few days), but I wanted to finish the design. Step by step. Now I can check the CR servos and go with schematics, and all that stuff.

 

Note: There is one file, "Sonar_mount_double.zip", with the original mount for the HCSR04 sensor, in the Rover mentioned below. It is not difficult to design, but I wanted to have at least a piece of it. It is appart from Printfiles.zip
 

Intro

 

This is Biribot, my first and very simple robot

The name "Biri" comes from an old Seville Futbol Club player, called "Biri biri" ( He was from Gambia ). I am a Seville supporter, so all my robots are dedicated to players in that team.

Battery holder, wheels and chains

          Drive train... servos                                   Battery holder, wheels and chains

Parts:

  • Chassis designed with OpenScad
  • Wheels designed with OpenScad
  • Wheels can be changed by chains.
  • Wheels may be conected using rubber chains.
  • Battery holder: modified from the Parameterized Battery pack with electrical connections, by Juan Gonzalez-Gomez (Obijuan) [email protected]( https://github.com/Obijuan/Miniskybot ). The design is derived from the Battery comparment generator, (c) Nikolaus Gradwohl (guru (at) local-guru.net) http://www.thingiverse.com/thing:5051 )
  • Motors: TowerPro 9g servos modified for continuous rotation ( https://www.robotshop.com/letsmakerobots/how-modify-micro-servo-continuous-rotation ). I have to test it, to remove the original L298N driver ( Txs ossipee )
  • L298N to control servos
  • Ultrasonic sensor HC-SR04
  • Arduino ProMini or Arduino nano

Hardware costs: Less than 15 euros

 

History:

When I got my Prusa Hephestos I wanted to start my projects "at the drop of a hat"  ( Bob Dylan should say ), but I realized that everything was new to me, so I needed to calm, going step by step.

I was working in another project with Arduino and VUSB and I found this "Rover" made with an ATTiny, called ProTrinket

( https://learn.adafruit.com/trinket-powered-rover )

I realized that my first project should be something like the Rover, but I didn't want to download the project and print it out to make my first robot.

My main aim was to design a simple, cheap robot, to show my students a simple project.

I use OpenScad, and soon I could design the chassis, and the front wheels. I tried to make modular arms for the wheels, in order to be printed in an easy and secure way. So I designed a chassis with holes to fit arms ( cylinders ) for the front wheels in.

For back wheels I designed the horn to be a “negative” in the wheels, to use the nylon horns provided wth the servo

Searching here and there in Internet I found a battery holder, ready to be modified, adding metal clips, so the body was finished! A simple tap to fit a L298N Driver for the motors ( cheap TowerPro servos modified for continuous rotation ) in a H bridge, and the Arduino board was easyto design and print.

 


This is a companion discussion topic for the original entry at https://community.robotshop.com/robots/show/biribot

Great!

Hi Josele!

I like the look of your robot and I think it will inspire many with 3D printer. It’s also nice all the info you published here already. I’m waiting for the videos and schematics on electronics :wink: Thanks and keep going!

Wow very thorough, thanks!

Wow very thorough, thanks! Nice robot!