element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • 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 Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • 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
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • 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
Twist, Turn and Move Design Challenge with TE Robotics
  • Challenges & Projects
  • Design Challenges
  • Twist, Turn and Move Design Challenge with TE Robotics
  • More
  • Cancel
Twist, Turn and Move Design Challenge with TE Robotics
Blog Rullit #5 - The software
  • Blog
  • Forum
  • Documents
  • Polls
  • Files
  • Leaderboard
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: amgalbu
  • Date Created: 4 Sep 2022 5:15 PM Date Created
  • Views 1330 views
  • Likes 8 likes
  • Comments 7 comments
  • rullit
  • te connectivity
  • Twist Turn and Move Robotics Design Challenge
  • terobotics
  • designchallenge
  • Turn and Move Design Challenge with TE Robotics
Related
Recommended

Rullit #5 - The software

amgalbu
amgalbu
4 Sep 2022
Rullit #5 - The software

In this blog, I'm writing about the software that controls Rullit

1. Introduction

Rullit will follow a simple path, shown in picture

image

The goals of the control software is to

  • constantly monitor the limit switches, to prevent the robot from falling from the PV modules
  • calculate the proper PWM values to drive the robot along the above-mentioned path

2. Safety controls

As already mentioned, it is very important to constantly monitor the limit switches and immediately stop the motors when the PV module edge has been reached. To achieve this goal, the software will be implemented as a state machine, meaning that there will be no blocking functions (i.e. functions that takes of lot of time). In this way, the loop() function will be called as fast as possible

3. Position control

The math to control the position of the robot is quite simple

image

With the  Pythagorean theorem, we can write

image

and, inverting the formulas,

image

According to the formula, the total width of PV modules to clean (D) must be known. In this first version I am going to use this simple approach. In next release, I would like to implement an algorithm that does not need to know the value of  D, so that I can plug-and-play Rullit on any PV plant and have the modules cleaned.

To move Rullit to position (x, y), we need to wind and unwind thread from the left and right pulleys so that lengths match the value calculated with the above mentioned formulas. This is the theory. To make a real implementation of this algorithm, we need to take into account two important factors

  1. at low PWM values, motor may stall
  2. due to construction tolerances, two motors may not run exactly at the same speed even when controlled with the same PWM signal

Regarding point n.2, I am evaluating whether to add a feedback mechanism based on a gear wheel and a limit switch. However, this application does not require an high precision in position control. For this reason, I am not going to implement this "encoder" at this stage.

Regarding point n.1, let's first have a look at how I am going to calculate PWM values. The software will implement a control loop that, given the maximum speed the thread can be winded, calculates for each motor a PWM value so that thread lengths allows the robot to move to next position in the path.

To make this calculation, it's useful to define some constants:

  • The wind and unwind speed (in mm/s) is given by

#define MOTOR_SPEED_RPM 30.0
#define PULLEY_RADIUS_MM 16.0
#define SECONDS_PER_MINUTE 60.0
#define THREAD_SPEED_MM_S ((MOTOR_SPEED_RPM * PULLEY_RADIUS_MM * 2 * PI) / SECONDS_PER_MINUTE)

  • The maximum distance the robot can be moved during a control cycle is given by

#define CYCLE_TIME_MS 100.0
#define CYCLE_TIME_S (CYCLE_TIME_MS / 1000.0)
#define SAFETY_MARGIN 0
#define STEP_MM (THREAD_SPEED_MM_S * CYCLE_TIME_S * (1.0 - SAFETY_MARGIN))

  • The horizontal distance robot has to move to right when I reach the top or the bottom of PV modules is 20 cm (paint roller is about 23 cm)

#define RIGHT_STEP_MM 200

  • the plant total width is 11 meters

#define WIDTH_MM 11000.0

Assuming the aLength and bLength store the current a and b thread length, the PWM to move to new position (x, y) are calculated as 

float a = sqrt(x*x + y*y);
float b = sqrt((WIDTH_MM-x)*(WIDTH_MM-x) + y*y);

float aDelta = a - aLength;
float bDelta = b - bLength;

float leftPerc = (aDelta * 100.0 / CYCLE_TIME_S) / THREAD_SPEED_MM_S;
float rightPerc = (bDelta * 100.0 / CYCLE_TIME_S) / THREAD_SPEED_MM_S;

where leftPerc and rightPerc are the PWM values (from -100 to 100%) for left and right motor. Value sign determines the direction of rotation

