Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* http://pastebin.com/umdfpmeg
- Nome do Projeto: Placas Solares
- Nome do Aquivo: PlacaSolar04.ino
- link:
- Dependencias: LiquidCrystal.h
- AccelStepper.h
- Wire.h
- MCU: ATmega
- Board: Arduino Uno/Mega/Mini
- Compilador N/A
- IDE: Arduino IDE 1.6.6
- Hardware: Arduino UNO/MEGA/Mini
- Escrito por: Rui Viana
- Modificado por: N/A
- Data: 03/03/2016
- Uso: Didático
- Desenhos N/A
- Copyright @ N/A
- Este programa é software livre;
- e é distribuído na esperança que possa ser útil, mas SEM QUALQUER GARANTIA;
- mesmo sem a garantia implícita de COMERCIALIZAÇÃO ou ADEQUAÇÃO A UM DETERMINADO FIM.
- REVISÕES
- 01/02/2016 Versão 01 PlacaSolar01
- 13/02/2016 Funciona ok sem calculos de deslocamento
- 15/02/2016 Versão 02 PlacaSolar02
- 16/02/2016 Funciona ok mas erro calculo de deslocamento de reinicio noturno
- 20/02/2016 Versão 03 PlacaSolar03
- 25/02/2016 Varias melhorias
- 28/02/2016 Versão 04 PlacaSolar03
- 03/03/2016 Inclusão de step motor
- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Descrição:
- Programa para manter placas solares sempre perpendicular à luz do sol em qualquer local, dia e hora.
- * Funcionamento do code:
- * É fornecido para o programa as coordenada do local onde ficarão as placas solares.
- * O programa faz a leitura da data e hora no RTC.
- * Com esta data calcula, o horario atual em segundos. TOD Time Of Day.
- * Chama também uma função que calcula o numero da data atual no ano.
- * Com esta data e com a formula ? = 23,45*sen(360/365*(284 + ndia)) ndia = numero do dia no anos,
- * calcula a declinação da terra.
- * E o tempo que o sol ilumina o local, é calculado com a fórmula ? = 2/15arccos(-tan?.tan?).
- * Com estes valores a placa é posicionada por 2 steps motors, e a cada fraçao de tempo calculado
- * de dividido 180 graus pelo numero de horas de sol para cada dia.
- * Ao desligar e religar o arduino, os motores retornam para a posição de home e rposicionam à posição atual
- * O horário de inicio do avanço partindo de 0 graus, é definido dividindo o numero de horas de luz de sol do dia,
- * por 2, e subitraindo de 12:00:00 o valor da divisão. O horário do final do percurso é encontrado somando esta
- * divisão com 12:00:00.
- * Ao Chegar à meia noite, o sistema identifica que houve mudança de dia e retorna os motores à posição de home,
- * para aguardar a hora de inicio da varedura.
- * Como a terra inclina de -23,5 graus(solsticio), até 0 grau(equinócio), depois a 23,5 graus(solsticio)
- * e novamente a 0 grau(equinócio).
- * Esta data é 20 de março, 20 de junho e 21 de setembro, 20 de dezembro com variações no ano bissexto.
- * Dias do anos 80, 171, 262, 354.
- */
- #include <LiquidCrystal.h> // Biblioteca LCD
- LiquidCrystal lcd(12, 11, A0, A1, A2, A3); // Pinos do LCD
- #include <AccelStepper.h> // Biblioteca StepMotor
- #include "Wire.h" // Biblioteca I2C
- #define DS1307_ADDRESS 0x68 // Endereço I2C do RTC
- AccelStepper motor1(1,7,8); // Definicao pinos STEP e DIR do motor 1
- AccelStepper motor2(1,9,10 ); // Definicao pinos STEP e DIR do motor 2
- #define EOLati 3 // Port do sensor de home de latitude motor 1
- #define EOLong 4 // Port do sensor de home de longitude motor 2
- int velocidade_motor = 1000; // Define velocidade do motor1
- int aceleracao_motor = 1000; // Define velocidade do motor2
- float TgF = 0; // Tangente das coordenadas
- float d = 0; // Declinacao da terra
- float CoordG = 3; // Cooodenadas cartezianas do locar (grau)
- float CoordM = 43; // Cooodenadas cartezianas do locar (minuto)
- float CoordS = 6; // Cooodenadas cartezianas do locar (segundos)
- float CoordDec = (CoordG*3600+CoordM*60+CoordS)/3600; // Soma das coordenadas total em segundos
- float LocalRad = 0; // Coordenadas locais em rdianos
- float Nht = 0; // Numero de horas de sol por dia
- long TOD = 0; // Time Of Day
- long TODAnt = 0; // Time Of Day segundo anterior
- long Posicao = 0; // Posição sol no ida
- unsigned long Nh = 0; // Horas calculadas de sol
- unsigned long Nm = 0; // Minuto calculados de sol
- unsigned long Ns = 0; // Segundos calculados de sol
- float Rad = PI/180; // Radianos
- String AbaixoEquador = "S"; // Posição em relação ao equador
- unsigned int MeuDia = 0; // Dia do Ano
- unsigned int MeuDiaAnt = 0; // Dia antrior
- unsigned long TTotal = 0; // Tempo total de sol
- long Inicio = 0; // Horiario do nascer do sol
- long Fim = 0; // Horiario do por do sol
- float Giro = 0; // Movimentação da terra
- byte Pwo = 0; // Flag de rodar com power on ou reset
- byte FlagRun = 0; // Flag MeuDiaAnt no primeiro dia do ano
- long Deslocamento = 0; // Deslocamento do dia em relação ao equinócio
- float Declinacao = 0; // Declinação da terra
- float Move = 0 ; // Valor de avanco em minutos
- int segundos = 0; // Segundos
- int minutos = 0; // Minutos
- int horas = 0; // Horas
- int diadasemana = 0; // Dia da semana
- int diadomes = 0; // Dia do mes
- int mes = 0; // Mes
- int ano = 0; // Ano
- byte Dsp = 0; // Dispaly no LCD
- long StepCount = 0; // Contagem de Steps para mover os steps motors
- //-----------------------------------------------------------------------------
- void setup()
- {
- pinMode(EOLati, INPUT_PULLUP); // Port do sensor de home de latitude como inpute e pull up
- pinMode(EOLong, INPUT_PULLUP); // Port do sensor de home de latitude como inpute e pull up
- motor1.setMaxSpeed(velocidade_motor); // Define velocidade máxima do motor1
- motor1.setAcceleration(aceleracao_motor*10); // Define aceleração do motor1
- motor2.setMaxSpeed(velocidade_motor); // Define velocidade máxima do motor2
- motor2.setAcceleration(aceleracao_motor*10); // Define aceleração do motor2
- float Local = 0; // Coordenadas Local em decimais
- Serial.begin(9600); // Inicializa o monitor serial
- lcd.begin(16, 2); // Inicializa o LCD
- Wire.begin(); // Inicializa o uso do I2CC
- if (AbaixoEquador == "S") // Se for abaixo do equador coordenadas negativas
- Local = -(CoordG + CoordM/60 + CoordS/3600); // Calcula o grau em decimais
- else // Se for acima do equador coordenadas positivas
- Local = (CoordG + CoordM/60 + CoordS/3600); // Calcula o grau em decimais
- LocalRad = Local*Rad; // Calcula as coordenadas em radianos
- TgF = tan(LocalRad); // Calcula a tangente das coordenadas
- Pwo = 0; // Informa reset ou power on
- }
- //-----------------------------------------
- void MoveMotorLat () // Move motor de declinação para posição atual
- {
- StepCount = (Giro/36); // Calcula posição do sol de 0 a 180 graus em numero de steps
- motor1.moveTo(StepCount); // Move motor de posição do sol
- }
- //------------------------------------------------------------------------------
- void MoveMotorDec () // Move motor de declinação para posição atual
- {
- StepCount = (Declinacao*100); // Calcula declinação d terra em numero de steps
- motor2.moveTo(StepCount); // Move motor de declinação
- }
- //-----------------------------------------------------------------------------
- void ImprimeTempo ()
- {
- Serial.print("Dia "); // Serial imprime "Dia "
- Serial.print (diadomes); // Serial imprime diadomes
- Serial.print("/"); // Serial imprime "/"
- Serial.print (mes); // Serial imprime mes
- Serial.print("/"); // Serial imprime "/"
- Serial.print (ano); // Serial imprime ano
- Serial.print(" "); // Serial imprime " "
- Serial.print (horas); // Serial imprime horas
- Serial.print(":"); // Serial imprime ":"
- Serial.print (minutos); // Serial imprime minutos
- Serial.print(":"); // Serial imprime ":"
- Serial.println (segundos); // Serial imprime segundos
- }
- //-----------------------------------------------------------------------------
- void LeData ()
- {
- byte zero = 0x00; // ??
- Wire.beginTransmission(DS1307_ADDRESS); // Inicia comunicacao com DS1331
- Wire.write(zero); // ??
- Wire.endTransmission(); // ??
- Wire.requestFrom(DS1307_ADDRESS, 7); // ??
- segundos = ConverteparaDecimal(Wire.read()); // Le segundos do RTC
- minutos = ConverteparaDecimal(Wire.read()); // Le minutos do RTC
- horas = ConverteparaDecimal(Wire.read() & 0b111111); // Le horas do RTC
- diadasemana = (Wire.read()); // Le dia da semana do RTC
- diadomes = ConverteparaDecimal(Wire.read()); // Le dia do mes do RTC
- mes = ConverteparaDecimal(Wire.read()); // Le mes do RTC
- ano = ConverteparaDecimal(Wire.read()); // Le ano do RTC
- TOD = (segundos + minutos*60 + horas*long (3600)); // Calcula hora em segundos
- if (TOD == 86399) // Se for 23:59:59
- {
- TODAnt = 0; // Zera TOD anterior, evita travamento à 1/2 noite
- TOD = 1; // TOD = 1, evita travamento à 1/2 noite
- }
- calculateDayOfYear(diadomes,mes,ano); // Calcula dia do ano
- }
- //-----------------------------------------------------------------------------
- byte ConverteparaDecimal(byte val)
- {
- return ( (val/16*10) + (val%16) ); // Converte numero Hexa para decimal
- }
- //-----------------------------------------------------------------------------
- int calculateDayOfYear(int day, int month, int year) // Calcula dia do ano
- {
- int daysInMonth[] = {31,28,31,30,31,30,31,31,30,31,30,31}; // Matriz de qtde dias dos meses
- if (year%4 == 0) // Verifica se é bissexto // Se o ano for bissexto
- {
- if (year%100 != 0) // Se não for centena cheia
- {
- daysInMonth[1] = 29; // Soma 1 em fevereio
- }
- else // Ou se for centena cheia
- {
- if (year%400 == 0) // Se for multiplo de 400
- {
- daysInMonth[1] = 29; // Soma 1 em fevereio
- }
- }
- }
- MeuDia = 0; // Zera contagem de dias
- for (int i = 0; i < month - 1; i++) // Soma até mes atual - 1
- {
- MeuDia += daysInMonth[i]; // Soma numero de dias dos meses
- }
- MeuDia += day; // Soma dias do mes atual
- // MeuDia = 171; // Para Diag
- }
- //-----------------------------------------------------------------------------
- void CalcH (long ValH) // Calcula horas/minutos/segundos inteiros
- {
- Nh = ValH/3600; // Horas inteiras
- Nm = (ValH-(Nh*3600))/60; // Minutos inteiros
- Ns = (ValH-(Nh*3600)- Nm*60); // Segundos inteiros
- }
- //-----------------------------------------------------------------------------
- void Imprime() // Serial imprime horarios
- {
- Serial.print(Nh); // Serial imprime horas
- Serial.print(":"); // Serial imprime :
- Serial.print(Nm); // Serial imprime minutos
- Serial.print(":"); // Serial imprime :
- Serial.println(Ns); // Serial imprime segundos
- }
- //-----------------------------------------------------------------------------
- void Inclinacao () // Inclinação da placa
- {
- /*
- Solsticio de verão é +- no dia 80 de cada ano (Varia no ano bissexto)
- À cada dia soma-se -929,6703297 à poiscão atual, vezes o numero de dias
- -91 e 91 em relacão ao sosticio
- O semestre solar vai de -11 (80 - 91), até 171 (80 + 91)
- Dia 1/1/xxxx = dia 11
- 80 = 0 -13386 | 171 = 91 | 172 = 90 71214 | 262 0 | 353 -91 - 97986
- */
- if (MeuDia<172) // Solsticio de inverno
- {
- Deslocamento = long(MeuDia) - 80; // Calcula inclinação
- }
- if ((MeuDia>171)&& (MeuDia<354)) // Equinócio de inverno
- {
- Deslocamento = 262 - long(MeuDia); // Calcula inclinação
- }
- if (MeuDia>353) // Solsticio de verão
- {
- Deslocamento = long(MeuDia) - 444; // Calcula inclinação
- } // inclinação conforme a posição do sol nas estácoes
- Declinacao = (0.25824175824*(-91+Deslocamento)+23.5-CoordDec); // Calculo da inclinação em Coordenadas geográficas decimais
- MoveMotorDec(); // Move motor2 para a posição de delinação
- }
- //-----------------------------------------------------------------------------
- void CalculosGeo ()
- {
- d = tan(23.45*sin(((float)360/365*(284+MeuDia)*Rad))*Rad); // Calcula declinacao da terra
- d = -(d * TgF); // Declinacao da terra = declinação * tangente das coordenadas
- Nht = ((float)2/15)*(acos(d))/PI*180; // Calcula horas total de sol por dias (float)
- Nh = Nht; // Horas de sol por dia (long)
- Nm = (Nht-Nh)*60; // Minutos de sol por dia (long)
- Ns = (Nht-Nh)*3600-Nm*60; // Segundos de sol por dia (long)
- // Serial.print("Tempo de sol: "); // Serial imprime "Tempo de sol: "
- // Imprime(); // Serial imprime o tempo total de sol do dia
- TTotal = (Nh*3600+ Nm*60+ Ns); // Metade do tempo total de segundos de sol por dia
- Inicio = 43200 - (TTotal/2); // Meio dia menos metade do tempo de sol
- Fim = 43200 + (TTotal/2); // Meio dia mais metade do tempo de sol
- Move = 648000/float(TTotal); // Segundos de graus de deslocamento por segundo de hora
- }
- //-----------------------------------------------------------------------------
- void loop()
- {
- motor1.run(); // Movimenta step motor1
- motor2.run(); // Movimenta step motor2
- // Inicio Reset ou troca de dia / ano --------------------------------------
- LeData(); // Le a data de hoje no RTC
- if ((MeuDia == 1) && (FlagRun == 0)) // Se é o primeiro dia do ano e ainda não rodou Calculos
- {
- MeuDiaAnt = 0; // Reinicializa dia anterior
- FlagRun = 1; // Informa que já Reinicializou MeuDiaAnt
- }
- if (MeuDia >1) FlagRun = 0; // Se nao for primeiro dia apaga indicador Reinicializa dia anterior
- if (MeuDiaAnt<MeuDia) // Se mudou o dia realinha e recalcula
- {
- /* while (digitalRead(EOLati) == 1) // Equanto não está no home reposiciona motor de deslocamento em 0 graus
- {
- Serial.println("Return Lati"); // Serial imprime "Return Lati"
- StepCount--; // Decrementa posição do motor
- motor1.moveTo(StepCount); // Move motor1 pra o home
- motor1.run(); // Movimenta step motor1
- }
- StepCount = 0;
- while (digitalRead(EOLong) == 1) // Equanto não está no home reposiciona motor de declinacao
- {
- Serial.println("Return Long"); // Serial imprime "Return Long"
- StepCount--; // Decrementa posição do motor
- motor2.moveTo(StepCount); // Move motor2 pra o home
- motor2.run(); // Movimenta step motor2
- } */
- Pwo = 0; // Reset falg de reposicionamento e recalculo
- CalculosGeo(); // Calcula horários e inclinação
- MeuDiaAnt = MeuDia; // Atualiza o dia anterior
- Inclinacao(); // Calcula a inclinação do sol
- }
- // Fim Reset ou troca de dia / ano ------------------------------------------
- // Inicio = 5; // Para Diag
- if (((TOD-Inicio) > 0) && ((Fim-TOD) > 0)) // Se TOD (agora) for maior que a hora do inicio e menor que hora do fim
- {
- if (Pwo == 0) // Se foi ligado agora ou feito reset
- { // Recupera posição atual
- Pwo = 1; // Informa reposicionamento
- Giro = 0; // Zera contador de posição
- Giro = Move*(TOD -Inicio-1); // Calcula a posicão atual -2 porque vai girar 1 em seguida
- }
- if (TOD>TODAnt) // Veja se passou um segundo
- {
- TODAnt = TOD; // Salva segundo antigo com o novo
- Dsp++;
- if (Dsp == 4) Dsp = 1; // Seleciona display no LCD
- if (Dsp == 1) // Display dia/hora
- {
- // ImprimeTempo(); // Imprime dia/hora atual
- lcd.setCursor(0,0); // LCD Lin 0 Pos 0
- lcd.print(diadomes); // LCD imprime dia
- lcd.print("/"); // LCD imprime /
- lcd.print(mes); // LCD imprime mes
- lcd.print("/"); // LCD imprime /
- lcd.print(ano); // LCD imprime ano
- lcd.print(" "); // LCD imprime espaço
- lcd.print(horas); // LCD imprime horas
- lcd.print(":"); // LCD imprime :
- lcd.print(minutos); // LCD imprime minutos
- lcd.print(":"); // LCD imprime :
- lcd.print(segundos); // LCD imprime segundos
- lcd.print(" "); // LCD imprime espaço
- }
- if (Dsp == 2) // Display hora nascer do sol
- {
- CalcH(Inicio); // Calcula hora de inicio format h/m/s
- // Serial.print("Nascer do Sol "); // Serial imprime Nascer do Sol
- // Imprime(); // Serial imprime h/m/s
- lcd.setCursor(0,0); // LCD Lin 0 Pos 0
- lcd.print("N. Sol "); // LCD imprime "N. Sol "
- lcd.print(Nh); // LCD imprime horas
- lcd.print(":"); // LCD imprime :
- lcd.print(Nm); // LCD imprime minutos
- lcd.print(":"); // LCD imprime :
- lcd.print(Ns); // LCD imprime segundos
- lcd.print(" "); // LCD imprime espaço
- }
- if (Dsp == 3) // Display hora por do sol
- {
- CalcH(Fim); // Calcula hora de fim format h/m/s
- // Serial.print("Por do Sol "); // Serial imprime Por do Sol
- // Imprime(); // Serial imprime h/m/s// Serial imprime
- lcd.setCursor(0,0); // LCD Lin 0 Pos 0
- lcd.print("P. Sol "); // LCD imprime "P. Sol "
- lcd.print(Nh); // LCD imprime horas
- lcd.print(":"); // LCD imprime :
- lcd.print(Nm); // LCD imprime minutos
- lcd.print(":"); // LCD imprime :
- lcd.print(Ns); // LCD imprime segundos
- lcd.print(" "); // LCD imprime espaço
- }
- lcd.setCursor(0,1); // LCD Lin 1 Pos 0
- lcd.print("d"); // LCD imprime d
- lcd.print(Declinacao); // LCD a declinação da terra :
- Giro = Giro + Move; // Move a cada segundo Movimento de rotação
- MoveMotorLat(); // Avança motor de deslocameto
- lcd.print(" p"); // LCD imprime p
- lcd.print(Giro/3600); // LCD imprime posição do sol
- }
- }
- else // Se TOD (agora) for menor que a hora do inicio ou maior que hora do fim
- {
- lcd.setCursor(0,0); // LCD Lin 0 Pos 0
- lcd.print(diadomes); // LCD imprime dia
- lcd.print("/"); // LCD imprime /
- lcd.print(mes); // LCD imprime mes
- lcd.print("/"); // LCD imprime /
- lcd.print(ano); // LCD imprime ano
- lcd.print(" "); // LCD imprime espaço
- lcd.print(horas); // LCD imprime horas
- lcd.print(":"); // LCD imprime :
- lcd.print(minutos); // LCD imprime minutos
- lcd.print(":"); // LCD imprime :
- lcd.print(segundos); // LCD imprime segundos
- lcd.print(" "); // LCD imprime espaço
- lcd.setCursor(0,1); // LCD Lin 1 Pos 0
- lcd.print("Waiting wakeup "); // LCD imprime "Waiting wakeup "
- // Serial.println("Waiting wakeup "); // LCD imprime "Waiting wakeup "
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement