Skip to content

Instantly share code, notes, and snippets.

@teju85
Last active March 13, 2025 21:59
Show Gist options
  • Select an option

  • Save teju85/da2a24255009a9c14538a6a26bc0587b to your computer and use it in GitHub Desktop.

Select an option

Save teju85/da2a24255009a9c14538a6a26bc0587b to your computer and use it in GitHub Desktop.
Notes I'm preparing while trying to build a squash ball launcher machine

Shopping List (aka Bill of Materials aka BoM)

Code

ESP32 code for controlling the speed of continuous servo

  • Install the “ESP32 Servo” library (by Kevin et.al)
#include <ESP32Servo.h>
Servo g_feeder_servo;
int g_feeder_servo_pin = 9; // change this as per your circuit
void setup() {
  g_feeder_servo.attach(g_feeder_servo_pin);
  // start with no rotation of the feeder servo
  int speed = map(0, -100, 100, 0, 180);
  g_feeder_servo.write(speed);
}
void loop() {
  // int feeder_servo_speed = ...
  int speed = map(feeder_servo_speed, -100, 100, 0, 180);
  g_feeder_servo.write(speed)
}

ESP32 code for controlling the speed of BLDC motor via ESC

  • Install the “ESP32 Servo” library (by Kevin et.al)
  • Make sure to power using the BEC output of ESC
#include <ESP32Servo.h>
Servo g_left_servo;
Servo g_right_servo;
int g_left_servo_pin = 14; // change this as per your circuit
int g_right_servo_pin = 15; // change this as per your circuit
void setup() {
  g_left_servo.attach(g_left_servo_pin);
  g_right_servo.attach(g_right_servo_pin);
  // start with no rotation of the main motors
  int speed = map(0, 0, 100, 0, 180);
  g_left_servo.write(speed);
  g_right_servo.write(speed);
}
void loop() {
  // int left_servo_speed = ...
  // int right_servo_speed = ...
  int lspeed = map(left_servo_speed, 0, 100, 0, 180);
  g_left_servo.write(lspeed)
  int rspeed = map(right_servo_speed, 0, 100, 0, 180);
  g_right_servo.write(rspeed)
}

ESP32 code for bluetooth functionality

  • use “Serial Bluetooth Terminal” app on Play Store.
#include <BluetoothSerial.h>
#include <ESP32Servo.h>

// Check if Bluetooth configs are enabled
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to enable it
#endif

class Motor {
  Servo m_servo;  // the servo object
  int m_pin;      // pin number on ESP32 where the wire is connected to
  int m_min;      // minimum value (user visible) for the servo (angle or speed)
  int m_max;      // maximum value (user visible)for the servo

 public:
  Motor(int pin, int mi, int ma): m_servo(), m_pin(pin), m_min(mi), m_max(ma) {
  }

  void set_value(long value) {
    int servo_value = map(value, m_min, m_max, 0, 180);
    m_servo.write(servo_value);
  }
};  // class Motor

enum Servo_Index {
  S_LEFT = 0,              // left main motor
  S_RIGHT,                 // right main motor
  S_FEEDER,                // ball feeder servo
  S_HORIZONTAL,            // horizontal rotation servo
  S_VERTICAL,              // vertical rotation servo
  S_N_SERVOS,
  S_LEFT_RIGHT,            // need to change the speed of both left and right motors together
  S_RANDOM                 // change all the servo values randomly
};  // enum Servo_Index

static const int MSGLEN = 64;

// NOTE: update the GPIO pin value as per your circuit!
Motor g_servos[S_N_SERVOS] = [
  Motor(9, 0, 100),
  Motor(10, 0, 100),
  Motor(11, -100, 100),
  Motor(12, 0, 100),
  Motor(13, 0, 100)
];

BluetoothSerial g_BTS;
String g_message;

// parses an int inside the substring of a given String
// eliminates the need for creating another String object
long to_int(const String& in, long start_pos, long end_pos) {
  long ret = 0;
  for (long i = start_pos; i < end_pos; ++i) {
    char c = in.charAt(i);
    if ('0' <= c && c <= '9') {
      ret = ret * 10 + c - '0';
    } else {
      return 0;
    }
  }
  return ret;
}

void setup() {
  g_BTS.begin("Squash Ball Feeder");
  g_message.reserve(STRLEN);
}

