Quartapounds SatNOGS Rotator v3.1

GOES Hurricane Dorian Mesoscale GIF I made (with Satnogs rotator pointed at GOES East)

close up of Hurricane Dorian (GOES East Mesoscale)

HRPT tracked with the rotator

7 Likes

i did all the steps from that page, but the rotor dont start move, can help me
i do the test and this is the result
C:\hamlib-w32-3.3\bin>rotctld -m 202 -r COM3 -s 9600 -T 127.0.0.1 -t 4533 -C timeout=500 -C retry=0 -vvvvvvvvvvvvvvv
rotctld, Hamlib 3.3
Report bugs to hamlib-developer@lists.sourceforge.net

rot_init called
initrots3_easycomm called
rot_register (201)
rot_register (202)
rot_register (204)
rot_token_lookup called
rot_confparam_lookup called
rot_set_conf called
rot_confparam_lookup called
rot_set_conf: timeout=‘500’
frontrot_set_conf called
rot_token_lookup called
rot_confparam_lookup called
rot_set_conf called
rot_confparam_lookup called
rot_set_conf: retry=‘0’
frontrot_set_conf called
rot_open called
serial_open called
serial_setup called
Opened rot model 202, ‘EasycommII’
rig_strstatus called
Backend version: 0.4, Status: Beta
Connection opened from techsmith:65459
rotctl(d): p ‘’ ‘’ ‘’ ‘’
rot_get_position called
easycomm_rot_get_position called
easycomm_transaction called: AZ EL

serial_flush called
write_block called
write_block(): TX 7 bytes
0000 41 5a 20 45 4c 20 0a AZ EL .
read_string called
read_string(): RX 18 characters
0000 41 5a 2d 31 38 34 2e 35 20 45 4c 2d 31 38 30 2e AZ-184.5 EL-180.
0010 30 0a 0.
easycomm_transaction read_string: AZ-184.5 EL-180.0

easycomm_rot_get_position got response: AZ-184.5 EL-180.0

rotctl(d): P ‘150,68’ ‘0,92’ ‘’ ‘’
rot_set_position called
easycomm_rot_set_position called: 150.000000 0.000000
easycomm_transaction called: AZ150.0 EL0.0 UP000 XXX DN000 XXX

serial_flush called
write_block called
write_block(): TX 34 bytes
0000 41 5a 31 35 30 2e 30 20 45 4c 30 2e 30 20 55 50 AZ150.0 EL0.0 UP
0010 30 30 30 20 58 58 58 20 44 4e 30 30 30 20 58 58 000 XXX DN000 XX
0020 58 0a X.
rotctl(d): p ‘’ ‘’ ‘’ ‘’
rot_get_position called
easycomm_rot_get_position called
easycomm_transaction called: AZ EL

serial_flush called
write_block called
write_block(): TX 7 bytes
0000 41 5a 20 45 4c 20 0a AZ EL .
read_string called
read_string(): RX 18 characters
0000 41 5a 2d 31 38 34 2e 35 20 45 4c 2d 31 38 30 2e AZ-184.5 EL-180.
0010 30 0a 0.
easycomm_transaction read_string: AZ-184.5 EL-180.0

easycomm_rot_get_position got response: AZ-184.5 EL-180.0

Wanted to provide another update, the rotator has now been outside for the past 6 months straight.

I have not had ANY issues with the rotator, it has been 100% reliable, and I’ve found that my 3D printed PETG enclosure has worked very well…
temperatures here in Southern Ontario Canada have been as low as -20C and as high as 33C… heavy rain, winds, snow and ice have not stopped it from working.

11 Likes

Hello @quartapound, congrats on your work !
I also plan to build a rotator v3.1 and am also looking for a dish. You seem to use the TP-Link ANT2424B antenna, what did you have to modify to have it work on weather satellites ? I’m mostly interested in the 2.2-2.4GHz region but having the possibility to go down to weather satellites would be great, but probably these frequencies are too far apart.
Alternatively there would be ANT2424MD that seems to have a wider range from the specs (2.3-2.7GHz instead of 2.4-2.5GHz) and maybe as it has 2 orthogonal feeds it could be used to produce RHCP using a phasing line and a combiner.

that’s what I did, simply add a spacer to the front reflector. I get Viterbi error rate as low as 36 on GOES16 using XRIT decoder. works great. i got the MMNOX 24 dBi Parabolic Antenna (SHD-D-2400-9)

