3D Printed worm drive gearboxes

With the aim to slow the robot down a bit and combat the issue that the robot would not stop straight away when the joystick was released, I started looking at alternative gearbox options. The one option I knew that would resolve both of these issues and give a very compact gearbox solution was to use a worm drive. These enable high reduction ratios and are very difficult to back drive, meaning that when the motor stops turning, the wheel will stop very quickly and won’t run on.
I had a look around online and knew that it was possible to 3D print a worm drive gearbox but I wasn’t sure how practical or long lasting these would be. I decided to give it a shot and set about designing and printing a prototype. Part 8 of the RC Robot video series shows the design, build and testing of the gearbox.

 

 

The gears were generated using this OpenSCAD generator: https://github.com/chrisspen/gears I modified the gears to include hubs for attaching them to a shaft. I also designed and printed a custom housing for the gearbox complete with bearings to support the drive shaft and one end of the worm gear. The worm gear was tricky to print well and I ended up printing it in one piece, stood on its end. I had to print this very slowly and still the print was not perfect but was good enough. I had a few failures of the worm gear early on and had to go through a few design iterations to add strength where it was needed to get a functional part. I also had to adjust the gear spacing a couple of times, once by modifying the gearbox housing and second time by altering the size of the spur gear. I found that if the gears were meshed too tight it would put too much force on the worm gear and cause damage, if meshed too loose, the backlash in the gearbox would be excessive. The video shows the assembly and testing of the gearbox and it works really well. Its a bit noisy but some lubrication helped a lot. I am hoping that as the gearbox is used, the gears will wear in slightly and the gearbox will operate more smoothly and quietly. How well the gears wear over the long term will need to be gauged as the gearbox is used.

I went on to build a second gearbox that needed to be a mirror of the first so that I had a gearbox for each side of the robot. At this stage I decided that I would strip the RC Robot down and build a new chassis to mount the worm drive gearboxes to and make a few more improvements along the way. Part 9 of the video series shows the rebuilt robot and details the design changes.

 

 

I’m really pleased with this version of the RC Robot platform. I drives nice and steadily with plenty of torque. The original spur gear gearboxes provided a gear reduction of around 3:1. The worm drive gearboxes give a reduction of 7:1 in a very compact unit. This slows the wheels down considerably and gives a good amount of torque to the wheels. I have tested the robot quite a bit now and it is easy to control and stops immediately when the joystick is released.

I now have a nice sturdy platform to work with and I will be continuing this project by adding more functionality to the robot. My aim has always been to automate this robot, even though I am calling it the RC Robot (I may need to rename it at some point in the future). The first step will be the addition of some more sensors so come back soon to check on the progress.

Homemade RC Controller and PID wheel control

With the RC robot test drive completed it was time to make a more permanent solution for the hand held controller. I designed and built a controller with 2 analogue control sticks and a TFT screen, powered by rechargeable NiMH batteries. Inside there is an Arduino Nano with a HC-05 module for bluetooth communications to the robot. I used some expanded PVC sheet along with 3D printed parts to make a case. Part 6 of the RC Robot video series shows the build of the controller.

I was really pleased with how the controller turned out. It works really well and fits in the hands nicely.

With the controller build completed, I turned my attention to the software for controlling the robots wheel speed. Initially I just had the wheel speeds controlling proportionally to the joystick positions. This worked ok but I wanted to implement closed loop speed control with feedback from the incremental encoders. I also wanted to be able to control the robot using only one of the analogue joysticks, which turned out to be trickier than I had first thought.
Part 7 of the video series covers the PID control and converting the control to using only one analogue joystick, along with some fun testing of the robot in the garden.

I really struggled to work out how to control the two wheel speeds and turning using just a single analogue joystick until I found a great explanation that can be found here http://home.kendra.com/mauser/Joystick.html
This page explains the theory, and the equations that pop out at the end enable the wheel speeds and directions to be calculated based on the input from the single analogue joystick.

After some more testing of the robot with the improved control software it became clear that the robot had a few design issues. The main one being that the robot was a real handful to control accurately. It is great fun to drive but I need to be aware that I am making a robot platform, not an RC car. One issue was that the robot was simply a bit too quick. This was easy enough to remedy by limiting the PWM output to the motor driver to limit the top speed. I also noticed that when you released the joystick, the robot had a tendency to continue rolling for a bit, due to its momentum. This sometimes didn’t matter too much but sometimes one wheel would continue while the other didn’t, putting the robot off course. I turned on motor braking on the motor driver when the joystick was centred and this helped a bit but didn’t cure the problem.

Therefore I had some decisions to make about the next steps of the project. I will go into more details in my next blog.

EDIT:  I have been asked to share the design and code for the controller so below is the circuit I am using.

Nano_HC_05_bb

I have also been asked to share the code. Other than writing to the TFT screen, the code is pretty straight forward. The joystick positions are read using an analogue read and then this data is formatted into a string to be sent via the serial port. I am using a software serial port to send data through the HC05 module as this keeps the main serial port free for debugging. I wanted to keep the data sent from the transmitter as simple as possible and the work of decoding and using the data is performed by whatever is receiving the data.

#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9340.h"

