LOCALIZADOR DE ASTROS DO SISTEMA SOLAR PARA …

69
LOCALIZADOR DE ASTROS DO SISTEMA SOLAR PARA CÂMERAS E TELESCÓPIOS Juan Felipe Azevedo Cura Vazquez Projeto de Graduação apresentado ao curso de Engenharia Eletrônica e de Computação, da Escola Politécnica da Universidade Federal do Rio de Janeiro para conclusão de curso. Orientador: Carlos Fernando Teodósio Soares Rio de Janeiro Julho de 2021

Transcript of LOCALIZADOR DE ASTROS DO SISTEMA SOLAR PARA …

LOCALIZADOR DE ASTROS DO SISTEMA SOLAR PARA CÂMERAS

E TELESCÓPIOS

Juan Felipe Azevedo Cura Vazquez

Projeto de Graduação apresentado ao curso de Engenharia Eletrônica e de Computação, da Escola Politécnica da Universidade Federal do Rio de Janeiro para conclusão de curso.

Orientador: Carlos Fernando Teodósio Soares

Rio de Janeiro

Julho de 2021

LOCALIZADOR DE ASTROS DO SISTEMA SOLAR PARA CÂMERAS E TELESCÓPIOS

Juan Felipe Azevedo Cura Vazquez

PROJETO DE GRADUAÇÃO SUBMETIDO AO CORPO DOCENTE DO CURSO DE ENGENHARIA ELETRÔNICA E DE COMPUTAÇÃO DA ESCOLA POLITÉCNICA DA UNIVERSIDADE FEDERAL DO RIO DE JANEIRO PARA CONCLUSÃO DE CURSO.

Autor:

________________________________________________ Juan Felipe Azevedo Cura Vazquez

Orientador:

________________________________________________ Prof. Carlos Fernando Teodósio Soares (D.Sc.)

Examinador:

________________________________________________ Prof. Carlos José Ribas D’Ávila (M.Sc.)

Examinador:

________________________________________________ Profa. Fernanda Duarte Vilela Reis de Oliveira (D.Sc.)

Rio de Janeiro – RJ, Brasil

Julho de 2021 ii

Declaração de Autoria e de Direitos Eu, Juan Felipe Azevedo Cura Vazquez CPF 142.058.397-23, autor da monografia Localizador de Astros do Sistema Solar para Câmeras e Telescópios, subscrevo para os devidos fins as seguintes informações:

1. O autor declara que o trabalho apresentado na disciplina Projeto de Graduação da Escola Politécnica da UFRJ é de sua autoria, sendo original em forma e conteúdo.

2. Excetuam-se do item 1. eventuais transcrições de texto, figuras, tabelas, conceitos e ideia que identifiquem claramente a fonte original, explicitando as autorizações obtidas dos respectivos proprietários, quando necessárias.

3. O autor permite que a UFRJ, por um prazo indeterminado, efetue em qualquer mídia de divulgação, a publicação do trabalho acadêmico em sua totalidade, ou em parte. Essa autorização não envolve ônus de qualquer natureza à UFRJ, ou aos seus representantes.

4. O autor pode, excepcionalmente, encaminhar à Comissão de Projeto de Graduação, a não divulgação do material, por um prazo máximo de 01 (um) ano, improrrogável, a contar da data de defesa, desde que o pedido seja justificado, e solicitado antecipadamente, por escrito, à Congregação da Escola Politécnica.

5. O autor declara, ainda, ter a capacidade jurídica para a prática do presente ato, assim como ter conhecimento do teor da presente Declaração, estando ciente das sanções e punições legais, no que tange a cópia parcial, ou total, de obra intelectual, o que se configura como violação do direito autoral previsto no Código Penal Brasileiro no art. 184 e art. 299, bem como na Lei 9.610.

6. O autor é o único responsável pelo conteúdo apresentado nos trabalhos acadêmicos publicados, não cabendo à UFRJ, aos seus representantes ou ao(s) orientador(es), qualquer responsabilização / indenização nesse sentido.

7. Por ser verdade, firmo a presente declaração.

Juan Felipe Azevedo Cura Vazquez

iii

UNIVERSIDADE FEDERAL DO RIO DE JANEIRO

Escola Politécnica – Departamento de Engenharia Eletrônica de de Computação

Centro de Tecnologia, bloco H, sala H-217, Cidade Universitária.

Rio de Janeiro – RJ CEP 21949-900

Este exemplar é de propriedade da Universidade Federal do Rio de

Janeiro, que poderá incluí-lo em base de dados, armazenar em computador,

microfilmar ou adotar qualquer forma de arquivamento.

É permitida a menção, reprodução parcial ou integral e a transmissão

entre bibliotecas deste trabalho, sem modificação de seu texto, em qualquer

meio que esteja ou venha a ser fixado, para pesquisa acadêmica, comentários e

citações, desde que sem finalidade comercial e que seja feita a referência

bibliográfica completa.

Os conceitos expressos neste trabalho são de responsabilidade do(s)

autor(es).

iv

DEDICATÓRIA

Dedico este projeto à minha avó Maria Amélia Azevedo da Silva. Foi

minha melhor amiga e minha companheira por 21 anos. Sempre participou da

minha vida, mesmo que em certos momentos a mesma fosse uma verdadeira

loucura, e esteve ao meu lado nos momentos em que mais estive sozinho.

Espero que essa dedicatória a faça sorrir, seja lá onde esteja.

v

AGRADECIMENTO

Agradeço à minha mãe Ana Lúcia Azevedo da Silva por todo apoio e

carinho todos esses anos. Agradeço ao meu pai Juan Felipe Cura Vazquez pelos

conselhos e paciência ao longo de minha formação. Este projeto não teria sido

possível sem vocês. Obrigado.

vi

RESUMO

Este projeto de graduação consiste no estudo e desenvolvimento de um

sistema de localização automático de astros do Sistema Solar, particularmente

os oito planetas. Este foi desenvolvido através de um microcontrolador

ATMega2560, em um Arduino Mega, e módulos para servir de portal de

comunicação entre o usuário e o sistema. O usuário dispõe de botões para

selecionar o planeta desejado e confirmar a escolha, a qual será visualizada

através de uma tela LCD. Após a escolha, o sistema irá calcular a posição do

planeta em questão e controlará dois motores para apontar uma base para o

astro em questão, se o mesmo estiver em um momento observável. Essa base

pode servir para um telescópio, uma câmera ou até mesmo um laser.

Palavras-Chave: controlador, módulos, localizador automático, planetas do

sistema solar, Arduino.

vii

ABSTRACT

This undergraduate Project consists on the study and development of an

automated Solar System bodies tracking device, particularly the eight planets. It

was developed with an Arduino controller and modules to perform the

communication between the user and the system. The user selects the desired

planet and confirms the choice. The desired planet is then be visualized through

a LCD display. After the user’s choice, the system calculates the planet position

and control two engines to point a base towards the celestial body, as long as it

is observable at the moment. The base can serve for a telescope, a camera or

even a laser.

Keywords: controller, module, automated tracker, solar system planets,

Arduino.

viii

SIGLAS

LCD – Liquid Crystal Display

RTC – Real Time Clock

GPS – Global Positioning System

JD – Julian Day

GST – Greenwich Sidereal Time

LST – Local Sidereal Time

HA – Hour Angle

SDA – Serial Data

SCL – Serial Clock

PWM – Pulse Width Modulation

SRAM – Static Random Access Memory

ix

SUMÁRIO

1. Introdução 1

1.1. – Tema ------------------------------------------------------------------------1

1.2. – Delimitação ---------------------------------------------------------------1

1.3. – Justificativa ----------------------------------------------------------------2

1.4. – Objetivos ------------------------------------------------------------------2

1.5. – Metodologia --------------------------------------------------------------2

1.6. – Materiais ------------------------------------------------------------------3

1.7. – Descrição-------------------------------------------------------------------3

2. Astrofísica utilizada 5

2.1. – Metodologia --------------------------------------------------------------5

2.2. – Determinação Ascensão e Declinação------------------------------6

2.3. – Determinação Azimuth e Altitude -----------------------------------8

3. Hardware do sistema 11

3.1. – Módulos Utilizados ----------------------------------------------------11

3.2. – Visão Geral do Circuito ------------------------------------------- ---18

4. Software do sistema 21

4.1. – Noção Geral -------------------------------------------------------------21

4.2. – Algoritmos Principais -------------------------------------------------21

5. Conclusões e pontos de aprimoramento 31

Bibliografia 33

Apêndice A Código Fonte do observador 34

x

Lista de Figuras

2.2 – Ascenção e Declinação --------------------------------------------------------------7

2.3 – Azimuth e Altura ----------------------------------------------------------------------8

3.1 – Modelo Display LCD ----------------------------------------------------------------12

3.2 – Foto do Display LCD em funcionamento --------------------------------------14

3.3 – Modelo Contador RTC -------------------------------------------------------------15

3.4 – Modelo Módulo GPS ---------------------------------------------------------------16

3.5 – Modelo Motor Servo ---------------------------------------------------------------17

3.6 – Base de movimento dos motores servos -------------------------------------17

3.7 – Modelo Arduino Mega -------------------------------------------------------------18

3.8 – Circuito Montado -------------------------------------------------------------------20

3.9 – Diagrama de conexões ------------------------------------------------------------20

3.10 – Imagem do circuito, com Saturno em um momento observável ------22

4.1 – Mapeamento sequencial dos eventos dentro do código -----------------30

4.2 – Confirmação dos dados de Júpiter ----------------------------------------------31

4.3 – Confirmação dos dados de Mercúrio ------------------------------------------31

4.4 – Confirmação da conversão em azimuth e altura ----------------------------32

xi

Lista de Tabelas

2.1 – Elementos Orbitais das órbitas planetárias em 2010 ----------------------------6

xii

1

Capítulo 1

Introdução

1.1 Tema

O tema do projeto consiste no estudo e desenvolvimento de um software

que seja capaz de localizar qualquer planeta pertencente ao sistema solar e de

um mecanismo que aponte uma base para o alvo em questão. Nem todos têm o

conhecimento astral para saber onde cada planeta está e simplesmente apontar

um telescópio para observá-los. Então, um sistema que os localiza

automaticamente é de grande ajuda para astrônomos amadores e até mesmo

profissionais. Para este propósito, foi usada uma placa Arduino Mega, alguns

sensores a serem tratados mais adiante e motores servos para controlar a base.

O projeto lida com a maior parte das áreas do curso, tendo forte ênfase na

parte de software. Foram necessários conhecimentos na área de programação,

em particular em C++ para programar o Arduino, bem como conhecimentos na

confecção de circuitos eletrônicos e como operar os pinos dos sensores.

1.2 Delimitação

O projeto tem como foco a observação de planetas, portanto, fica limitado à

visibilidade dos mesmos. Nesse sentido, depende de o alvo estar no céu

observável, bem como das condições climáticas do momento, apesar de ainda

assim as posições em si poderem ser calculadas. Além disso, os motores usados

têm uma capacidade de cobrir 180° de angulação, não podendo, assim, cobrir

360°, embora o sistema consiga facilmente ser adaptado para isso.

O sistema também está limitado somente aos planetas do sistema solar, mas

também pode ser adaptado para qualquer astro, desde cometas, até galáxias

inteiras.

2

1.3 Justificativa

Desde o inicio da civilização, a humanidade sempre foi fascinada pelo que há

no céu, criando até mitologias incríveis sobre cada planeta e estrela. Eu não sou

diferente, sempre me interessei muito por astronomia e estive em uma casa, no

alto de uma montanha, com um belo céu estrelado e quis saber onde estavam

os planetas. Como não sou um astrônomo profissional, tive dificuldade em

distinguir cada astro e pensei em criar um sistema para me ajudar e ajudar

outras pessoas que compartilhem dessa paixão.

A dificuldade na observação certamente seria reduzida com um localizador

automático para cada planeta, havendo também a possibilidade de uma

eventual ampliação para outros tipos de astros também. Assim sendo, o

presente projeto utiliza de estudos realizados anteriormente para buscar uma

automação de um projeto, não só útil para sociedade, mas também de interesse

pessoal, podendo até se tornar base para um produto comercial.

1.4 Objetivos

O projeto se propõe a facilitar a observação dos planetas do sistema solar no

céu noturno, nesse sentido, possui como objetivos específicos: (1) desenvolver

um método computacional para que se possa calcular a posição dos planetas a

questão em qualquer momento, de qualquer lugar da Terra; (2) configurar um

conjunto de sensores para transmitirem as informações necessárias para o

cálculo do posicionamento; (3) criar um hardware que sirva de comunicação

entre o usuário e o sistema; (4) adaptar uma base para servir de suporte, de

maneira que os motores consigam apontar uma câmera ou um telescópio para

o alvo.

1.5 Metodologia

Este trabalho utiliza metodologias vindas da Astronomia para realizar os

cálculos dos posicionamentos. Para isso, são necessários alguns dados:

elementos orbitais de cada astro, latitude, longitude, data e hora. Os elementos

orbitais, que serão tratados na Seção 2.1, são adquiridos a partir de uma tabela.

A latitude e a longitude podem vir de um sensor GPS ou ser manualmente

inseridas no código. A data e hora são dados a partir de um sensor RTC.

3

O usuário pode selecionar um planeta, dentre uma lista com todos os astros

disponíveis, através de 3 botões. Um botão para avançar na lista, outro para

retroceder e um último para confirmar a escolha. Um display LCD mostra o

planeta atual, bem como informa se o mesmo se encontra em um momento

observável.

Os sinais dos sensores e dos botões são interpretados por um script em C++

inserido no Arduino Mega utilizado. O script realiza os cálculos e envia sinais

para dois motores servos controlarem uma base. Um motor servo controla o

eixo horizontal e o outro o eixo vertical. O sistema mantém a posição até outro

planeta ser selecionado.

1.6 Materiais

O projeto utiliza um sensor RTC para adquirir data e hora e um sensor GPS

para a latitude e longitude. São utilizados 3 botões eletrônicos para a navegação

e um display LCD para exibição dos dados. São utilizados também dois motores

servos para controlar os eixos horizontal e vertical.

A interpretação dos sinais e envio dos sinais de controle são dados por um

Arduino Mega programável, utilizando um script em C++.

Finalmente, também foi utilizada uma base de plástico para o encaixe dos

motores servos e demonstrar a movimentação dos mesmos.

1.7 Descrição

No Capítulo 2 é tratada a astrofísica, que possibilita o posicionamento

matemático dos planetas no céu, como são feitos os cálculos, e os conceitos

necessários para compreensão do que foi feito.

O Capítulo 3 detalha o hardware, explicando a pinagem e o funcionamento

correto de cada sensor utilizado, bem como os botões e o display LCD. No

mesmo capítulo, também são tratados os motores servos e o a placa Arduino.

Em seguida, é apresentado no Capítulo 4 o código do software em C++ que

gera os sinais de controle e interpreta o sinais dos sensores, realiza os cálculos e

envia sinais de controle para os motores servos.

4

Finalmente, a conclusão reflete pontos de melhorias no projeto para uma

futura implementação.

5

Capítulo 2

Astrofísica utilizada

2.1 – Metodologia

A estratégia a ser tomada para localizar os planetas consiste em uma

sequencia de passos. Primeiramente, iremos determinar as coordenadas

heliocêntricas no momento, ou seja, o posicionamento do astro em questão em

relação ao Sol. Em sequência, somos capazes de converter esse valor para a

localização em relação à Terra, particularmente em relação ao seu centro. Por

fim, novamente faz-se uma conversão do valor encontrado para um novo

posicionamento em relação à localização do usuário.

Puderam ser adotadas algumas simplificações nos cálculos, como por

exemplo, considerar a trajetória dos planetas circular ao invés de elíptica e

sempre alinhada com a projeção da trajetória aparente do Sol observada a

partir da Terra. Essas simplificações alteram o resultado em alguns milésimos de

segundos angulares. Como os motores servos não possuem precisão o

suficiente para diferenciar esses pequenos valores, não há comprometimento

no resultado do projeto.

Para todos os cálculos serem possíveis, é necessária uma tabela com os

elementos orbitais de cada planeta, que nada mais são do que dados a respeito

do astro e sua órbita, como tamanho, velocidade e raio.

6

Tp ϵ ω e a i Ω θ Vo

Mercúrio 0,24 75,56 77,61 0,200 0,38 7,00 48,45 6,74 -0,42

Vênus 0,61 272,30 131,54 0,006 0,72 3,39 76,77 16,92 -4,40

Terra 0,99 99,55 103,20 0,016 0,99

Marte 1,88 109,09 336,21 0,093 1,52 1,84 49,63 9,36 -1,52

Júpter 11,85 337,91 14,66 0,048 5,20 1,30 100,56 196,74 -9,40

Saturno 29,31 172,39 89,56 0,053 9,51 2,49 113,75 165,60 -8,88

Urano 84,03 271,06 172,88 0,046 19,21 0,77 73,93 65,80 -7,19

Netuno 165,84 326,89 23,07 0,010 30,19 1,77 131,88 62,20 -6,87

Tabela 2.1 – Elementos orbitais planetários em 2010 [1]

Os dados da tabela acima são os elementos orbitais de cada planeta na época

de 2010:

Tp: Período de órbita (anos tropicais)

ϵ: Longitude na época (graus)

ω: Longitude do periélio (graus)

e: Excentricidade orbital

a: Semi-eixo maior da órbita (unidades astronômicas)

i: Inclinação orbital (graus)

Ω: Longitude do nó ascendente (graus)

θ: Diâmetro angular (unidades astronômicas)

Vo: Magnitude visual em (unidades astronômicas)

2.2 – Determinação Ascensão e Declinação

O primeiro passo a se tomar é a determinação das coordenadas

heliocêntricas do planeta selecionado. Para isso é necessário primeiro entender

o esses termos significam.

7

Figura 2.1: - Ascenção e Declinação.

A ascensão de um corpo celeste P em relação a um ponto central é o

ângulo entre a projeção horizontal da reta que liga o ponto ao corpo e uma reta

de referência. A declinação é o ângulo entre o plano horizontal e a reta que liga

o ponto ao corpo celeste. Ambos os ângulos estão ilustrados na Figura 2.1.

A latitude heliocêntrica será zero, uma vez que definimos que a órbita

está no plano eclíptico. Assim, resta somente calcular a longitude heliocêntrica,

, através da equação (2.1) [1]:

(

) (

) (2.1)

onde D é a quantidade de dias passados entre a época de 2010 e a data de

observação em questão. Analogamente, faz-se o mesmo procedimento para

encontrar as coordenadas heliocêntricas do planeta Terra, sendo novamente a

latitude igual a zero e a longitude dada pela fórmula acima. Para representar a

longitude da Terra, será usada a letra .

O próximo passo é calcular as coordenadas geocêntricas do planeta a ser

observado. Novamente, a latitude será zero e a longitude geocêntrica é

calculada dependendo do posicionamento do planeta no sistema solar.

Para planetas entre a Terra e o Sol a longitude geocêntrica, , é

determinada por [1]:

{ ( )

( )} (2.2)

8

Para planetas após a Terra, temos [1]:

{ ( )

( )} (2.3)

Finalmente, de posse desses valores, é possível determinar os ângulos de

ascenção, , e declinação, δ, através das fórmulas [1]:

( ( ) ( )) (2.4)

( ( ) ( )) (2.5)

Com isso, determinamos com sucesso a posição de um planeta qualquer

em relação ao centro geográfico da Terra. Resta agora adaptar esse valor para

qualquer ponto no globo, para apresentar mais adequadamente o planeta em

relação à posição do usuário, através dos ângulos de azimuth e altitude.

2.3 – Determinação do Azimuth e da Altitude

Chamam-se azimuth e altitude os ângulos de ascensão e declinação,

respectivamente, para um referencial específico ao longo do globo (ou seja, não

mais o centro da esfera), conforme a Figura 2.2. Para o cálculo do azimuth e da

altitude, os dados correspondentes à data, hora, latitude e longitude serão de

grande importância.

Figura 2.2: - Azimuth e altura.

9

É necessário compreender um conceito muito utilizado na astronomia

que é o dia Juliano (JD). Nada mais é que um método para contar os dias a partir

de uma data específica, para padronizar os cálculos. Esse método de contagem

temporal recebe seu nome devido ao fato de que inicialmente se baseava no

calendário Juliano, que, por sua vez, recebe o nome em homenagem ao

imperador romano Júlio César. Depois, passou a ser usado o calendário

Gregoriano. Sua data de referência inicial corresponde ao meio dia do dia 24 de

novembro de 4714 a.C., pelo calendário gregoriano. O algoritmo de cálculo é

simples. Dados o ano, y, o mês, m, e o dia, d, basta seguir os seguinte passos [1]:

1: Se o mês for janeiro (1) ou fevereiro (2), y = y -1 e m = m + 12

2: Utilizando as variáveis auxiliares A, B, C e D temos:

A = TRUNC(y / 100) (2.6)

B = 2 – A + TRUNC(A / 4) (2.7)

C = TRUNC(365.25y) (2.8)

D = TRUNC(30.6001(m+1)) (2.9)

Onde TRUNC retorna a parte inteira do valor

3: JD = A + B + C + D + d + 1720994,5 (2.10)

O dia Juliano foi expresso em função dos parâmetros A, B, C e D,

conforme a equação 2.10, para simplificação visual, de forma que não seja uma

equação demasiadamente grande.

De posse do dia Juliano, é necessário um cálculo de precisão em relação à

hora. Há um método de contagem temporal mais preciso do que o método

convencional, chamado tempo sideral [2]. Serve justamente para cálculos de

observações e posicionamentos precisos de corpos celestes. Tendo a posse da

hora local do usuário, então, o procedimento é transferir esse horário para o

horário padrão (Greenwich), calcular o tempo sideral de Greenwich (GST) e

transferir de volta para a latitude do usuário. Assim obtém-se o tempo sideral

local (LST). Vale notar que o horário deve ser convertido em hora decimal,

simplesmente dividindo os minutos por 60 e adicionando ao número de horas.

10

Para converter para o horário padrão, devemos corrigir o fuso horário de

acordo com a latitude. Então, seguem-se os passos [1]:

1: Criam-se duas variáveis auxiliares T e S, onde

T = (JD – 2451545) / 36525 (2.11)

S = 6,697 + (2400,051 x T) + (0,000026 x T²) (2.12)

2: Divide-se o resultado acima em intervalos de 24, para que fique em

uma faixa entre 0 e 24.

3: Tendo em mãos o horário padrão, já convertido em hora decimal,

multiplica-se o mesmo por 1,0027.

4: Soma-se S ao valor do item 3, novamente dividindo o valor final em

intervalos de 24, se necessário. Este será o GST.

O resultado já está em horas decimais, como desejado para o cálculo do

tempo sideral local (LST). Para tanto, basta seguir o seguinte algoritmo [1]:

1: Pegar a longitude do usuário, que deverá estar em graus.

2: Dividir a longitude por 15, para converte-la em horas.

3: Somar o valor calculado no item 2 ao valor do GST, também reduzindo

o valor final em intervalos de 24, se necessário. O resultado é o LST.

Os cálculos até o momento tiveram como objetivo achar o horário

angular. O horário angular é a diferença entre o ângulo de ascensão e o LST.

Indica a posição do astro em relação ao meridiano local do observador. Para o

cálculo, subtraímos o valor do ângulo de ascensão do LST. Por exemplo, se o

horário angular encontrado for 2,5 horas, isso significa que o objeto cruzou o

meridiano local há 2,5 horas atrás. Para converter em graus, multiplica-se por

15, que é o número de meridianos na Terra. Portanto, o objeto está 2,5 x 15 =

37,5° a oeste do meridiano.

De posse da latitude, declinação e horário angular, podemos localizar,

com precisão, o astro escolhido, calculando o azimuth, az, e a altitude, alt [1]:

1: ( ( ) ( ) ( ) ( ) ( )) (2.12)

onde lat é o valor da latitude, HÁ é o horário angular e é a declinação.

2: ( ( ) ( ) ( )

( ) ( )) (2.13)

11

3: Para um ajuste final do azimuth; calcula-se o seno de HA. Se este seno

for positivo, az = 360° – az. Caso contrário, mantém-se o valor.

Com isso, conclui-se o conhecimento de astrofísica necessário para

entender o que deve ser feito no software. Esses cálculos foram escritos em

linguagem inteligível para o microprocessador em C++. No entanto, antes disso,

vale olhar mais a fundo como será o hardware desse projeto, bem como cada

componente utilizado.

12

Capítulo 3

Hardware

3.1 – Módulos Utilizados

Nessa parte, são abordados todos os módulos utilizados na confecção

deste trabalho. São eles: display LCD 16x2, contador RTC, módulo GPS, botões

pressionáveis, motores servos, um Arduino MEGA, bem como fios, resistências e

uma base para os motores movimentarem e apontarem para o alvo.

Display LCD [3]:

Figura 3.1: Modelo Display LCD.

A Figura 3.1 é um display LCD 16x2 modelo GDM1602k, com uma

plataforma soldada, contendo seis botões, cuja pinagem é mapeada da seguinte

maneira:

13

1: Vss (terra)

2: Vdd (tensão +5V para lógica)

3: V0 (tensão variável para ajuste de contraste)

4: RS (sinal de seleção de registro)

5: R/W (sinal de escrita ou leitura)

6: E (Enable do sinal de escrita e leitura)

7 – 14: Sinais lógicos para escolha do caractere a ser escrito na tela

15 – 16: Pinos extras para controle da luz de fundo da tela

Os botões são mapeados como:

1: Select (Selecionar)

2: Left (Esquerda)

3: Up (Cima)

4: Down (Baixo)

5: Right (Direita)

6: Reset (Reiniciar)

Os botões estão ligados a um divisor de tensão de forma que dependendo da

tensão de saída, sabe-se qual botão foi apertado:

Tensão entre 800 e 600mV corresponde ao botão Select.

Tensão entre 600 e 400mV corresponde ao botão Left.

Tensão entre 400 e 200mV corresponde ao botão Up.

Tensão entre 200 e 60mV corresponde ao botão Down.

Tensões menores que 60mV correspondem ao botão Right.

14

O botão de Reset está ligado diretamente ao Arduino e serve para

reiniciar o sistema.

Esses botões pressionáveis serão a principal maneira de interação entre o

sistema e o usuário, servindo para navegar pela lista de planetas disponíveis,

selecionar um planeta para ser observado ou reiniciar o sistema.

Figura 3.2: Foto do display LCD em funcionamento.

Neste projeto, o LCD indica o nome do planeta na primeira linha, seguido

do valor da altitude e do valor do azimuth, ambos na segunda linha. Na Figura

3.2, Netuno está em um momento não observável, pois sua altitude é negativa,

ou seja, está abaixo da linha do horizonte.

15

Contador RTC (Real Time Clock) [4]

Figura 3.3: Modelo contador RTC.

A Figura 3.3 representa um contador RTC, cuja corrente é de 1,5 mA, é o

meio de mantermos contagem da hora e data. Vem com uma bateria CR2032 de

3 V embutida, para que possa manter a contagem mesmo quando o circuito

estiver sem energia. O modelo utilizado é o RTC DS1307.

1: SQ (pino para amostragem de frequências em quadratura)

2: DS (pino que serve para possibilitar leitura de temperatura)

3: SCL (para sincronizar o clock com o do Arduino)

4: SDA (serve para possibilitar a comunicação serial)

5: VCC (pino de alimentação de 5V)

6: GND (terra)

7: BAT (pino para indicar a voltagem vinda da bateria, verificando seu

funcionamento)

16

Módulo GPS [5]

Figura 3.4: Modelo do módulo GPS.

A Figura 3.4 representa o módulo GPS, o qual é nosso principal método

para adquirir a latitude e a longitude do usuário. O modelo utilizado é o GY-

NEO6MV2. Em caso de mau funcionamento desde módulo, o sistema projetado

assume a latitude e a longitude da cidade do Rio de Janeiro. O módulo GPS

possui uma tensão de funcionamento entre 3,3 V e 5 V, e possui uma antena

para adquirir informações da rede de satélites. Os pinos estão listados como:

1: VCC (pino para alimentação, com a tensão supracitada)

2: RX (pino para receber dados)

3: TX (pino para transmitir dados)

4: GND (terra)

Motor Servo [6]

Esses motores, representados na Figura 3.5, são responsáveis por realizar

os movimentos para apontar um objeto para o astro a ser observado. Um motor

será responsável pelo movimento horizontal (azimutal) e o outro pelo

17

movimento vertical (zenital). O modelo utilizado nesse projeto é o Micro Servo

TowerPro 9g SG90.

Os motores servos utilizados são alimentados por uma bateria de 9V e cada um

possui um torque de 1,8 kgf.cm.

1: Vcc (pino para tensão)

2: GND (terra)

3: Imput (pino lógico para movimento)

Figura 3.5: Modelo motor servo.

Figura 3.6: Base de movimento dos motores servos.

18

A Figura 3.6 mostra os motores servos instalados em uma base giratória de

plástico para representar o azimuth e a altitude.

Arduino Mega [7]

A peça central deste projeto é um Arduino Mega 2560, com um

microcontrolador ATmega2560. O Arduino Mega 2560 possui 54 pinos de E/S

digitais (dos quais 14 podem ser usados como saída PWM), 16 pinos de E/S

analógicos, um oscilador de cristal de 16 MHz, conexão USB e um botão de reset

(ilustrado em vermelho na Figura 3.7). Possui também uma memória flash de

256 kB e uma SRAM 8 kB.

Figura 3.7: Modelo Arduino Mega.

Recomenda-se uma alimentação entre 7 V e 12 V, através de um cabo de

impressora, e cada pino tem uma corrente de aproximadamente 40 mA. Os

pinos do Arduino Mega possui as seguintes funções:

A0 ~ A15: Pinos de E/S analógicos.

1 ~ 53: Pinos de E/S digitais, sendo que:

Os pinos 1 ao 13: Funcionam como geradores de PWM.

19

Os pinos 14 ao 19: Funcionam como transmissores e receptores, de

maneira alternada (14 é um transmissor, 15 é um receptor, etc).

Pino 20: funciona como SDA (Serial Data)

Pino 21: como SCL (Serial Clock)

Os dois primeiros pinos na parte de baixo da Figura 3.7 são geradores de

tensão de 5 V e 3,3 V, já o terceiro pino funciona como terra.

Boa parte dos pinos são utilizados pelo display LCD e seus respectivos

botões. O pinos 18 e 19 são utilizados como o receptor e transmissor,

respectivamente, para o módulo GPS.

É importante ressaltar também que, apesar de a fonte de energia dos

motores servos virem de uma bateria separada, o terra deve ser o mesmo para

todos os componentes.

A programação é feita em C++ através do software próprio do Arduino,

cuja versão é Arduino 1.8.15, e é discutida no Capítulo 4.

3.2 – Visão Geral do Circuito

De uma maneira geral, o circuito se baseia principalmente nos sensores e

nos motores servos. Nas primeiras versões do projeto, haviam botões

separados, os quais funcionavam através de resistências à parte. Com a

utilização do LCD shield com os botões embutidos, o tamanho do circuito pôde

ser significantemente reduzido, de maneira a utilizar menos componentes. Uma

foto do circuito é apresentada na Figura 3.8 e um diagrama de conexões simples

do circuito é apresentado na Figura 3.9.

20

Figura 3.8: Circuito montado

Figura 3.9: Diagrama de conexões.

21

O RTC deve ter seu pino SCL conectado à entrada 21 do Arduino,

enquanto o pino SDA deve estar conectado à entrada 20. O módulo GPS tem

seu transmissor Tx conectado à entrada 19, enquanto o receptor Rx deve estar à

entrada 18. Finalmente, o pino lógico de entrada do motor da altitude deve

estar conectado à entrada 17 do Arduino, enquanto a entrada do motor do

azimuth deve estar conectada ao pino 16 do Arduino. Caso haja desejo de

mudar estar configuração, é necessário alterar o código, de acordo com a

preferência do leitor. Na Figura 3.9, os pinos de tensão Vcc estão indicados em

vermelho, enquanto os pinos de terra Gnd estão indicados em cinza. O encaixe

da placa LCD é direta no Arduino, não precisando de fios.

Na Figura 3.8, vale ressaltar os botões como divisores de tensão. A tensão

resultante dos divisores é lida pela entrada analógica A0 do Arduino. O display

LCD recebe informações do Arduino, enquanto a plataforma com botões está

enviando informações.

Os módulos GPS e RTC enviam informações ao Arduino. Os motores

servos, por outro lado, irão receber informações vindas do Arduino.

A alimentação dos módulos poderá vir tanto da bateria, quanto dos 5 V

do Arduino e a alimentação do próprio Arduino virá através de um cabo USB

CBX. A alimentação dos motores servos deve invariavelmente vir da bateria,

uma vez que o Arduino não consegue gerar corrente o suficiente para mantê-los

funcionando, podendo danificar o equipamento.

A Figura 3.10 mostra uma fotografia do protótipo do circuito montado e

funcionando, com Saturno em um momento observável.

22

Figura 3.10: Imagem do circuito, com Saturno em um momento observável.

23

Capítulo 4

Software

4.1 – Noção geral

Nesta seção, são abordados os algoritmos que regem o sistema, através

da linguagem C++. O código, de maneira geral, foi dividido em quatro partes: a

declaração das variáveis necessárias, a parte de setup, o loop e as funções.

Como estamos lidando com vários módulos (como RTC e LCD), é

necessária a inclusão das bibliotecas adequadas. As seguintes bibliotecas foram

utilizadas:

- Servo.h: Para controlar os dois motores servos;

- RTClib.h: Para interpretar os dados vindos do módulo RTC;

- LiquidCrystal.h: Para controlar o display LCD;

- SoftwareSerial.h: Para receber dados seriais;

- TinyGPS.h: Para interpretar os dados vindos do módulo GPS;

4.2 – Algoritmos principais

Na parte do setup, é realizada a inicialização dos módulos, o que implica

na configuração dos pinos utilizados do Arduino, e a sincronização do RTC. Vale

relembrar que o RTC possui uma bateria integrada. Desta forma, é capaz de

guardar a data e a hora, mesmo com o sistema desligado. Há, então, a leitura

dos dados do GPS, sucesso da operação da qual está ligado ao sinal de

triangularização recebido pela antena, pois só é possível essa leitura se houver

um sinal sendo recebido pela antena. O Algoritmo 1 descreve como o sistema

lida com o RTC e o Algoritmo 2 descreve como o sistema lida com o GPS.

24

Algoritmo 1: Sincronização do RTC

if !rtc.begin() { Serial.println(“RTC not found”); } if !rtc.running() { rtc.adjust(Datetime(F(_DATE_), F(_TIME_))); }

Se inicialização do RTC retornar zero - RTC não está conectado Se RTC não estiver rodando antes - Sincronizar data e hora com os valores atuais

Algoritmo 2: Recepção do GPS

while (serial1.available()) { char cIn = serial1.read(); recebido = gps1.encode(cIn); } gps1.get_position(&lat, &lon); if (lat != TinyGPS::GPS_INVALID_F_ANGLE) { lat = lat / 1000000; } else { lat = -22.906847; } if (lon != TinyGPS::GPS_INVALID_F_ANGLE) { lon = lon / 1000000; } else { lon = -43.172897; }

Enquanto houver informação serial no receptor, armazenar as informações. Uma vez que as informações estiverem completas, dividi-las entre latitude e longitude. Se forem válidas, dividir por 1000000 (para colocar o dado no formato decimal) Caso não sejam válidas, assumir manualmente a latitude -22.906847 e longitude em -43.172897, que se referem às coordenadas no Centro de Tecnologia da UFRJ, na ilha do Fundão.

25

É importante garantir a possibilidade de as coordenadas serem inseridas

manualmente no código, pois a antena demonstra a necessidade de estar em

um ambiente externo para receber sinal.

Após ajustado o RTC, o GPS e a pinagem, inicia-se a fase de loop, que nada mais

é do que a parte do código que estará se repetindo até o desligamento do

sistema.

Nessa fase, o usuário deverá selecionar o planeta (Algoritmo 3), os dados

são apresentados no display (Algoritmo 4), e há a interpretação do botão

pressionado, caso haja algum (Algoritmo 5).

Algoritmo 3: Seleção dos planetas

switch(index) { case 0: coordinates(mercury, y, m, dia, h, mi, true) break; . . . case 6: coordinates(neptune, y, m, dia, h, mi, false) break;

O índice vai de zero à seis, de acordo com a lista de planetas. Após a leitura desse índice, há uma chamada para a função coordinates, a qual recebe o nome do planeta, a data, a hora e uma variável booleana indicando se o planeta está entre o Sol e a Terra, ou se está após a Terra, uma vez que este dado afeta os cálculos. A função coordinates será tratada mais adiante.

A variável index, do Algoritmo 3, é um índice para controle e guarda qual

planeta está selecionado no momento. Inicialmente, o programa calcula as

coordenadas de Mercúrio e as apresenta no display. Após essa inicialização, o

programa espera alguma interação com os botões, seja para se mover na lista,

seja para tentar apontar os motores servos.

26

Algoritmo 4: Apresentação dos dados no display

lcd.setCursor(0,0); lcd.print(planet[index]); lcd.setCursor(0,1); lcd.print(altitude); lcd.print(" / "); lcd.print(azimuth); delay(1);

Mover cursor para o ponto 0,0 do display Imprimir o nome do planeta atual Mover cursor para o ponto 0,1 do display Imprimir valor da altitude / azimuth O delay serve para estabilizar a imagem, caso contrário, a mesma estará piscando de maneira desagradável

Algoritmo 5: Leitura dos botões

if ((buttomValue < 800) && (buttomValue >= 600)) { state(Select); } else if ((buttomValue < 600) && (buttomValue >= 400)) { state(Left); } else if (buttomValue < 60) { state(Right); } else { state(noButtom); } }

Caso a leitura da tensão seja entre 800 e 600 mV, botão Select. Caso seja entre 600 e 400 mV, botão Left. Caso seja menor que 60 mV, botão Right. Se não, nenhum botão foi pressionado. A leitura dos botões realiza uma chamada da função state a ser detalhada mais a frente.

Conforme mencionado no Capítulo 3, a leitura dos botões é feita através

da tensão de saída de um divisor de tensão. Essa tensão qual é lida por um pino

analógico do Arduino, o pino A0.

Resta detalhar as funções extras do programa, que são a coordinates

(para o cálculo das coordenadas do planeta), state (para controle do botão) e

buttomPressed (para interpretação do que cada botão deve fazer).

A função coordinates, detalhada no Apêndice 1, é longa e inclui todos os

cálculos já explicados no Capítulo 2, mas é necessário atenção a um detalhe: os

elementos orbitais, bem como o valor final da altura e do azimuth, deverão

estar em graus. No entanto, a linguagem C++ espera os argumentos em

27

radianos. Nesse sentido, deve ser feita uma conversão dos valores iniciais para

radianos e, naturalmente, uma conversão dos valores finais para graus.