1 Like

when i start rotctld.bat this open a black window and after its close by it self, i dont know why?

Rotator in action during high winds

4 Likes

Awesome! Thanks for all your hard work and for posting this. This is exactly what I was looking for. I’m using this as a template for my SatNOGS rotator build v3.1 (stepper motor version).

1 Like

Hello
Beautiful video of the HRPT antenna with reception and decoding.
Finally using the Satnogs rotor it is possible to receive the hrpt.
To support the 24 db grid antenna I use the 5:18 gear stepper motor rotor which has a little more strength, but I see that even with the classic stepper motor you can use a counterweight to solve the problem.
I too will have to make a suitable counterweight. I was thinking of an aluminum square tube like you did and basically create some container with the 3d printer in order to put some weight on it.
For the meridian flip problem I currently have no problems because I use the modified satnogs firmware version.
Do you recommend the satcom software as a software or can you decode well even with the linux versions?
What pc do you recommend?

Hello and congratulations
IZ5RZR

1 Like

Heavy Storm, but the rotator works perfectly!

Iz5zr - I don’t have experience decoding with Linux. My understanding is you can’t decode all the HRPT satellites with Linux, and Satcom’s xHRPT is by far the best one out there. Some of the satellites require a fairly powerful PC for live decoding (fengyun and metop if I recall). They’re recommend 4 cores at 3ghz if I remember correctly

6 Likes

Hello, is the stl for the cover available?

I can’t find the Bottom file :frowning: … I waited too long to post this, sorry. I have the top available if you’d like. the bottom was a simple box, slightly smaller than the top, so that it slides into the top

Quartapounds SatNOGS 3.1 Top Cover.stl (469.3 KB)

2 Likes

Hi @remy. Nice pics ! I am finishing my rotator V3.1, I want to use a tripod too. Did you print yourself the red adapter for the tripod? Could you share with me the 3D model? I will appreciate your help.

1 Like

Hello all, I just started to build a 3.1 rotator with arduino CNC shield.
I could not find anywhere about the installation details of the mechanichal endstop swithcs.
Can anyone put a close up photo of where and how to mount to mechanical endstops so I can understand.?

Hi Aseyhan,
Try this link go to Assembly step 8, Bearing side with encoder and end-stop mounts.
There is a drawing that may help.File:A1032-1.png
Also this, Rotator 3.1 End stop switch mounting .
Steve

1 Like

Hello! My club is building a v3.1 rotator and following this guide (SatNOGS Arduino Uno/CNC Shield Based Rotator Controller - SatNOGS Wiki) for using an Arduino CNC Shield as a rotator controller, but we’ve been running into some issues with testing.

After starting the .bat file and opening up the Antenna module in GPredict, we tried to get our stepper motors to turn by changing the Azimuth and Elevation in the GPredict Rotator Control panel. However, the stepper motors didn’t move and we got connection timeout errors in hamlib. We also see a “Read: ERROR” message under Azimuth and Elevation in GPredict. Does anyone know what the problem could be?

image

This is what we’re seeing in hamlib:

C:\Users\anika\Desktop\Red\UA Space\hamlib-w64-3.3\hamlib-w64-3.3\bin>rotctld -m 202 -r COM5 -s 9600 -T 127.0.0.1 -t 4533 -C timeout=500 -C retry=0 -vvvvvvvv 1>pause
rotctld, Hamlib 3.3
Report bugs to hamlib-developer@lists.sourceforge.net

rot_init called
initrots3_easycomm called
rot_register (201)
rot_register (202)
rot_register (204)
rot_token_lookup called
rot_confparam_lookup called
rot_set_conf called
rot_confparam_lookup called
rot_set_conf: timeout=‘500’
frontrot_set_conf called
rot_token_lookup called
rot_confparam_lookup called
rot_set_conf called
rot_confparam_lookup called
rot_set_conf: retry=‘0’
frontrot_set_conf called
rot_open called
serial_open called
serial_setup called
rig_strstatus called
Backend version: 0.4, Status: Beta
Connection opened from LAPTOP-LS4D11VE:59701
rotctl(d): p ‘’ ‘’ ‘’ ‘’
rot_get_position called
easycomm_rot_get_position called
easycomm_transaction called: AZ EL