When Rullit is close to the left edge, rightPerc is close to 0 (similarly, when the robot is close to the right edge, leftPerc is close to 0). This leads to motor stall. A simple workaround is not to move the motor until the calculate PWM value is above a certain threshold. If the PWM value is below the threshold, I do not update the aLength or bLength variables, so that the distance between the current thread length and the expected thread length increases. This is the new code 

float a = sqrt(x*x + y*y);
float b = sqrt((WIDTH_MM-x)*(WIDTH_MM-x) + y*y);

float aDelta = a - aLength;
float bDelta = b - bLength;

float leftPerc = (aDelta * 100.0 / CYCLE_TIME_S) / THREAD_SPEED_MM_S;
float rightPerc = (bDelta * 100.0 / CYCLE_TIME_S) / THREAD_SPEED_MM_S;

leftOnMs = CYCLE_TIME_MS;
if (leftPerc < PERC_LOW_LIMIT)
{
  leftPerc = 0;
}

rightOnMs = CYCLE_TIME_MS;
if (rightPerc < PERC_LOW_LIMIT)
{
  rightPerc = 0;
}

if (leftPerc > 0)
  aLength = a;

if (rightPerc > 0)
  bLength = b;

PERC_LOW_LIMIT is the minimum PWM value we want to drive motor with. I set the threshold to 50%

#define PERC_LOW_LIMIT 50

Note that, according to the code, the PWM value is given by the formula

image

which means that the thread winded or winded during a control cycle is given by

image

With the above-mentioned values, the distance that leads to a 50% PWM is 2.5 mm, which is neglectable in comparison with other errors. One major source of positioning are the changes in bobbin radius due to the rope being winded and unwinded. To compensate for this, I implemented the calculation of the radius based on estimated a and b lengths. Given the minimum and maximum bobbin radius and the total length of the rope, the actual diameter is calculated as

image

This is the radius that is used in above formulas 

The application logic is streamlined in below flowchart

image 

4. Limit switch

I created a small class that encapsulates the logic for handling all the issues related to limit switches (namely, debouncing). The class has two methods (init() and update()) and two accessors to get the current debounced state of the limit switch. The update() takes care of debouncing the input signal and return to the caller a stable input state

bool LimitSwitch::update()
{
  int status = digitalRead(_pin);
  if (status != _status)
  {
    if (_changeMs = 0)
    {
      _changeMs = millis();    
    }

    unsigned long delta = millis() - _changeMs;
    if (delta > DEBOUNCE_MS)
      _status = status;
  }
  else
  {
    _changeMs = 0;    
  }
}

5. Water dispenser

All the logic that controls the solenoid valve that let water flow toward the roller is encapsulated in the class Dispenser. As usual, the class has two methods (init() and update()). The update is called periodically to let the class decide whether to open or close the solenoid valve.

Currently I implemented two control algorithms

  • the first one uses fixed timeouts (the valve is opened for a fixed amount of time every x seconds)
  • the second one reads rollers humidity and open the valve when the roller is too dry

The second algorithm uses a moisture sensor made by DFRobot. This is a quite easy resistive sensor, with a NPN transistor to amplify the voltage drop between the sensor probes. 

image

Voltage drop is proportional to resistance between the  pads, which, in turn, is proportional to the level of humidity of the roller. DFRobot reports the following typical values for soil humidity

  • 0 - 300: dry soil
  • 300 - 700: humid soil
  • 700 - 950: in water

After some tests, I selected a threshold of 500. Here is the flowchart of the dispenser's control logic

image

Sensor has three pins: Vcc, GND and an analogue output. Analogue output is connected to Arduino Uno's A0 pin

image  

Here are some pictures of the moisture sensor installed on the chassis

imageimageimage

imageimage

Prev: Building the robot

Next: The software (update)

  • Sign in to reply
  • amgalbu
    amgalbu over 2 years ago in reply to cstanton

    Thanks cstanton

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • amgalbu
    amgalbu over 2 years ago in reply to DAB

    Hi DAB. The sensor is powered with 5 volts, so thank you for pointing out this problem!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • amgalbu
    amgalbu over 2 years ago in reply to javagoza

    Hi javagoza. I agree. Plywood is not very water-resistant, but I can paint it with resin or something similar. The choice was mainly to lack of skill and machine for working with metallic materials (for example, aluminum sheets) and to weight considerations (for example, plexyglass that can handle the weight of the battery is much heavier than plywood) 

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • cstanton
    cstanton over 2 years ago

    Nice work!

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • beacon_dave
    beacon_dave over 2 years ago in reply to javagoza

    Marine grade plywood coated with epoxy resin sealer might help there. It works for boats.

    • Cancel
    • Vote Up 0 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