Project tutorial
Compass for astronomers

Compass for astronomers © CC0

A telescope alignment compass, for amateur stronomes, without GPS

  • 1,456 views
  • 0 comments
  • 2 respects

Components and supplies

Ard nano
Arduino Nano R3
×1
LSM303D - compass - discontinued
×1
lcd 16x2 - generic
×1
I2C Serial Module for LCD Display - generic
×1
push button - generic
×3
On-off button with lock
×1

Necessary tools and machines

Apps and online services

About this project

The idea

I like astronomy and recently bought a telescope.

To start observing the sky, I found that would have the need for a level compass and a tilt meter to correctly position my telescope.

I could do all this calibration with my cell phone.

However, I thought that eventually I wouldn't be able to count on him, so I had the idea of assembling a device that would meet all my needs without a cell phone.

How to assemble the hardware

The assembly was not difficult, after designing the structure in FreeCAD, I printed the parts on the 3D printer and placed the Arduino, the compass and the buttons. I made the connection in a mini proroboard.

The software

To make the software, I set up a sketch on the Arduino API with the help of some youtubers programmers. I made the reference in the comments of the main.INO file. I also made some comments. Only they are in Brazilian Portuguese, my native language.

Operation

To operate is easy.

1) When turning on the equipment, it will calibrate the LSM303 D, automatically.

2) The menu indicates the magnetic compass.

You can navigate to the other functions using the left and right buttons.

But the first thing to do is to level the telescope's tripod.

To do this, mount the tripod, with one leg turned for the North, if you are in the northern hemisphere of the planet or for the south, if you are in the southern hemisphere. Navigate the menu to "Nivelamento" and press the central button. The indicator shows the values that must be at zero for the base to be level.

3) After leveling press the middle button to stop the reading and navigate with the side buttons to "Bussola Magn" and activate the central button again for the reading.

Locate the north. Use the pointer to mark the geographic north, according to your location on the planet. Point the telescope to the north or to the geographical south, depending on the hemisphere you are in.

4) If you want to know the vertical inclination of the observed object, just go to the "Inclinação" menu, activate the reading and place the base of the equipment on the telescope body.

Finally, I put a scale in centimeters, next to the equipment, in case you want to use it on a map for geographic location.

This is the first version. The next will have a GPS, barometer and air temperature and humidity meters. It will be suitable for people who enjoy walking, running or cycling in nature.

Code

Bussola3Arduino
This is the main Arduino file, with the void setup and the void loop. I decided to do the functions in separate tabs, which gave rise to an .INO file for each function.
/*
 * Sketch feito com base:
 * 1)https://www.carnetdumaker.net/articles/faire-une-barre-de-progression-avec-arduino-et-liquidcrystal/ em 05/2020
 * 2)http://mikrokontroler.pl/2017/07/05/akcelerometr-i-magnetometr-kamodlms303-arduino/
 * 3)https://www.youtube.com/watch?v=Swr2Q1IFiBM
 */

//Bibliotecas
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <LSM303.h>

//bussola/acelerometro. define pinos A4(SDA) e A5(SCL)
LSM303 compass;

//Constantes: LCD/Menus
LiquidCrystal_I2C lcd(0x27, 20, 3);
#define menu_max 3

//Botoes
#define Bot1Enter 11 //Enter
#define Bot2Esq 12 //Esquerda
#define Bot3Dir 10 //Direita

//Funes
void MudarMenu();
void MostrarMenu();
void Compasso();
void Config_barprogresso();
void Calibrar();
void Bar_progresso();
void Nivelamento();
void Inclinacao();

//Variaveis globais
float acc_x,
      acc_y,
      ax_offset = 0,
      ay_offset = 0;

const int LCD_NB_ROWS = 2;
const int LCD_NB_COLUMNS = 16;

byte DIV_0_OF_5[8] = {B00000,B00000,B00000,B00000,B00000,B00000,B00000,B00000}; // 0/5
byte DIV_1_OF_5[8] = {B10000,B10000,B10000,B10000,B10000,B10000,B10000,B10000}; // 1/5
byte DIV_2_OF_5[8] = {B11000,B11000,B11000,B11000,B11000,B11000,B11000,B11000}; // 2/5
byte DIV_3_OF_5[8] = {B11100,B11100,B11100,B11100,B11100,B11100,B11100,B11100}; // 3/5
byte DIV_4_OF_5[8] = {B11110,B11110,B11110,B11110,B11110,B11110,B11110,B11110}; // 4/5
byte DIV_5_OF_5[8] = {B11111,B11111,B11111,B11111,B11111,B11111,B11111,B11111}; // 5/5

static byte percent = 0; //Valor percentual da barra de progresso

int contador = 0; //Contador do calibrador