Bastando, para isso, multiplicar o valor em graus por

para o resultado em

radianos, ou multiplicar o valor em radianos por

para o resultado em graus.

A função state, detalhada no Algoritmo 6, serve para estabilizar o botão,

no sentido de evitar que dois botões ou mais sejam apertados ao mesmo

tempo, ou que dois ou mais botões sejam apertados em um intervalo de tempo

muito pequeno. Essa função usa outra função do sistema chamada millis(), a

qual conta o tempo de execução do programa.

Algoritmo 6: Controle de estabilidade

if ((millis() - delayButtom) > 50) { if ((buttom != noButtom) && (buttomState == noButtom) ) { buttomPressed(buttom); delayButtom = millis(); } } buttomState = buttom; }

Essa função garante que um botão só vai ser lido se houver um espaçamento de 50 milissegundos entre um pressionamento e outro, assim, tornando o sistema mais estável. Se não houver nenhum botão já pressionado no momento, o sistema identifica o botão pressionado e chama a função seguinte, buttomState.

Na função seguinte, há uma interpretação do que fazer quando cada

botão é pressionado. Primeiramente, é chamada a função lcd.clear() para limpar

a tela do display LCD. Caso seja o botão Right, o índice incrementa em uma

unidade (ou retorna ao valor inicial da lista) e avança para o próximo planeta.

Caso seja o botão Left, o índice decrementa em uma unidade (ou retorna ao

valor final da lista) e aponta para o planeta anterior. Finalmente, caso seja o

botão Select, o sistema identifica se o planeta está numa posição observável e,

caso esteja, comanda os motores servos para que apontem para o mesmo. Este

mecanismo está detalhado no Algoritmo 7 e Algoritmo 8.

28

Algoritmo 7: Botão Right

if (buttom == Right) { if (index < 7) { index++; } if (index > 6) { index = 0; } }

Se o botão for Right Se índice for menor que 7 Incrementar o valor do índice Se índice for maior que 6 Retornar ao começo da lista

Algoritmo 8: Botão Left

if (buttom == Left) { if (index > -1) { index--; } if (index < 0) { index = 6; }; }

Se o botão for Left Se índice for maior que -1 Decrementar o valor do índice Se índice for menor que zero Posicionar índice no final da lista

O botão Select precisa tratar um mapeamento do motor servo, pois ele se dá

de maneira diferente do mapeamento do eixo do azimuth e da altura. Neste

projeto, o ponto zero dos eixos do azimuth e da altura está sempre apontado

para o norte. No entanto ponto zero dos motores está imediatamente direita do

norte. Isso ocorre porque o programa faz uma varredura de 0° a 180° nos

valores do azimuth, enquanto os motores leem os ângulos como sendo de -90°

à 90°. Nesse sentido, há uma conversão a ser feita entre o valor das

coordenadas encontradas e o valor a ser passado para os motores, conforme o

Algoritmo 9.

29

Algoritmo 9: Botão Select

if (buttom == Select) { if (altitude > 0) { if (azimuth <= 90) { auxAz = 90 - azimuth; auxAlt = 90 - altitude; ServoAzimuth.write(auxAz); delay(1000); ServoAltitude.write(auxAlt); delay(1000); } if ((azimuth > 90) && (azimuth <= 180)) { auxAlt = 90 - altitude; ServoAzimuth.write(0); delay(1000); ServoAltitude.write(auxAlt); delay(1000); } if ((azimuth > 180) && (azimuth < 270)) { auxAlt = 90 - altitude; ServoAzimuth.write(180); delay(1000); ServoAltitude.write(auxAlt); delay(1000); } if (azimuth >= 270) { auxAz = 450 - azimuth; auxAlt = 90 - altitude; ServoAzimuth.write(auxAz); delay(1000); ServoAltitude.write(auxAlt); delay(1000); } } }

Se o botão for Select Se a altura for maior que zero (porque é impossível observar algo abaixo da linha do horizonte, isto é, abaixo de zero) Se o azimuth está abaixo de 90°, está observável, então, faz-se a conversão e é dada a ordem de mover os motores através da função servo.write(). Dá-se um delay de 1 segundo para garantir estabilidade. Se o azimuth estiver entre 90° e 270°, o planeta não está observável, porque esse modelo de motor não consegue girar 360°. Então, para indicar isso, o motor é posto em 90° ou em 270° (dependendo do valor mais próximo). O valor da altitude é mantido e apontado pelo servo respectivo. Se o azimuth estiver maior do que 270°, o planeta é observável e, novamente, faz-se a conversão para as coordenadas dos servos, dando em seguida a ordem para posicioná-los de acordo. Novamente, aqui é dado um espaçamento de 1 segundo.

30

A Figura 4.2 mostra a sequência lógica do código implementado e

gravado no microcontrolador do Arduino.

Figura 4.1: Mapeamento sequencial dos eventos dentro do código

Para averiguar o funcionamento deste projeto, foi feita uma comparação

de resultados entre três exemplos do livro no qual o algoritmo deste projeto foi

baseado [1]. O primeiro exemplo constitui no cálculo da ascensão e declinação

de Júpiter no dia 22 de novembro de 2003. O livro encontrou um para ascensão

de 11,18 h e 6,35° para a declinação. O segundo exemplo trata de calcular as

mesmas grandezas para Mercúrio na mesma data, encontrando um valor de

16,82 h para a ascensão e -24,30° para a declinação.

31

Utilizando o algoritmo supracitado, chegamos aos mesmos valores,

conforme mostram as Figuras 4.3 e 4.4.

Figura 4.2: Confirmação dos dados de Júpiter.

Figura 4.3: Confirmação dos dados de Mercúrio.

O terceiro exemplo trata da conversão da ascensão e declinação, uma vez

obtidas, em horário angular e, consequentemente, em azimuth e altura. Dado

um horário angular de 5 h 51 m e uma declinação de 23° 13’ 10”, utiliza-se o

algoritmo para os cálculos e encontram-se um azimuth de 283,27° e uma altura

de 19,33°.

Novamente, seguindo o algoritmo fornecido pelo livro, o programa

implementado encontrou os mesmos valores, conforme mostrado na figura 4.5.

Os resultados dos três exemplos batem com o Astronomical Almanac do

Observatório Naval dos Estados Unidos [8], no qual o livro [1] se baseia. Nesse

sentido, fica claro o funcionamento do projeto e do algoritmo como um todo.

32

Figura 4.4: Confirmação da conversão em Azimuth e Altura.

33

Capítulo 5

Conclusões e pontos de aprimoramento

Tendo como base os resultados obtidos pelo projeto, em relação aos

resultados obtidos pelas bibliografias, o projeto obteve os resultados esperados.

Há, no entanto alguns pontos em que o projeto pode ser. Primeiramente,

quanto aos servos, eles podem ser mais precisos e o servo azimutal idealmente

deve girar 360°, como idealizado. É necessário também que os motores servos

sejam maiores para suportarem um telescópio apropriado para a observação.

Isso não foi possível simplesmente por falta de orçamento, pois um servo

preciso e que realize uma circunferência completa está fora do alcance

monetário deste projeto. Por outro lado, o código seria praticamente idêntico,

se não mais simples, pois não haveria a necessidade de verificar se o planeta

está fora do alcance do motor do azimuth.

Outro ponto importante que talvez possa ser trabalhado com um

orçamento maior seria um GPS com uma antena mais potente. O projeto foi

testado em diversos lugares foi observado que a antena somente recebia sinal

em espaços abertos. Nas montanhas de Itaipava, funcionou perfeitamente,

onde era um ambiente limpo e amplo. Em um apartamento, no entanto, a

antena não conseguiu identificar o sinal.

Houve duas partes desafiadoras do projeto; a primeira sendo entender os

conceitos de astrofísica que tornaram possível os equacionamentos e,

consequentemente, a localização dos planetas dentro do escopo. O desafio se

deu por serem muitos termos novos e que precisavam ser abordados

corretamente e com precisão para compreensão do trabalho. Além disso, cada

