Another readout for an antenna aka a G2700 / G2800 / G1000 substitute

Sometimes spare parts are hard to find. So was the control clock for a Yaesu G2700 rotator at ON6NL ‘s place. The decision to make one was made easy. There is a potmeter in the rotor, normally 500 Ohms. The rotor has 450 degrees turning angle allowing overlap on either side. of 45 degrees.. So starting northwest the rotor can rotate through north, east, south, west, north and northeast.

The rotor driver consisted of a Chinese module PWM control and direction control found at Aliexpress for around €10-15 and a transformer, diodes and electrolytic capacitors from the junkbox. This is only for DC motors!

The complete unit

The readout was kept as simple as possible. A 2x16LCD an arduino nano and the software.

Display showing the antenna direction NE and the degrees. It warns you to rotate CCW. This is showing only close to the mechanical end-stop. The number is the digital value (0-1023) . This is for alignment and calibration procedure.

The display showing a 15 degrees overlap.

Over the pot-meter output a capacitor of 470nF was placed to ground. This made the readout more stable.

// Antenna direction display for rotors with potmeter
//            By PA3CSG and ON6NL - April 2024
//
// Reads pot.meter and displays compass direction, degrees
// and warnings for overlap and nearing end stops
//
// Hardware: LCD i2c display 16 positions, 2 lines, Arbduino Nano and  potmeter in rotor
// 
// First fill in 
// the maximum position you allow the rotor to turn to the left = CCW as DegMinus
//     with degrees left of North as minus ( 45 degrees CCW (NW) overlap is -45)  
// the maximum position you allow the rotor to turn to the right = CW as DegMax
//     with degrees right of North added to 360 ( 45 degrees CW (NE) overlap is 405)  
//
// To calibrate ; Turn rotor fully Counter Clock Wise position
//                Note the number in the lower right corner of the display.
//                This number must be entered as the valueCCW
//                Turn rotor fully Clock Wise position
//                Note the number in the lower right corner of the display.
//                This number must be entered as the valueCW
//                Compile and upload the sketch 

#include <LiquidCrystal_I2C.h>
#include <Wire.h>

//+++++++++++++  Calibration settings +++++++++++++++++++++++++++++

int valueCCW = 2;    // Digital value of the pot meter at full CCW
int valueCW = 915;   // Digital value of the pot meter at full CW

int DegMinus = -45;  // DEGREES of the maximum position the rotor turns CCW
int DegMax   = 405;  // DEGREES of the maximum position the rotor turns CW

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int analogInputPin = 0;               // analog input on Pin 0 of Arduino

LiquidCrystal_I2C lcd(0x27,  16, 2); // Address of the Display, 16 chars, 2 lines

byte N[8] = {
  B00100,
  B01110,
  B10101,
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
};

byte EW[8] = {
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B00000,
  B11111,
};

byte S[8] = {
  B00100,
  B00100,
  B00100,
  B00100,
  B00100,
  B10101,
  B01110,
  B00100,
};

byte BS[8] = {
  B00000,
  B10000,
  B01000,
  B00100,
  B00010,
  B00001,
  B00000,
  B00000,
 };

void setup() {
//initialize lcd screen
  lcd.init();
// turn on the backlight
  lcd.backlight();
// Welcome screen
  lcd.setCursor ( 0 , 0);
  lcd.print(F("Antenna readout"));

  lcd.setCursor ( 0 , 1);
  lcd.print(valueCCW);
  lcd.print(F("="));
  lcd.print(DegMinus);lcd.print((char)223);  //Degrees symbol
  lcd.print(F(" "));
  lcd.print(valueCW);
  lcd.print(F("="));
  lcd.print(DegMax);lcd.print((char)223);  //Degrees symbol

  lcd.createChar(0, N);
  lcd.createChar(1, EW);
  lcd.createChar(2, BS);
  lcd.createChar(3, S);


  delay (2000);
  lcd.clear ();

//Serial print set up
Serial.begin(115200);
}

void loop() {

// Convert pot. meter value to digital value

int Dvalue = analogRead(analogInputPin); // Read pot. meter value 

Serial.print(F(" Dvalue "));             // Debug in Serial Monitor
Serial.println(Dvalue);

// Digital readout Value on display
lcd.setCursor(12,1); //col 12 line 2
                                                                // Fill with space to align
if (Dvalue < 1000)  { lcd.print(F(" ")); }  // Below 1000 one fill space
if (Dvalue <  100)  { lcd.print(F(" ")); }  // Below 100 one more fill space
if (Dvalue <   10)  { lcd.print(F(" ")); }  // Below 10  one more fill space
lcd.print(Dvalue);

// Map digital value to degrees between full CCW and full CW
int Degrees = map(Dvalue , valueCCW , valueCW , DegMinus , DegMax );

// Direction in degrees on display with degrees symbol
lcd.setCursor(6,0);  
                                                                // Fill with space to align
if ((Degrees >  -10) && (Degrees <  0))   { lcd.print(F(" ")); }   // -9 to -1
if ((Degrees >   -1) && (Degrees <  10))  { lcd.print(F("  ")); }  // 0 to 9
if ((Degrees >    9) && (Degrees <  100)) { lcd.print(F(" ")); }   // 10 to 99

lcd.print(Degrees); 
lcd.print((char)223);  //Degrees symbol

// Compass Direction  on display
lcd.setCursor(11,0); 
if (Degrees < -23 )                      { lcd.print(F("NW")); }
if ((Degrees > -22) && (Degrees <  23 )) { lcd.print(F(" N")); }
if ((Degrees >  22) && (Degrees <  68))  { lcd.print(F("NE")); }
if ((Degrees >  67) && (Degrees <  113)) { lcd.print(F(" E")); }
if ((Degrees >  112) && (Degrees < 158)) { lcd.print(F("SE")); }
if ((Degrees >  157) && (Degrees < 203)) { lcd.print(F(" S")); }
if ((Degrees >  202) && (Degrees < 248)) { lcd.print(F("SW")); }
if ((Degrees >  247) && (Degrees < 293)) { lcd.print(F(" W")); }
if ((Degrees >  292) && (Degrees < 338)) { lcd.print(F("NW")); }
if ((Degrees >  337) && (Degrees < 381)) { lcd.print(F(" N")); }
if (Degrees >  382)  {lcd.print(F("NE")); }

// Compass rose on display
if (Degrees < -23 ) { lcd.setCursor(0,0);  lcd.write(byte(2));  lcd.print(F("  ")); } // NW "\"
if ((Degrees > -22) && (Degrees <  23 )) { lcd.setCursor(0,0);  lcd.print(F(" ")); lcd.write(byte(0));  lcd.print(F(" ")); } //N
if ((Degrees >  22) && (Degrees <  68))  { lcd.setCursor(0,0); lcd.print(F("  /")); } // NE 
if ((Degrees >  67) && (Degrees <  113)) {  lcd.setCursor(0,0);  lcd.print(F("  ")); lcd.write(byte(1)); }  // E

if ((Degrees >  112) && (Degrees < 158)) { lcd.setCursor(0,1); lcd.print(F("  ")); lcd.write(byte(2)); }  // SE
if ((Degrees >  157) && (Degrees < 203)) { lcd.setCursor(0,1); lcd.print(F(" ")); lcd.write(byte(3));  lcd.print(F(" "));  } //S
if ((Degrees >  202) && (Degrees < 248)) { lcd.setCursor(0,1); lcd.print(F("/  ")); } //SW

if ((Degrees >  247) && (Degrees < 293)) { lcd.setCursor(0,0); lcd.write(byte(1)); lcd.print(F("  ")); } //W
if ((Degrees >  292) && (Degrees < 338)) { lcd.setCursor(0,0); lcd.write(byte(2));  lcd.print(F("  ")); } // NW "\"
if ((Degrees >  337) && (Degrees < 381)) { lcd.setCursor(0,0); lcd.print(F(" ")); lcd.write(byte(0));  lcd.print(F(" ")); } //N
if (Degrees >  382)  { lcd.setCursor(0,0); lcd.print(F("  /")); } // NE 

if ((Degrees >  112) && (Degrees < 248)) {lcd.setCursor(0,0); lcd.print(F("   ")); } // Clear unused top positions
                                    else {lcd.setCursor(0,1); lcd.print(F("   ")); } // Clear unused bottom positions

                                                     // Special positions
lcd.setCursor(0,1); 
if ((Degrees <  0 ) ||  (Degrees >  360 )) 
     {
      lcd.print(F("overlap     "));     // Overlap areas
      if (Dvalue <= (valueCCW + 5) ) {          // Rotor close to end stop CCW        
          lcd.setCursor(0,1); lcd.print(F(" ROTATE CW  ")); //col 1, line 2  
                                     }                                      
      if (Dvalue >= (valueCW - 5) ) {          // Rotor close to end stop CW        
          lcd.setCursor(0,1); lcd.print(F(" ROTATE CCW ")); //col 1, line 2                                         
                                    }
     }
else {
   lcd.setCursor(3,1); lcd.print(F("         "));    // No special position
     }   

delay (200); // wait  between readings

   }