In the last post about my Portable Rotator for satellite use we got the basics working, we had a system where can send a command to set the Azimuth and Elevation by sending the following command:
SET 180 57
By sending those commands we can move the rotator to an Azimuth of 180 and Elevation of 57. This works great, but we don’t want to be sending these commands manually. Ideally we want to link it to satellite prediction software. In this example we will use the well known Gpredict which is an opensource real-time satellite tracking and orbit prediction application. It runs on Windows and Linux.

Normally Gpredict connects to a Hamlib instance which is setup for your controller. Hamlib is a Ham Radio Control Library. It aims to use a consistent api to control either radios or rotators or both. Hamlib supports various commercial rotators, but since our rotator is custom made and Node-Red controlled we can’t use it (atleast not without some extra coding). Instead we will be emulating a Hamlib server right in our Node-Red that will accept the commands and return the current Az/El Status back to our prediction software. This means that any satellite prediction software that supports Hamlib will be able to control our rotator. Our flow in Node-Red will look something like this:

The protocol between Gpredict and Hamlib is fairly simple as documented here. For our use we only need to cater for the following commands:
p – Request current Azimuth/Elevation. When Hamlib normally receives this command it will respond with the Az and El values.
P – Set current Azimuth/Elevation. When Hamlib normally receives this command it expects the Azimuth and Elevation values to be sent along and will then relay that to the rotator.
These commands get sent over a TCP socket connection. We can easily implement this in Node-Red using the TCP IN and TCP OUT Nodes. Our TCP IN node will listen on the default hamlib port which is 4533. After dropping a TCP IN Node on our flow we need to configure it as follow:

All this means is that our Node-Red will be listening for any data sent to port 4533 and then outputs the data received as a stream of String payloads to our next Node. We also need to be able to send data back to Gpredict so we also add and configure a TCP Out node as follow:

Whatever we send to this Node will automatically be send back on the same incoming connection. We will use this acknowledge commands received and to send the current Az/El status to Gpredict.
Our next Node is a function node where we can add some custom code. The custom code is where we implement our handling of the above protocol. We will configure our function Node with the 2 outputs. The input of our function node is the TCP in node and the first output of the function Node is what we want to send back to Gpredict. Your flow will look something like this:

We add the following code into the hamlib_emu function:
if (msg.payload.startsWith("p")) {
var az = flow.get("az")
var el = flow.get("el")
msg.payload = az + "\n" + el + "\n";
return [msg, null];
}
if (msg.payload.startsWith("P")) {
var data = msg.payload.split(" ");
var newValues = {
payload: { 'az': Math.round(data[1]), 'el': Math.round(data[2]) } }
msg.payload = "RPRT 0\n";
return [msg, newValues];
}
msg.payload = "RPRT 0\n";
return [msg, null];
The code is fairly simple, the first if statement checks whether our received command starts with a lowercase p. This means that gpredict wants to request the current Az/El values. From our previous base project we are already storing the current Az/El values in the az and el global variables. So we can get them from there and return it.
The second if statement looks for the command that starts with uppercase P. This command requests a new position for the rotator. In our function we split out the Azimuth and Elevation and create a new message that goes to our 2nd function output. We also acknowledge this message by return “RPRT 0\n” back to Gpredict.
Lets add a debug node so that we can test our diy hamlib:

On Gpredict we need to configure our Node-Red controlled rotator. You can find the setting under Edit -> Preferences -> Interfaces -> Rotators:

Select Add New to add a new rotator control and configure it will the following settings. Remember to replace the ip address with the address of your raspberry pi running Node-Red:

We should now be able to open up the Antenna Control:

Select your newly added rotator device and click on Engage.

If all went well then you should see the following. On your flow your TCP IN node should show 1 connection and the debug window will start showing the Az/El values coming from Gpredict.

You now have a fully working setup where our satellite prediction software (Gpredict) is sending Az/El commands to our Node-Red controlled Rotator. If you chance the az/el values in Gpredict then the debug should update with the new values. And if you start tracking a satellite then it will automatically update the az/el values and send it through.
Our last step is to connect this to our existing rotator flow control. This will vary based on how you configured your rotator, but if you followed along and your flow is same as mine, then all you need to do is add a function that takes the received Az/El values and convert them into a SET command for our arduino:

The code for this function simply takes the 2nd output of the hamlib_emu function block and converts it into a serial command for our arduino. Here is the code:
msg.payload = 'SET ' + msg.payload.az + " " + msg.payload.el;
return msg;
If all went according to plan you should now be able to control the rotator directly from Gpredict and also track satellites 🙂
Instead of building this addition to your flow you can also import it using the following snippet:
[{"id":"6542816c73b47af2","type":"tcp in","z":"42f128ee4e0cd227","name":"","server":"server","host":"","port":"4533","datamode":"stream","datatype":"utf8","newline":"","topic":"tcppacket","trim":false,"base64":false,"tls":"","x":160,"y":520,"wires":[["94f0b44a435b0240"]]},{"id":"94f0b44a435b0240","type":"function","z":"42f128ee4e0cd227","name":"hamlib_emu","func":"if (msg.payload.startsWith(\"p\")) {\n var az = flow.get(\"az\")\n var el = flow.get(\"el\")\n msg.payload = az + \"\\n\" + el + \"\\n\";\n return [msg, null];\n}\n\nif (msg.payload.startsWith(\"P\")) {\n var data = msg.payload.split(\" \");\n\n var newValues = {\n payload: { 'az': Math.round(data[1]), 'el': Math.round(data[2]) } }\n\n msg.payload = \"RPRT 0\\n\";\n return [msg, newValues];\n}\n\nif (msg.payload.startsWith(\"S\")) {\n msg.payload = \"RPRT 0\\n\";\n return [msg, null];\n}\n\n\nmsg.payload = \"RPRT 0\\n\";\nreturn [msg, null];\n\n","outputs":2,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":520,"wires":[["4cb06bd8dfa08263"],["a0d3b1f6cb0867a2"]]},{"id":"4cb06bd8dfa08263","type":"tcp out","z":"42f128ee4e0cd227","name":"","host":"","port":"","beserver":"reply","base64":false,"end":false,"tls":"","x":510,"y":480,"wires":[]},{"id":"a0d3b1f6cb0867a2","type":"function","z":"42f128ee4e0cd227","name":"Set AZ/EL","func":"msg.payload = 'SET ' + msg.payload.az + \" \" + msg.payload.el;\nreturn msg;\n\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":520,"y":560,"wires":[["600ad39ff69fcc3e"]]}]
The full rotator project can be found here.
Have fun and let me know if you have questions or comments 🙂
73, ZR6TG
Thank you for all your work you do for DATV & BATC.
Tom, Has you now i have problems in working thing out.
I ham still waiting for local help to help reline both my Rx & Tx dishes.
thinking of getting a motor to Aline the dish up
Hello Tom – You have done a lot of excellent work there with satellite tracking hardware and software. I am in the process of collecting all the bits and pieces here to build a L Band satellite tracking dish, and have lots of questions. I recently obtained a pretty nice camera pan/tilt unit made by Pelco that I want to use for my motorized dish drive. This Pelco does have the Az/El feedback pots in it, and from what I saw in your Arduino sketch for motor control – it should work just fine with my Pelco. Can you send me your email address please so I can contact you directly with my questions? Thanks, and I look forward to talking with you! 73 -Mark- KE0PMT
I have sent you an email 🙂