ARDUINO BASED ANTENNA ROTATOR – PART3 – Software tracking update

This version is compatible with EASYCOMM2 antenna protocol.
After getting in touch with PstRotator (tracking software) developer, he kindly gave me the solution I was searching for, in order to send back the antenna position to be displayed in the software. He also generously gave me a license for his software, thank you very much.

In the Easycom2 protocol, the software sends the target position to the controller, like
AZxxx.x ELxx.x
There is no fix length for the coordinates.
The software asks for the current antenna position by sending
AZ EL
And the controller should respond with
+xxx.x xx.x
where the first is the azimuth, then the elevation. There is no fix length, but the decimal is mandatory, even if it is 0. Like +23.0 5.0

Note that so far, PstRotator was the only software who could display the antenna position.

This Arduino version is compatible with all tracking software using EasyComm protocol / 9600 bauds.
PstRotator, WXtrack, HRD, MacDoppler… Even WXtoIMG can control the rotator. Orbitron needs the plugin listed below.
It accepts 0-180º elevation, but rotates the antenna accordingly, for max. 90º elevation.

There’s also a variant for AC motors, which offers dry contacts (ON/OFF). It can be easily interfaced with commercial rotators. And one for 180º elevation, one for 0.1º precision. Just give me a shout.

If you only want azimuth control, that’s fine. Just don’t install the parts for elevation. Put A1 to GND to always read 0° elevation. This is an example of electric diagram for azimuth only.

Jean-Jacques – ON7EQ made an excellent modification to the code for a simple controller -azimuth only- and YAESU communication protocol. Check out his work HERE.

The DC motors version has the advantage of using PWM for a softer/smoother antenna movement. It outputs a power response proportional with angle error (Target<->Antenna).
There’s an adjustable Dead Zone, where the antenna doesn’t move for the slightest target offset.
This is the 
plot of Power output corresponding to Angle error.

Once the project is complete and it can move, you must apply the Potentiometer calibration procedure. It ensures correct reading of 0-359º / 0-90º, no matter what kind of potentiometer you are using.
The motor calibration is only for DC, and tunes the soft stop feature. This is only necessary if you don’t like the default settings.
The code has been updated several times, and now, for example, you can set the
antenna update in your tracking software, as fast as you want, 0.5 sec. if you like.

Check the Arduino code page for the codes, drawings and procedures.

Thank you very much to all who sent me feedback, helping to make this project more reliable.

Orbitron DDE Azimuth Elevation To Serial

Arduino code

PstRotator tracking software

PART1 – SOFTWARE AND PROTOTYPING 

PART2 – HARDWARE, BOARDS AND MOTORS

Some afterthoughts after months/years of using this controller and rotator.
I have a home-made DC rotator Az/El 360º/90º. The azimuth motor draws 12V/3A in full power.

1. After adding 12m of LiYCY-12×0.75 cable from controller to rotator, the azimuth reading had a noise of +/- 10º.
One 1μF capacitor GND-AzPot on Arduino side lowered the noise to +/- 2º. After days of measurements and oscilloscoping, I replaced the 5V adaptor because it had a very big ripple (noise). I added one 5V adaptor for Arduino, LCD, encoders and potentiometers, and another one for relays and MOSFETs. The potentiometer noise disappeared. Thanks Bernd-OE6HBD for the tip.

2. The relay module for azimuth direction (rated at 10A) failed – replaced.
I added the ‘cold switch’ feature
 in the code.

3. The MOSFET module (rated 10 times the power) for azimuth PWM failed – replaced.
It warms up only when antenna is moving slow (PWM = repetitive MOSFET switching). After days of measurements and oscilloscoping, I found no flyback phenomenon
, nothing special. I added a small fan to the case, to ensure a little flow of air over the heat-sink.

