Armando Leonardo
Published © CC0

Compass for astronomers

A telescope alignment compass, for amateur stronomes, without GPS

IntermediateFull instructions providedOver 2 days2,851
Compass for astronomers

Things used in this project

Hardware components

Arduino Nano R3
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

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

3D printer - Creality Ender 3

Story

Read more

Custom parts and enclosures

FreeCAD

I used FreeCAD to design the pieces.

Keyboard

Cover for keyboard buttons.

Body

Main box of the equipment body.

Pointer

Pointer to be used as pointed from the geographical north.

Cover

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.

Code

Bussola3

Arduino
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.ino

Arduino
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.ino

Arduino
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.ino

Arduino
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.ino

Arduino
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.ino

Arduino
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.ino

Arduino
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.ino

Arduino
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.ino

Arduino
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); 
      }
   }
}
  

Credits

Armando Leonardo

Armando Leonardo

3 projects • 4 followers
I have electronics and computer as a hobby. I like to build and create things as well as solve logic problems

Comments