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();
}
6 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?

nice work!

thank you i’m appreciate your response :blush:

alright sorry i’m a bit bussy with my works so i can continue this project again

V2 Ardutracker to Tracking an airPlane

what we need
RTL-SDR

Careful of the many fake products. I’ve tried the cheaper ones, and the difference the power maximum only 19dBm and the sensitivity was also very poor.
So be sure to read this link to know which is real and which is fake.

https://www.rtl-sdr.com/genuine

and install dump1090 to decrypt the adsb encryption from here
just follow what they said

after you succeed and loading the dump1090, the port which human can read only at 30003 (you can telnet that port and see it by your self)
so let’s make it more compact

remove previously dump1090 with
make clean

and then replave the net_io.c with the file mod by me (attached)
or you can edit and make some change with it as you needed
and then
make

and load

dump1090 --metric --gain 29.7 --net --quiet

after that if you check again the port 30003 will generate
ICAO_ID|CALLSIGN|LATITUDE|LONGITUDE|ALTITUDE|HEADING|GROUNDSPEED
enough for us to send that data to MAVPROXY as ADSB data

one more script we need to add adsb streaming into mavproxy
load the python script (file attached)

and don’t forget to add this paramater to your running mavproxy

Ps: that’s only the basic how to add adsb data from SDR to MAVPROXY, and that are what i can share with you all, because in real i’m not using this way (mine are a bit complex) so i made simple for you and try to start modifying by your self

and this is the result

sdr.zip (22.0 KB)