15 comments

  1. salut.foarte fain proiectul…am facut un rotor de antena folosind un compas electronic dar am ceva probleme cand transmit cu putere peste 20w cam deranjeaza compasul!!!dar acum gasind proiectul tau cred ca o sa incerc si abordarea asta fara compas electronic dar cu potentiomete ca feedback…totusi am cateva intrebari:
    1.am ceva potentiometre multitura de 20k,crezi ca ar merge in locul celor de 1k din schema?!
    2.am vazut in unul din video ca aveai ceva dificultati in a avea o citire stabila a valorii de la potentiometru si asta ar fi datorat “zgomotului”produs de celelalte module precum si de PC,cum sar putea elimina aceste interferente astfel incat sa faci rotorul cat mai precis?!

    1. Salut Cristian,
      Potențiometrul de 1K de la azimut produce mult mai mult zgomot (2-3 grade) decât cel de 200 ohm de la elevație (0 – 1 grad).
      Cred ca valoarea ideală e de 100 – 200 ohm. Mi-e teamă că 20K ar fi prea zgomotos.
      Nu mă deranjează o precizie de câteva grade, de vreme ce diagrama de 3dB a antenei are 20-30 de grade.
      Ți-am dat un mail, în caz că vrei să continui cu acest proiect.
      Toate cele bune.

  2. HI
    About EasyComm2 Protocol.What is the correct response to the AZ EL command to query the antenna position?I used HRD software and homemade rotator EasyComm protocol. For “AZ EL” response “+12.3 45.6”, the HRD dashboard did not have any only indicating changes.
    DE BG0AUB

  3. Hi,
    It is true, I was not able to get HRD to connect with EasyComm2 Protocol. Perhaps it wants a different response from the controller, which I haven’t figured out yet.
    The only software that displays the antenna position was PstRotator.
    I guess there are different implementations of EasyComm2 and more documentation was impossible to find. If I will find information for a better protocol, I will definitely update his project.
    All the best.

    1. Hey Rodrigues,
      Do you have big enough servos to move the antenna?
      The azimuth servo rotates 360 degrees?
      If so, it’s very possible. The code and construction would be even simpler.
      I’ve sent you an email.

  4. does the code change if I would like to use servos instead of Dc motors ?? and can the azimuth driven by two 180 degree servos??
    Thanks

  5. DEEK-ROBOT Motorshield
    Hello to the group. I’m using Arduino Uno with Deek-Robot Motorshield and I’m trying
    to figure out in the Arduino code what the pin number settings should be for Motor A and
    Motor B output should be?
    For CW/CCW I have AzRotPin =12 AzPWMPin = 9
    For Up/Down I have ElRotPin =13 ElPWMPin = 8
    I’m not sure if this correct for the Deek-Robot Motorshield or not but if anyone has an
    answer on pin number setting, I would appreciate the help and feedback
    Thanks 73’s
    Eric/KB3DTQ

  6. Hey Eric.
    AzPWMPin / ElPWMPin are the ones which activate the motors (Speed).
    AzRotPin / ElRotPin change the direction of rotation. They were supposed to drive a relay who changes the voltage polarity of the motor.
    I did a bit of research on Deek-Robot Motorshield. It uses a H-Bridge to change the direction of rotation and can drive small motors (2 Ampers each), but I think it’s barely enough for an antenna rotator.
    I would be glad to help you in finishing this project. Just let me know.

    1. Believe me, the Deek-Robot Motorshield works like a Charm. I’ve already tested it with the K3NG Rotator Controller project and works very well
      with PstRotator software. The only fun part is getting command control of the Rotator 🙄📡. But anyway thanks for the reply. Yes I could use extra help on the pin settings for the Motorshield. All I need to do is figure out which pins from Arduino Uno are feeding Motor A and
      Motor B on the Motorshield board?
      73’s
      Eric/KB3DTQ

    2. Hello again from Eric/KB3DTQ
      Here is the project I am currently working on.
      (K3NG Antenna Rotator Controller)
      Hardware: Arduino Mega 2560, Deek-Robot Motorshield R3, Nextion Enhanced 3.2 TFT Screen
      (2) Worm-gear motors for Azimuth and Elevation. (2) Sensors for AZ & EL (1) GPS Module
      Software code: K3NG Rotator Controller from GitHub.
      I’m trying to get control of motor outputs of the Motorshield DIR A=pin 12 DIR B= pin 13.
      The problem is my DIR A -negative output (Elevation) is active after bootup of the program, all other outputs are inactive. What I need to accomplish is Command Control from Nextion Touchscreen to activate CW/CCW & UP/DOWN control which is configured in pins.h file of the K3NG code. My question about the Motorshield is, which pins control ON, OFF, and DIRECTION?
      Here is the pins.h file I’m working with as of now, hopefully someone knows which configurations
      I need to use for Azimuth CW/CCW/PWM and Elevation CW/CCW/PWM? Once again, I’m only looking at Azimuth pins and Elevation pins in this code file.
      Many Thanks for any help on this.
      ERIC/KB3DTQ

      /* ————————————- Pin Definitions ——————————————

      You need to look at these and set them appropriately !

      Most pins can be disabled by setting them to 0 (zero). If you’re not using a pin or function, set it to 0.

      Pins > 99 = remote unit pin, for example: pin 109 = pin 9 on remote unit, pin A0+100 = pin A0 on remote unit

      */

      /* azimuth pins ——————— (use just the azimuth pins for an azimuth-only rotator) */

      #define rotate_cw 5 // goes high to activate rotator R (CW) rotation – pin 1 on Yaesu connector
      #define rotate_ccw 6 // goes high to activate rotator L (CCW) rotation – pin 2 on Yaesu connector
      #define rotate_cw_ccw 0 // goes high for both CW and CCW rotation
      #define rotate_cw_pwm 0 // optional – PWM CW output – set to 0 to disable (must be PWM capable pin)
      #define rotate_ccw_pwm 0 // optional – PWM CCW output – set to 0 to disable (must be PWM capable pin)
      #define rotate_cw_ccw_pwm 0 // optional – PWM on CW and CCW output – set to 0 to disable (must be PWM capable pin)
      #define rotate_cw_freq 0 // optional – CW variable frequency output
      #define rotate_ccw_freq 0 // optional – CCW variable frequency output
      #define button_cw 0 // normally open button to ground for manual CW rotation (schematic pin: A2)
      #define button_ccw 0 // normally open button to ground for manual CCW rotation (schematic pin: A3)
      #define serial_led 0 // LED blinks when command is received on serial port (set to 0 to disable)
      #define rotator_analog_az A0 // reads analog azimuth voltage from rotator – pin 4 on Yaesu connector
      #define azimuth_speed_voltage 24 // optional – PWM output for speed control voltage feed into rotator (on continually unlike rotate_cw_pwm and rotate_ccw_pwm)
      #define overlap_led 0 // line goes active when azimuth rotator is in overlap (> 360 rotators)
      #define brake_az 0 // goes high to disengage azimuth brake (set to 0 to disable)
      #define az_speed_pot 0 // connect to wiper of 1K to 10K potentiometer for speed control (set to 0 to disable)
      #define az_preset_pot 0 // connect to wiper of 1K to 10K potentiometer for preset control (set to 0 to disable)
      #define preset_start_button 0 // connect to momentary switch (ground on button press) for preset start (set to 0 to disable or for preset automatic start)
      #define button_stop 0 // connect to momentary switch (ground on button press) for preset stop (set to 0 to disable or for preset automatic start)
      #define rotation_indication_pin 0
      #define blink_led 0
      #define az_stepper_motor_pulse 44 //0
      #define az_stepper_motor_direction 0
      #define az_rotation_stall_detected 0

      /*———– elevation pins ————–*/

      #define rotate_up 7 // goes high to activate rotator elevation up
      #define rotate_down 8 // goes high to activate rotator elevation down
      #define rotate_up_or_down 0 // goes high when elevation up or down is activated
      #define rotate_up_pwm 0 // optional – PWM UP output – set to 0 to disable (must be PWM capable pin)
      #define rotate_down_pwm 0 // optional – PWM DOWN output – set to 0 to disable (must be PWM capable pin)
      #define rotate_up_down_pwm 0 // optional – PWM on both UP and DOWN (must be PWM capable pin)
      #define rotate_up_freq 0 // optional – UP variable frequency output
      #define rotate_down_freq 0 // optional – UP variable frequency output
      #define rotator_analog_el A1 // reads analog elevation voltage from rotator
      #define button_up 0 // normally open button to ground for manual up elevation
      #define button_down 0 // normally open button to ground for manual down rotation
      #define brake_el 0 // goes high to disengage elevation brake (set to 0 to disable)
      #define elevation_speed_voltage 25 // optional – PWM output for speed control voltage feed into rotator (on continually unlike rotate_up_pwm and rotate_down_pwm)
      #define el_stepper_motor_pulse 45
      #define el_rotation_stall_detected 0

      // rotary encoder pins and options
      #ifdef FEATURE_AZ_PRESET_ENCODER
      #define az_rotary_preset_pin1 0 // CW Encoder Pin
      #define az_rotary_preset_pin2 0 // CCW Encoder Pin
      #endif //FEATURE_AZ_PRESET_ENCODER

      #ifdef FEATURE_EL_PRESET_ENCODER
      #define el_rotary_preset_pin1 0 // UP Encoder Pin
      #define el_rotary_preset_pin2 0 // DOWN Encoder Pin
      #endif //FEATURE_EL_PRESET_ENCODER

      #if defined(FEATURE_AZ_POSITION_ROTARY_ENCODER) || defined(FEATURE_AZ_POSITION_ROTARY_ENCODER_USE_PJRC_LIBRARY)
      #define az_rotary_position_pin1 0 // CW Encoder Pin
      #define az_rotary_position_pin2 0 // CCW Encoder Pin
      #endif //FEATURE_AZ_POSITION_ROTARY_ENCODER

      #if defined(FEATURE_EL_POSITION_ROTARY_ENCODER) || defined(FEATURE_EL_POSITION_ROTARY_ENCODER_USE_PJRC_LIBRARY)
      #define el_rotary_position_pin1 0 // CW Encoder Pin
      #define el_rotary_position_pin2 0 // CCW Encoder Pin
      #endif //FEATURE_EL_POSITION_ROTARY_ENCODER

      #ifdef FEATURE_AZ_POSITION_PULSE_INPUT
      #define az_position_pulse_pin 0 // must be an interrupt capable pin!
      #define AZ_POSITION_PULSE_PIN_INTERRUPT 0 // Uno: pin 2 = interrupt 0, pin 3 = interrupt 1 ; Mega: pin 2 = interrupt 0, pin 3 = interrupt 1, pin 21 = interrupt 2, pin 20 = interrupt 3, pin 19 = interrupt 4, pin 18 = interrupt 5
      #endif // read http://arduino.cc/en/Reference/AttachInterrupt for details on hardware and interrupts

      #ifdef FEATURE_EL_POSITION_PULSE_INPUT
      #define el_position_pulse_pin 1 // must be an interrupt capable pin!
      #define EL_POSITION_PULSE_PIN_INTERRUPT 1 // Uno: pin 2 = interrupt 0, pin 3 = interrupt 1 ; Mega: pin 2 = interrupt 0, pin 3 = interrupt 1, pin 21 = interrupt 2, pin 20 = interrupt 3, pin 19 = interrupt 4, pin 18 = interrupt 5
      #endif // read http://arduino.cc/en/Reference/AttachInterrupt for details on hardware and interrupts

      #ifdef FEATURE_PARK
      #define button_park 0
      #endif

      //classic 4 bit LCD pins
      #define lcd_4_bit_rs_pin 12
      #define lcd_4_bit_enable_pin 11
      #define lcd_4_bit_d4_pin 5
      #define lcd_4_bit_d5_pin 4
      #define lcd_4_bit_d6_pin 3
      #define lcd_4_bit_d7_pin 2

      #ifdef FEATURE_JOYSTICK_CONTROL
      #define pin_joystick_x A0
      #define pin_joystick_y A1
      #endif //FEATURE_JOYSTICK_CONTROL

      #ifdef FEATURE_AZ_POSITION_HH12_AS5045_SSI
      #define az_hh12_clock_pin 11
      #define az_hh12_cs_pin 12
      #define az_hh12_data_pin 13
      #endif //FEATURE_AZ_POSITION_HH_12

      #ifdef FEATURE_EL_POSITION_HH12_AS5045_SSI
      #define el_hh12_clock_pin 53 //11
      #define el_hh12_cs_pin 52 //12
      #define el_hh12_data_pin 51 //13
      #endif //FEATURE_EL_POSITION_HH_12

      #ifdef FEATURE_PARK
      #define park_in_progress_pin 0 // goes high when a park has been initiated and rotation is in progress
      #define parked_pin 0 // goes high when in a parked position
      #endif //FEATURE_PARK

      #define heading_reading_inhibit_pin 0 // input – a high will cause the controller to suspend taking azimuth (and elevation) readings; use when RF interferes with sensors

      #ifdef FEATURE_LIMIT_SENSE
      #define az_limit_sense_pin 0 // input – low stops azimuthal rotation
      #define el_limit_sense_pin 0 // input – low stops elevation rotation
      #endif //FEATURE_LIMIT_SENSE

      #ifdef FEATURE_AZ_POSITION_INCREMENTAL_ENCODER
      #define az_incremental_encoder_pin_phase_a 18 //3 must be an interrupt capable pin
      #define az_incremental_encoder_pin_phase_b 19 //3 // must be an interrupt capable pin
      #define az_incremental_encoder_pin_phase_z 22 //4
      #define AZ_POSITION_INCREMENTAL_ENCODER_A_PIN_INTERRUPT 5 //0 // Uno: pin 2 = interrupt 0, pin 3 = interrupt 1 ; Mega: pin 2 = interrupt 0, pin 3 = interrupt 1, pin 21 = interrupt 2, pin 20 = interrupt 3, pin 19 = interrupt 4, pin 18 = interrupt 5
      #define AZ_POSITION_INCREMENTAL_ENCODER_B_PIN_INTERRUPT 4 //1 // Uno: pin 2 = interrupt 0, pin 3 = interrupt 1 ; Mega: pin 2 = interrupt 0, pin 3 = interrupt 1, pin 21 = interrupt 2, pin 20 = interrupt 3, pin 19 = interrupt 4, pin 18 = interrupt 5
      // read http://arduino.cc/en/Reference/AttachInterrupt for details on hardware and interrupts
      #endif //FEATURE_AZ_POSITION_INCREMENTAL_ENCODER

      #ifdef FEATURE_EL_POSITION_INCREMENTAL_ENCODER
      #define el_incremental_encoder_pin_phase_a 2 //18 //2 // must be an interrupt capable pin
      #define el_incremental_encoder_pin_phase_b 3 //19 //3 // must be an interrupt capable pin
      #define el_incremental_encoder_pin_phase_z 5 //22 //4
      #define EL_POSITION_INCREMENTAL_ENCODER_A_PIN_INTERRUPT 0 //5 //0 // Uno: pin 2 = interrupt 0, pin 3 = interrupt 1 ; Mega: pin 2 = interrupt 0, pin 3 = interrupt 1, pin 21 = interrupt 2, pin 20 = interrupt 3, pin 19 = interrupt 4, pin 18 = interrupt 5
      #define EL_POSITION_INCREMENTAL_ENCODER_B_PIN_INTERRUPT 1 //4 //1 // Uno: pin 2 = interrupt 0, pin 3 = interrupt 1 ; Mega: pin 2 = interrupt 0, pin 3 = interrupt 1, pin 21 = interrupt 2, pin 20 = interrupt 3, pin 19 = interrupt 4, pin 18 = interrupt 5
      // read http://arduino.cc/en/Reference/AttachInterrupt for details on hardware and interrupts
      #endif //FEATURE_EL_POSITION_INCREMENTAL_ENCODER

      #ifdef FEATURE_YOURDUINO_I2C_LCD
      #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
      #endif //FEATURE_YOURDUINO_I2C_LCD

      #ifdef FEATURE_MOON_TRACKING
      #define moon_tracking_active_pin 0 // goes high when moon tracking is active
      #define moon_tracking_activate_line 0 // ground this pin to activate moon tracking (not for use with a button)
      #define moon_tracking_button 0 // use with a normally open momentary switch to ground
      #endif //FEATURE_MOON_TRACKING

      #ifdef FEATURE_SUN_TRACKING
      #define sun_tracking_active_pin 0 // goes high when sun tracking is active
      #define sun_tracking_activate_line 0 // ground this pin to activate sun tracking (not for use with a button)
      #define sun_tracking_button 0 // use with a normally open momentary switch to ground
      #endif //FEATURE_SUN_TRACKING

      #ifdef FEATURE_GPS
      #define gps_sync 0
      #endif //FEATURE_GPS

      #ifdef FEATURE_POWER_SWITCH
      #define power_switch 0 // use with FEATURE_POWER_SWITCH
      #endif //FEATURE_POWER_SWITCH

      #ifdef FEATURE_EL_POSITION_MEMSIC_2125
      #define pin_memsic_2125_x 0
      #define pin_memsic_2125_y 0
      #endif //FEATURE_EL_POSITION_MEMSIC_2125

      #ifdef FEATURE_ANALOG_OUTPUT_PINS
      #define pin_analog_az_out 0
      #define pin_analog_el_out 0
      #endif //FEATURE_ANALOG_OUTPUT_PINS

      #ifdef FEATURE_SUN_PUSHBUTTON_AZ_EL_CALIBRATION
      #define pin_sun_pushbutton_calibration 0 // normally HIGH, have button pull LOW
      #endif //FEATURE_SUN_PUSHBUTTON_AZ_EL_CALIBRATION

      #ifdef FEATURE_MOON_PUSHBUTTON_AZ_EL_CALIBRATION
      #define pin_moon_pushbutton_calibration 0 // normally HIGH, have button pull LOW
      #endif //FEATURE_MOON_PUSHBUTTON_AZ_EL_CALIBRATION

      //#define reset_pin 22 // if defined, goes HIGH to reset unit

      #if defined(FEATURE_AZ_POSITION_A2_ABSOLUTE_ENCODER) || defined(FEATURE_EL_POSITION_A2_ABSOLUTE_ENCODER)
      #define pin_sei_bus_busy 24
      #define pin_sei_bus_send_receive 22
      #endif

      #ifdef FEATURE_YWROBOT_I2C_DISPLAY
      #define ywrobot_address 0x3F
      #define ywrobot_pin_en 2
      #define ywrobot_pin_rw 1
      #define ywrobot_pin_rs 0
      #define ywrobot_pin_d4 4
      #define ywrobot_pin_d5 5
      #define ywrobot_pin_d6 6
      #define ywrobot_pin_d7 7
      #define ywrobot_pin_bl 3
      #define ywrobot_blpol POSITIVE
      #endif //FEATURE_YWROBOT_I2C_DISPLAY

      // #define pin_led_cw 0
      // #define pin_led_ccw 0
      // #define pin_led_up 0
      // #define pin_led_down 0

      #ifdef FEATURE_AUTOPARK
      #define pin_autopark_disable 0 // Pull low to disable autopark
      #define pin_autopark_timer_reset 0 // Pull low to reset the autopark timer (tie in with rig PTT)
      #endif

      #ifdef FEATURE_AUDIBLE_ALERT
      #define pin_audible_alert 2
      #endif

      //#define pin_status_led 0 // Status LED – blinks when there is rotation in progress

      // Added 2020.07.24.01
      #define satellite_tracking_active_pin 0
      #define satellite_tracking_activate_line 0
      #define satellite_tracking_button 0 // use with a normally open momentary switch to ground

  7. Motor A – azimuth is AzPWMPin (pin 9)
    Motor B – elevation is ElPWMPin (pin 8)
    Please give me an email if you want to discuss in more details.
    Sincerely,
    Viorel

Leave a Reply

Your email address will not be published. Required fields are marked *