Automação no parque, 06/07/2013

Nesse dia apareceu o César Munoz, vindo do ABC para brincar conosco no Parque. Trouxe consigo componentes para fazer um relógio digital com o DS1307. Montamos dois circuitos, simples, que vcs podem achar facilmente na net: um para ligar o DS1307 e outro para ligar o LCD. Aqui no blog mesmo tem um post sobre a ligação de um LCD de 20 colunas X 2 linhas, e a ligação de um 16x2, mais comum, é a mesma.

Aqui, uma imagem ensinando como ligar o DS1307:


A bateria B1 é de 3,3V e X1 é um clock de 32,786 kHz.

O que fizemos de novidade nesse circuito foi colocar botões para acertar data e hora. Esse circuito foi feito com três botões: um que comanda o que vai ser alterado (vc seleciona dia, mês, ano, hora, minuto ou segundo) e os outros dois servem para aumentar/diminuir o valor selecionado. O sistema indica com um * no canto superior esquerdo da tela que está em modo de atualização da hora e com uma letra indica o que está sendo  atualizado no momento, ex: *h indica que se vc mexer nos botões estará alterando a hora.

Os botões são ligados a portas digitais do Arduino na forma de circuito "pull down". Aqui um exemplo de como ligar um botão no Arduino usando-se essa técnica. O resistor pode ser qualquer valor entre 1k e 100k, ou até fora dessa faixa, a se testar. No site do Arduino tem um bom texto que explica a ideia por trás do pull down: http://arduino.cc/en/tutorial/button



No nosso circuito, ligamos o botão que controla o setup no pino 7, o que aumenta o número no pino 8 e o que baixa no pino 9.

É isso. Abaixo, foto do circuito e filme dele funcionando. E, mais abaixo, os fontes.





#include <LiquidCrystal.h>
#include <DS1307RTC.h>
#include <Wire.h>
#include <Time.h>

// Clock set command pins
#define clockSet 7
#define clockUp 9
#define clockDown 8

//Clock states
#define stClockRunning 0
#define stSetDay 1
#define stSetMonth 2
#define stSetYear 3
#define stSetHour 4
#define stSetMinute 5
#define stSetSecond 6

int stat = stClockRunning;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

void Print(int number)
{
  lcd.print(number/10);
  lcd.print(number%10);
}

// Fill lcd display
void printTime()
{
  lcd.setCursor(6,1); Print(hour());
  lcd.print(":");     Print(minute());
  lcd.print(":");     Print(second());
  lcd.setCursor(5,0); Print(day());
  lcd.print("/");     Print(month());
  lcd.print("/");     Print(year());
  lcd.setCursor(0,0);
  if (stat != stClockRunning)
     lcd.print("*");
  else  
     lcd.print("  ");
  switch(stat)
  {
    case stSetDay:
      lcd.print("d");
      break;
    case stSetMonth:
      lcd.print("m");
      break;
    case stSetYear:
      lcd.print("a");
      break;
    case stSetHour:
      lcd.print("h");
      break;
    case stSetMinute:
      lcd.print("M");
      break;
    case stSetSecond:
      lcd.print("s");
      break;
  }
}

// Read pin using threshold, as a switch, that is,
// first time pressed switch on, second time switch off
int readPinSwitch(int pin, int threshold)
{
  if (digitalRead(pin))
  {
    unsigned long tt = millis();
    while (digitalRead(pin));
    if ((millis() - tt) > threshold)
       return 1;
    else
       return 0;  
  }
  else
    return 0;
}

//Read pin using threshold
int readPin(int pin, int threshold)
{
  if (digitalRead(pin))
  {
    unsigned long tt = millis();
    while ((digitalRead(pin) && (millis() - tt) <= threshold));
    if (digitalRead(pin))
       return 1;
    else
       return 0;  
  }
  else
    return 0;
}

// Get new status, if any
int getStat()
{
  if (readPinSwitch(clockSet,300))
     if (stat == stSetSecond)
        return stClockRunning;
     else
        return stat+1;
  else
     return stat; 
}

// set Arduino and RTC time
void setRTCTime(int hour, int minute, int second, int day, int month, int year)
{
// set Arduino time 
    setTime(hour,minute,second,day,month,year);
    time_t t = now();    
// set RTC time
    RTC.set(t);
}

void setup()
{
  pinMode(clockUp,INPUT);
  pinMode(clockDown,INPUT);
  pinMode(clockSet,INPUT);

  lcd.begin(16, 2); // Set the display to 16 columns and 2 rows
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet)
  {
     lcd.setCursor(0,0);
     lcd.print("Erro RTC");
  }
}

int oldStat = stat;
unsigned long t=millis();

void loop()
{
  int value = 0;
  printTime();
  delay(100);
  stat=getStat();
  if (stat != oldStat)
  {
    t=millis();
    oldStat = stat;
  }
  else
    if ((stat != stClockRunning) && ((millis() - t) > 5000))
       stat=stClockRunning;
  switch(stat)
  {
    case stClockRunning:
      break;
    case stSetDay:
// init value
      value=day();
//button up pressed
      while(readPin(clockUp,300))
      {
        value++;
        if (value > 31)
          value=1;
        setRTCTime(hour(),minute(),second(),value,month(),year());
        printTime();
      }
//button down pressed
      while(readPin(clockDown,300))
      {
        value--;
        if (value < 1)
          value=31;
        setRTCTime(hour(),minute(),second(),value,month(),year());
        printTime();
      }
      break;
// see comments stSetDay
    case stSetMonth:
      value=month();
      while(readPin(clockUp,300))
      {
        value++;
        if (value > 12)
          value=1;
        setRTCTime(hour(),minute(),second(),day(),value,year());
        printTime();
      }
      while(readPin(clockDown,300))
      {
        value--;
        if (value < 1)
          value=12;
        setRTCTime(hour(),minute(),second(),day(),value,year());
        printTime();
      }
      break;
    case stSetYear:
      value=year();
      while(readPin(clockUp,300))
      {
        value++;
        if (value > 2050)
          value=2000;
        setRTCTime(hour(),minute(),second(),day(),month(),value);
        printTime();
      }
      while(readPin(clockDown,300))
      {
        value--;
        if (value < 2000)
          value=2050;
        setRTCTime(hour(),minute(),second(),day(),month(),value);
        printTime();
      }
      break;
    case stSetHour:
      value=hour();
      while(readPin(clockUp,300))
      {
        value++;
        if (value > 23)
          value=0;
        setRTCTime(value,minute(),second(),day(),month(),year());
        printTime();
      }
      while(readPin(clockDown,300))
      {
        value--;
        if (value < 1)
          value=24;
        setRTCTime(value,minute(),second(),day(),month(),year());
        printTime();
      }
      break;
    case stSetMinute:
      value=minute();
      while(readPin(clockUp,300))
      {
        value++;
        if (value > 59)
          value=0;
        setRTCTime(hour(),value,second(),day(),month(),year());
        printTime();
      }
      while(readPin(clockDown,300))
      {
        value--;
        if (value < 0)
          value=59;
        setRTCTime(hour(),value,second(),day(),month(),year());
        printTime();
      }
      break;
    case stSetSecond:
      value=minute();
      while(readPin(clockUp,300))
      {
        value++;
        if (value > 59)
          value=0;
        setRTCTime(hour(),minute(),value,day(),month(),year());
        printTime();
      }
      while(readPin(clockDown,300))
      {
        value--;
        if (value < 0)
          value=59;
        setRTCTime(hour(),minute(),value,day(),month(),year());
        printTime();
      }
      
  }

Comentários

  1. Parabens por compartilhar seu projeto muito bom obrigado.

    ResponderExcluir
    Respostas
    1. Douglas, muito bom que vc tenha gostado. Se todo mundo fizer o mesmo, a nossa vida fica melhor, certo?

      Excluir
  2. Mauro fiquei super feliz em ler essa postagem, estou desenvolvendo um despertador com arduino, e estava sem ideia para criar a interface para setar a hora de despertar, tu me salvou cara, parabens, por favor continue assim... faz 40 minutos que to no teu blog e ja favoritei umas 10paginas

    ResponderExcluir
    Respostas
    1. Bruno, que bom que vc gostou, esse é o espírito da coisa. Realmente é fácil usar essa rotininha de acertar a hora para estar a hora de despertar.
      Apareça de vez em quando, ou passe a segar o blog, sempre tem uma e outra novidade.

      Excluir
  3. Respostas
    1. Boa noite tentei suas fontes com meu arduino uno e me deu oerro:
      error: 'hour' was not declared in this scope
      sketch_aug09c:34: error: 'minute' was not declared in this scope
      sketch_aug09c:35: error: 'second' was not declared in this scope
      sketch_aug09c:36: error: 'day' was not declared in this scope
      sketch_aug09c:37: error: 'month' was not declared in this scope
      sketch_aug09c:38: error: 'year' was not declared in this scope
      sketch_aug09c.ino: In function 'void setRTCTime(int, int, int, int, int, int)':
      sketch_aug09c:118: error: 'setTime' was not declared in this scope
      sketch_aug09c:119: error: 'time_t' was not declared in this scope
      sketch_aug09c:119: error: expected `;' before 't'
      sketch_aug09c:121: error: 'RTC' was not declared in this scope
      sketch_aug09c:121: error: 't' was not declared in this scope
      sketch_aug09c.ino: In function 'void setup()':
      sketch_aug09c:131: error: 'RTC' was not declared in this scope
      sketch_aug09c:131: error: 'setSyncProvider' was not declared in this scope
      sketch_aug09c:132: error: 'timeStatus' was not declared in this scope
      sketch_aug09c:132: error: 'timeSet' was not declared in this scope
      sketch_aug09c.ino: In function 'void loop()':
      sketch_aug09c:162: error: 'day' was not declared in this scope
      sketch_aug09c:169: error: 'hour' was not declared in this scope
      sketch_aug09c:169: error: 'minute' was not declared in this scope
      sketch_aug09c:169: error: 'second' was not declared in this scope
      sketch_aug09c:169: error: 'month' was not declared in this scope
      sketch_aug09c:169: error: 'year' was not declared in this scope
      sketch_aug09c:178: error: 'hour' was not declared in this scope
      sketch_aug09c:178: error: 'minute' was not declared in this scope
      sketch_aug09c:178: error: 'second' was not declared in this scope
      sketch_aug09c:178: error: 'month' was not declared in this scope
      sketch_aug09c:178: error: 'year' was not declared in this scope
      sketch_aug09c:184: error: 'month' was not declared in this scope
      sketch_aug09c:190: error: 'hour' was not declared in this scope
      sketch_aug09c:190: error: 'minute' was not declared in this scope
      sketch_aug09c:190: error: 'second' was not declared in this scope
      sketch_aug09c:190: error: 'year' was not declared in this scope
      sketch_aug09c:198: error: 'hour' was not declared in this scope
      sketch_aug09c:198: error: 'minute' was not declared in this scope
      sketch_aug09c:198: error: 'second' was not declared in this scope
      sketch_aug09c:198: error: 'year' was not declared in this scope
      sketch_aug09c:203: error: 'year' was not declared in this scope
      sketch_aug09c:209: error: 'hour' was not declared in this scope
      sketch_aug09c:209: error: 'minute' was not declared in this scope
      sketch_aug09c:209: error: 'second' was not declared in this scope
      sketch_aug09c:217: error: 'hour' was not declared in this scope
      sketch_aug09c:217: error: 'minute' was not declared in this scope
      sketch_aug09c:217: error: 'second' was not declared in this scope
      sketch_aug09c:222: error: 'hour' was not declared in this scope
      sketch_aug09c:228: error: 'minute' was not declared in this scope
      sketch_aug09c:228: error: 'second' was not declared in this scope
      sketch_aug09c:236: error: 'minute' was not declared in this scope
      sketch_aug09c:236: error: 'second' was not declared in this scope
      sketch_aug09c:241: error: 'minute' was not declared in this scope
      sketch_aug09c:247: error: 'second' was not declared in this scope
      sketch_aug09c:255: error: 'second' was not declared in this scope
      sketch_aug09c:278: error: expected `}' at end of input
      pode me ajudar para resolver

      Excluir
    2. Anônimo.

      Acabei de dar Ctrl-C/Ctrl-V do códio acima no Arduino e compilou direitinho, veja a mensagem que dá no fim:

      Binary sketch size: 9.434 bytes (of a 30.720 byte maximum)

      Eu acho que tá faltando alguma biblioteca na sua máquina, porque essas funções de que ele reclama não estão mesmo definidas nesse fonte, mas em alguma das lib indicadas com #include no começo do script. Veja se ele dá alguma mensagem antes dessas indicando qual está faltando, ou então confira no diretório libraries do Arduino se elas estão lá.

      Excluir
  4. Deixe me perguntar, acha que é possível adaptar esse código para um PIC da família 18f usando MikroC? E pq os comentários estão em inglês?

    ResponderExcluir
    Respostas
    1. 1) Como o código é muito simples, acredito que ele rodará em quase qualquer processador.

      2) Boa pergunta. É que, escrevendo ao menos o código em inglês, gringos podem também entender e usar o que eu posto aqui. E como os programadores brazucas normalmente se viram bem com códigos e comentários em inglês, isso não atrapalha os nossos compatriotas...

      E pelo que eu vejo nas etatísticas do blogger, muita gente de outras terras acaba realmente passando por cá.

      Obrigado,

      Mauro

      Excluir
  5. Qual programa você esta utilizando para programas, MickroC ou Visual Basic??
    Pois essa linguagem que esta utilizando e tudo C ??

    ResponderExcluir
    Respostas
    1. É Arduino amigo, ele usa C++. MikroC normalmente é pra PIC. Visual basic é diferente de Basic que usam pra MCUs

      Excluir

Postar um comentário

Postagens mais visitadas deste blog

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte III

Dividindo um programa (sketch) do Arduino em mais de um arquivo

Controle PID de Potência em Corrente Alternada - Arduino e TRIAC - Parte I