equação teve que ser entendida com muito cuidado, pois um pequeno detalhe

gera erros astronômicos. O segundo desafio foi manter uma programação

coerente com o livro utilizado, especialmente com os detalhes de conversão

entre graus e radianos.

É de suma importância que o usuário considere a inclinação do local de

observação, pois o projeto deve estar em uma base paralela ao nível do mar. É

também necessário o uso de uma bússola para garantir que os motores estejam

34

inicialmente apontados para o norte. Ambos os requerimentos podem ser

automatizados em um momento futuro através de sensores específicos para

essas funções.

Um ponto belo do projeto, e que é possível ser mais trabalhado, é a

expansão para outros astros do Universo. Bem como os planetas, todos os

corpos celestes têm um algoritmo matemático bem definido para sua

localização. Isso inclui estrelas, nebulosas, galáxias e até cometas. O planeta

Terra é somente uma pequena gota azul em um infinito oceano, e explorar além

do Sol seria uma arte. Caso exista interesse, basta adicionar os elementos

orbitais destes outros astros e suas respectivas equações para se tornar um

observador mais completo.

35

Bibliografia

[1] DUFFET-SMITH, P., ZWART, J., Practical Astronomy with your Calculator or

Spreadsheet. v.4, United Kingdom: University of Cambridge, jul. 2017.

[2] BERGMANN, T. S., Tempos Astronômicos, Instituto de Física Universidade

Federal do Rio Grande do Sul, disponível em:

<https://www.if.ufrgs.br/~riffel/notas_aula/ensino_astro/roteiros/Tempos.htm

>, acesso em: mar. 2021.

[3] Robotshop, Shield-LCD user’s Manual, jul. 2011, disponível em:

<https://www.robotshop.com/media/files/pdf/cytron-lcd-keypad-shield-

arduino-datasheet.pdf>, acesso em: mai 2021.

[4] Maxim integrated, DS1307, disponível em:

<https://datasheets.maximintegrated.com/en/ds/DS1307.pdf>, acesso em: mai

2021.

[5] Terra Electronica, UART GPS NEO-6M User Manual, disponível em:

<https://www.terraelectronica.ru/pdf/show?pdf_file=%2Fz%2FDatasheet%2FU

%2FUART+GPS+NEO-6M+User+Manual.pdf>, acesso em: mai 2021.

[6] DatasheetsPDF, SG90 Servo, disponível em:

<https://datasheetspdf.com/pdf/791970/TowerPro/SG90/1>, acesso em: mai

2021.

[7] Robotshop, Arduino Mega 2560 Datasheet, disponível em

<https://www.robotshop.com/media/files/pdf/arduinomega2560datasheet.pdf

> , acesso em: mai 2021.

[8] SEIDELMANN, P.K. The Explanatory Supplement to the Astronomical

Ephemeris and the American Epheris and Nautical Almanac, v.3, University

Science Books, jan. 2010.

36

Apêndice A:

Código fonte do observador

/* This will be the final version */

#include <Servo.h>

#include "RTClib.h"

#include <LiquidCrystal.h>

#include <SoftwareSerial.h>

#include <TinyGPS.h>

RTC_DS1307 rtc;

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

Servo ServoAzimuth;

Servo ServoAltitude;

SoftwareSerial serial1(18, 19); // RX, TX

TinyGPS gps1;

String planet[7] = {"Mercury", "Venus", "Mars", "Jupiter", "Saturn", "Uranus",

"Neptune"};

/*

37

Orbital elements for each planet on January 2010

[0] = period of orbit

[1] = longitude at the epoch

[2] = longitude of the perihelion

[3] = eccentricity of the orbit

[4] = semi-major axis of the orbit

[5] = orbital inclination

[6] = longitude of the ascending node

[7] = angular diameter at 1 A.U.

[8] = visual magnitude at 1 A.U.

*/

float mercury[9] = {0.24085, 75.5671, 77.612, 0.205627, 0.387098, 7.00051,

48.449, 6.74, -0.42};

float venus[9] = {0.615207, 272.30044, 131.53, 0.006812, 0.723329, 3.3947,

76.769, 16.92, -4.40};

float earth[9] = {0.999996, 99.556772, 103.2055, 0.16671, 0.999985, 0, 0, 0, 0};

float mars[9] = {1.880765, 109.09646, 336.217, 0.093348, 1.523689, 1.8497,

49.632, 9.36, -1.52};

float jupiter[9] = {11.857911, 337.917132, 14.6633, 0.048907, 5.20278, 1.3035,

100.595, 196.74, -9.40};

float saturn[9] = {29.310579, 172.398316, 89.567, 0.053853, 9.51134, 2.4873,

111.752, 165.60, -8.88};

float uranus[9] = {84.039492, 271.063148, 172.884833, 0.046321, 19.21814,

0.773059, 73.926961, 65.80, -7.19};

float neptune[9] = {165.84539, 326.895127, 23.07, 0.010483, 30.1985, 1.767,

131.879, 62.20, -6.87};

38

float dRef = 2455197.5; // Julian Day of January 1st, 2010

float pi = 3.1415927;

long lon;

long lat;

float altitude;

float azimuth;

int index = 0; // will be used to cycle through the planet list

int auxAz = 0; // for calculations adjustments of the azimuth value

int auxAlt = 0; // for calculations adjustments of altitude value

#define noButtom 0

#define Select 1

#define Left 2

#define Right 3

unsigned long delayButtom;

int buttomState = noButtom;

void state(int buttom);

void buttomPressed(int buttom);

void setup() {

pinMode(10, OUTPUT);

digitalWrite(10, HIGH);

39

Serial.begin(9600);

// starting the lcd display

lcd.begin(16, 2);

// starting the rtc and capturing the time

if (! rtc.begin()) {

Serial.println("DS1307 não encontrado");

while(1);

}

if (! rtc.isrunning()) {

Serial.println("DS1307 rodando!");

rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); //Captures date and time of

compilation

}

// for then the GPS is available

bool recebido = false;

while (serial1.available()) {

char cIn = serial1.read();

recebido = gps1.encode(cIn);

}

gps1.get_position(&lat, &lon);

if (lat != TinyGPS::GPS_INVALID_F_ANGLE) {

40

lat = lat / 1000000;

}

else

{

lat = -22.906847;

}

if (lon != TinyGPS::GPS_INVALID_F_ANGLE) {

lon = lon / 1000000;

}

else

{

lon = -43.172897;

}

// starting both engines

ServoAzimuth.attach(16);

ServoAltitude.attach(17);

}

void loop() {

int buttomValue = analogRead(A0);

DateTime now = rtc.now();

41

// now we have access to the date and time

float m = now.month();

float dia = now.day();

float y = now.year();

float h = now.hour();

float mi = now.minute();

Serial.print("Data: ");

Serial.print(now.day(), DEC);

Serial.print('/');

Serial.print(now.month(), DEC);

Serial.print('/');

Serial.print(now.year(), DEC);

Serial.print(" / Horas: ");

Serial.print(now.hour(), DEC);

Serial.print(':');

Serial.print(now.minute(), DEC);

Serial.print(':');

Serial.print(now.second(), DEC);

Serial.println();

42

// this will be our planet selection

switch(index)

{

case 0: coordinates(mercury, y, m, dia, h, mi, true);

break;

case 1: coordinates(venus, y, m, dia, h, mi, true);

break;

case 2: coordinates(mars, y, m, dia, h, mi, false);

break;

case 3: coordinates(jupiter, y, m, dia, h, mi, false);

break;

case 4: coordinates(saturn, y, m, dia, h, mi, false);

break;

case 5: coordinates(uranus, y, m, dia, h, mi, false);

break;

case 6: coordinates(neptune, y, m, dia, h, mi, false);

43

break;

default: Serial.println("Planet not found"); // <-- this is not supposed to

happen }

// this part will print the results, in case something goes wrong with the lcd

display

Serial.print(index);

Serial.print(" ");

Serial.print(planet[index]);

Serial.print(" - altitude: ");

Serial.print(altitude);

Serial.print(" / - azimuth: ");

Serial.print(azimuth);

Serial.println();

// this will print the results directly on the lcd display

lcd.setCursor(0,0);

lcd.print(planet[index]);

lcd.setCursor(0,1);

lcd.print(altitude);

lcd.print(" / ");

lcd.print(azimuth);

delay(1);

44

if ((buttomValue < 800) && (buttomValue >= 600)) {

state(Select);

} else if ((buttomValue < 600) && (buttomValue >= 400)) {

state(Left);

} else if (buttomValue < 60) {

state(Right);

} else {

state(noButtom);

}

}