#include <SoftwareSerial.h>
SoftwareSerial BTSerial(8, 9); //  TX,RX

#if defined(__SAM3X8E__)
    #undef __FlashStringHelper::F(string_literal)
    #define F(string_literal) string_literal
#endif

// These are the pins used for the UNO
// for Due/Mega/Leonardo use the hardware SPI pins (which are different)
#define _sclk 13
#define _miso 12
#define _mosi 11
#define _cs 7
#define _dc 5
#define _rst 6

#define XCENTRE 506
#define YCENTRE 528

Adafruit_ILI9340 tft = Adafruit_ILI9340(_cs, _dc, _rst);

const int LeftButton = A2;     // the number of the pushbutton pin
const int RightButton = A5;     // the number of the pushbutton pin

String X = "X";
String Y = "Y";

const int LeftXin = A1;  // Analog input pin for left joystick X
const int LeftYin = A0;  // Analog input pin for left joystick Y
const int RightXin = A6;  // Analog input pin for right joystick X
const int RightYin = A7;  // Analog input pin for right joystick Y

int prevLXDisplay = 0;
int prevLYDisplay = 0;
int prevRXDisplay = 0;
int prevRYDisplay = 0;

void setup() {

  tft.begin();
  delay(300);
  tft.setRotation(3);
  tft.fillScreen(ILI9340_BLACK);
  delay(300);
  tft.setCursor(20, 60);
  tft.setTextColor(ILI9340_BLUE);  tft.setTextSize(6);
  tft.println("BIG FACE");
  tft.setCursor(20, 120);
  tft.println("ROBOTICS");
  delay(500);

  Serial.begin(9600);
  BTSerial.begin(9600); //Bluetooth software serial
  
  pinMode(LeftButton, INPUT_PULLUP);
  pinMode(RightButton, INPUT_PULLUP);
 

  while(digitalRead(RightButton) == HIGH){ //Wait right here until right joystick button is pressed
  }
  tft.fillScreen(ILI9340_BLACK);
}

void loop(void) {

  tft.fillCircle(prevLXDisplay, prevLYDisplay, 10, ILI9340_BLACK);
  tft.fillCircle(prevRXDisplay, prevRYDisplay, 10, ILI9340_BLACK);
  drawGuides();
  
  int LXValue = analogRead(LeftXin);
  int LXDisplay = map(LXValue, 1023, 0, 20, 140);
  int LYValue = analogRead(LeftYin);
  int LYDisplay = map(LYValue, 0, 1023, 60, 180);
  
  int RXValue = analogRead(RightXin);
  int RXDisplay = map(RXValue, 1023, 0, 180, 300);
  int RYValue = analogRead(RightYin);
  int RYDisplay = map(RYValue, 0, 1023, 60, 180);

  tft.fillCircle(LXDisplay, LYDisplay, 10, ILI9340_RED);
  tft.fillCircle(RXDisplay, RYDisplay, 10, ILI9340_RED);
  prevLXDisplay = LXDisplay;
  prevLYDisplay = LYDisplay;
  prevRXDisplay = RXDisplay;
  prevRYDisplay = RYDisplay;

  int XValue = (XCENTRE-RXValue)/2;
  if (XValue < -255){
    XValue = -255;}
  if (XValue > 255){
    XValue = 255;}
  
  int YValue = (YCENTRE-RYValue)/2;
  if (YValue < -255){
    YValue = -255;}
  if (YValue > 255){
    YValue = 255;}
 

  // print the results to the serial monitor:
  String XString = X + XValue;
  String YString = Y + YValue; 
  Serial.print(XString);
  Serial.println(YString);

  BTSerial.print(XString);
  BTSerial.println(YString);


  delay(100);


}

void drawGuides(){
  //tft.drawLine(x1, y1, x2, y2, color);

  int LeftCentX = 80;
  int LeftCentY = 120;
  int RightCentX = 240;
  int RightCentY = 120;
  
  tft.drawLine(LeftCentX, LeftCentY, LeftCentX-60, LeftCentY, ILI9340_WHITE);
  tft.drawLine(LeftCentX, LeftCentY, LeftCentX+60, LeftCentY, ILI9340_WHITE);
  tft.drawLine(LeftCentX, LeftCentY, LeftCentX, LeftCentY-60, ILI9340_WHITE);
  tft.drawLine(LeftCentX, LeftCentY, LeftCentX, LeftCentY+60, ILI9340_WHITE);

  tft.drawLine(RightCentX, RightCentY, RightCentX-60, RightCentY, ILI9340_WHITE);
  tft.drawLine(RightCentX, RightCentY, RightCentX+60, RightCentY, ILI9340_WHITE);
  tft.drawLine(RightCentX, RightCentY, RightCentX, RightCentY-60, ILI9340_WHITE);
  tft.drawLine(RightCentX, RightCentY, RightCentX, RightCentY+60, ILI9340_WHITE);
  
}
excitingtechnology.net

Facts and Thoughts on Technological Progress

Turing's Radiator

Pleasantly Warm Topics in Computational Philosophy

Mind the Leap

One small step for the brain. One giant leap for the mind.

Steve Grand's Blog

Artificial Life in real life

jimsickstee

Hi, I'm Jim. Read what I write and I'll write more to read.