I am sharing with you all the details of my arduino WiFi / Bluetooth Digital Setting Circles project I put together in April 2020 and tested dozens of times since then.
I designed it for communication with SkySafary and it worked flawlesly from day one.
The code was written with focus on speed, reducing as many lines of code as possible. SkySafary can poll the DSC 10 times per second with the encoders geared for 1:40000 without breaking a sweat.
Below you will find the list of parts, the wiring diagram, the arduino code, the Gerber file I used to order PCBs for fabrication and few pictures of my 12" dobsonian with the system installed.
Parts list (available on eBay):
ESP32 board $8 (check pinout in the attached pictures)
Level Shifter $2 (check pinout in the attached pictures
Encoders $10 (any encoder 5-24V, 600 pulses with 2 channels)
GT2 pulleys and belts as per your need (or direct drive, 1:1 gearing)
Since the ESP32 board is 3.3V (5V tolerant) and the encoders are 5V, I felt a level shifter should be used to convert the encoder signal from 5V to 3.3V. Also, the level shifter has some resistors that act as pin - pulling resistors. Level shifters and ESP 32 boards with different pinouts can be used, but they must be wired accordingly.
The wiring and board pinouts are in the attached file named "wiring.png"
The code for wifi version is attached in the file named "dsc_wifi.ino.txt"
The code for bluetooth version is attached in the file named "dsc_bluetooth.ino.txt"
The gerber file I used to order the PCBs at the factory in China is attached in file "Gerber.zip"
I also fabricated my own PCB using attached PDF file "pcb.pdf"
The code is attached as txt files because .ino is not allowed to upload. Download the files and remove the .txt part, then open them with the Arduino IDE.
Once the project is built, you can install the bluetooth or wifi version of the code, depending on your preference. Keep in mind, bluetooth does not work on IOS.
Some people prefer bluetooth because they use Android devices and want to keep wifi for using the internet while observing, I prefer wifi because it works on Android and IOS and i don't need internet when I observe.
Gearing:
The encoders are 600 pulses per revolution, programmed in quadrature for 600 x 4 = 2400 pulses
If you gear 1:1, you set up 2400 in Sky Safari (more details about settings later)
If you gear 1:2 you gear 2400 x 2 = 4800 in SkySafari (more details about settings later)
If you gear 1:10, you gear 2400 x 10 = 24000 in sky safari (more details about settings later)
Whatever gear ratio you use, multipli it with 2400 and that's what you use in SkySafari settings
I tested gearing ratios between 1:1 and 1:20 and all worked OK, obviously, the higher the gearing, the smoother the movement and the better the accuracy ,but 1:1 still worked.
Here is a movie of Alt gearing 1:1 and Azimuth gearing 1:3.75, so you can see the difference in smoothness between the 2 axes.
https://www.youtube....h?v=_xI3exGk98o
Settings:
After powering up by USB, the system creates a new network named "stargazing". From the mobile device, connect to it using the password "orionnebula". To change the network name or password, edit these 2 lines of code:
const char *ssid = "stargazing";
const char *password = "orionnebula";
After you connect the mobile device to the new network, you start SkySafari and go to telescope settings and set the following:
- Equipment Selection/ Scope Type = Basic Encoder System
- Equipment Selection/ Mount Type = Alt-Az Push To
- RA/Azm = 2400 (multiply this number with your gear ratio for Azimuth or leave 2400 if yo have gearing 1:1)
- Dec/Alt = 2400 (multiply this number with your gear ratio for Altitude or leave 2400 if yo have gearing 1:1)
- Get Automatically = No (disable)
- Communication Settings / IP Address = 192.168.4.1
- Communication Settings / Port Number = 80
- Communication Settings / Set Time & Location = Yes
- Communication Settings / Readout Rate = 10 per second
- tap on Done
When the telescope menu settings closes, you should see at the bottom of the app a telescope "Connect" button. Tap on it and wait for the sytem to connect. Once connected, you should see the crosshairs in the app moving in sync with your telescope movement.
Now the scope is not aligned. Point it to a star you recognize in the sky, then tap on the star in the app and tap "align" and then "confirm alignment". Done, you are aligned, but it is a one star alignment and not very accurate, especially if the base is not horizontal. To improve the alignment, perform few more alignments on different stars.
After alignment, you should be able to easily find stars, planets, DSOs, or satellites. The system is so accurate, that my kids point it on the path of the satellites and wait to see them zipping across the FOV.
Few extra details on the project can be found here: https://astrostuff.w...com/magic/magic
Feel free to ask any questions, I will do my best to answer.
The WiFi version of the code is below, if you prefer the bluetooth version, you can find it attached.
String firmwareVersion = "2.0";
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
const char *ssid = "stargazing";
const char *password = "orionnebula";
WiFiServer server(80);
WiFiClient client;
#define enc_az_A 27
#define enc_az_B 26
#define enc_al_A 25
#define enc_al_B 33
volatile int lastEncodedAl = 0, lastEncodedAz = 0;
volatile long encoderValueAl = 0, encoderValueAz = 0;
void setup()
{
delay(1000);
pinMode(enc_al_A, INPUT_PULLUP);
pinMode(enc_al_B, INPUT_PULLUP);
pinMode(enc_az_A, INPUT_PULLUP);
pinMode(enc_az_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(enc_al_A), EncoderAl, CHANGE);
attachInterrupt(digitalPinToInterrupt(enc_al_B), EncoderAl, CHANGE);
attachInterrupt(digitalPinToInterrupt(enc_az_A), EncoderAz, CHANGE);
attachInterrupt(digitalPinToInterrupt(enc_az_B), EncoderAz, CHANGE);
//Serial.begin(115200);
//Serial.println();
WiFi.softAP(ssid, password);
server.begin();
}
void loop() {
client = server.available(); // listen for incoming clients
if (client) {
while (client.connected()) { // loop while the client's connected
if (client.available()) {
int c = client.read();
if (c == 81) {
printEncoderValue(encoderValueAz);
client.print("\t");
printEncoderValue(encoderValueAl);
client.print("\r");
}else if(c == 86) {
client.print(firmwareVersion);
client.print("\r");
}
}
}
// close the connection:
//client.stop();
//Serial.println("Client Disconnected.");
//delay(50);
}
}
void EncoderAl() {
int encodedAl = (digitalRead(enc_al_A) << 1) | digitalRead(enc_al_B);
int sum = (lastEncodedAl << 2) | encodedAl;
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValueAl ++;
if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValueAl --;
lastEncodedAl = encodedAl;
}
void EncoderAz() {
int encodedAz = (digitalRead(enc_az_A) << 1) | digitalRead(enc_az_B);
int sum = (lastEncodedAz << 2) | encodedAz;
if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValueAz ++;
if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValueAz --;
lastEncodedAz = encodedAz;
}
void printEncoderValue(long val)
{
unsigned long aval;
if (val < 0)
client.print("-");
else
client.print("+");
aval = abs(val);
if (aval < 10)
client.print("0000");
else if (aval < 100)
client.print("000");
else if (aval < 1000)
client.print("00");
else if (aval < 10000)
client.print("0");
client.print(aval);
}
Attached Files
Edited by Speo, 01 February 2021 - 11:07 AM.