void loop() {
  if (g_BTS.available()) {
    char in_char = g_BTS.read();
    if (in_char != '\n') {
      g_message += String(in_char);
      return;
    }
  }
  if (g_message.length() < 2) {
    goto RETURN;
  }
  char first = g_message.charAt(0);
  char second = g_message.charAt(1);
  long value;
  Servo_Index s_idx;
  int start = 1;
  switch (first) {
    case 's':
      if (second == 'l') {
        start = 2;
        s_idx = S_LEFT;
      } else if (second == 'r') {
        start = 2;
        s_idx = S_RIGHT;
      } else {
        s_idx = S_LEFT_RIGHT;
      }
      break;
  case 'f':
    s_idx = S_FEEDER;
    break;
  case 'h':
    s_idx = S_HORIZONTAL;
    break;
  case 'v':
    s_idx = S_VERTICAL;
    break;
  case 'r':
    s_idx = S_RANDOM;
    break;
  default:
    goto RETURN;
  }
  if (s_idx == S_RANDOM) {
    // TODO
  } else {
    long value = to_int(g_message, start, g_message.length());
    if (s_idx == S_LEFT_RIGHT) {
      servos[S_LEFT].set_value(value);
      servos[S_RIGHT].set_value(value);
    } else {
      servos[s_idx].set_value(value);
    }
  }
 RETURN:
  g_message.clear();
}

ESP32 code for WiFi access point

#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
const char* g_ssid = "";
const char* g_password = "";
WiFiServer server(80);
void setup() {
  WiFi.softAP(g_ssid, g_password);
}
void loop() {
}

Background reading during the project

VEX

Structures

  • L-Channels
  • C-Channels
  • Plates
  • Baseplates
  • Dimensions of all structures can be found here.

Motion

  • Motors
  • Servos - good for angles. Usually smaller than motors
  • Gears
  • Sprockets - larger teeth, bigger gap between the teeth
  • Shaft - to attach Motor/Servo or Gear/Sprocket to your machine
  • Cortex - the main controlling agent

Fasteners

  • screws to hold things together (usually black)
  • need a hex shaft to tighten/loosen the screw
  • screws fit well to most parts, except motor screws and collars
  • motor screws - to attach motors to things (usually gold)
  • collars - attach to drive shaft to hold things in place

Things to keep in mind

  1. Steel and Aluminium based C-Channels. Steel is strong but heavy. Aluminium is light.
  2. Try to avoid cutting the C-Channels (once cut, hard to rejoin!)
  3. C-Channel lengths: 25 holes and 35 holes (aka full length)
  4. Mount your C-Channels with Nylocks (avoid kegnuts which can become loose)
  5. Use Axles of proper lengths
  6. Keep the Axles in place using shaft collars
  7. Ensure a bearing whenever there’s an Axle
  8. Use spacers on Axles to position your wheels. Also prevents metal-metal contact. Spacers also come in different thicknesses. Make use of all of them when needed!

Wheels

Flex wheels

Wheels

Design Notes

  1. Squash ball diameter: 40mm +/- 0.5mm (From WSF), which is basically ping-pong ball size

Electronics

  • 22 AWG (American Wire Gauge) aka 0.64mm diameter wires fit well into the slots of breadboard

Motors

  • brushless motors theoretically need not maintenance and are efficient
  • BLDC = Brushless DC motors

ESC - Electric Speed Controller

  • Controls the power supply to the motors
  • they come for both brushles and brush motors. So choose the right one for your motor!
  • there are reversible ESCs as well, but are a bit costly
  • current rating of ESC should be greater than the that of the motor
  • but the voltage ratings for them should be the same
  • BEC - Battery Eliminator Circuit
    • eliminates the need for a separate battery for microcontroller
  • ESCs use the same mechanism to control the motors like in servos
  • You can also do ESC calibration using potentiometer set to max before powering up and then after 2s pulling it all the way to minimum
  • the above calibration is useful for ESCs with “non standard” min-max levels (standard is 1ms-2ms 50Hz PWM)

power supply

  • 2S, 3S, 4S all stand for number of cells in a LiPo pack (which determines the voltage)
  • 1S = 3.7V
  • but be careful with LiPo batteries are they are extremely dangerous and can catch fire very quickly

Kv in brushless motors?

  • Kv = constant velocity
  • So, M Kv motor runs at M rpm with 1V of power
  • but you should also look at its generated torque!
  • Kt = constant torque, should be another parameter to keep an eye on
  • Kt = 1 / Kv
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment