terça-feira, 15 de setembro de 2015

Java 8 DateTime API - LocalDate e Period

Olá Pessoal, hoje iremos retomar o nosso estudo sobre a nova API de Data do Java 8. Esse artigo é o segundo da série sobre o assunto, você pode ler a primeira parte clicanco aqui. No post anterior vimos as classes Instant e Duration, que são conhecidas por Computer Dates, e são usadas, por exemplo, para medir o tempo de duração de um algoritmo.

Nós humanos geralmente precisamos representar datas mais complexas, com dias, meses, anos, fusos horários. Isso não possível através de Instant. Para tal, precisamos utilizar a classe java.time.LocalDate, ideal para representar datas do tipo Human Dates

LocalDates

Existem basicamente dois tipos de classes para representar datas na nova API, as Local Date/Time (LocalDate e LocalDateTime) e a ZonedDateTime. As datas locais possuem uma data ou hora de um dia, mas sem associação fusos horários, por exemplo, 11/05/1984, que é o em que eu nasci. Porém essa data não representa um instante de tempo preciso. Precisamos usar então a classe ZonedDateTime, com ela podemos criar uma data do tipo: 11/05/1984 11:30 [America/Cayenne], que representaria o exato momento do meu nascimento. Vejamos então um primeiro exemplo do uso de LocalDate.


Como você deve ter notado, diferentemente do que ocorria em java.util.Date, não é possível instanciar uma classe LocalDate diretamente, ela também não pode ser estendida, pois é uma classe final. Além disso, a classe LocalDate é imutável, ou seja, nenhuma operação nela irá modificar os valores instanciados, seus métodos sempre retornarão uma nova instância com as modificações desejadas.

No exemplo acima foi utilizado o método now, que retorna a data corrente do sistema. Em seguida fizemos uso do método of(int ano, Month mes, int dia) que possui uma versão sobrecarregada of(int ano, int mes, int dia). Vale destacar que foi corrigida uma bizarrice que havia na versão antiga da API que usava 0 para Janeiro, e isso causava muita confusão, agora você pode usar Month.MAY ou 5 para criar uma data com mês de Maio.

Manipulando Datas

Vejamos algumas operações importantes que existem na classe LocalDate. Vamos ao código e em seguida comentaremos o que ele faz.

Neste exemplo vemos como é fácil, através dos métodos plusXXX e minusXXX, adicionar ou remover uma medida de tempo de uma data de forma fácil e segura, mesmo que a data precise passar de um mês para o outro ou mesmo de um ano comum para um ano bissexto.

Ajustadores de Tempo

Um outro conceito bacana que foi introduzido na nova API de Datas é o de Temporal Adjuster. Imagine que você deseja implementar uma agendador para algum evento que vai se repetir, por exemplo, toda primeira segunda-feira de cada mês. Você já deve imaginar o trabalhão que dava para fazer isso com a API antiga. Pois bem, agora temos a classe TemporalAdjusters, que possui vários métodos estáticos para operações como essas. Vejamos algumas possibilidades.

Diferença entre Datas

Quando trabalhamos com a classe Instant vimos que para calcular a diferença entre dois Instants usamos a classe Duration. O mesmo resultado pode ser obtido com a classe Period, que armazena a diferença entre duas instâncias de LocalDate. Podemos obter informações como número de dias, meses ou anos passados entre duas datas. Vejamos um exemplo demonstrando o uso de Period.

O método until retorna uma instância de Period, que armazena o tempo passado entre duas datas em anos, meses e dias, isso nos poupa algum trabalho de conversão, mas pode ser que queiramos saber quantos dias absolutos existem entre duas datas, para isso, usamos o  método until sobrecarregado que recebe dois parâmetros, o primeiro é a data que estamos comparando e o segundo é a unidade de tempo que desejamos calcular (os valores permitidos são: DAYS, WEEKS, MONTHS, YEARS, DECADES, CENTURIES, MILLENNIA, ERAS).

Conclusão

A nova API de Datas ficou bastante rica se comparada com a anterior. Apesar do maior número de classes, elas ficaram mais coesas e com responsabilidades bem definidas. Até aqui vimos as datas para computadores, Instant e Duration, e as datas para humanos, LocalDate e Period. No próximo post veremos como utilizar datas com horas e fusos horários. Até o próximo post!

sábado, 5 de setembro de 2015

Contador Binário com Raspberry Pi 2

Fala pessoal! Tô meio sumido do blog, mas hoje resolvi voltar com um post sobre um 'brinquedinho' que tem feito muito sucesso por aí: o Raspberry Pi. Pra quem não sabe, o Raspberry é um computador do tamanho de um cartão de crédito, no qual você pode conetar um monitor, teclado, mouse, e na versão mais nova (Pi 2) vem com porta Ethernet e HDMI. Se você quiser mais detalhes sobre o modelo 2 é só clicar aqui.

Fig. 1 - Raspberry Pi 2 Model B

O Raspberry é ideal para quem deseja explorar a computação em um nível um pouco mais baixo e aprender linguagens como Python ou Scratch (Na verdade dá pra usar várias outras linguagens como C, Java, Ruby, etc). A ideia desse post não é explicar todo o funcionamento do Raspberry, mas sim mostrar um aplicação bem simples escrita em Python e que faz uso da GPIO (General Purpose I/O). Vou deixar pra você a tarefa de pesquisar mais detalhes sobre o Pi (No final do post colocarei alguns links interessantes pra começar).

Digamos que é a GPIO que torna o Raspberry Pi divertido. Através dela podemos enviar e receber dados/sinais de/para dispositivo externos plugados ao Pi. Antes de começarmos a por a mão na massa, vejamos alguns detalhes sobre a GPIO. Na figura abaixo temos a GPIO do Pi 2 (os modelos anteriores possuem tamanho e pinagem diferentes).

Fig. 2 - GPIO Raspberry 2

A contagem dos pinos começa no canto inferior esquerdo da figura 2, e vai do Pino 1 até o Pino 40, na parte inferior direita. Você pode programar os pinos de diversas maneiras. As entradas podem receber sinais de sensores, de um computador ou de outros dispositivos. A saída pode ser usada pra acender LEDs, Displays, ou enviar sinais para outros dispositivos.

A GPIO fornece também pinos com saída de 3.3V, 5V e 0V (Ground ou Terra). E claro, é possível alterar o modo de operação do pino para INPUT ou OUTPUT programaticamente. Na figura a seguir podemos ver a descrição de cada um dos pinos da GPIO.
Fig. 3 - Descrição dos Pinos da GPIO

Hello Raspberry!

Vamos então dar início ao desenvolvimento do nosso programa. Construiremos um contador binário de três bits, ou seja, poderemos contar de 0 a 7 apenas. Para deixar o projeto mais simples utilizaremos LEDs para representar cada bit. Inicialmente o contador irá rodar automaticamente, mas depois acrescentaremos um botão que será usado para incrementar o contador. O programa será construído de forma incremental para você ir se familiarizando com os conceitos abordados. Para o projeto completo precisaremos dos seguintes componentes:
  • Raspberry Pi 2 Model B
  • 3 LEDs
  • 3 Resistores de 270 ohms
  • 1 Resistor de 1 Kohm 
  • 1 Push Button
  • 1 Protoboard
  • Fios para conexão (Macho-Fêmea e Macho-Macho)
Fazendo um LED piscar

A primeira versão do programa irá apenas acender e apagar um LED. Na figura abaixo você pode ver o desenho do circuito montado na Protoboard e na GPIO do Raspberry (Foi utilizado o programa Fritzing para fazer os desenhos).

Fig. 4 - Circuito com 1 LED

No LED a perna maior é o anodo (+) e a menor é o catodo (-), por isso ligamos o Pino 7 (3,3V de saída) no anodo do LED e o Pino 6 (Terra) no catodo. Ligamos um resistor de 270 ohms em série com o LED pra diminuir a corrente sobre ele, a ideal é torno 12 a 30 mA. O cálculo pode ser feito usando a Lei de Ohm, onde: R = V / I   => R = 3,3V / 12mA ~ R = 275 Ohms.

Deixando um pouco o mundo da eletrônica de lado, vamos agora o programa que fará o nosso LED piscar. O código foi escrito em Python e utiliza as libs time e RPi.GPIO. PS: Desde já esclareço que meu conhecimento de Python é bastante limitado, podem ficar a vontade para me corrigir caso eu cometa algum deslize. :)


Vejamos alguns pontos importantes sobre o código. No trecho em #1, o método GPIO.setmode configura a forma como os pinos da GPIO são referenciados, BOARD significa que a referência é a pinagem da placa, a outra opção é BCM, que usa como referência o número após GPIO no esquema da figura 3, ou seja, o pino é 7 no modo BOARD e 4 no modo BCM. Vale lembrar que a referência muda entre as versões do Raspberry.

O trecho em #2 apenas desabilita os warnings durante a execução do programa. O código do trecho #3 é importante, ele configura o pino como saída. Sempre que precisarmos ler ou escrever em um pino é preciso configurá-lo como entrada(GPIO.IN) ou saída(GPIO.OUT).

O trecho em #4 é o que faz com que o LED acenda e apague. O método output recebe 2 parâmetros, o primeiro é o número da pino (BCM ou BOARD) e o segundo é o valor a ser enviado, pode ser usado True, 1 ou GPIO.HIGH para acender, e False, 0, GPIO.LOW para apagar. Utilizamos o método sleep entre os estados apenas para termos o efeito do LED piscando. 

Ensinando o Pi a contar até 7! 

Nosso próximo passo agora é acrescentar mais dois LEDs ao projeto de forma que possamos representar números de 0 a 7 (000 a 111 em binário). Além disso, iremos modificar o programa Python para que ele faça a contagem e exiba o valor do contador através dos LEDs. A figura abaixo mostra o desenho do circuito com 3 LEDs. Os pinos utilizadas para representar os três bits foram: 7, 15, 16. Assim, o número 100 (4) será representado pelos LEDs 7(1), 15(0), 16(0).

Fig. 5 - Circuito com 3 LEDs

Precisamos alterar o programa que irá disparar o contador. Vejamos o código completo primeiro e em seguida farei alguns comentários sobre trechos que considero relevante.

No trecho #1 declaramos um array contendo a lista de pinos onde os LEDs estão conectados, isso vai nos ajudar no momento em que formos setar o estado de cada pino. O método Display recebe como parâmetro o número binário que será exibido, usamos o método zfill (#2) para garantir que enviaremos um número binário de 3 dígitos (001 por exemplo, ao invés de apenas 1), em seguida percorremos os pinos e setamos cada um deles pra 0 ou 1 de acordo com o número a ser exibido.

A contagem dos números é feita no método Count. Nele nós controlamos o valor do contador para este seja reiniciado sempre que atingir o valor 7 (máximo que podemos exibir com 3 bits, ou seja, 111). Em #3 usamos um método utilitário de Python que converte um número decimal em binário, como o valor retornado é uma string no formato '0b111', enviamos a substring a partir do índice 2. Por fim, o método loop executará a contagem até que o usuário interrompa o programa apertando as teclas: CTRL + C (#4), além de retornar os pinos aos seus estados iniciais.

Interagindo com o Pi!

Nosso contador está começando a ficar interessante, mas ainda ainda está faltando algo nele: Interatividade. Até aqui nós utilizamos os pinos da GPIO apenas como saída, mas e se precisarmos enviar alguma informação para o nosso programa? É isso que faremos a seguir. Nossa próxima tarefa será fazer com que o contador binário seja acionado através de um botão, e não mais fique executando de forma automática.

Os pinos da GPIO podem ser configurados como Entrada ou Saída. Como vimos anteriormente, ao configurarmos um pino como Saída, ele enviará uma tensão de aproximadamente 3.3V quando ligado e 0V quando desligado. Como Entrada, para que o Pi entenda o sinal recebido como sendo o valor lógico 1 é preciso uma tensão de entrada entre 1.5V e 3.3V, e para o valor lógico 0 qualquer tensão entre 0V e 1.5V (esses valores podem variar dependendo da versão do Pi). ATENÇÃO: Nunca utilize uma tensão maior que 3.3V em um pino da GPIO, pois você poderá causar danos permanentes em seu Raspberry.

Vejamos então o circuito final do projeto, o contador com os 3 LEDs e um botão para acionar a contagem. O circuito dos LEDs é o mesmo de antes, o botão do tipo push button foi ligado em série com um resistor, em um circuito conhecido como Pull Up Resistor, usado para garantir que o pino de entrada estará em nível lógico 1 enquanto o botão não for pressionado e em 0 quando for apertado.

Fig. 6 - Esquema com 3 LEDs e um botão de acionamento

Fig. 7 - Esquema real montado na protoboard

Por fim, vamos analisar o código que faz a leitura do pressionamento do botão e o acionamento da contagem. As mudanças no código foram poucas. Adicionamos um variável que faz referência ao pino em que o botão está ligado (#1) e configuramos esse pino como INPUT (#2).

A principal novidade está no trecho #3, onde está a lógica de incremento do contador ao pressionarmos o botão, fazendo com que o valor lógico do pino mude de HIGH para LOW (0 ou False). O restante do programa é igual ao que tínhamos desenvolvido no passo anterior. Vejamos então o código final completo.

Conclusão

O Raspberry Pi tem se mostrado uma ótima opção para quem deseja entrar no mundo dos embarcados. Com um tamanho razoavelmente pequeno, porém com uma configuração de hardware bastante generosa, o Pi pode ser usado em projetos bem simples como que fizemos, como em projetos bem sofisticados como: Media Center, Clusters, Arcades, Mini Computadores, dentre outros.

O preço do Pi aqui na República das Bananas ainda é um pouco salgado, algumas lojas chegam a cobrar cerca de R$ 300,00 pelo modelo B 2, um verdadeiro assalto visto que o preço lá fora é de apenas U$ 35.00 (com um dólar a R$ 4,00 ainda assim custaria apenas R$ 140,00). No Mercado Livre existem algumas lojas vendendo a preços mais mais amigáveis, fazendo uma boa pesquisa é possível achar um que caiba no seu bolso. :)

Você pode incrementar o projeto que apresentamos adicionando um outro botão para decrementar o número, exibir a saída através de um display de 7 segmentos, ou até mesmo um display de LCD daqueles usados em calculadoras, por exemplo. Assim que possível irei escrever um outro artigo mostrando como utilizar a linguagem Java para interagir com a GPIO. Espero que tenham gostado e fiquem a vontade para enviar suas críticas e sugestões. Até o próximo post!

Links Interessantes