char menu = 0x01, //Ao ligar aparece o menu1
     set1 = 0x00, //Variveis de acionamento
     set2 = 0x00;

boolean e_Bot1Enter = 0x00, //variaveis de estado dos botes
        e_Bot2Esq = 0x00,
        e_Bot3Dir = 0x00;

////////////////////////////////////
void setup(){
  
  //sada LCD
  lcd.init();
  lcd.backlight();

  //configurao da barra de progresso
  Config_barprogresso();
   
  //Botoes
  pinMode(Bot1Enter, INPUT_PULLUP); //definio de entradas dos botes
  pinMode(Bot2Esq, INPUT_PULLUP);
  pinMode(Bot3Dir, INPUT_PULLUP);

  e_Bot1Enter = 0x00; //limpar o estado dos botes
  e_Bot2Esq = 0x00;
  e_Bot3Dir = 0x00;

  //Inicializacao da bussola
  Wire.begin();
  compass.init();
  compass.enableDefault();
  compass.m_min = (LSM303::vector<int16_t>){-32767, -32767, -32767};
  compass.m_max = (LSM303::vector<int16_t>){+32767, +32767, +32767};

  //Calibrao automtica da bssola 
  Calibrar();
  percent = 0;
  lcd.clear();
}

//////////////////////
void loop(){

     MudarMenu();
     MostrarMenu();
}
Bar_progresso.inoArduino
This is the function of the calibration progress bar.
//Funo para desenhar a barra de progresso com a porcentagem a ser exibida. 

void Bar_progresso(){//Exibe o novo valor em formato numrico na primeira linha * / 
  
  lcd.clear();
  lcd.setCursor (0,0); 
  lcd.print (percent); 
  lcd.print (F("%"));
  
  // NB Os dois espaos no final da linha permitem apagar os nmeros da porcentagem anterior // quando voc passa de um valor com dois ou trs dgitos para um valor com dois ou um dgitos. / * Mova o cursor para a segunda linha * / 
  lcd.setCursor (0,1); 
  
  //Mapeie o intervalo (0 ~ 100) para o intervalo (0 ~ LCD_NB_COLUMNS * 5) 
  byte nb_columns = map(percent,0,100,0,LCD_NB_COLUMNS * 5 );
  
  //Desenhe cada caractere da linha
  for (byte i=0; i<LCD_NB_COLUMNS; ++i){ 
  
  //Dependendo do nmero de colunas restantes a serem exibidas
    if (nb_columns == 0){ // Case 
        lcd.write((byte)0); 
    }else if(nb_columns >= 5){ // Caixa cheia 
      lcd.write(5); 
      nb_columns -= 5; 
     }else { //ltima caixa no vazia 
       lcd.write(nb_columns); 
       nb_columns = 0 ; 
       } 
   //Incrementa a porcentagem
    percent ++;
    // Retorna a zero se a porcentagem exceder 100% 
   
  }
 delay(500);
}
Calibrar.inoArduino
This is the calibration function.
//Funo de calibrao da bssola

void Calibrar(){

    while (contador != 101){
          compass.read();
          
          LSM303::vector<int16_t> running_min = {-32767, -32767, -32767}, running_max = {32767, 32767, 32767};
      
          running_min.x = min(running_min.x, compass.m.x);
          running_min.y = min(running_min.y, compass.m.y);
          running_min.z = min(running_min.z, compass.m.z);

          running_max.x = max(running_max.x, compass.m.x);
          running_max.y = max(running_max.y, compass.m.y);
          running_max.z = max(running_max.z, compass.m.z);
    
          lcd.clear();
          lcd.setCursor (0,0); 
          lcd.print("Calibrando ");
          lcd.print (percent); 
          lcd.print (F("%"));
    
          lcd.setCursor (0,1); 
          byte nb_columns = map(percent,0,100,0,LCD_NB_COLUMNS * 5 );
    
          for (byte i=0; i<LCD_NB_COLUMNS; ++i){
            if (nb_columns == 0){ // Case 
              lcd.write((byte)0); 
            }
            else if(nb_columns >= 5){ // Caixa cheia 
            lcd.write(5); 
            nb_columns -= 5; 
            }
            else{ //ltima caixa no vazia 
            lcd.write(nb_columns); 
            nb_columns = 0 ; 
            } 
          }
          if (++percent == 101){
            percent = 0;
            delay(1000);
          }
          delay(100);
          contador++;
    
   }
   lcd.setCursor(0,0);
   lcd.print("Calibrada! ");
   delay(3000);
}
Compasso.inoArduino
That's the function of the compass
//Funo bssola

void Compasso(){ 

  lcd.setCursor(0,0);
  lcd.print("< Bussola Magn >");
      
  if(!digitalRead(Bot1Enter))e_Bot1Enter = 0x01; //Boto Enter pressionado? Seta flag
  
  if(digitalRead(Bot1Enter) && e_Bot1Enter){     //Boto Enter solto e flag setada?
                                                 //Sim...
     e_Bot1Enter = 0x00;                         //Limpa flag
     set1++;                                     //Incrementa set1
     
     if(set1 > 2) set1 = 0x01;                   //Se maior que 2, volta a ser 1
     
     while (set1 == 0x01){
                                   
          compass.read();
          int heading = compass.heading();
          lcd.setCursor(0,1);
          lcd.print(heading);
          lcd.write(B11011111);

          if(heading >= 0 && heading <= 5 ){
            lcd.print(" Norte          ");
          }
          if(heading > 5 && heading < 85){
            lcd.print(" Nordeste       ");
          }
          if(heading >= 85 && heading <= 95){
            lcd.print(" Leste          ");
          }
          if(heading > 95 && heading < 175){
            lcd.print(" Sudeste        ");
          }
          if(heading >= 175 && heading <= 185){
            lcd.print(" Sul            ");
          }
          if(heading > 185 && heading < 265){
            lcd.print(" Sudoeste       ");
          }
          if(heading >= 265 && heading <= 275){
            lcd.print(" Oeste          ");
          }
          if(heading > 275 && heading < 355){
           lcd.print(" Noroeste       ");
          }
          if(heading >= 355 && heading <= 360){
            lcd.print(" Norte          ");
          }
                   
          if(!digitalRead(Bot1Enter))e_Bot1Enter = 0x01; //Boto Enter pressionado? Seta flag
          if(digitalRead(Bot1Enter) && e_Bot1Enter){     //Boto Enter solto e flag setada?
                                                         //Sim...
          e_Bot1Enter = 0x00;                         //Limpa flag
          set1++;                                 
          }
          delay(300); 
      }
    }
}
Config_barprogresso.inoArduino
This is the function that makes the configuration of the progress bar.
//Armazena caracteres personalizados na memria da tela LCD para a
//barra de progresso.

void Config_barprogresso() {
  lcd.createChar ( 0 , DIV_0_OF_5);
  lcd.createChar ( 1 , DIV_1_OF_5);
  lcd.createChar ( 2 , DIV_2_OF_5);
  lcd.createChar ( 3 , DIV_3_OF_5);
  lcd.createChar ( 4 , DIV_4_OF_5);
  lcd.createChar ( 5 , DIV_5_OF_5);
}
Inclinacao.inoArduino
This is the function of checking the tilt of the telescope.
//Funo de mostrar o ngulo de inclinao horizontal ou Latitude

void Inclinacao(){

    lcd.setCursor(0,0);
    lcd.print("<  Inclinacao  >");

    if(!digitalRead(Bot1Enter))e_Bot1Enter = 0x01; //Boto Enter pressionado? Seta flag
  
    if(digitalRead(Bot1Enter) && e_Bot1Enter){     //Boto Enter solto e flag setada?
                                                  //Sim...
      e_Bot1Enter = 0x00;                         //Limpa flag
      set1++;                                     //Incrementa set1
     
      if(set1 > 2) set1 = 0x01;                   //Se maior que 2, volta a ser 1
     
      while (set1 == 0x01){
     
            int regis_Y;
            compass.readAcc();
            regis_Y = (compass.a.y/100)*90/175*-1;
   
            lcd.setCursor(0,1);
            lcd.print("<= ");
            lcd.print(regis_Y);
            lcd.write(B11011111);
            lcd.print(" Latitude       ");
        
            if(!digitalRead(Bot1Enter))e_Bot1Enter = 0x01; //Boto Enter pressionado? Seta flag
            if(digitalRead(Bot1Enter) && e_Bot1Enter){     //Boto Enter solto e flag setada?
                                                           //Sim...
            e_Bot1Enter = 0x00;                            //Limpa flag
            set1++;                                 
            }
            delay(300); 
      } 
   }
}
MostrarMenu.inoArduino
This is the function that shows the equipment's operation menu.
//Funo para mostrar o menu

void MostrarMenu(){
  
  switch(menu){                                       //Controle da varivel menu
    
       case 0x01:                                       //Caso 1
             Compasso();                               //Chama a Bussola
             
             break;                                     //break
       case 0x02:                                       //Caso 2
             Nivelamento();                             //Chama Nivelamento
             
             break;                                     //break
       case 0x03:                                       //Caso 3
             Inclinacao();                              //Chama Inclinao
            
             break;                                     //break
       
  }
}
MudarMenu.inoArduino
This is the function that operates the menu, for the execution of the functions.
//Funo para mudar o menu

