My brother recently got a telescope, and we have been having a blast with it. It isn't a particularly expensive one; it totaled out to about $350 dollars. You can see Jupiter's big red dot and Saturn's rings. It is absolutely stunning. However, one thing you quickly discover is how tiring and tedious it can be aligning your telescope on the planet justttt right. Once you do, the planet has quickly moved out of frame! In an effort to resolve this issue quickly, I searched the internet for cheap motorized platforms to move the telescope automatically instead of manually. That is where the biggest problem arose. They can be pricey. So, I sought to create a motorized telescope stand on a budget with an autonomous upgrade path for the future!
This project will be a fun change from my previous projects. We will be dealing in electrical, mechanical, and electro-mechanical design. With this in mind, we will have to focus on:
Picking proper components: We will need precise motors and a beefy microcontroller for future upgrade paths.
Portability; Integration Shield (PCB): I'd like to integrate all these components into a tight package since this stand will have to be portable.
Good Mechanical Design: So that this stand can work well, we will need robust mechanical design for precision, stability, and portability.
The neat thing about this project's component selection is that we don't need to source JLCPCB components. Many of the boards already did that for us. So, we need to integrate them together. This board will be used mainly to connect these components together in a compact way while also helping distribute power in a consolidated way.
This block diagram helps break down the main component connection a little bit. Does it make sense? Great! This leads us to our schematic. This might look a little different. Remember, we are dealing with nets. I.e., signals, voltages, etc. are all tied together through connectors, headers, and pins.
You may notice a few differences. I added some LEDs to confirm things are working properly. Some dip switches help us select the step size we want for our motor drivers. Next, we have the addition of two electrolytic capacitors. The datasheet of the A4988 Stepper Motor Driver lists these decoupling capacitors as necessary to help filter out noise from the power supply. We also have additional pins from the Teensy 4.0 exposed with header pins to help in our future upgrade path and for ease of prototyping as needed. Lastly, we have a spot for a fuse so that we can protect our sensitive components from being burned.
You also may be wondering why I didn't list out specific components for the dip switches, leds, capacitors, fuse, etc. I designed this board with through-hole components in mind, and many of these components I will size and pick from scraps I have laying around my workshop (size correctly, of course). Keep in mind you can't just solder any capacitor to the board, for example. You have to size it correctly, preferrably with a low ESR, properly voltage-derated cap.
As I mentioned, this is an integration board, so everything is meant to slot into place. Looking at the design, you may notice it differs a bit from my previous designs. I forgot mounting holes! This is a big oversight for V1, but I can make do regardless by compensating for this in the enclosure. We keep our standard GND plane for these two-layer boards. However, since we are dealing with high currents, I wanted to create copper pours for our power plane where possible Along with the copper pours, I kept my traces thick to ensure I can handle the necessary current.
The boards finally arrived, and we were able to build and assemble! Since all these parts were through-hole, soldering this board was a blast and meant good $$$ savings instead of having JLCPCB assemble it.
The RAW board. If you look closely, you can see bigger copper pours for the power plane on this board compared to previous projects.
The assembled board.
Probably my least favorite part was creating the rest of the harnessing. What this means is adding male JST connectors to our joysticks and motors. I quickly learned how TEDIOUS those little JST pins can be.
Before writing any code, we have to decide how we want to actually program it. We do have a few options.
We can use the Arduino IDE, which has a vast library support. Arduino IDE is great for prototyping, but I am honestly not a fan of Arduino's language. You can compile in C and C++, but the toolchain set-up seems to be like a huge hassle, and we don't get any advantages of picking the Teensy. To do this, I would have chosen a barebones STM32 product instead. So, that leaves us with CircuitPython! Although I am most familiar with C in an embedded environment, I have used quite a bit of Python in everyday development. This makes using CircuitPython a matter of learning a few new libraries. On top of that, I really like that we can still take advantage of the openness of the platform. This is going to be very important for when we inevitably have to connect the Teensy 4.0 to stargazing apps like SkySafari for automatic pointing.
With that being said, here is the code. The V1 (this has now been updated to V2) code is quite simple since we want simple motor-moving-telescope functionality to start. This means: I give X-Y commands on the joystick, and the X-Y stepper motors move accordingly. You'll also notice we won't have to pay too much attention to the steps. Since we added DIP switches during the hardware design portion of the project, we can make these changes on the board to increase/decrease our resolution.
Our pin definitions were quite easy. These were, obviously, defined by our hardware first. So, it is a matter of following our schematic. You may notice that we use mostly digital pins for the 2 motor drivers. However, the joystick requires analog input pins. This is because the signals being returned are voltages, manipulated by a potentiometer.
The main code is very straight forward at the moment and will definitely use some optimization as the project progresses. With each loop, we poll our joystick values. Our ADC has an input range of about (0 - 65535). This is because we have a 16-bit ADC resolution; this translates to (2^16 - 1). We apply different step delays to the motors per range so that we can have speed control. For example, 65535 in the Y direction gives us the smallest step delay and therefore the fastest speed. This is really for done for two reasons. Speed control, as already mentioned. We also do it to have non-blocking behavior. If we continued to use time.sleep, it would hold up our CPU. This will allow future code to run when our motors do not need to be.
So why do we use step pulses and a simple high and low bit? This has to do with the motor driver we are using. These motor drivers handle the PWM for us (which is what you would typically use for controlling steppers), so we only have to send high and low bits. This application is simple enough that there are no immediate performance issues. We essentially send 200'steps' (this is gathered from the Nema 17 motor datasheet). Each step is a pulse sent for a certain period. So we change our digital STEP pin to on, wait a delay, then to off. Our step frequency comes out to about 500 Hz. With a total delay of 2 ms, we calculate the frequency at (1/.002). With this, we have stepper motors that move!