element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      • Japan
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Vietnam
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Personal Blogs
  • Community Hub
  • More
Personal Blogs
Legacy Personal Blogs A Small Simple Robot Arm : Part 2 Initial Software Implementation
  • Blog
  • Documents
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: dubbie
  • Date Created: 31 Jan 2020 3:36 PM Date Created
  • Views 1659 views
  • Likes 9 likes
  • Comments 14 comments
  • nano
  • robot arm
Related
Recommended

A Small Simple Robot Arm : Part 2 Initial Software Implementation

dubbie
dubbie
31 Jan 2020

Having constructed the small 4 degree of freedom (4 DOF) plastic robot arm, similar to the MeArm,  ( A Small Simple Robot Arm : Part 1 Mechanical Construction  ) I have now added a Nano controller and some simple software.

 

You don't have permission to edit metadata of this video.
Edit media
x
image
Upload Preview
image

 

For this initial software I have not used the Servo library but instead written my own PWM generation for the micro servo motors. I did this for two reasons; first I wanted to have complete control over the servo motors rather than relying on someone else's library and second to reduce the drain on the battery. Using the Servo library results in the servo motors being driven all the time, which is good for position control but bad for power consumption. As I generally use AA batteries to power most of my projects then reducing battery drain is important, especially during the initial getting going and testing periods. I may well change to using a servo library in later software once I am happy with everything else.

 

RC servo motors, including micro servo motors, use much the same PWM structure to operate. Every 20 ms there is a pulse of at least one ms but no longer than 2 ms. Altering the pulse width from 1 ms (equivalent to 0 degrees on the servo motor shaft) to 2 ms (equivalent to 180 degrees on the servo motor shaft) enables the angle of the servo motor to be controlled very easily from a microcontroller such as the Nano.

 

Below is the function I have written to produce this waveform, without using any timers or interrupts.

 

void myservo(int select_servo, int servo_value)

// servo_value must be between 0 and 2000
{

  int index;

  if (servo_value < 0)
    servo_value = 0;
  if (servo_value > 2000)
    servo_value = 2000;
   
  for (index = 0; index < 30; index++)
    {
      digitalWrite(select_servo, HIGH);   // Start the servo pulse
      delayMicroseconds(500);             // Basic pulse period part
      delayMicroseconds(servo_value);     // Additional delay for servo position
      digitalWrite(select_servo, LOW);    // End the servo pulse.
      delayMicroseconds(2000 - servo_value);
      delay(18);                          // wait for the pulse space
    } /* for */
}

 

I create a pulse of at least 1000 us which is then extended by up to a further 1000 us to provide accurate control of the pulse and hence (hopefully) the servo motor angle, with a 18 ms delay, the space delay, at the end. It is not particularly clever but it does work.

 

I decided to use a serial text user interface as this provides the options of using the Serial Monitor built into the Arduino IDE or using a Bluetooth serial communications link to a mobile phone, using an App called BlueTerm. I have used this App before, it is not the best as it can be a bit unreliable with the Bluetooth link, but it is simple. At the moment I am using the Serial Monitor within the Arduino IDE.

 

Arduino does not provide a comprehensive ASCII character input function, just the Serial.read() function, which is for individual characters so I have modelled my User Interface on single character entry. To avoid crashing the input I treat all inputs as ASCII characters instead of integers and then use a switch statement to convert to integers. It is a bit clunky but it it is simple and it does work. Below is an example of selecting the Base rotation. I allow angles to be multiples of 10 degrees so the selection is from 0 degrees to 180 degrees (the number 0 to the letter I).

 

void Base(void)

{

int base_select;
int base_angle;

  base_angle = 0;
  base_select = 0;
  Serial.println("Base Servo Selected ");
  Serial.println("Select Base Angle ");
  Serial.println();

  Serial.println("0 degrees   : 0 ");
  Serial.println("10 degrees  : 1 ");
  Serial.println("20 degrees  : 2 ");
  Serial.println("30 degrees  : 3 ");
  Serial.println("40 degrees  : 4 ");
  Serial.println("50 degrees  : 5 ");
  Serial.println("60 degrees  : 6 ");
  Serial.println("70 degrees  : 7 ");
  Serial.println("80 degrees  : 8 ");
  Serial.println("90 degrees  : 9 ");
  Serial.println("100 degrees : a ");
  Serial.println("110 degrees : b ");
  Serial.println("120 degrees : c ");
  Serial.println("130 degrees : d ");
  Serial.println("140 degrees : e ");
  Serial.println("150 degrees : f ");
  Serial.println("160 degrees : g ");
  Serial.println("170 degrees : h ");
  Serial.println("180 degrees : i ");

  Serial.println();
  base_select = ' ';
  while (Serial.available() < 1)
    {
      delay(10);
    } /* while */
  base_select = Serial.read(); 
  switch (base_select)
    {
      case '0' : base_angle = 0;   break;
      case '1' : base_angle = 10;  break;     
      case '2' : base_angle = 20;  break;
      case '3' : base_angle = 30;  break;
      case '4' : base_angle = 40;  break;
      case '5' : base_angle = 50;  break;
      case '6' : base_angle = 60;  break;
      case '7' : base_angle = 70;  break;
      case '8' : base_angle = 80;  break;
      case '9' : base_angle = 90;  break;
      case 'a' : base_angle = 100; break;
      case 'b' : base_angle = 110; break;
      case 'c' : base_angle = 120; break;
      case 'd' : base_angle = 130; break;
      case 'e' : base_angle = 140; break;
      case 'f' : base_angle = 150; break;
      case 'g' : base_angle = 160; break;                 
      case 'h' : base_angle = 170; break;                  
      case 'i' : base_angle = 180; break;               
      default  : Serial.println("Unknown Command ");
                 base_angle = 90;
                 delay(1000);             
    } /* switch */

 

There are similar functions for the Shoulder(), Arm() and Grip() servos, although the gripper only has three positions; open, middle, closed. The main loop then just cycles through to select which servo motor is to be changed (Base, Shoulder, Arm, Gripper) and uses another switch statement to activate the appropriate joint function, see below.

 

 

while (1)
  {
    Serial.println("Small robot Arm " );
    Serial.println("Dubbie Dubbie : Just for Fun " );
    Serial.println(" 21st Jan'20 ");
    Serial.println();
    delay(500);

    Serial.println("Select Servo  ");
    Serial.println("Base     : 1 ");
    Serial.println("Shoulder : 2 ");   
    Serial.println("Arm      : 3 ");
    Serial.println("Grip     : 4 ");
    Serial.println();
    int value = ' ';
    while (Serial.available() < 1)
      {
        delay(10);
      } /* while */
    value = Serial.read();

    switch (value)
      {
        case '1' : Base();
                   break;
        case '2' : Shoulder();
                   break;
        case '3' : Arm();
                   break;
        case '4' : Grip();
                   break;
        default  : Serial.println("Unknown Command "); delay(1000);             
      } /* switch */
    delay(1000);
     
  } /* while */

 

I am quite happy with what I have produced so far but I am thinking of making it better, if I can. The servo motor movements are fairly jerky as they try to move from the current position to the next position as quickly as possible, without any acceleration or deacceleration. I would like to see if I can make these movements much smoother which I believe may be called servo easing. I'm not sure what the trigonometric function is, some sort of sine or cosine I think, which I could put into a lookup table and then somehow combine with the distance to be moved.

 

Dubbie

  • Sign in to reply

Top Comments

  • luislabmo
    luislabmo over 5 years ago +5
    Hello Dubbie, nice update!. I believe a couple of loops and some ascii conversions could have saved you a lot of coding when printing the menu and also when translating the input to degrees. Luis
  • dubbie
    dubbie over 5 years ago in reply to luislabmo +4
    Luis, I agree, with a bit of thought I could have made it more efficient but time was short and I wanted some software that was easy to understand, most likely to work and easy to amend/extend. Then, once…
  • shabaz
    shabaz over 4 years ago in reply to dubbie +4
    Hi Dubbie, You might find that depending on the position of where one servo is, it affects the amount of motion available to the other servo, due to the linkages affecting them. Not sure. Anyway, if you…
Parents
  • luislabmo
    luislabmo over 5 years ago

    Hello Dubbie, nice update!.

     

    I believe a couple of loops and some ascii conversions could have saved you a lot of coding when printing the menu and also when translating the input to degrees. image

     

    Luis

    • Cancel
    • Vote Up +5 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • dubbie
    dubbie over 5 years ago in reply to luislabmo

    Luis,

     

    I agree, with a bit of thought I could have made it more efficient but time was short and I wanted some software that was easy to understand, most likely to work and easy to amend/extend. Then, once it's working, the desire to make it 'better' seems to fade away. Maybe when I do the servo easing I might have another look at making it more efficient as I would like to be able to enter the required angles directly as numbers for maximum flexibility. I'll have to see what happens.

     

    Dubbie

    • Cancel
    • Vote Up +4 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • neilk
    neilk over 4 years ago in reply to dubbie

    dubbie  wrote:

     

    .... once it's working, the desire to make it 'better' seems to fade away.

    Oh I am so familiar with that problem!!!!!!!!!

     

    An MIT AppInventor App on a smartphone or tablet, controlling the arduino via bluetooth would be fun.....

     

    Neil

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • dubbie
    dubbie over 4 years ago in reply to neilk

    Neil,

     

    One day I will do this too. One day.

     

    Dubbie

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • neilk
    neilk over 4 years ago in reply to dubbie

    Dubbie, I've already done it, but it only controls the speed of 2 motors:

     

    Arduino rejuvenates an elderly Real Robots/Eaglemoss publications Cybot - Part 1

    Arduino and Cybot - Part 2 - Now on Bluetooth and Batteries

    Arduino and Cybot Part 3 - UNO replaced by NANO; fairly neat and tidy!

     

    Getting it to replace your Serial Monitor input would be quite easy.

     

    MIT AppInventor has moved on a great deal since then!

     

    Neil

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • shabaz
    shabaz over 4 years ago in reply to dubbie

    Hi Dubbie,

     

    You might find that depending on the position of where one servo is, it affects the amount of motion available to the other servo, due to the linkages affecting them. Not sure.

    Anyway, if you do, then there's a high risk of getting in a situation where you command a position, and it hits the limit of motion. At that point, with low-cost servos, the current will just rise, and if it remains in that condition, until the motor smokes : ( It might need some hardware fix for this, e.g. current monitoring (there are current monitor boards available that might be connectable to your microcontroller perhaps via ADC pin), or maybe with polyswitch/polyfuse components. It would need some measurement/experimentation to see what the current consumption is under the normal conditions, and under the limit conditions, or when it hits an immovable object and continues to attempt to move but can't. Some things are possible in software but this one is hard to fix in software alone, without that feedback or additional sensors. Or another option is to have a current-limited supply. Or just keep a spare servo in case of failure.

    • Cancel
    • Vote Up +4 Vote Down
    • Sign in to reply
    • More
    • Cancel
Comment
  • shabaz
    shabaz over 4 years ago in reply to dubbie

    Hi Dubbie,

     

    You might find that depending on the position of where one servo is, it affects the amount of motion available to the other servo, due to the linkages affecting them. Not sure.

    Anyway, if you do, then there's a high risk of getting in a situation where you command a position, and it hits the limit of motion. At that point, with low-cost servos, the current will just rise, and if it remains in that condition, until the motor smokes : ( It might need some hardware fix for this, e.g. current monitoring (there are current monitor boards available that might be connectable to your microcontroller perhaps via ADC pin), or maybe with polyswitch/polyfuse components. It would need some measurement/experimentation to see what the current consumption is under the normal conditions, and under the limit conditions, or when it hits an immovable object and continues to attempt to move but can't. Some things are possible in software but this one is hard to fix in software alone, without that feedback or additional sensors. Or another option is to have a current-limited supply. Or just keep a spare servo in case of failure.

    • Cancel
    • Vote Up +4 Vote Down
    • Sign in to reply
    • More
    • Cancel
Children
  • dubbie
    dubbie over 4 years ago in reply to shabaz

    Shabaz,

     

    Thanks for all these tips. I always find it surprising when moving from a conceptual proof of concept to a realistic design, how much real-world effects get in the way and have to be accommodated. It would seem that some form of sensor is going to be needed, either to detect when the robot isn't moving but should be, or when the motors start drawing too much current.

     

    Dubbie

    • Cancel
    • Vote Up +3 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube