Arduino Rotator Computer Interface and Controller

Updated 2014-04-02

The documentation below is for the current stable version of code.  Documentation for the unstable 1.9-x version is available here.


This is an Arduino-based rotator interface that interfaces a computer to a rotator or rotator controller, emulating the Yaesu GS-232A/B and Easycom protocols which are supported by a myriad of logging, contest, and control programs.  It can be easily interfaced with commercial rotator control units.  With the addition of a proper capacity power supply and several interface components such as relays, this unit could also serve as a total replacement for a rotator control unit or serve as the basis for a 100% homebrew rotation system.  Several azimuth and elevation position sensors including potentiometers, rotary encoders, and I2C devices are supported.  The code is very flexible, modular, and easy to read allowing intermediate and advanced experimenters and builders to customize it.

Video featuring Bent Andersen, OZ1CT, and the rotator controller he built using the K3NG Rotator Controller code.

Looking for a PC board or kit?  Try these fine folks:

Anthony Stirk, M0UPU, offers a parts and PC board kit

EA4TX offers a kit with an enclosure and LCD Display offers a kit with an LCD and AC / DC motor support


  • Azimuth only and azimuth / elevation rotator support
  • Serial interface using the standard Arduino USB port
  • Control Port Protocol Support:
    • Yaesu GS-232A
    • Yaesu GS-232B
    • Easycom
  • Support for position sensors:
    • Potentiometers / Analog Voltage
    • Rotary Encoders
    • Pulse Ouput
    • HMC5883L digital compass
    • ADXL345 accelerometer
    • LSM303 digital compass and accelerometer support under development
  • LCD display (2 x 20 preferred, but any LCD over 15 columns supported)
  • Can be interfaced with non-Yaesu rotators, including homebrew systems
  • Directional indication on LCD display (North, South, North Northwest, etc.) along with degrees
  • Intelligent automatic rotation (utilizes overlap on 450 degree rotators)
  • Support for both 360 degree and 450 degree azimuth rotators or any rotation capability up to 719 degrees
  • North Center and South Center support
  • Support for any starting point (fully clockwise)
  • Optional automatic azimuthal rotation slowdown feature when reaching target azimuth
  • Optional rotation slow start (now with smooth ramp up)
  • Optional brake engage/disengage lines for azimuth and elevation
  • Buttons for manual rotation
  • Command timeout
  • Timed interval rotation
  • Overlap LED Indicator
  • Help screen
  • Speed Control, both single PWM output (compatible with Yaesu controllers) and dual PWM rotate CW and rotate CCW outputs and dual elevate up and elevate down outputs
  • Variable frequency outputs
  • Preset Control using either potentiometers or rotary encoders with optional preset start button
  • Speed Potentiometer
  • Manual Rotation Limits
  • Classic 4 bit, Adafruit I2C LCD, and Display Support
  • Optional tenth of a degree support with Easycom protocol (i.e. 123.4 degrees)
  • Park button
  • Azimuth and elevation calibration tables
  • Host unit and Remote unit operation for remotely located sensors using two Arduinos or ATMega chips
  • Works with hamlib rotctl/rotcltd

This unit can be interfaced with Yaesu rotator controller using the standard 6 pin DIN port on the back.  Older controllers may not have the DIN interface and will require opening and soldered connections.  This unit does not disable the rotator controller and all controls on it can continue to be used (although it is advisable not to attempt to control the rotator with manual controls and with the interface simultaneously.)  Other rotator controllers can be interfaced as well with a little research and design.

Basic Schematic

Schematic (click to enlarge)

Note: Refer to the pin numbers on the inside of the Arduino component outline (i.e. D1, D2, A0, A1, etc.) and not the numbers on the outside of it (1, 2, 3…).

The schematic above shows a basic setup supporting a 4 bit interface LCD, azimuth and elevation voltage inputs, manual buttons, and a single variable speed voltage output.  Additional controls and options such as an azimuth present potentiometer, azimuth and elevation preset rotary encoders, and brake control lines can be added as needed if the appropriate pins are chosen and set in code at compilation time.  If using with an azimuth-only rotator, all components related to elevation can be omitted.  So, again, keep in mind the above schematic is a basic unit that will work for most applications and additional features will require additional components.

I have this unit interfaced to a Yaesu GS-1000DXA control unit, and others have interfaced it to various other rotator control units.  I’m also building a complete azimuth/elevation rotation system called Frakenrotator.  This project illustrates how to build a complete system without a commercial control unit.  Consult this for additional ideas for interfacing, power supplies, and master/slave operation.

Selecting Code Features

All features and options are configured in the Features and Options section of the code in the rotator_features.h file.  Various #defines need to be enabled by uncommenting them (by removing double slashes “//”) or disabled by commenting them out (prefixing with double slashes “//”).  After the appropriate features and options are configured, compile the code, upload to your Arduino, and test.

Configuring Arduino / AVR Pins

All interface pins are defined in the Pin Definitions section of the code in the rotator_pins.h file .  Many pins offer optional functionality which can be left disabled by leaving the pin defined with a zero (0) value.  Pin settings and functionality are described in more detail below.

Arduino / AVR Hardware

For an azimuth-only system or an azimuth/elevation system with minimal features, an Arduino Uno, Arduino Nano, or similar variants, or an ATMega328 chip will have enough memory.  The code has been tested on an Arduino Mega and Mega ADK.  If you plan to use the master/slave functionality, you will need an Arduino Mega or Mega ADK, or an ATMega1284 or ATMMega2560 chip in order to have a second serial port.  The remote slave unit can run on an Uno or an ATMega328 chip.

Computer Interface

The unit is interfaced to the computer simply using the native Arduino USB port.  Currently Yaesu and Easycom protocols are supported.

To enable Yaesu GS-232A emulation, uncomment this line:


To activate Yaesu GS-232B emulation, also uncomment this line:


To activate Easycom emulation, uncomment just this line:


Further information specific to the protocols is below.

Azimuth and Elevation Rotators

To activate the elevation functionality, uncomment this line in the code and recompile:


If you are using this unit for an azimuth-only rotator, you can omit the following components: R6, Q3, C5, R7, Q4, C6, C2, R3, S3, and S4.

(Throughout this documentation you will often see elevation mentioned.  If you have an azimuth-only rotator, rest assured that all functionality is supported for azimuth-only rotators and the code works equally well for azimuth-only and azimuth/elevation rotators.)

Position Sensors

Currently several types of position sensors are supported:

  • Potentiometer / Analog Voltage Inputs
  • Rotary Encoder
  • Pulse
  • ADXL345 Accelerometer
  • HMC5883L digital compass
  • LSM303 digital compass and accelerometer

You can mix and match azimuth and elevation sensors.  For example, you can use a potentiometer for the azimuth and an ADXL345 accelerometer for the elevation.  Aren’t choices great?

Potentiometers / Analog Voltage Inputs

Most installations will use potentiometers as these are used in all mainstream commercial rotators (including Yaesu) and is often the easiest solution to implement in homebrew rotators.  If you are using a commercial rotator and are interfacing with a rotator control unit that outputs an analog voltage for the azimuth (like the Yaesu G Series), this is the option you want to use.  Potentiometer position sensors are activated with these lines:



The input pins for potentiometer / voltage sensors are defined here:

#define rotator_analog_az A0

#define rotator_analog_el 0

You must use an analog capable pin such as A0, A1, A2, etc.  The input expects 0 to 5 volts, with 0 volts being fully counterclockwise (CCW) and 5 volts fully clockwise (CW).  (For elevation, 0 volts equates to 0 degrees, 5 volts equals 180 degrees or any maximum elevation you choose.)  The Yaesu G series rotator controllers output this voltage.

Note that if you have an azimuth only rotator, you do not need to define anything associated with elevation, and disabling FEATURE_ELEVATION_CONTROL will cause all elevation related parameters and features to be ignored at compile and run time.

ADXL345 Accelerometer

The ADXL345 accelerometer can be used for elevation readings.  Two libraries are supported, the Adafruit library and the Love Electronics library.  Pick one or the other, but not both.  Either one works fine.

To use the Adafruit library, uncomment these lines:


Adafruit_ADXL345 accel = Adafruit_ADXL345(12345);

To use the Love Electronics library, uncomment these lines:


ADXL345 accel;

The ADXL345 device is interfaced with the Arduino or ATMega chip via the I2C bus.  Consult this for more information on I2C.

Note that the accelerometer responds by rotating the sensor about the X axis.

Rotary Encoders

Rotary encoders can be enabled with these feature defines:



Additionally, you need to configure the rotary encoder pins here:

#define az_rotary_position_pin1 0
#define az_rotary_position_pin2 0

#define el_rotary_position_pin1 0
#define el_rotary_position_pin2 0

Replace the zeros with your pin numbers.  There are no restrictions on the pin assignments.

The last thing you need to do is set the amount of azimuthal or elevation heading change per rotary encoder pulse:



Note that these options related to rotary encoder position sensors are enabled by default in the code:

#define OPTION_AZ_POSITION_ROTARY_ENCODER_HARD_LIMIT // stop azimuth at lower and upper limit rather than rolling over

#define OPTION_EL_POSITION_ROTARY_ENCODER_HARD_LIMIT // stop elevation at lower and upper limits rather than rolling over

Pulse Inputs

Pulse inputs operate by increasing or decreasing the azimuth and/or elevation headings by a preset amount each time a pulse arrives.  To enable this, first enable the appropriate feature defines:



Then configure the pulse input pins.  Note that these pins must be interrupt capable pins.  (Pins 2 and 3 are interrupt capable on an Arduino Uno.)

#define az_position_pulse_pin 0

#define el_position_pulse_pin 0

And then set the appropriate interrupts for the pins you configured abover



On an Arduino Uno pin 2 uses interrupt 0 and pin 3 uses interrupt 1.  Consult for details on hardware and interrupts.

Last, set the amount of azimuth or elevation heading change in degrees:



You may also be interested in these options.  They are activated by default in the code:

#define OPTION_AZ_POSITION_PULSE_HARD_LIMIT // stop azimuth at lower and upper limit rather than rolling over

#define OPTION_EL_POSITION_PULSE_HARD_LIMIT // stop elevation at lower and upper limits rather than rolling over


HMC5883L Digital Compass

The HMC5883L digital compass is supported using the Love Electronics library.  Enable using this feature define:


The sensor is connected using the I2C bus.

LCD Display

Standard 4 Bit LCD Interface

To use a classic 4 bit LCD display unit, uncomment out these lines (remove the double-slashes “//”) to enable it:


#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

The LiquidCrystal declaration specifies the pins the be used for interfacing.  Consult the Arduino LiquidCrystal library documentation for details.

A 2 row by 20 column LCD display is preferred, but a 16 column can be used.  Set the number of columns of your display in this line:

#define LCD_COLUMNS 20

Adafruit I2C LCD

To use an Adafruit I2C LCD unit, comment out these lines as so:

//#include <LiquidCrystal.h>

//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

…and uncomment these lines:

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();

The I2C are hard coded for whatever Arduino board you are using and are not set in the code.  On an Uno, the I2C pins are A4 and A5.

Yourduino LCD Display

To use the I2C display, uncomment and configure this entire section:

//#define I2C_ADDR 0×20
//#define BACKLIGHT_PIN 3
//#define En_pin 2
//#define Rw_pin 1
//#define Rs_pin 0
//#define D4_pin 4
//#define D5_pin 5
//#define D6_pin 6
//#define D7_pin 7
//#define LED_OFF 1
//#define LED_ON 0
//#include <LCD.h>
//#include <LiquidCrystal_I2C.h>
//LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);

Buttons / Human Interface

Button Switch Interfacing

All button switches are momentary normally off switches.  When the button is pressed, the switch is closed which forces the Arduino interface pin to 0 volts or a logic low level.

Manual Rotation

Buttons are provided for manual rotation control if desired.  These buttons can be omitted without any code changes if manual button rotation control is not desired.  When not using a button, set its pin to 0 (zero) in the code prior to compilation:

#define button_cw 0
#define button_ccw 0

#define button_up 0
#define button_down 0

There is an optional stop button feature that can be enabled by assigning a pin number to this line:

#define button_stop 0

The stop button is mainly for halting automatic rotation initiated by the computer serial interface and not for stopping manual rotating activated by rotate CW and rotate CCW button depressing.

Park Function

The Park feature enables the user to press a button and have the rotator rotate to a preset azimuth (and elevation), usually to safegaurd antennas from high winds or tuck away antennas on mobile arrays for travel.  The Park function is enabled by activating FEATURE_PARK and defining a pin for the button here:

#define button_park 0

The preset azimuth and/or elevation is set here:

#define PARK_AZIMUTH 0.0
#define PARK_ELEVATION 0.0

Rotate to Long Path

If you would like to automagically rotate to long path, the \L command is your friend.

Heading Calibration

Yaesu GS-232 Emulation

On the serial interface, issue the O command and manually rotate the rotator to full counter-clockwise 180 degrees and send a carriage return.  Then issue the F command and manually rotate the rotator to full clockwise (270 degrees on a 450 degree rotator, or 180 degrees on a 360 degree rotator) and send a carriage return.

The elevation can be calibrated similarly with the O2 and F2 commands at 0 degrees and 180 degrees, respectively.

The calibration settings are written to non-volatile EEPROM memory.

Easycom Emulation

The Easycom protocol does not have calibration commands like the Yaesu protocol, therefore you must manually configure these settings at compile time:

#define ANALOG_AZ_FULL_CW 1009

Calibration Tables

If you have an azimuth or elevation sensor that is not linear and requires a calibration lookup table, that is provided in the code here:

float azimuth_calibration_from[] = {0, 450};
float azimuth_calibration_to[] = {0, 450};

float elevation_calibration_from[] = {-180, 0, 180};
float elevation_calibration_to[] = { 180, 0, 180};

To enable it, activate FEATURE_AZIMUTH_CORRECTION and/or FEATURE_ELEVATION_CORRECTION and configure the arrays above.  The from array is for the values coming from the sensor, and the to values are what you want to translate the values to.  Values that are between from values are extrapolated so there is no need to fill the arrays with every possible value, just end points and a reasonable number of points in between, depending on how non-linear your sensor is and how much accuracy is needed.  Note that you must have an equal number of members in each from and to array.  The azimuth and elevation correction features apply to any sensor when activated.

Heading Sampling / Averaging

There are several settings to help you tweak the behavior of the heading sample.


The smoothing factor settings make the unit average a fraction of the newly sampled heading with the current heading.  These factors can be set from 0 to 99.9.  The higher the number, the higher percentage of the current heading is used in the averaging formula.


The measurement frequency settings determine how often headings are sampled.  The unit is in milliseconds (mS).

Computer Interface Protocols

Yaesu GS-232 Emulation and Ham Radio Deluxe

Uncomment the following lines to make the interface in Yaesu mode play better with HRD:



Note: At the time of this writing, “Yaesu GS-232B Az/El” mode in the free version HRD Rotator program has a bug in which it will not properly parse and display the elevation.  Use “Yaesu GS-232A Az/El” mode instead.

Yaesu GS-232B Emulation

When activating FEATURE_YAESU_EMULATION the code defaults to GS-232A emulation, however also activating OPTION_GS_232B_EMULATION will default thhe interface protocol to GS-232B emulation.  This emulation adds support for the following commands:

Z – toggle north and south center mode

P36 – switch to 360 degree mode

P45 – switch to 450 degree mode

Additionally, the output of the B, C, and C2 commands is slightly different than in GS-232A emulation.

Yaesu Timed Buffer Commands

To enable Yaesu timed buffer commands, uncomment this line:


Disabling this feature will free up some memory for other features.

Easycom Protocol

Surprisingly, the Easycom protocol does not offer a means of querying the azimuth or elevation from a controller.  However, the code contains two non-standard extensions to the protocol that can be activated with these lines:


With these options, the AZ and EL commands with no parameters will return the current azimuth or elevation.

Tenth of a Degree Resolution

Higher precision headings are activated with this line:


The Easycom protocol natively supports tenth of a degree resolution (i.e. 123.4 degrees), however the Yaesu protocol does not.  If this feature is enabled, the Yaesu protocol emulation will still report azimuths and elevations as integers.  With this feature enabled, the LCD display will show headings with the increased resolution.

Alternate Rotators

Configuration for Other Than 450 Degree Rotators (Maximum Clockwise)

To change the rotation capability, change this setting:


The settings is the rotation capability in degrees. Rotations of up to 719 degrees should work.  Note that if Yaesu GS-232B emulation is enabled, the P36 and P45 commands will switch between 360 degree and 450 degree modes and will override this setting.

The Easycom protocol does not have a means of changing this at runtime, however the #define above is still applicable.

Alternate Starting Points (Maximum Counterclockwise)

By default the code is configured for the azimuth rotation starting at 180 degrees or “south center” in Yaesu terminology.  The default can be changed with this setting:


To default to “north center” or 0 degrees, change this setting to 0.  Note that if Yaesu GS-232B emulation is enabled, the Z command will toggle between north (0 degree) and south (180 degree) center modes and will override the setting.

The Easycom protocol does not have a means of changing this at runtime, however the #define above is still applicable.

Support for Elevation Rotators That Don’t Rotate (Elevate) 180 Degrees

Change this setting to alter the maximum elevation:


Rotation Speed Control

The controller in its simplest configuration activates the rotate_cw and rotate_ccw pins, and in the case of an AZ/EL rotator also the rotate_up and rotate_down pins.  This is sufficient for many installations, however larger antenna arrays present some physical and engineering challenges and require variable speed control and acceleration and deacceleration to avoid damage to components.  This controller supports such needs.

Single “Always On” PWM Output / Yaesu Control Unit Interfacing

The Yaesu X1, X2, X3, and X4 speed commands are supported through a pulse-width modulation (PWM) pin connected to the Yaesu rotator controller, pin 3.  If this functionality is not desired, simply connect a jumper between pins 3 and 6 on the Yaesu controller.  This will send +5V into the rotation speed pin and will hardwire the unit for the fastest speed.

The antenna speed voltage pin can be changed by modifying this line:

#define azimuth_speed_voltage 10

To disable the pin, set it to 0 (zero).  Note that PWM is supported only on a specific Arduino pins; check your documentation if you intend on using a different pin.

The PWM frequency is 490 Hz.  An RC filter using a 4.7k resistor and 10 uF cap creates a 2 Hz filter which “smooths out” the squarewave and provides a nice voltage to the rotator controller.

Note that the Easycom protocol does not have a standard means of changing rotational speed.

Switched Multiple PWM Outputs

If you need PWM outputs on the rotate CW and CCW lines instead of just one separate speed voltage pin (such as for a homebrew rotator), PWM pins can be defined here (replace the zeros with your desired pins):

#define rotate_cw_pwm 0
#define rotate_ccw_pwm 0

Elevation PWM pins can be defined here:

#define rotate_up_pwm 0
#define rotate_down_pwm 0

As if that wasn’t enough, we have more choices for you.  If you would like switched PWM that comes on when azimuthal or elevation rotation is occurring, we got you covered with these pins:

#define rotate_cw_ccw_pwm 0

#define rotate_up_down_pwm 0

As with most other pin definitions, setting them to 0 (zero) disables them.  Again, remember that not all Arduino pins support PWM and you must select PWM capable pins for the output pins above for PWM to work.

Switched Variable Frequency Outputs

If you need variable frequency outputs, pins for this can be defined here:

#define rotate_cw_freq 0
#define rotate_ccw_freq 0

#define rotate_up_freq 0
#define rotate_down_freq 0

The minimum and maximum speed frequencies are defined here:

#define AZ_VARIABLE_FREQ_OUTPUT_LOW 1 // Frequency in hertz of minimum speed
#define AZ_VARIABLE_FREQ_OUTPUT_HIGH 50 // Frequency in hertz of maximum speed
#define EL_VARIABLE_FREQ_OUTPUT_LOW 1 // Frequency in hertz of minimum speed
#define EL_VARIABLE_FREQ_OUTPUT_HIGH 50 // Frequency in hertz of maximum speed

Automatic Azimuth Rotation Slowdown

To enable this feature, changed the 0 (zero) in this line to a 1 (one):


This option will slow the rotation down when automatically rotating and the target azimuth is within 10 degrees.  This can save some wear-and-tear on your rotator, especially with larger installations.  The point at which automatic slowdown kicks in can be adjusted with this line:


The unit is in degrees.

Azimuth Rotation Slow Start

To enable this feature, changed the 0 (zero) in this line to a 1 (one):


This feature starts the rotation at a slower speed and gradually ramps it up to the currently set default speed.  The amount of time spent in slow start is configured with this setting:

#define AZ_SLOW_START_UP_TIME 2000

The time is in milliseconds.

Automatic Elevation Rotation Slowdown

To enable this feature, changed the 0 (zero) in this line to a 1 (one):


This option will slow the rotation down when automatically rotating elevation and the target elevation is within 10 degrees.  The point at which automatic slowdown kicks in can be adjusted with this line:


The unit is in degrees.

Elevation Rotation Slow Start

To enable this feature, changed the 0 (zero) in this line to a 1 (one):


The amount of time spent in slow start is configured with this setting:

#define EL_SLOW_START_UP_TIME 2000

The time is in milliseconds.

Tweaking Slow Start and Slow Down Behavior

There are various settings available for altering the operation of slow start and slow down.  The operation of them is not covered here, however if you need more information, please post on the Radio Artisan group.

#define AZ_SLOW_START_STARTING_PWM 1 // PWM starting value for slow start

#define AZ_SLOW_DOWN_PWM_START 200 // starting PWM value for slow down
#define AZ_SLOW_DOWN_PWM_STOP 20 // ending PWM value for slow down

#define EL_SLOW_START_STARTING_PWM 1 // PWM starting value for slow start

#define EL_SLOW_DOWN_PWM_START 200 // starting PWM value for slow down
#define EL_SLOW_DOWN_PWM_STOP 20 // ending PWM value for slow down

Overlap LED

To activate the Overlap LED line, change the 0 (zero) in this line to whatever pin you wish to use:

#define overlap_led 0

To disable, set the pin to 0.  The Overlap LED will be activated whenever the azimuth is greater than the rotator starting (fully CCW) azimuth.

Brake Operation

Two I/O pins can be defined for brake operation, one for azimuth and one for elevation:

#define brake_az 0

#define brake_el 0

A setting of zero (0) disables the line.

The brake engage delay time is configured with these settings:

#define AZ_BRAKE_DELAY 3000

#define EL_BRAKE_DELAY 3000

The delay time is in milliseconds.  Each brake line goes high when rotation is in progress, so the lines can be used to engage a relay which would supply voltage to activate a solenoid and disengage a brake.

Preset Controls

A present control lets the user dial a desired azimuth or elevation and initiate rotation.  Two types of preset controls are supported, potentiometers and rotary encoders.  A present start button can be defined for either

Preset Potentiometer

A preset potentiometer can be added by defining an analog pin in this line:

#define az_preset_pot 0

As of this writing the potentiometer is not on the schematic, however it’s easy to connect.  Merely take a 1K to 100K potentiometer, connect one end to ground, the other end to +5 volts, and the center or wiper potentiometer pin to the analog Arduino pin defined in the line above.  For good measure you can add a 0.01 uF capacitor from the +5V potentiometer to the ground pin.

The unit will automatically rotate a half second after the potentiometer is rotated.  If you would prefer a start button to initiate rotation rather than having it occur automatically, define an input pin in this line:

#define az_preset_start_button 0

The button is not on the schematic, but it’s simply a momentary normally open button that grounds the pin upon closure.  No pull resistor is required.  Upon pressing the button, the unit will initiate rotation based on the position of the potentiometer.

Both pin settings are defaulted in the code to 0 (zero) which disables them and the preset potentiometer functionality.  (Do not enable this feature unless you have a potentiometer connected, otherwise stray noise on the analog pin will trigger false rotations.)

The settings and limits for the potentiometer can be set here:


The default settings in the code are for a rotator with a starting azimuth of 180 degrees and 450 degrees of rotation capability.  A rotator with a starting point of 0 degrees and 360 degree rotation capability would be set up as so:


The preset potentiometer is currently implemented only for the azimuth, not elevation.  Post on the Radio Artisan group if you’re interested in an elevation preset potentiometer, or you can use the rotary encoder preset control which is implemented for both azimuth and elevation.

Preset Rotary Encoders

Preset controls using rotary encoders are supported for both azimuth and elevation.  To enable, uncomment the appropriate lines:




Pins for the controls are defined here:

#define az_rotary_pin1 0

#define az_rotary_pin2 0

#define el_rotary_pin1 0

#define el_rotary_pin2 0

The center pin of the rotary control should be grounded.  No pull up resistors on CW and CCW pins of the rotary encoder are needed as internal Arduino pullups are enabled with this line:


By default the rotary encoders have “absolute” values that are initiated with the current azimuth (and elevation) at start up.  If the azimuth or elevation is changed through other means such as commands or the manual rotation buttons, the rotary encoder presets maintain their values.  If you would like the encoder to act in a “relative” fashion, enable this line:


This will cause the rotary encoder preset controls to decrease or increase the azimuth or elevation relative to the current azimuth or elevation.  If the unit is rotating or elevating to a heading when a rotary encoder preset is invoked, the current target azimuth and/or elevation is used and adjusted.

Speed Potentiometer

A speed potentiometer can be added by defining an analog pin in this line:

#define speed_pot 0

As of this writing the potentiometer is not on the schematic, however you can use a 1K to 100K potentiometer, connect one end to ground, the other end to +5 volts, and the center or wiper potentiometer pin to the analog Arduino pin defined in the line above.  You may want to add a 0.01 uF capacitor from the +5V potentiometer to the ground pin.

The setting for this pin in the code is defaulted to 0 (zero) which disables the pin.  As with all analog input pins, don’t enable this feature unless you have a potentiometer connected, otherwise noise on the pin will cause false readings.

The mappings for the potentiometer can be set here:

#define SPEED_POT_LOW 0
#define SPEED_POT_HIGH 1023
#define SPEED_POT_HIGH_MAP 255

Rotation Limits

If you would like to set limits for the azimuth rotation commands and buttons uncomment this line:


…and customize these settings:


The above settings will stop CCW rotation when an azimuth of 185 is reached, and stop CW rotation when 175 degrees is reached (“5:30″ on a 180 degree starting azimuth rotator.)

This functionality is useful if for some reason you do not want your rotation system going beyond a certain point due to physical limits.

There is a corresponding feature and settings for elevation rotation limits:



Rotation Pin Logic State Inversion

Normally the rotate_cw, rotate_ccw, rotate_up, and rotate_down pins operate in an “inactive low / active high” manner.  If you wish to invert this behavior, modify these lines, switching the LOW and HIGH values:


Direct Rotator Interfacing

Rotators can basically be divided into two major groups, DC rotated and AC rotated.  Most Yaesu G series rotators are DC based, usually with a voltage from 0 to 24 volts and the polarity of  the DC voltage is switched to provide clockwise and counter-clockwise rotation.  The G-5500 is one exception; it has AC operated motors.

Older rotators are most often AC operated.  Either dual motor windings will be used or a single winding with a switch phase shift capacitor provides alternate direction rotation.  Voltages are usually in the 12 to 30 VAC range, however never assume and always use a voltmeter to measure actual voltages.  Also, be aware that capacitors such as the phase shift capacitor you find in control units (and any large capacitor for that matter) can hold a lethal charge and should be discharged before working on equipment.

Often the most challenging part of interfacing to an older rotator is the azimuth potentiometer. These are often low resistance values, such as 25 to 100 ohms, originally intended to drive mechanical (needle) current meters in the control unit, and may not play well with a 5 volt supply voltage. The Arduino rotator control unit with FEATURE_AZ_POSITION_POTENTIOMETER and/or FEATURE_EL_POSITION_POTENTIOMETER requires a 0 to 5 volt azimuth and elevation voltage range to provide the best accuracy and precision.  Therefore, if using a low resistance potentiometer, an operation amplifier (“op amp”) such as a 741 will be needed to transform the small voltage swing to a 0-5 volt swing.

If the rotator has a reostat (a variable resistor with two leads) or a potentiometer with a grounded wiper which essentially makes it a reostat, you can place a fixed resistor of equal value in series with the reostat and supply the fixed resistor with 10 volts to get the desired 5 volt swing.

Questions about interfacing to rotators should be posted on the Radio Artisan group, which is frequented by many radio amateurs who have built homebrew rotation systems or have interfaced to older rotators.

Host and Remote Unit Operation

I2C sensors offer some real neat options for sensing azimuth and elevation.  These devices are commonly used in game controllers and mobile devices to sense position or movement of the device.  Magnetometers or digital compasses measure azimuth and accelerometers can be used to sense the Earth’s gravity and provide an elevation reading.

One issue facing the builder using these devices is the distance limitations of the I2C bus.  I don’t know the exact limit, but anecdotal evidence leads me to believe it is several meters, which poses a problem when attempting to use these devices on an antenna up a tower or in an array perhaps several hundred meters from the operating position.

But, never fear, others have thought of this issue and as usual we have a solution.  The controller code allows you to compile code for a remote unit which interfaces with a host unit located inside.  The remote unit interfaces with the position sensor devices locally at the rotator/antenna location.  Any normally supported position sensor can be used with the remote unit, including potentiometers, rotary encoders, and I2C devices.  The host unit talks to the remote via serial using a simple protocol, querying it periodically for azimuth and elevation.  The control protocol also offers some ancillary commands for controlling output pins, sniffing remote serial ports, and sending data out remote serial ports which may be useful for automatting other things out at the tower such as antenna switching.  But I digress.


The host unit needs to have two hardware serial ports, the usual Serial port (“Serial0″) and Serial1.  This means that an Arduino Mega or a homebrew “bare chip” ATMega2560 or ATMega1284P is required to provide the second serial port.  The host unit Serial1 port interfaces to the Serial port (Serial0) on the remote unit.  Since the remote unit needs only one serial port, an Uno, bare chip ATMega328 or just about any Arduino variant will work.

Serial Control Link

To interface the host with the remote, you simply need to connect TX on the host to RX on the remote, and RX on the host to TX on the remote.  On an Arduino Mega the Serial1 port TX and RX is pins 18 and 19, respectively.  On the remote, using an Arduino Uno, the Serial TX and RX pins are pins 1 and 0, respectively.

Depending on your particular installation, some line and signal conditioning may be required.  I have successfully sent the 9600 baud serial link though 700 meters of unshielded twisted pair CAT 5 cable, using two twisted pairs with one conductor in each pair carrying ground and the other conductor carrying the signal.  An additional conductor in the cable can carry DC voltage to power the remote unit.

A more robust solution would be to use specialized chips or a simple transistor interface to convert the 5 volt logic levels to standard RS-232 voltage levels which are +12 to 25 volts for a logic low, and -12 to -25 volts for a logic low.  This however may be overkill.  I’m experimenting with a simple 0 volt / +12 volt system and will post a schematic soon.

RF bypassing is a consideration as the remote will be operating in a high RF level environment and any long cabling will undoubtedly pick up RF along the way.  Bypass capacitors of 0.01 uF or 0.001 uF should be placed on both serial lines at the host and remote units.  RF shielding is another consideration for the remote unit.

The speed of the host/remote serial link is defaulted to 9600 baud, however higher speeds are possible and conversely if issues are encountered the link speed may be lowered.  Configuration tweaking details are below.

Host Unit Compilation and Configuration

The host unit needs to have the following configured:

  1. A one computer interface protocol, such FEATURE_YAESU_EMULATION or FEATURE_EASYCOM_EMULATION.
  2. The appropriate azimuth and/or elevation position sensors pointed to the remote unit by activating FEATURE_AZ_POSITION_GET_FROM_REMOTE_UNIT and/or FEATURE_EL_POSITION_GET_FROM_REMOTE_UNIT.  Do not configure any position sensors unless they are directly connected to the host unit.  (You could theoretically have one position sensor on a remote unit and one on the host.)
  3. Configure the usual button pins, rotate pins, etc.

Remote Unit Compilation and Configuration

To configure a remote unit, do the following:

  2. Activate the appropriate azimuth and/or elevation sensors (potentiometers, rotary encoders, I2C sensors) and configure the appropriate pins.
  3. DO NOT activate any computer interface protocols such as FEATURE_YAESU_EMULATION or FEATURE_EASYCOM_EMULATION.  The serial port on the remote will talk the host/remote protocol.

Host/Remote Serial Protocol

In order to operate a host/remote system you do not need to know the host/remote serial protocol, but The host/remote protocol is simple and easy to understand.  The design goals included fixed length arguments, consistent responses and event messages, and human-creatable and readable commands to insure easy testing and debugging.  Below is a summary of the protocol.

Host to Remote Commands

PG - ping; the remote should respond with "PG"
AZ - read azimuth
EL - read elevation
DOxx - digital pin initialize as output; xx = pin # (01, 02, A0,etc.)
DIxx - digital pin initialize as input; xx = pin #
DPxx - digital pin initialize as input with pullup; xx = pin #
DRxx - digital pin read; xx = pin #
DLxx - digital pin write low; xx = pin #
DHxx - digital pin write high; xx = pin #
DTxxyyyy - digital pin tone output; xx = pin #, yyyy = frequency
NTxx - no tone; xx = pin #
ARxx - analog pin read; xx = pin #
AWxxyyy - analog pin write; xx = pin #, yyy = value to write (0 - 255)
SWxy - serial write byte; x = serial port # (0, 1, 2, 3), y = byte to write
SDx - deactivate serial read event; x = port #
SSxyyyyyy... - serial write sting; x = port #, yyyy = string of characters to send (variable length)
SAx - activate serial read event; x = port #
RB - reboot
Remote to Host Responses
ERxx - report an error; xx = error #
EV - report an event
OK - report success
CS - report a cold start
Error Codes
ER01 - Serial port buffer timeout
ER02 - Command syntax error
EVSxy - Serial port read event; x = serial port number, y = byte returned

Each command and response is terminated with a carriage return.  Line feed characters may be sent either way, but are ignored.

For a real world example of master and remote slave operation, check out my Frankenrotator project page.

Testing and Debugging

To test the remote unit, configure the code as described above, upload it to the remote unit Arduino/AVR chip and connect it to the computer with the appropriate baud rate (9600 baud by default).  Set the terminal program for carriage return and line feed.

Upon start up, the remote should send a cold start notification such as:


This indicates the version of software running on the remote.

Next, test if the remote will respond to commands.  Send a ping command:


The remote unit should respond back with a ping:


If that works, you can then read the azimuth and/or elevation from the connected sensors using the AZ and EL commands.  For fun you can play around reading and writing to pins.  The following commands turn the LED on pin 13 on and off:


If you have remote unit hardware that supports additional serial interfaces like Serial1, Serial2, etc., you can read and write byte and strings on those ports.  The commands below turn on monitoring of Serial1 and sends characters out it.

SS1test 1 2 3

The remote unit code supports the \d (backslash d) debugging commands which activates the periodic debug dump.

If the remote unit appears to be functioning properly, it’s time to connect the host and remote units, as described above.  I recommend you do this on the bench and not with the remote installed already outside.  I would also recommend doing a direct connection at +5V logic levels and forgo any line signal level converters until later after you have the units talking on the bench.

If all goes well, the host unit should be reading the azimuth and/or elevation from the remote unit and report normally, just as though the position sensors were connected directly to the host unit.  If not, the \d command should be used to view debugging information.  In host mode, the debug dump displays an additional line showing link command counters:

debug: 2013042001BETA GS-232B
 AZ: IDLE Q: - AZ: 178.3 (raw: 178.3) Target: 0.0 (raw: 0.0) AZ Speed Norm: 255 Current: 255
 EL: IDLE Q: - EL: -50.7 Target: 0.0
 AZ: 180-450 AZ ana: 4-1009 EL ana: 2-1018
 Remote: Command: 1 Good: 31736 Bad: 0 Index: 0 CmdTouts: 0 BuffTouts: 0 Result: -50.70

Here’s a description of the counters:

Command: The current or most recently executed link command.  1 = AZ, 2 = EL

Good: The number of successfully executed commands.  This counter rolls over at 65,536.

Bad: The number of unsuccessful commands.  This may included commands that timed out waiting for a response or responses received that were malformed or invalid.  This counter rolls over at 65,536.

Index: The number of bytes currently in the serial receive buffer.  A non-zero value indicates a response is in progress or errant bytes are sitting in the buffer.  (If bytes sit in the buffer for a period of time, the buffer is cleared and a buffer timeout is registered.)

CmdTouts: The number of commands that timed out awaiting a response from the remote.

BuffTouts: The number of times we received bytes from the remote, but no terminating carriage return.  Without a carriage return, the response is considered incomplete and the receive buffer on the host is cleared.

Result: This is the last valid result received from an AZ or EL command.  Normally this value will match the azimuth or elevation displayed in the debug dump lines.

A number of remote communications debugging commands are available on the host for troubleshooting and overall playing around:

\T – sniff the remote port transmit

\R – sniff the remote port receive

\Z – suspend automatic remote commands

\S – send a text string to the remote

With the \T command you can see the commands that are being transmitted to the remote.  The \R command lets you see what is coming back from the remote.  The \Z command suspends automatic commands.  This is useful if you want to temporarily stop all the AZ and EL commands spewing on the screen and want to issue some specific commands for testing purposes.  The \S command sends a text string to the remote.  The \S command in combination with the remote port receive sniffing activated (\R) basically gives you an open command prompt to the remote unit.  For example, you could do this:


These commands turn on remote receive sniffing, suspend automatic commands, send a PG (ping) to the remote.  You should see a ping back.  As you would expect, with the \S command you can send all of the other host/remote protocol commands like AZ, EL, DH, DDL, etc.

Another trick you can do is the get the remote unit to do a period debug dump using this sequence:




Tweaking the Link Parameters

The serial control link is configured by default for 9600 baud.  To change the link speed on the remote modify this line:

#define SERIAL_BAUD_RATE 9600

And on the host unit, modify this line:

#define SERIAL1_BAUD_RATE 9600

Various other host/remote communications settings:



John, W3SA, has tested on a Yaesu Az/El unit, contributed several updates to the elevation code, and tweaked the code for a 16 column LCD display.

Anthony, M0UPU, wrote about his rotator controller construction and is offering PC boards.

Bent, OZ1CT, has contributed several ideas and feature requests, and performed testing.

G4HSK has a nice page documenting his project using this code, the PstRotator control software, and a Yaesu G-5500 rotator.

All trademarks mentioned on this page and in the code are property of their respective owners.


I will donate parts, units, or specially customized software for DXpeditions.  Email me at anthony dot good at gmail dot com.  DX IS!

Source Code

Source code is located on SourceForge.  The master tree is the main stable release tree and is what you should use for production units.  Code with new features which may not be fully tested (and not documented here) is located in unstable tree.

Support and Feature Requests

Please consult this page for support information.

Please note that I do this work in my spare time as I can and I am not a professional developer, however I play one on TV.  I do my best to answer support requests,  however I don’t like having to answer questions for items that are explained here in the documentation.  I do maintain a list of feature requests.  Development items are prioritized by me based on the level of difficulty and what I’m interested in.  I welcome code contributions, code testing, bug reports, and any help you can provide.  This can even be helping with documentation or providing support to others on the Radio Artisan discussion group.

Code History


rotate_up_or_down pin


Fixed bug in in handling ADXL345 Love Electronics library output
Fixed bug in rotation logic for 360 azimuth rotators
\L command – rotate to long path
Updated to work with Hammlib rotctl / rotctld
Pin rotate_cw_ccw_pwm
Pin rotate_up_down_pwm

2013051801 – Added smooth factor and heading sampling frequency settings, the preset start button now also acts like a kill switch if the unit is rotating, and extra carriage return/line feeds in Yaesu GS-232A and B modes have been removed.  Added note above about HRD Yaesu GS-232B Az/El being broken.

2013042102 – Host remote port debugging commands

2013042101 – Azimuth and elevation calibration tables, Remote Unit functionality, rotation pin logic state inversion setting

2013032901 – Another Major Update!

Easycom Protocol

Rotary Encoder Position Sensors

Pulse Position Sensors

Park Button

Tenths of a Degree Support

Rotary Preset Controls

2013021601 – Major Update!

Totally rebuilt main state machine

Ramp up of speed control voltage for Slow Start feature

Ramp down of speed control voltage for Slow Down feature

Rotary Encoder Preset Controls

Rebuilt LCD display code for better state handling and to be more responsive

Azimuth and Elevation Frequency Outputs

Elevation Speed Voltage

2012112901 – Added FEATURE_PWM_CW_CCW_OUTPUTS which gives optional PWM (pulse width modulation) outputs for the CW and CCW pins, instead of just one speed voltage output pin

2012112802 – Added speed potentiometer, preset potentiometer, preset start button, and manual rotation limit functionality.  Also changed core azimuth rotation code to use raw azimuth (i.e. > 360) rather than display azimuth (i.e. 0-180).

2012060801 – Experimental code contributed by IZ2XBZ to support the HMC5883L digital compass and ADXL345 accelerometer.  Also added additional debug code in check_serial()

Older releases (before I started posting files on Sourceforge.  Use the code below only if you have to.  The latest version is always on SourceForge.):

2012050501 Code – Added brake functionality, slow start capability, and new way to define rotator starting point and rotation capability.

2012032501 Code – Additional minor fix with 360 degree rotator code and now button pins can be disabled by setting to 0 (zero)

2012031401 Code – Fixes issue with 360 degree rotator rotation logic

2011120701 Code – Adds Overlap LED function, minor bug fixes (Arduino 1.0)

2011102901 Code – Fixes bug with azimuth direction text (Last Arduino 0022 compilation)


78 responses to “Arduino Rotator Computer Interface and Controller

  1. Pingback: Welcome « Radio Artisan·

    • Anthony, that is one nice program. I have downloaded your code, it compiled nicely in Arduino 22, and I hope to build that before too long.

      Thank you for a good project.

      73 de Ken H> K9FV

  2. Can you please provide me with an email address for Anthony. I have built the rotator controller, but I am having some difficylty getting it to work properly. I would like to cantact Anthony for some guidance.

    Chris VK4CVL

  3. Updated code posted. GS-232B emulation is now an option, the X1/2/3/4 speed commands are supported, the P36, P45, and Z commands are supported. Additional Az/El testing and improvements have been made by W3SA.

  4. This is a very interesting project for me, as I’m looking for an interface for my G-1000SDX and a home made elevation system with an actuator and an ordinary potmeter for elevation readout. If I’ve read well these are both supported by thsi design/project.

    I’m not into PIC programming e.g. but very familiar with electronics and a bit of programming.. When I sudied electronics back in 1985 we used 8088 (IBM) / 6502 (Apple) / Z80 ;-) programming in machine code.. those were the days my friend… hihihi thought they never end

    My question is what do I need ? A development kit ? 8 or 16 MHz clock ?

    Any info would be very welcome.

    • John, nice talking with you on email. Let me know how you make out when your Uno arrives. 73 Goody

  5. Updated code posted. Elevation rotators other than 180 degree rotators supported now. Also, WordPress was wrecking the first two include statements in the code, apparently thinking the was html.

    • Got the boards, start plumbing and YES got it working for Azimuth, haven’t connected Elevation at the moment as I need to make some connections on my elevation rotorboard.

      The only thing which is strange is that the heading is allways North on the display. Azimuth is showing 83 deg for example but the text above shows North, no matter what direction I turn. Also when I let HRD turn the antenna by clicking a direction. The display shows Rotating to 99 deg for example. When the rotor stops at 99deg Bearing shows North.

      So making progress.. ;-)

  6. With the given code it works on Azimuth only, it shows NE on the first line and Azimuth 50 on the second line

    but if I uncomment this line,

    //#define FEATURE_ELEVATION_CONTROL // uncomment this for AZ/EL rotators

    recompile and upload to my arduino board

    it shows

    N on the first line
    and AZ 50 El 10 on the second line

    No matter what I do it remains on N(orth)

    • Could you bring up the serial monitor (set it for 9600 baud), issue a \d command (backslash delta), manually rotate the rotator, and tell me what you see in a debug line that starts with “display_direction:” ? (Issuing the \d command again will turn off debug mode.)

      • I’ve send you an e-mail with the debug results, in Azimuth only mode and in Azimuth + elevation mode.

  7. Hi I am interested in the Rotator controller using the Arduino. Can someone tell me the type number for the Arduino and possibly a UK supplier. Thanks and 73 for any advice. Vlive GW0PPO

  8. Clive, I build mine with an Arduino uno, you cand find them on Ebay too. They don’t cost that much, think you can get them for less than 15 uk pound. The arduino is a bare board, you need a 2×16 / 2×20 or 4/16 character display as well with a HD44780 or compatible controller on it

    73! John PA5MS

  9. Thanks for that John. I will check out eBay for an Arduino Uno

    Can you program the Arduino via the USB port and do you need a special programme to do it?

    Thanks for any help. 73 Clive GW0PPO

    • clive you need a special program but if you go to you can find all info needed. programming is realy simple last time i programmed something was r decades ago and even i got it running. the package you need to download is big you also need to install the arduino driver for windows or whatever operating system you run

      sorry for typing errors this message is form my ewindows phome with a tiny keyboard and fat fingers hihihi

      73 &ohn pa5ms

  10. Hi John, thanks for that. I know what its like typing on a phone. Mind you I have enough problems typing on a Laptop keyboard! 73 Clive GW0PPO

  11. Pingback: 2012 « Radio Artisan·

  12. HI Guy,

    I was reading this project year ago and I decided to build and have PCB dedicated for the Az-EL project instead of use ARDUINO BOARD.

    So I have PCB and finish but I changed the LCD connection to be match same as LCD shield, Check it out

  13. Hello Goody,

    thank you for this nice projekt!

    I would like to use Arduino in combination with my Microham station master as controller for more
    as one rotator, only what i need is to have output with same reference level for same direction!
    for each rotator one card……

    Cann you help me with it?

    thanks in advance!


    • Hello Braco,

      I’m not quite sure I understand. Do you want to connect a Microham Station Master to an Arduino and have the Arduino control multiple rotators?


      • Hi Goody,

        i am not sure if you get my previos mesage!
        I would like to use multiple rotators with Arduino cards and to controll it with
        Microham Stationmaster. MH SM have outputs for CCW and CW reference voltage (not needed)
        and POT input (analog). In this case i will need probably DAC inbetween Arduino and MH SM.
        Idea is to get same analog level from each rotator (of course over arduino and DAC) for all rotators
        for each antenna direction! Then i cann swicth any rotator (automaticly or manual) i have to MH SM.



      • John PA5MS is correct in his response below. This Arduino project essentially does a portion of what the Microham unit does, interfacing a rotator controller to a computer. It sounds like you want to switch the CW rotation contact, the CCW rotation contact, and the analog azimuth voltage line between multiple rotators, allowing the MH to control multiple rotators. This is fairly easily to do with switches, relays, or transistors. It would not require an Arduino unless you wanted to interface it somehow to a computer or you needed something more intelligent to invoke the switching. I’m not familiar with the MH unit capabilities, however I’m guessing you could use contact closures to control a switching circuit which would be a more integrated solution than an Arduino. If you need just a simple switching circuit, let me know and I could probably draw something up.

  14. Braco,

    I think you don’t understand quite well what this rotor interface does.. It is a sort of digital read-out of an analog rotor with POTMETER. Also this controller is an interface between your computer and the rotor. It makes it possible to control your rotor by computer. Like with Ham Radio Deluxe (HRD)

    It can replace you rotor controller if you use relays and a suitable power supply.

    If you understand the concept then Also I don’t understand what you have in mind to build with the microham station manager. I think the station manager is also a computer interface to control a rotor which the arduino is as well so basically the same.

  15. Hello John,

    well i know very well what for it is!

    I have 12 differnt rotators and i would like to use single controll box for it!
    In this case i need same signal level from each rotator pot. My idea was to use
    Arduino to digitalize analog signal from pot and then convert it back to analog but with same
    signal level for same direction! This will allow me to use single controllbox for all rotators i have
    of course i will need to install on each rotator one card and i will need to have some
    switching martix for it! MH SM i have allready and i want to use it as controll box, but it could
    be anything else!


    • Hi Braco,

      I believe you can convert the signal back to analog by utilizing digital pot. The only problem here would be the resolution, but I believe that 8bit would be fair enough for HF beams.


  16. Branco,

    Now it is clear to me what you want to do with the arduino board. The rotor interface has no control voltage output for Azimuth / Elevation. These are just inputs which the board needs to read Azimuth and elevation. So it reads the analog voltage from the pot and calculates the coresponding Azimuth / Elevation and shows this on the display. Don’t think you can use it as a sort of “level converter” wich gives you an equal output at an Azimuth / Elevation regardless the rotor you use. Think there are easier solutions to convert the azimut / Elevation from whatever rotor you use to a “standard” for example 0.00 to 5.00 V output

    The Yaesu 1000SDX rotor has an adjustable output 0 to 4.5V for 0-450 degrees

    If your rotor has a potmeter inside you can use a simple op-amp circuit to adjust the level to a “standard” which is useable for you.

  17. Hello,
    do you think that is possible to use a compass sensor and an accelerometer instead of potentiometers?
    I want to use a compass sensor HMC5883L for rotation positioning and an ADXL345 to get elevation degree.
    Any idea?

    • Hi Giorgio. I’ve never worked with compass sensors or accelerometers, but looking briefly at the data sheets for both of the devices you mention I see they have I2C interfaces. This would make it fairly easy to interface both devices to an Arduino. With a little bit of research, I could probably give you some code to do this, however the read_azimuth() and read_elevation() subroutines in the code are where you would want to drop the I2C interface code in to read the devices. Let me know if you want to pursue this.

      • Hi thanks for your kind and fast reply.
        I can confirm that I’m using this sensors trough i2c and I’m already getting Azimut and elevation value in a separate sketch.
        I will really appreciate If you could help me to put code in your project

      • Could you send me your I2C code to my email address which is anthony dot good at gmail dot com? I will embed your code in the proper places and make it a compile time option (a define) to include the code.

  18. Hello Goody,

    Thank you for great arduino project!

    I need to ask, is this motor shield can be used instead of K3NG rotor interface?

    “This motor shield allows Arduino to drive two channel DC motors. It uses a L298N chip which deliveries output current up to 2A each channel. The speed control is achieved through conventional PWM which can be obtained from Arduino’s PWM output Pin 5 and 6. The enable/disable function of the motor control is signalled by Arduino Digital Pin 4 and 7.

    The Motor shield can be powered directly from Arduino or from external power source.”

    Thank you,

    • Hi Didi. Yes, I think it could. I’m a little unclear on how exactly the direction pin works. Does the PWM always control the speed and a high on the direction pin reverse the direction, and a low makes it go forward? Are you intending to use this to build your own rotator? You would also need potentiometers for reading the azimuth and optionally the elevation. In the code we would need to convert any digitalWrite command for the rotate_cw, rotate_ccw, rotate_up, and rotate_down pins to instead turn on the necessary pins for the shield direction control and PWM output. This would not be hard to do. I would convert the digitalWrite statements to call subroutines to do this. Let me know if you’re interested in pursuing further and we can look at it in more detail.

      • Hi Woody, thank you for prompt reply,

        I am collecting information to build an antenna rotator from a common ham rotator 360deg potentiometer sensor type as azimuth and a satellite actuator screw jack reed switch sensor type as elevation. The reed switch sensor will be changed to potentiometer later.

        Please look sample codes at:

        It’s Arduino variant which is embedded a 2A rotor shield. It might have all the codes we need.

        Please take your time, I hope it will be a contribution for your great rotor control project.

    • Didi,

      Take a look at this is the manual of K6XOX who uses K3NG software in his designed controller board. It’s actually an Arduino with all extra components on one board. He exactley describes how to connect the L298N board which you can get as cheap as 19 dollar. The link to the website where they sell them is there too.

      73! John PA5MS

  19. Hello !

    first of all many thank for your super project for Arduino rotor-controller.
    I just started playing with arduino uno and uploaded your software setting some #define as required by my setup. Seem to work great except command Mxxx. Let me explain:

    - rotor is a Kenpro KR-5400B (only azimuth is actually used)
    - Azimuth indication on controller is 180 – 270 – 0 – 90 – 180 (so center is North )
    - Potentiometer voltage out: left 180 = 0V / North = 2,5V / right 180 = 5V

    I try different software setup and tweak(360 deg rotor, nCenter, etc) and got correct azimuth indication on serial monitor and display, but if i give Mxxx command, something go wrong.

    Example: actual azimuth = 90 deg (the needle is on the right side of controller’s indicator and voltage about 3,7 V). Send M270 command, it should move CCW because position 270 is on the left side of indicator, voltage = 1,25V. What happen ? rotor start turning CW instead CCW, I think because he knows that 270 is > than 90 so also analog voltage should be greater.

    For sure I am doing something wrong. Any comment please ?

    Thank you Pietro / hb9rxc

    • Hello Pietro.

      Last week a New Zealand amateur brought to my attention an issue with the 360 degree rotator rotation logic. I have fixed the issue and posted new code here, version 2012031401. Please try this and let me know if this works for you. Also, please set your code for South Center (comment out #define OPTION_NCENTER_ROTATOR), since it starts at 180 degrees.


      • Hi Goody

        thank you for prompt reply ! I downloaded your latest release and comment out #define OPTION_NCENTER_ROTATOR as required (but why ? it is a N-center system … )and uploaded. After calibration I moved to 135deg (right side of indicator) and then issued a M270 command. Now rotor start moving in the right direction CCW but when passing 360 (north) beaming to 270 … it stop and goes back CW to 020 then stop. I tried also to go manually with controller to 270, but everytime passed 360 sostware bringh back to 020 …

        I wrote my own software (based on VE2DX example) with couple of tweaking to solve this problem … actually it’s work great ! I would like to send you my rotor.ino file but I need your PM e-mail …. btw if you are interested to see what I deed !
        Waiting … 73′ Pietro

      • You can send your .ino file to anthony dot good at gmail dot com.

        Regarding “North Center” and “South Center”, the terms are a bit misleading. The Yaesu manual indicates that the “Z” command toggles the needle starting point between North and South. Default is South. Later in the manual they call it “North Center” and “South Center”, so I use that terminology. However, the term “Center” is very misleading as it really isn’t the center of the rotation, it’s the start.

      • Also, if you could send me a debug dump of the controller in action, that would help me troubleshoot the problem. If you issue the \d comment it will activate debug mode. Please issue the command before you initiate rotation and copy all of the text into an email.

  20. Hi Radioartisan , thanks for great rotator code . However 90deg overlap one way and none the other direction is not my favorit food . My rotor G-800 ( and box) has mechanical stop in North + 90deg overlap . However I have offset the rotor in the tower -45deg , giving me an overlap of 45deg CW but also 45deg CCW . Can the code compensate (calibreate) this 2x45deg overlap?
    Great with PWM and slowdown before fullstop , but how about a slow-up start ?
    Again great code ,
    happy easter, vy73 de oz1bxn chris

    • Hi Chris. I can implement slow start as an optional feature and change the code to accommodate your rotation scheme. I think I’m going to rewrite the rotation logic code from scratch so it can handle custom starting points and rotation capabilities other than just 360 and 450 degrees.

      Just to be clear, your rotator setup starts at 315 degrees and rotates clock wise to 45 degrees, with 450 degrees of rotation, correct?


      • Super. Yes the rotor is a 450deg type and start in 315 and move on overlap towards 45 (this is the mechanical stop in the rotor bell) .

        It would be smart if this overlap values could be calibrated to any value E.g. in-case a storm twist the antenna.

        btw all this overlap has made me thinking what is the best way to run overlap . It is tradition here to run +-45deg , but it actually perhaps be wiser to use the default 90deg.

        look forward to test the new code

        best vy73 de oz1bxn chris

      • I haven’t forgotten about this, I’ve just been real busy. I have the slow start working and I rewrote the rotation logic so it can essentially handle any starting azimuth and rotation capability up to 719 degrees. I’m also working on brake engage/disengage outputs for azimuth and elevation for rotators that are equipped with brakes. I should have a code update posted this coming weekend.

  21. Easy Man , no stress . Great work you do and it works great , but take it easy

    best vy73 de oz1bxn Chris

  22. Updated code posted. This code has slow startup and brake operation capability and can now be configured for just about any rotation starting point and rotation capabilities up to 719 degrees. Enjoy.

    • Flashed my rotor with the new code here tonight . Seems to work perfectly . Will test more in the next days . best vy73 de oz1bxn chris

  23. Hi Goody,

    Great project, indeed!
    Built and set up for tests on bredboard within 20 minutes but I am hitting issue with serial communication – I only get response for the first command I issue. After that I only get “?>” response in arduino serial monitor. Thought it could be memory issue, but debug mode reports 1441 bytes free mem. Any help would be appreciated!


    • Hello Vesko,

      Are you using the Arduino IDE Serial Monitor or another program? Is there a particular command you are executing each time before it only responds with “?>” , or is it any first command that is successful? Could you email to anthony dot good at gmail dot com the .ino file you are compiling?


      • Hi Goody,

        Thank you for your fast response and for showing me the mistake I made!
        I hope that both CR an CRLF options for serial communication will be available in future versions as well :)


  24. New code posted. No major new stuff, but I’m now posting code on Sourceforge rather than create new WordPress pages which is a bit laborious.

  25. Hi,
    Thanks for a great program.
    Have just completed the construction of a interface. No problems. Worked just fine.

    OZ1OP / Ole

  26. Hello
    I can not find the LCD anywhere in Europe
    Anyone can help?
    Can I use an HD44780 instead?
    Is it true that only the code to be loaded?
    Or are there extra files?
    I am now for this.

  27. Hi!

    I am highly Interested in this for my cheap rotor project. I have a Rotor with absolute no direction indication so Magneto and/or accelerometers are my way to go, I know about deviation etc.

    One reason I love this project is the arduino CPU which is nicely programmable by my Mac. The motor is 3 wire and AC switched by 2 relays. It has a memory computer control but that is of no use. I can make it turn freely around by removing the two small notches.

    Any hints or tips are welcome!


    • Hello Martijn. I don’t have any tips at this point, but I would be glad to work with you on getting a digital compass and/or accelerometer working with the code. The code that is in there now was contributed by someone and hasn’t been tested by me. I do have an LSM303DLHC combination accelerometer and digital compass which I intend to interface and test sometime soon.


  28. Dear Goody,

    First of all, Thank you and all contributors for this great controller project. I am following carefully and look forward to see some new improvements in the near feature like use of digital compass, accelerometer sensors for accurate beaming. Bigger Color Display with some more info on the display like Callsign, UTC Time, Local Time etc. 73 DE TA2LE – HALUK

  29. Is it possible to use TI MSP430 LaunchPad which is only 4.30 USD ? Anyway to convert existing code for Code Composer Studio ?

    73 DE TA2LE – HALUK

    • Unfortunately, Haluk, I don’t know the answer to this as I’m not familiar with that platform.

    • Yes, google Cheap Rotor Controller. I mangle messages trying to post a line with symbols.
      Its on tomdoyle dot org

      AF5FP — Don Lewis

  30. Hello,
    Will this run on a V3.x Arduino nano? The pin out seems a little different from the one in the schematic. I just want a small board with Arduino and needed supporting hardware and nothing else. I want to install it inside the controller box.

    • It should run fine on a Nano. The pin assignments are not critical; you can adjust the code as needed to reassign the pins.

      • Hi Anthony,
        I was given a old Yaesu G-800 rotor without anything else. I was going to develop my own controller but fortunatly ran across this web page and you saved me a lot of time and effort. I ordered a arduino uno r3 from mp3car, a sainsmart 12864 glcd from sainsmart and went for it. Though there were some challenges in your latest release, CODE_VERSION 2012050501, I did get it working over the labor day weekend. Your program would show only short unreadable pixels on my display. I kept thinking it was my display or character addressing routines but by changing the ‘>’ to a ‘ LCD_UPDATE_TIME) { ” in your update_display() function, I was able to get it working fine. To get to this point I placed debug statements inside that “if” test and they never printed. I found millis was below count of lcd_update which stayed well below LCD_UPDATE_TIME. After getting it working I took a pause and have not determined why this was happening. Testing with HRD rotator using LED’s for the azimuth motor drive and a 500 ohm pot it all checks out. Later I would love to take up a question about how the overlap is only used on one direction of the rotor giving a large overlap rather than on both ends of the rotor’s rotation range and dividing the overlap in half, My rotor has 45 degrees of overlap at the end of CW and CCW before activating the stop switches as I interpret it.
        Again, thank you for some most excellent project and code.
        AF5FP — Don Lewis

      • Anthony,
        I see that didnt make sense.
        I changed the right arrow > to a left arrow LCD_UPDATE_TIME)
        in your update_display function.

        AF5FP — Don Lewis

      • Hi Don. Note that the latest release is 2012060801 on SourceForge, though there weren’t any changes that I can recall in the area of the code you’re working on between 21012050501 and 2012060801.

        if ((millis() – last_lcd_update) > LCD_UPDATE_TIME)

        This line of code checks the duration of time since the last LCD update and if it’s over LCD_UPDATE_TIME which is defaulted to 2000 mS (2 seconds), it updates the LCD. If you’re changing the “>” to a “<", it's making the LCD get updated every time update_display() is called, which is every main loop (quite frequently, probably on the order of every 200 to 300 uS). There's a chance if one of the other subroutines in the main loop takes a long time (over 2000 mS), the LCD will never update again as the duration of time since the last update is over 2000 mS. But I digress. I'm not sure why your display would need more rapid updates. Are you using the regular LiquidCrystal library or are you doing I2C?

      • Regarding “overlap”, it’s more a state of mind than actually placing it somewhere, if that makes sense. :-) If you manipulate these lines:


        …you can pretty much place the rotation wherever you like. If your G-800 controller is like my G-1000, you can move the needle to accommodate a “non-standard” starting point. The overlap LED won’t come on after the usual 180 degrees when going clockwise, but will come on after 360 degrees of rotation.

  31. Pingback: Arduino based Yaesu Rotator Controller | Ava High Altitude Balloon Project·

Comments are closed.