void MudarMenu(){

   if(!digitalRead(Bot2Esq)){e_Bot2Esq = 0x01;}          //Boto Esquerdo pressionado? Seta flag
   if(!digitalRead(Bot3Dir)){e_Bot3Dir = 0x01;}          //Boto Direito pressionado? Seta flag
      
   if(digitalRead(Bot2Esq) && e_Bot2Esq){          //Boto Esquedo solto e flag setada?
                                                   //Sim...
      e_Bot2Esq = 0x00;                            //Limpa flag
      
      lcd.clear();                                //Limpa display
      menu++;                                      //Incrementa menu
      
      if(menu > 0x03){ menu = 0x01;}                  //Se menu maior que 4, volta a ser 1
   } 
   
   if(digitalRead(Bot3Dir) && e_Bot3Dir){           //Boto Direito solto e flag setada?
                                                    //Sim...
      e_Bot3Dir = 0x00;                             //Limpa flag
      
      lcd.clear();                                 //Limpa display
      menu--;                                       //Decrementa menu
      
      if(menu < 0x01){ menu = 0x03;}                      //Se menu menor que 1, volta a ser 4
   }    
}
Nivelamento.inoArduino
This is the function that checks the tripod level.
//Funo nivelamento

void Nivelamento(){
    
    lcd.setCursor(0,0);
    lcd.print("<  Nivelamento >");
    
    if(!digitalRead(Bot1Enter))e_Bot1Enter = 0x01; //Boto Enter pressionado? Seta flag
    
    if(digitalRead(Bot1Enter) && e_Bot1Enter){     //Boto Enter solto e flag setada?
                                                 //Sim...
      e_Bot1Enter = 0x00;                         //Limpa flag
      set1++;                                     //Incrementa set1
     
      if(set1 > 2) set1 = 0x01;                   //Se maior que 2, volta a ser 1
     
      while (set1 == 0x01){                      
            
            byte setacima[8] = {0b00100,0b01110,0b10101,0b00100,0b00100,0b00100,0b00100,0b00100};
            lcd.createChar (1, setacima);
            byte setabaixo[8] = {0b00100,0b00100,0b00100,0b00100,0b00100,0b10101,0b01110,0b00100};
            lcd.createChar (2, setabaixo);
    
            int regis_X;
            int regis_Y;
        
            compass.readAcc();

            regis_X = (compass.a.x/1000);
            regis_Y = (compass.a.y/1000);

            lcd.setCursor(0,1);
            lcd.write(B01111110);
            lcd.print("+");
            lcd.write(B01111111);
            lcd.print("-:");
            lcd.print(regis_X);

            lcd.print("  ");        
            lcd.write(2);
            lcd.print("+");
            lcd.write(1);
            lcd.print("-:");
            lcd.print(regis_Y);
    
            lcd.print("  ");
    
            if(!digitalRead(Bot1Enter))e_Bot1Enter = 0x01; //Boto Enter pressionado? Seta flag
            if(digitalRead(Bot1Enter) && e_Bot1Enter){     //Boto Enter solto e flag setada?
                                                         //Sim...
            e_Bot1Enter = 0x00;                         //Limpa flag
            set1++;                                 
            }
            delay(300); 
      }
   }
}
  

Custom parts and enclosures

FreeCAD
I used FreeCAD to design the pieces.
Bussolafreecad 3n3qgkuv3y
Keyboard
Cover for keyboard buttons.
Main box of the equipment body.
Pointer
Pointer to be used as pointed from the geographical north.
Main box cover
Arduino cover
case opening cover for Arduino connector.
Battery cover.
cover of the box opening for placing the battery.

Schematics

Scheme
The SDA and SCL pins on the compass and the LCD I2C go on pins A4 (SDA) and A5 (SCL).
The buttons go on pins D10, D11 and D12 of the Arduino.
Esquema bussola c35j6qedjx

Comments

Similar projects you might like

DIY Flight Instruments for Horizon and Compass

Project tutorial by Aritro Mukherjee

  • 54,544 views
  • 26 comments
  • 97 respects

Car HUD - Windscreen Display for Speed & Compass

Project tutorial by marcozonca

  • 7,902 views
  • 10 comments
  • 18 respects

EasyFFT: Fast Fourier Transform (FFT) for Arduino

Project tutorial by abhilash_patel

  • 45,277 views
  • 13 comments
  • 23 respects

Direction_Control using KK flight controller & Arduino

Project tutorial by harsh dokania

  • 3,654 views
  • 0 comments
  • 5 respects

Made of Mars + Adafruit Circuit Playground Express + DFRobot

Project tutorial by Kitty Yeung

  • 2,800 views
  • 0 comments
  • 20 respects
Add projectSign up / Login