Newbie interested in building a Satnogs Rotator -- with wayy too many questions :)

l’m a newbie interested in building a V3 Satnogs Rotator.
after poking around online for awhile I found this project and I’m glad I did, what you guys are doing here is awesome!

I’ve been reading for quite awhile and I think I’m starting to get a grasp on things but I’ve got almost as many questions as when I started, they are just different questions now.
I’m finding the information to be quite fragmented.

All I really want to accomplish is controlling the AZ/EL via Orbitron or Gpredict. I’d like to use the latest V3.1 design using NEMA 17 stepper motors, an arduino uno, and TB6600 drivers. (I’ll add a Pi if I have to?)

  1. there are measurement discrepancies between the BOM and the build https://ohai.satnogs.org/project/satnogs-rotator-v3-mechanical-assembly/hardware/
    one states the 2020 measurements as 160mm and 102mm the BOM included in 3.1 states 140mm and 100mm…
    which is the ideal cut length?

  2. the ohai build log references a Homing Ring (which as far as I can tell is a necessary part for both DC and stepper, but can’t find many other references to it. the BOM shows mechanical endstop switches(which I have laying around) but I don’t see them installed in the ohai build?

  3. Do I understand this right, I still need Satnogs running on a Pi to send commands to the arduino (from the PC) and allow tracking via Gpredict with TLE’s? I can’t get a connection directly between the arduino and PC currently using satnogs rotator firmware? I managed to compile the firmware and get it successfully flashed to my Uno, but the serial window does nothing… looking at the sketch it seems to use easycomm, which is pointed to the Pi, and not the serial port?

  4. Is there a walkthough for the electronics? (similar to that of the V3 hardware guide on ohai?)

…building the controller from scratch with a custom PCB, etc, really adds to the complexity level of a project which I think I’m already barely within the limits of my ability… and takes a lot more time than if I just used an arduino I already have laying around. there are cheap nema 17 motors with TB6600 drivers on amazon that seem like they’d really lower the complexity level of getting a functional system working in less time?

I ordered 2 of these. If they don’t workout I’ll use the 4988’s spec’d for satnogs I guess.

I can’t wait to get my station setup and start contributing! :slight_smile:

1 Like

okay I’ve gotten a bit further I think? … maybe you can send commands direclty from PC to arduino? I feel kinda lost but like I’m making progress. Need to wait for my stepper motors and drivers to show up tomorrow I think… I may add some serial outputs to the arduino code so that I can monitor it and debug though.

I 've installed hamlib and I run * cmd /k “rotctld -m 202 -r COM3 -s 9600 -T 127.0.0.1 -t 4533 -C timeout=500 -C retry=0 -vvvvvvvv”

… I can see the RX light blinking on the arduino when I click ‘engage’ in Gpredict…?
I see this in the CMD window

C:\Program Files (x86)\hamlib-w64-3.2\bin>rotctld -m 202 -r COM3 -s 9600 -T 127.0.0.1 -t 4533 -C timeout=500 -C retry=0 -vvvvvvvv
rotctld, Hamlib 3.2
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 lmlicenses:38503
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.649267 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

then it repeats at the moment. nothing is hooked upto the arduino right now though

Okay gotten a bit further. the newest version of Gpredict seems to have helped 2.3.37. I was using 2.2.1 and I wasn’t getting any data from Gpredict into rotctld.

C:\Program Files (x86)\hamlib-w64-3.2\bin>rotctld -m 202 -r COM3 -s 9600 -T 127.0.0.1 -t 4533 -C timeout=500 -C retry=0 -vvvvvvvv
rotctld, Hamlib 3.2
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 lmlicenses:24149
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.649267 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.649265 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

Well…I GOT IT WORKING!! I don’t even have any servo’s here yet, but I’ve managed to setup the arduino to talk directly to the PC and bypass the Pi completely… I can connect the Arduino directly to my PC and control it via Gpredict. it accurately displays the Read: number gradually changing as I switch between satellites. Getting excited.
output from rotctl

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 14 characters
0000    41 5a 31 35 34 2e 33 20 45 4c 30 2e 30 0a           AZ154.3 EL0.0.
easycomm_transaction read_string: AZ154.3 EL0.0

easycomm_rot_get_position got response: AZ154.3 EL0.0

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 14 characters
0000    41 5a 31 35 34 2e 33 20 45 4c 30 2e 30 0a           AZ154.3 EL0.0.
easycomm_transaction read_string: AZ154.3 EL0.0

easycomm_rot_get_position got response: AZ154.3 EL0.0

I did this by Editing the easycomm.h file. I basically removed every call to the RS485 library (which allows communications between the Pi and the Arduino directly) and replaced each ‘rs485’ with ‘Serial’ instead… I need to wait to see if I can get it to move the servos tomorrow… Need to start ordering the rest of the parts and find a place to get things 3d printed next!

here’s the edited easycomm.h file so that you can use the arduino sketch directly with gpredict and a PC.
I haven’t tested this with hardware yet. but it compiles and seems to communicate properly.

/*!
* @file easycomm.h
*
* It is a driver for easycomm 3 protocol as referred, in Hamlib.
*
* Licensed under the GPLv3
*
*/

#ifndef LIBRARIES_EASYCOMM_H_
#define LIBRARIES_EASYCOMM_H_

#include <Arduino.h>
#include <WString.h>
#include <avr/wdt.h>
//#include "rs485.h"
#include "rotator_pins.h"
#include "globals.h"

#define RS485_TX_TIME 9     ///< Delay "t"ms to write in serial for RS485 implementation
#define BUFFER_SIZE   256   ///< Set the size of serial buffer
#define BAUDRATE      19200 ///< Set the Baudrate of easycomm 3 protocol

//rs485 rs485(RS485_DIR, RS485_TX_TIME);

/**************************************************************************/
/*!
    @brief    Class that functions for easycomm 3 implementation
*/
/**************************************************************************/
class easycomm {
public:

    /**************************************************************************/
    /*!
        @brief    Initialize the RS485 bus
    */
    /**************************************************************************/
    void easycomm_init() {
       // rs485.begin(BAUDRATE);
	    Serial.begin(9600);
    }

    /**************************************************************************/
    /*!
        @brief    Get the commands from RS485 and response to the client
    */
    /**************************************************************************/
    void easycomm_proc() {
        char buffer[BUFFER_SIZE];
        char incomingByte;
        char *Data = buffer;
        char *rawData;
        static uint16_t BufferCnt = 0;
        char data[100];
        String str1, str2, str3, str4, str5, str6;

        // Read from serial
        while (Serial.available() > 0) {
            incomingByte = Serial.read();

            // Read new data, '\n' means new pacakage
            if (incomingByte == '\n' || incomingByte == '\r') {
                buffer[BufferCnt] = 0;
                if (buffer[0] == 'A' && buffer[1] == 'Z') {
                    if (buffer[2] == ' ' && buffer[3] == 'E' &&
                        buffer[4] == 'L') {
                        // Send current absolute position in deg
                        str1 = String("AZ");
                        str2 = String(control_az.input, 1);
                        str3 = String(" EL");
                        str4 = String(control_el.input, 1);
                        str5 = String("\n");
                        Serial.print(str1 + str2 + str3 + str4 + str5);
                    } else {
                        // Get the absolute position in deg for azimuth
                        rotator.control_mode = position;
                        rawData = strtok_r(Data, " ", &Data);
                        strncpy(data, rawData + 2, 10);
                        if (isNumber(data)) {
                            control_az.setpoint = atof(data);
                        }
                        // Get the absolute position in deg for elevation
                        rawData = strtok_r(Data, " ", &Data);
                        if (rawData[0] == 'E' && rawData[1] == 'L') {
                            strncpy(data, rawData + 2, 10);
                            if (isNumber(data)) {
                                control_el.setpoint = atof(data);
                            }
                        }
                    }
                } else if (buffer[0] == 'E' && buffer[1] == 'L') {
                        // Get the absolute position in deg for elevation
                        rotator.control_mode = position;
                        rawData = strtok_r(Data, " ", &Data);
                        if (rawData[0] == 'E' && rawData[1] == 'L') {
                            strncpy(data, rawData + 2, 10);
                            if (isNumber(data)) {
                                control_el.setpoint = atof(data);
                            }
                        }
                } else if (buffer[0] == 'V' && buffer[1] == 'U') {
                    // Elevation increase speed in mdeg/s
                    rotator.control_mode = speed;
                    strncpy(data, Data + 2, 10);
                    if (isNumber(data)) {
                        // Convert to deg/s
                        control_el.setpoint_speed = atof(data) / 1000;
                    }
                } else if (buffer[0] == 'V' && buffer[1] == 'D') {
                    // Elevation decrease speed in mdeg/s
                    rotator.control_mode = speed;
                    strncpy(data, Data + 2, 10);
                    if (isNumber(data)) {
                        // Convert to deg/s
                        control_el.setpoint_speed = - atof(data) / 1000;
                    }
                } else if (buffer[0] == 'V' && buffer[1] == 'L') {
                    // Azimuth increase speed in mdeg/s
                    rotator.control_mode = speed;
                    strncpy(data, Data + 2, 10);
                    if (isNumber(data)) {
                        // Convert to deg/s
                        control_az.setpoint_speed = atof(data) / 1000;
                    }
                } else if (buffer[0] == 'V' && buffer[1] == 'R') {
                    // Azimuth decrease speed in mdeg/s
                    rotator.control_mode = speed;
                    strncpy(data, Data + 2, 10);
                    if (isNumber(data)) {
                        // Convert to deg/s
                        control_az.setpoint_speed = - atof(data) / 1000;
                    }
                } else if (buffer[0] == 'S' && buffer[1] == 'A' &&
                           buffer[2] == ' ' && buffer[3] == 'S' &&
                           buffer[4] == 'E') {
                    // Stop Moving
                    rotator.control_mode = position;
                    str1 = String("AZ");
                    str2 = String(control_az.input, 1);
                    str3 = String(" EL");
                    str4 = String(control_el.input, 1);
                    str5 = String("\n");
                    Serial.print(str1 + str2 + str3 + str4 + str5);
                    control_az.setpoint = control_az.input;
                    control_el.setpoint = control_el.input;
                } else if (buffer[0] == 'R' && buffer[1] == 'E' &&
                           buffer[2] == 'S' && buffer[3] == 'E' &&
                           buffer[4] == 'T') {
                    // Reset the rotator, go to home position
                    str1 = String("AZ");
                    str2 = String(control_az.input, 1);
                    str3 = String(" EL");
                    str4 = String(control_el.input, 1);
                    str5 = String("\n");
                    Serial.print(str1 + str2 + str3 + str4 + str5);
                    rotator.homing_flag = false;
                } else if (buffer[0] == 'P' && buffer[1] == 'A' &&
                           buffer[2] == 'R' && buffer[3] == 'K' ) {
                    // Park the rotator
                    rotator.control_mode = position;
                    str1 = String("AZ");
                    str2 = String(control_az.input, 1);
                    str3 = String(" EL");
                    str4 = String(control_el.input, 1);
                    str5 = String("\n");
                    Serial.print(str1 + str2 + str3 + str4 + str5);
                    control_az.setpoint = rotator.park_az;
                    control_el.setpoint = rotator.park_el;
                } else if (buffer[0] == 'V' && buffer[1] == 'E') {
                    // Get the version if rotator controller
                    str1 = String("VE");
                    str2 = String("SatNOGS-v2.2");
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '0') {
                    // Get the inside temperature
                    str1 = String("IP0,");
                    str2 = String(rotator.inside_temperature, DEC);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '1') {
                    // Get the status of end-stop, azimuth
                    str1 = String("IP1,");
                    str2 = String(rotator.switch_az, DEC);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '2') {
                    // Get the status of end-stop, elevation
                    str1 = String("IP2,");
                    str2 = String(rotator.switch_el, DEC);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '3') {
                    // Get the current position of azimuth in deg
                    str1 = String("IP3,");
                    str2 = String(control_az.input, 2);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '4') {
                    // Get the current position of elevation in deg
                    str1 = String("IP4,");
                    str2 = String(control_el.input, 2);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '5') {
                    // Get the load of azimuth, in range of 0-1023
                    str1 = String("IP5,");
                    str2 = String(control_az.load, DEC);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '6') {
                    // Get the load of elevation, in range of 0-1023
                    str1 = String("IP6,");
                    str2 = String(control_el.load, DEC);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '7') {
                    // Get the speed of azimuth in deg/s
                    str1 = String("IP7,");
                    str2 = String(control_az.speed, 2);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'I' && buffer[1] == 'P' &&
                           buffer[2] == '8') {
                    // Get the speed of elevation in deg/s
                    str1 = String("IP8,");
                    str2 = String(control_el.speed, 2);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'G' && buffer[1] == 'S') {
                    // Get the status of rotator
                    str1 = String("GS");
                    str2 = String(rotator.rotator_status, DEC);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if (buffer[0] == 'G' && buffer[1] == 'E') {
                    // Get the error of rotator
                    str1 = String("GE");
                    str2 = String(rotator.rotator_error, DEC);
                    str3 = String("\n");
                    Serial.print(str1 + str2 + str3);
                } else if(buffer[0] == 'C' && buffer[1] == 'R') {
                    // Get Configuration of rotator
                    if (buffer[3] == '1') {
                        // Get Kp Azimuth gain
                        str1 = String("1,");
                        str2 = String(control_az.p, 2);
                        str3 = String("\n");
                        Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '2') {
                        // Get Ki Azimuth gain
                        str1 = String("2,");
                         str2 = String(control_az.i, 2);
                         str3 = String("\n");
                         Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '3') {
                        // Get Kd Azimuth gain
                        str1 = String("3,");
                        str2 = String(control_az.d, 2);
                        str3 = String("\n");
                        Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '4') {
                        // Get Kp Elevation gain
                        str1 = String("4,");
                         str2 = String(control_el.p, 2);
                         str3 = String("\n");
                         Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '5') {
                        // Get Ki Elevation gain
                        str1 = String("5,");
                        str2 = String(control_el.i, 2);
                        str3 = String("\n");
                        Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '6') {
                        // Get Kd Elevation gain
                        str1 = String("6,");
                        str2 = String(control_el.d, 2);
                        str3 = String("\n");
                        Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '7') {
                        // Get Azimuth park position
                        str1 = String("7,");
                        str2 = String(rotator.park_az, 2);
                        str3 = String("\n");
                        Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '8') {
                        // Get Elevation park position
                        str1 = String("8,");
                        str2 = String(rotator.park_el, 2);
                        str3 = String("\n");
                        Serial.print(str1 + str2 + str3);
                    } else if (buffer[3] == '9') {
                        // Get control mode
                        str1 = String("9,");
                        str2 = String(rotator.control_mode);
                        str3 = String("\n");
                        Serial.print(str1 + str2 + str3);
                    }
                } else if (buffer[0] == 'C' && buffer[1] == 'W') {
                    // Set Config
                    if (buffer[2] == '1') {
                        // Set Kp Azimuth gain
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            control_az.p = atof(data);
                        }
                    } else if (buffer[2] == '2') {
                        // Set Ki Azimuth gain
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            control_az.i = atof(data);
                        }
                    } else if (buffer[2] == '3') {
                        // Set Kd Azimuth gain
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            control_az.d = atof(data);
                        }
                    } else if (buffer[2] == '4') {
                        // Set Kp Elevation gain
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            control_el.p = atof(data);
                        }
                    } else if (buffer[2] == '5') {
                        // Set Ki Elevation gain
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            control_el.i = atof(data);
                        }
                    } else if (buffer[2] == '6') {
                        // Set Kd Elevation gain
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            control_el.d = atof(data);
                        }
                    }  else if (buffer[2] == '7') {
                        // Set the Azimuth park position
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            rotator.park_az = atof(data);
                        }
                    } else if (buffer[2] == '8') {
                        // Set the Elevation park position
                        rawData = strtok_r(Data, ",", &Data);
                        strncpy(data, rawData + 4, 10);
                        if (isNumber(data)) {
                            rotator.park_el = atof(data);
                        }
                    }
                } else if (buffer[0] == 'R' && buffer[1] == 'S'
                        && buffer[2] == 'T') {
                    // Custom command to test the watchdog timer routine
                    while(1)
                        ;
                } else if (buffer[0] == 'R' && buffer[1] == 'B') {
                    // Custom command to reboot the uC
                    wdt_enable(WDTO_2S);
                    while(1);
                }
                // Reset the buffer an clean the serial buffer
                BufferCnt = 0;
                Serial.flush();
            } else {
                // Fill the buffer with incoming data
                buffer[BufferCnt] = incomingByte;
                BufferCnt++;
            }
        }
    }