serial_flush called
write_block called
write_block(): TX 7 bytes
0000 41 5a 20 45 4c 20 0a AZ EL .
read_string called
read_string(): Timed out 0.908258 seconds after 0 chars
easycomm_transaction read_string failed with status -5
easycomm_rot_get_position got error: -5
rotctl(d): P ‘180.00’ ‘45.00’ ‘’ ‘’
rot_set_position called
easycomm_rot_set_position called: 180.000000 45.000000
easycomm_transaction called: AZ180.0 EL45.0 UP000 XXX DN000 XXX

serial_flush called
write_block called
write_block(): TX 35 bytes
0000 41 5a 31 38 30 2e 30 20 45 4c 34 35 2e 30 20 55 AZ180.0 EL45.0 U
0010 50 30 30 30 20 58 58 58 20 44 4e 30 30 30 20 58 P000 XXX DN000 X
0020 58 58 0a XX.
rotctl(d): p ‘’ ‘’ ‘’ ‘’
rot_get_position called
easycomm_rot_get_position called
easycomm_transaction called: AZ EL

serial_flush called
write_block called
write_block(): TX 7 bytes
0000 41 5a 20 45 4c 20 0a AZ EL .
read_string called
read_string(): Timed out 0.916899 seconds after 0 chars
easycomm_transaction read_string failed with status -5
easycomm_rot_get_position got error: -5
rotctl(d): p ‘’ ‘’ ‘’ ‘’
rot_get_position called
easycomm_rot_get_position called
easycomm_transaction called: AZ EL

serial_flush called
write_block called
write_block(): TX 7 bytes
0000 41 5a 20 45 4c 20 0a AZ EL .
read_string called
read_string(): Timed out 0.912913 seconds after 0 chars
easycomm_transaction read_string failed with status -5
easycomm_rot_get_position got error: -5
rotctl(d): S ‘’ ‘’ ‘’ ‘’
rot_stop called
easycomm_rot_stop called
easycomm_transaction called: SA SE

serial_flush called
write_block called
write_block(): TX 7 bytes
0000 53 41 20 53 45 20 0a SA SE .
read_string called
read_string(): Timed out 0.910071 seconds after 0 chars
easycomm_transaction read_string failed with status -5
rotctl(d): p ‘’ ‘’ ‘’ ‘’
rot_get_position called
easycomm_rot_get_position called
easycomm_transaction called: AZ EL

serial_flush called
write_block called
write_block(): TX 7 bytes
0000 41 5a 20 45 4c 20 0a AZ EL .
read_string called
read_string(): Timed out 0.914573 seconds after 0 chars
easycomm_transaction read_string failed with status -5
easycomm_rot_get_position got error: -5
Connection closed

Hi. I recently finished same project without a problem. I think your problem Can be because of a few things. First things came to my mind are:

-Are you sure the com port is right?

-how are you connecting to arduino: via usb of arduino or via rx tx gnd pins on cnc shield? If it is the second one you need to be sure you dont use rs 232 but TTL. A ftdi chipset usb-ttl converter works good for that. And also checking the pins can be good. Some cnc shield clones/versions have different pin layout then the one in the project. Like mine had x endstop on Y labeled end stop pins and Y endstop on Z pins.

Br.

Hello @quartapound! I don’t know if you still monitor this thread. I stumbled across this about a year ago and have been playing with your code for a bit. I am not a developer at all. I have this running with PstRotator software using EasyComm protocol. It’s working flawlessly.

I know that this isn’t an issue but more a feature request / request for coding help.

I’d like to add an LCD screen as well that shows current El and Az positioning, even while moving the antenna. How would I do that? I have my LCD up and running but not sure how to pull the string / var or whatever it is to lcd.print(???) whatever is needed? I am also showing some special characters (compass directions) so the code needs to show its “place”.

How would I go about doing this? Many thanks for your help!

WA7ZYW

I answered my own question. Using ChatGPT no less. :slight_smile: I’d like to share this code. I know it still needs a lot of work. :slight_smile: I took out the homing items as for now, this is more of a pointer project. Will attach an antenna soon. The LCD I am using is the SunFounder IIC I2C TWI Serial 2004 20x4 LCD Module.

Maincode.INO

#define SAMPLE_TIME 0.1 ///< Control loop in s
#define RATIO 1 ///< Gear ratio of rotator gear box default 54
#define MICROSTEP 8 ///< Set Microstep
//#define MIN_PULSE_WIDTH 20 ///< In microsecond for AccelStepper
#define MIN_PULSE_WIDTH 0.5 ///< ChatGPT told me so…
#define MAX_SPEED 3200 ///< In steps/s, consider the microstep
#define MAX_ACCELERATION 3200 ///< In steps/s^2, consider the microstep
#define SPR 1600L ///< Step Per Revolution, consider the microstep
#define MIN_M1_ANGLE 0 ///< Minimum angle of azimuth
#define MAX_M1_ANGLE 360 ///< Maximum angle of azimuth
#define MIN_M2_ANGLE 0 ///< Minimum angle of elevation
#define MAX_M2_ANGLE 90 ///< Maximum angle of elevation
//#define DEFAULT_HOME_STATE LOW ///< Change to LOW according to Home sensor
//#define HOME_DELAY 12000 ///< Time for homing Deceleration in millisecond

#include <AccelStepper.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <globals.h>
#include <easycomm.h>
#include <rotator_pins.h>

uint32_t t_run = 0;
easycomm comm;
AccelStepper stepper_az(1, M1IN1, M1IN2);
AccelStepper stepper_el(1, M2IN1, M2IN2);
enum _rotator_error homing(int32_t seek_az, int32_t seek_el);
int32_t deg2step(float deg);
float step2deg(int32_t step);
LiquidCrystal_I2C lcd(0x27, 20, 4); // Address, # Chars, # Rows - Wiring: SDA to A4 and SCL to A5 via I2C, address 0x27
byte north [8] = {0x04, 0x0E, 0x1F, 0x04, 0x04, 0x04, 0x04, 0x00}; // build LCD specific characters ‘North or Up’
byte ne [8] = {0x0, 0xf, 0x3, 0x5, 0x9, 0x10, 0x0}; // build LCD specific characters ‘Northeast’
byte east [8] = {0x00, 0x04, 0x02, 0x1F, 0x02, 0x04, 0x00, 0x00}; // build LCD specific characters ‘East or Right’
byte se [8] = {0x00, 0x00, 0x10, 0x09, 0x05, 0x03, 0x0F, 0x00}; // build LCD specific characters ‘Southeast’
byte south [8] = {0x00, 0x04, 0x04, 0x04, 0x04, 0x1F, 0x0E, 0x04}; // build LCD specific characters ‘South or Ddown’
byte sw [8] = {0x00, 0x00, 0x01, 0x12, 0x14, 0x18, 0x1E, 0x00}; // build LCD specific characters ‘Southwest’
byte west [8] = {0x00, 0x04, 0x08, 0x1F, 0x08, 0x04, 0x00, 0x00}; // build LCD specific characters ‘West or Left’
byte nw [8] = {0x00, 0x1E, 0x18, 0x14, 0x12, 0x01, 0x00, 0x00}; // build LCD specific characters ‘Northwest’

void setup() {
comm.easycomm_init();
stepper_az.setEnablePin(MOTOR_EN);
stepper_az.setPinsInverted(false, false, true);
stepper_az.enableOutputs();
stepper_az.setMaxSpeed(MAX_SPEED);
stepper_az.setAcceleration(MAX_ACCELERATION);
stepper_az.setMinPulseWidth(MIN_PULSE_WIDTH);
stepper_el.setPinsInverted(false, false, true);
stepper_el.enableOutputs();
stepper_el.setMaxSpeed(MAX_SPEED);
stepper_el.setAcceleration(MAX_ACCELERATION);
stepper_el.setMinPulseWidth(MIN_PULSE_WIDTH);
setuplcd();
}

void loop() {
comm.easycomm_proc();

// Control Loop
int32_t deg_az = deg2step(control_az.setpoint);
int32_t deg_el = deg2step(control_el.setpoint);

if (stepper_az.currentPosition() != deg_az || stepper_el.currentPosition() != deg_el) {
//printCurrentAzimuth();
//printCurrentElevation();
} else if (stepper_az.currentPosition() == deg_az && stepper_el.currentPosition() == deg_el) {
printCurrentAzimuth();
printCurrentElevation();
}

stepper_az.moveTo(deg_az);
stepper_el.moveTo(deg_el);

control_az.input = step2deg(stepper_az.currentPosition());
control_el.input = step2deg(stepper_el.currentPosition());

rotator.rotator_status = pointing;

// Move azimuth and elevation motors
stepper_az.run();
stepper_el.run();

// Idle rotator
if (stepper_az.distanceToGo() == 0 && stepper_el.distanceToGo() == 0) {
rotator.rotator_status = idle;
}
}

