Movers and Shakers

Enter Your Electronics & Design Project for Your Chance to Win a $100 Shopping Cart!

Back to The Project14 homepage

Project14 Home
Monthly Themes
Monthly Theme Poll


I was building a big project and wanted to move the nozzle of a squirting flower, and the only servos I had were micro servos which did not have enough power to move the mechanism, so I decided to build something, a Jumbo Servo.

As mentioned in element14 Essentials: Motor Control 1  a servo consists of a motor with some kind of position feedback and a control circuit. I decided that a potentiometer and an arduino should be capable of this. I found a 12v gearbox motor in the spares drawer and after a little cleaning and lubrication got that running. There was a gear on the output shaft that could be used for driving a the potentiometer. I added a mounting plate and determined where I could add a potentiometer. A 3D printed gear was added to slip onto the pot and mesh with the output gear. Also something to drive the motor would be needed and I had a suitable L298 H-Bridge module which fitted the spec.



So that my jumbo servo would look the part, I made a wooden case and wooden servo horn. A 3D printed output shaft was also added.


Next up was the electronics. I decided to go with I2C for communication rather than the analogue PWM which is typically used by a servo. This allows me to stop the motor when the servo has reached it's destination rather than constantly seeking position, it also means that I can read back the position to the controlling software and avoid that twitch you get when you first power on a servo.


To test this I used two arduinos and used the examples from Arduino to work out what code was needed. Because I was using a long cable (for I2C at least) I added some low value pullups on the servo end.

Here's my first draft of the code.


#include <Wire.h>

const int slaveAddress = 8;

const int sensePin = A0;
const int drivePin1 = 3;
const int drivePin2 = 4;
const int speedPin = 5; //Needs to support PWM

short registers[5];
int readCmd;
int blink = 0;

enum readRegisters { Target = 0,
  Running = 1,
  Position = 2,
  Speed = 3,
  Direction = 4

enum commands { CmdStop = 1,
  CmdAngle = 2,
  CmdSpeed = 3,

void setup() {

  pinMode(drivePin1, OUTPUT);
  pinMode(drivePin2, OUTPUT);
  pinMode(speedPin, OUTPUT);
  pinMode(13, OUTPUT); //Onboard LED
  pinMode(sensePin, INPUT);

  Wire.begin(slaveAddress); // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // write data
  Wire.onRequest(requestEvent); // requests to read data


void loop() {
  digitalWrite(13, blink);
  blink = !blink;  
  registers[Position] = analogRead(sensePin);

  if (registers[Running]) {
       if (registers[Direction] == 1) {
            if (registers[Position] >= registers[Target]) {
       if (registers[Direction] == -1) {
            if (registers[Position] <= registers[Target]) {

void stop() {
  digitalWrite(drivePin1, LOW);
  digitalWrite(drivePin2, LOW);
  analogWrite(speedPin, 0);
  registers[Running] = false;

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int bytesReceived) {
  char command;
  int value;
  int lowB;
  int highB;

  switch (bytesReceived) {
  case 1:
  //Read request register
  readCmd =;
  case 3:
       command =; // receive byte as a character
       //Pi is low endian
       lowB =;
       highB =;
       value = (highB << 8) | lowB;

       switch (command) {
       case CmdStop:
       case CmdAngle:
            registers[Target] = value;
            registers[Running] = true;
            if (registers[Target] > registers[Position]) {
                 digitalWrite(drivePin1, LOW);
                 digitalWrite(drivePin2, HIGH);
                 registers[Direction] = 1;
            else {
                 digitalWrite(drivePin2, LOW);
                 digitalWrite(drivePin1, HIGH);  
                 registers[Direction] = -1;
       case CmdSpeed:
            registers[Speed] = value;
            analogWrite(speedPin, registers[Speed]);
       for (int a = 0; a < bytesReceived; a++) {
  ; // throw buffer away so we can read again

// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
// Don't add serial print to this routine, it will error!!

void requestEvent() {

  short value = registers[readCmd];
  Wire.write((uint8_t *)&value, sizeof(value));


I've got myself an AdaFruit "ItsyBitsy" which is basically a small form factor Arduino Leonado. So the next step is to wire this in, instead of the Arduino.



I'll also need to do some simple calibration to turn the 0-1023 value into a degrees value. Because of the gearing on the pot the servo can do a bit more than 180 degress so I should be able to set it up with a safe limit so I don't over drive the pot.

Have added a breakout board for the ItsyBity and completed some further testing with some LEDs in place of the H-Bridge,

It H-Bridge Test

I then did some testing with the H-Bridge. I used back to back LEDs to check that the circuit was wired correctly and the software was working. After a few loose connections I got that working. However, swapping the motor in caused my 2A PSU to shutdown.


So I plugged these into the bench power supply (thanks again Secret Santa) and set the voltage and current limit. Luckily I happened to have a slightly smaller motor that had the same size shaft and screw holes that took a lot less current. Next up I'll swap that in.



The gearbox I used is available on CPC.


Is it running?

Did a message go in/out at @date?

Something has gone wrong how to diganose



            Typically low

                GSIS (vessel itineraries) are a few thousand per day but many of these are not for our vessels.


Filtering input data


Activation by




  Data change


Reference data alignment









    One to many and many to one


Handling problems

   Invalid data provided

   Mismatched reference data



   Stage for user

   Target is not available



Where will it run?

   .Net core?

   On premise

   On cloud



Network issues






    Ftp / SFTP







   API pull and push

   For exports can we leverage the custom data sources?


Permissions and credentials


How to handle changes that have been made to the connected systems and interface itself?

   API changes (one view)

   API changes third party

   Functional changes

   Audit / traceability of changes





Leverage existing skills




Verification / validation


Build and provisioning


Discovery of data, some API and message formats are complex


How do we activate an extract?

                User initiated

                Schedule initiated

                Third party system initiated e.g. some kind of API