Upload
others
View
3
Download
1
Embed Size (px)
Citation preview
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.
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.
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.
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.
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;
}