//////////////////////////////////////////////////////////////////////

///////////// Functions ////////////////////////////

////////////////////////////////

void state(int buttom) // To indentify when a buttom is pressed and make it

more stable

{

45

// When one of the buttoms is pressed

if ((millis() - delayButtom) > 50) {

if ((buttom != noButtom) && (buttomState == noButtom) )

{

buttomPressed(buttom);

delayButtom = millis();

}

}

buttomState = buttom;

}

void buttomPressed(int buttom) // Once it is verified that a buttom was pressed

and it is allowed to be so

{

lcd.clear();

if (buttom == Right) // Move foward on the list

{

if (index < 7)

{

index++;

}

if (index > 6)

{

index = 0;

}

46

}

if (buttom == Left) // Move backward on the list

{

if (index > -1)

{

index--;

}

if (index < 0)

{

index = 6;

};

}

if (buttom == Select) // Confirm choice to observe planet

{

if (altitude > 0) // mapping the value on the engine and verifying if it is

observable

{

if (azimuth <= 90)

{

auxAz = 90 - azimuth;

auxAlt = 90 - altitude;

ServoAzimuth.write(auxAz);

47

delay(1000);

ServoAltitude.write(auxAlt);

delay(1000); }

if ((azimuth > 90) && (azimuth <= 180))

{

auxAlt = 90 - altitude;

ServoAzimuth.write(0);

delay(1000);

ServoAltitude.write(auxAlt);

delay(1000);

}

if ((azimuth > 180) && (azimuth < 270))

{

auxAlt = 90 - altitude;

ServoAzimuth.write(180);

delay(1000);

ServoAltitude.write(auxAlt);

delay(1000);

}

if (azimuth >= 270)

{

auxAz = 450 - azimuth;

auxAlt = 90 - altitude;

ServoAzimuth.write(auxAz);

48

delay(1000);

ServoAltitude.write(auxAlt);

delay(1000);

}

}

}

}

void coordinates(float planetData[7], float yAux, float mAux, float dAux, float

hours, float minutes, boolean inner) // this is the function responsible for

calculating the coordinates

{

//Finding the current Julian Day and the time difference between the

current day and the epoch

float a1 = trunc(yAux / 100);

float b1 = 2 - a1 + trunc(a1 / 4);

float c1 = trunc(365.25 * yAux);

float d1 = trunc(30.60001 * (mAux + 1));

float dPos = b1 + c1 + d1 + dAux + 1720994.5;

float d = dPos - dRef;

float tp = planetData[0]; //Period of orbit

float ep = planetData[1]; // Longitude at the epoch

float w = planetData[2]; // Longitude of perihelion

49

float e = planetData[3]; // Eccentricity of the orbit

float a = planetData[4]; // Semi-major axis of the orbit

float i = planetData[5]; // Orbital inclination

float om = planetData[6]; // Longitude of the ascending node

float te = planetData[7]; // Angular diameter at 1 A.U.

float v0 = planetData[8]; // Visual magnitude at 1 A.U.

// Finding the approximate Heliocentric Longitude

float l = (360 / 365.242191) * (d / tp) + ep;

if (l > 360)

{

do

{

l = l - 360;

}

while (l > 360);

}

if (l < 0)

{

do

{

l = l + 360;

50

}

while (l < 0);

}

/* NEXT STEP IS TO DO THE SAME THING FOR PLANET EARTH! */

float tpEarth = earth[0]; // Period of orbit

float epEarth = earth[1]; // Longitude at the epoch

float wEarth = earth[2]; // Longitude of perihelion

float eEarth = earth[3]; // Eccentricity of the orbit

float aEarth = earth[4]; // Semi-major axis of the orbit

float iEarth = earth[5]; // Orbital inclination

float omEarth = earth[6]; // Longitude of the ascending node

float teEarth = earth[7]; // Angular diameter at 1 A.U.

float v0Earth = earth[8]; // Visual magnitude at 1 A.U.

// Finding the approximate Heliocentric Longitude for Earth

float lEarth = (360 / 365.242191) * (d / tpEarth) + epEarth;

if (lEarth > 360)

{

do

{

lEarth = lEarth - 360;

51

}

while (lEarth > 360);

}

if (lEarth < 0)

{

do

{

lEarth = lEarth + 360;

}

while (lEarth < 0);

}

// Calculation of the Geocentric Latitude and Geocentric Logitude

float lamb;

if (inner == true)

{

lamb = 180 + lEarth + atan((a * sin((lEarth - l) * pi / 180)) / (l - a *

cos((lEarth - l) *pi / 180))) * 180 / pi;

}

if (inner == false)

{

52

lamb = (atan( sin((l - lEarth) * pi / 180) / (a - cos((l - lEarth) * pi / 180) )) *

180 / pi ) + l;

}

float beta = 0;

lamb = lamb * pi / 180;

float T = (dPos - 2451545.0) / 36525;

float de = (46.815 * T) + (0.0006 * pow(T,2)) - (0.00181 * pow(T,3));

// Finding the Obliquity of the Ecliptic

float oe = 23.439292 - (de / 3600);

oe = oe * pi / 180;

// Proceding to find the Right Ascention and Declination

float tempX = cos(lamb);

float tempY = sin(lamb) * cos(oe);

53

float alpha = atan(((tempY) / (tempX))) * 180 / pi;

if (tempX < 0)

{

alpha = alpha + 180;

}

if (tempX > 0 && tempY < 0)

{

alpha = alpha + 360;

}

float ra = alpha / 15;

float dec = asin(sin(lamb) * sin(oe)) * 180 / pi;

// Next step is finding the LST, to find the hour angle and convert the Right

Ascention and Declination to Azimuth and Altitude

// Proceeding to find the Universal Time

float totalHours = hours + minutes/60;

54

totalHours = totalHours + 4;

float ut = totalHours;

// Finding Greenwich Sidereal time

float t0 = 6.697374558 + (2400.051336 * T) + (0.000025862 * T * T);

if (t0 > 24)

{

do

{

t0 = t0 - 24;

}

while (t0 > 24);

}

if (t0 < 0)

{

do

{

t0 = t0 + 24;

}

while (t0 < 0);

}

55

ut = ut * 1.002737909;

float gst = ut + t0;

if (gst > 24)

{

do

{

gst = gst - 24;

}

while (gst > 24);

}

if (gst < 0)

{

do

{

gst = gst + 24;

}

while (gst < 0);

}

//Now to find Local Sidereal Time

56

float lst = gst + ( lon/ 15);

if (lst > 24)

{

do

{

lst = lst - 24;

}

while (lst > 24);

}

if (lst < 0)

{

do

{

lst = lst + 24;

}

while (lst < 0);

}

float ha = lst - ra;

if (ha < 0)

{

57

ha = ha + 24;

}

// Finally finding the Azimuth and Altitude

ha = ha*15*pi/180;

dec = dec*pi/180;

lat = lat*pi/180

float sinA = (sin(dec)*sin(lat)) + (cos(dec)*cos(lat)*cos(ha));

float alt = sinA * 180 / pi;

float altRad = alt * pi / 180;

float az = acos( (sin(dec) - (sin(lat)*sin(altRad))) / (cos(lat)*cos(altRad)) ) *

180 / pi;

if (sin(ha) > 0)

{

az = 360 - az;

}

altitude = alt;

azimuth = az;

}