Install Antenna Tracker on PTZ Camera (Hikvision)

Mostly PTZ Camera have API or at least Onvif Support on their system, so i have an idea to put the AAT inside the PTZ Camera, and Convert the AUX for the Servo into API to moving the PTZ

What Inside

Yes, I use Esp32 to translate the PWM OUT from FC into API

The API what we need bassically only two: PAN and TILT

curl -X PUT --data-raw '<PTZData><pan>VALUE</pan></PTZData>' -H Expect: http://a:b@c/ISAPI/PTZCtrl/channels/1/Continuous

a = User Name (Must Administrator)
b = Password
c = IP Address of the PTZ Camera

Example:

Pan right
curl -X PUT --data-raw '<PTZData><pan>30</pan></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Pan left
curl -X PUT --data-raw '<PTZData><pan>-30</pan></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Stop Pan Movement
curl -X PUT --data-raw '<PTZData><pan>0</pan></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Tilt up
curl -X PUT --data-raw '<PTZData><tilt>30</tilt></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Tilt Down
curl -X PUT --data-raw '<PTZData><tilt>-30</tilt></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Stop Tilt Movement
curl -X PUT --data-raw '<PTZData><tilt>0</tilt></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Combining Together

Pan Right + Tilt up
curl -X PUT --data-raw '<PTZData><pan>30</pan><tilt>30</tilt></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Pan left + Tilt Down
curl -X PUT --data-raw '<PTZData><pan>-30</pan><tilt>30</tilt></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

Stop Pan+Tilt Movement
curl -X PUT --data-raw '<PTZData><pan>0</pan><tilt>0</tilt></PTZData>' -H Expect: http://admin:kora1234@192.168.1.100/ISAPI/PTZCtrl/channels/1/Continuous

For Stop, we can give both 0 to stop all movement or to specific such as Pan only and leave the tilt still moving

Result so far

Gentlemen, this thread still develop i create this time because my time are so limited, so i will continue on another my free of time

Later fix:

Seems ZOOM is useless, because when we ZOOM IN into the sky the camera won’t focus, so better I will use ZOOM for other reasons

Compass is not supposed to put on DOME, because Compass must always be HORIZON, the compass seems a little bit glitch when the DOME goes up more than 45 degrees

ILLUSTRATION

//*************************************************************************************
// PWM TO API CONVERTER
// by KORAKORA 2026
//
// README !!
// THIS VALUE ARE VARY! DEPEND OF YOUR SETTING FROM THE AAT
// *Example: if you choose Continues Rotations of the Servo the Value will be different
// Please Customize by your self
// or Consult with the members of forum in this thread
// https://discuss.ardupilot.org/t/install-antenna-tracker-on-ptz-camera-hikvision/143662 
//
// WE TALKING IP PTZ CAMERA NOT ANALOG
// so the Esp32 must to connected to the PTZ CAMERA by TCP/IP
// The conditions are vary based on what your setup is
// mine i connect the Esp32 to PTZ Camera by WiFi because my Esp32 don't have Ethernet
//***************************************************************************************

#include <WiFi.h>
#include <HTTPClient.h>

//**********************************************************
// PanIO = GPIO From Esp32 to FC Channel Connected to
// TiltIO = GPIO From Esp32 to FC Channel Connected to
//**************************
byte PanIO = 15;
byte TiltIO = 16;
void ReadPWM() {

  //*** CHECK PWM VALUE FROM FC FOR PAN
  int PanPWM = pulseIn(PanIO,HIGH);
  int PanVal;
  if (PanPWM > 1900) PanVal = 70;       // RIGHT TURN WITH FAST SPEED
  else if (PanPWM > 1700) PanVal = 50;  // RIGHT TURN WITH MEDIUM SPEED
  else if (PanPWM > 1550) PanVal = 30;  // RIGHT TURN WITH SLOW SPEED
  else if (PanPWM < 1100) PanVal = -70;  // LEFT TURN WITH FAST SPEED
  else if (PanPWM < 1300) PanVal = -50;  // LEFT TURN WITH MEDIUM SPEED
  else if (PanPWM < 1450) PanVal = -30;  // LEFT TURN WITH SLOW SPEED  
  else PanVal = 0;                      // STOP !!

  //*** CHECK PWM VALUE FROM FC FOR TILT
  int TiltPWM = pulseIn(TiltIO,HIGH);
  int TiltVal;
  if (TiltPWM > 1900) TiltVal = 50;      // TILT UP WITH FAST SPEED
  else if (TiltPWM > 1700) TiltVal = 40; // TILT UP WITH MEDIUM SPEED
  else if (TiltPWM > 1550) TiltVal = 30; // TILT UP WITH SLOW SPEED
  else if (TiltPWM < 1100) TiltVal = -50; // TILT DOWN WITH FAST SPEED
  else if (TiltPWM < 1300) TiltVal = -40; // TILT DOWN WITH MEDIUM SPEED
  else if (TiltPWM < 1450) TiltVal = -30; // TILT DOWN WITH SLOW SPEED  
  else TiltVal = 0;                      // STOP !!

  ReqPTZ(PanVal, TiltVal);
}

//************************************
// USER = User Login Admin
// PASSWORD = Password Login
// IPADRESS = IP Address of PTZ Camera
//************************************
String PTZurl = "http://USER:PASSWORD@IPADDRESS/ISAPI/PTZCtrl/channels/1/Continuous";
int PrevPan, PrevTilt;
uint32_t SuspendTime;
void ReqPTZ(int Pan, int Tilt) {
  if (Pan == PrevPan and Tilt == PrevTilt) return;
  if (millis() < SuspendTime) return;
  PrevPan = Pan;
  PrevTilt = Tilt;
  String xmlData = "<PTZData><pan>" + String(Pan) + "</pan><tilt>" + String(Tilt) + "</tilt></PTZData>";
  HTTPClient Http;
  Http.begin(PTZurl);
  Http.addHeader("Content-Type", "application/xml");
  Serial.println(xmlData);
  int httpResponseCode = Http.PUT(xmlData);
  String ResponseStr = Http.getString();
  if (httpResponseCode == 200) Serial.print(" OK");
  else {
    Serial.print(" ERROR: " + String(httpResponseCode));
    Serial.println("ResponseStr: " + ResponseStr);
    SuspendTime = millis() + 3000; // IF ERROR THE SYSTEM WILL SUSPEND FOR 3 SECONDS TO AVOID SYSTEM PROBLEMS
  }
  Http.end();
}

void loop() {
  ReadPWM();
}
5 Likes

That is quite cool ! Congrats on the working build.

Normally, we got some ONVIF support, so it may be possible to make something robust !

Would you like to share your code so other can replicate ? (got an old camera that can probably serve for this)

Thank You, and of course i’m already edit my first post :blush:

Very nice work! have a similar camera laying around and wanted to do the same for a long time!

You may set the the focus to manual + min focus distance infinity in the camera settings then it might fit always for each zoom?