int32_t deg2step(float deg) {
return (RATIO * SPR * deg / 360);
}

float step2deg(int32_t step) {
return (360.00 * step / (SPR * RATIO));
}

LCD setup code

void setuplcd() {
lcd.init();
lcd.backlight();
lcd.createChar(0, north);
lcd.createChar(1, ne);
lcd.createChar(2, east);
lcd.createChar(3, se);
lcd.createChar(4, south);
lcd.createChar(5, sw);
lcd.createChar(6, west);
lcd.createChar(7, nw);
bootlcd();
}

void bootlcd() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(“SatTracker by WA7ZYW”);
lcd.setCursor(1,1);
lcd.print(“Powered by SatNogs”);
lcd.setCursor(9,2);
lcd.print(“-”);
lcd.setCursor(3,3);
lcd.print(“Happy Tracking”);
delay (10000);
staticlcd();
}

void staticlcd() {
lcd.clear();
lcd.setCursor(1,0); lcd.print(“Selected Satellite”);
lcd.setCursor(2,1); lcd.print(“Is Now Tracking:”);
lcd.setCursor(2,2); lcd.print("Az = ");
lcd.setCursor(2,3); lcd.print("Ez = ");
}

LCD Logic

void printCurrentAzimuth() {
lcd.setCursor(7, 2); lcd.print(" "); // cls
lcd.setCursor(7, 2); lcd.print(control_az.input, 1); // Displays current Az on LCD and updates while other text stays static
lcd.setCursor(12, 2); lcd.print((char)223); // Print Special Character for Degree

int dirNumber = 0;
if (control_az.input > 345) {
dirNumber = 0;
} else if (control_az.input <= 345 && control_az.input > 285) {
dirNumber = 7;
} else if (control_az.input <= 285 && control_az.input > 235) {
dirNumber = 6;
} else if (control_az.input <= 235 && control_az.input > 195) {
dirNumber = 5;
} else if (control_az.input <= 195 && control_az.input > 165) {
dirNumber = 4;
} else if (control_az.input <= 165 && control_az.input > 115) {
dirNumber = 3;
} else if (control_az.input <= 115 && control_az.input > 75) {
dirNumber = 2;
} else if (control_az.input <= 75 && control_az.input > 15) {
dirNumber = 1;
} else {
dirNumber = 0;
}

// Write the direction
String directions = {" N", " NE", " E", " SE", " S", " SW", " W", " NW"};
lcd.setCursor(14, 2); lcd.print(" "); // cls
lcd.setCursor(14, 2); lcd.write(dirNumber); lcd.print(directions[dirNumber]);
}

void printCurrentElevation() {
lcd.setCursor(7, 3); lcd.print(" "); // cls
lcd.setCursor(7, 3); lcd.print(control_el.input, 1); // Displays current El on LCD and updates while other text stays static
lcd.setCursor(11, 3); lcd.print((char)223); // Print Special Character for Degree

if (control_el.input <= 0 && control_el.input < 180) {
lcd.setCursor(14, 3); lcd.print(" “); // Clears the Buffer
lcd.setCursor(14, 3); lcd.write(4); lcd.print(” BH");
} else if (control_el.input >= 0 && control_el.input < 30) {
lcd.setCursor(14, 3); lcd.print(" “); // Clears the Buffer
lcd.setCursor(14, 3); lcd.write(6); lcd.print(” Hz");
} else if (control_el.input >= 30 && control_el.input < 80) {
lcd.setCursor(14, 3); lcd.print(" “); // Clears the Buffer
lcd.setCursor(14, 3); lcd.write(7); lcd.print(” AH");
} else if (control_el.input >= 80 && control_el.input < 100) {
lcd.setCursor(14, 3); lcd.print(" “); // Clears the Buffer
lcd.setCursor(14, 3); lcd.write(0); lcd.print(” OH");
} else if (control_el.input >= 100 && control_el.input < 150) {
lcd.setCursor(14, 3); lcd.print(" “); // Clears the Buffer
lcd.setCursor(14, 3); lcd.write(1); lcd.print(” AH");
} else if (control_el.input >= 150 && control_el.input <= 180) {
lcd.setCursor(14, 3); lcd.print(" “); // Clears the Buffer
lcd.setCursor(14, 3); lcd.write(2); lcd.print(” Hz");
}
}

very interesting, I don’t know how to program but I would like to have a display that indicates me in the radio shack.
I hope further evolution and how to connect it.
LW2DYB

1 Like