private:
    bool isNumber(char *input) {
        for (uint16_t i = 0; input[i] != '\0'; i++) {
            if (isalpha(input[i]))
                return false;
        }
        return true;
    }
};

#endif /* LIBRARIES_EASYCOMM_H_ */
1 Like

Take a look in wiki and here (rotator controller) about
cables and how the controller is mounted in the rotator.

The rs485.h is using the Serial library so i can not understand why doesn’t work.

:beers:

This thread looks like your personal blog! :smile: I look forward to the further development of your project!

https://community.libre.space/t/v3-1-cut-length-discrepancy-140mm-or-160mm/3257/5

:slight_smile:

Hey, glad your making process with the rotator! I am about to start mine with my team very soon. A few questions for you:

  1. Did you end up making the V3.0.1 or V3.1 rotator?
  2. Did you end up making the rotator controller board? Or the drivers that came with your stepper motors in the first post?
  3. Why did you choose PC control versus using a Pi?
    Thanks!

1 & 2 Quartapounds SatNOGS Rotator v3.1

3 my primary use for this will be HRPT, and the decoder I want to use is windows based. I might add a Pi to it later, I already have one running goestools, one in the attic on rtltcp, another on my 3d printer running OctoPrint, love them!

2 Likes

I am just getting started and have this same question. I am doing a build using servos and am not seeing reference to the homing sensor. Did you end up needing it for your build?

Also, I am lost on the “axis gear” and “shaft gear” showing up in different places, I have found that there are different gear designs. Is this a difference in the two versions, which should I go with?

I am a high school teacher trying to get this worked out for students to do. Simple solutions are better if there are options. :slight_smile:

Hey!

What kind of servos are you using?

The homing ring in v3.1 is changed to parts C1040-1 and C1041-1, which are
used also for rotary encoder. If you do not want the rotary encoder then you can use
the homing ring from v3.0.1.

1 Like

I am using Nema 17 servos. I bought these since they came with the mounting bracket. My understanding is that the rotary encoder is not needed when using servos. Is there any advantage to include it? Also, I am having trouble finding the v3.0.1 homing pin file. Any guidance in this?
Thanks for your help!

You have position feedback of the output axis.

Release: v3.0.1, part: homing_ring.fcstd

If you using the above part you must use the optical end-stop not the
mechanical.