segunda-feira, 23 de abril de 2012

Código Fonte RTC+LCD - Curso Arduino Advanced - Aula 7


Pessoal,

Segue abaixo o código fonte utilizado na Aula 7 do Curso Arduino Advanced, sobre o Relógio em Tempo Real com Display LCD 16x2.



#include
#include
#include


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


void setup()
{
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  lcd.begin(16, 2);
  if (!RTC.isrunning())
  {
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
}


void loop()
{
  DateTime agora = RTC.now();
  String relogio_data = "DT: ";
  String relogio_hora = "HR: ";
  
  int dia = agora.day();
  int mes = agora.month();
  int ano = agora.year();
  
  relogio_data += ArrumaZero(dia);
  relogio_data += "/";
  relogio_data += ArrumaZero(mes);
  relogio_data += "/";
  relogio_data += ano;
  
  int hora = agora.hour();
  int minuto = agora.minute();
  int segundo = agora.second();
  
  relogio_hora += ArrumaZero(hora);
  relogio_hora += ":";
  relogio_hora += ArrumaZero(minuto);
  relogio_hora += ":";
  relogio_hora += ArrumaZero(segundo);
  
  lcd.setCursor(0, 0);
  lcd.print(relogio_data);
  lcd.setCursor(0, 1);
  lcd.print(relogio_hora);
  
  delay(500);
}


String ArrumaZero(int i)
{
  String ret;
  if (i < 10) ret += "0";
  ret += i;
  return ret;
}


Abraços,
Renato

sábado, 7 de abril de 2012

Matrizes Multi-Dimensionais no Arduino

Em uma aula do Curso Arduino aprendemos sobre matrizes de 1 dimensão, ou seja, matrizes com um indíce. Não existe nada que diga que matrizes são limitadas a uma única dimensão de vetores. Na verdade, você pode ter um número arbitrário de dimensões em uma matriz. As matrizes de 2 dimensões são muito comuns, especialmente para guardar coisas como coordenadas de uma tela, ou linhas e colunas de uma planilha. Dimensões maiores são usadas quando temos mais aspectos que especificam mais itens únicos (coordenadas 3D, por exemplo).
Uma coisa importante a se entender sobre matrizes é que tecnicamente, não existe tal coisa como matriz multi-dimensional. Todas camadas são vetores (ou matrizes de uma dimensão), mas algumas delas contém matrizes de matrizes de matrizes. Isso significa que quando você encontra algo como isso:
int multiarray[4][2]


Você provavelmente está pensando em uma grade de inteiros como isso:
   0       1
0 [0][0]  [0][1]
1 [1][0]  [1][1]
2 [2][0]  [2][1]
3 [3][0]  [3][1]


Na realidade, o Arduino não pode guardar a “grade”, pois a memória é uma longa linha de endereços. A linguagem C trata cada linha como uma matriz de 2 elementos, a qual é um único elemento de 4 matrizes de elementos. Em outras palavras, cada elemento é uma matriz, que contém 2 elementos. Então a variável multiarray[0] é uma matriz de 2 elementos, multiarray[1] é outra matriz de 2 elementos, assim por diante. Isso também significa que multiarray[0] é um ponteiro! O tipo da variável multiarray[0] é int*. Assim, como a variável multiarray é um ponteiro para multiarray[0], isso significa que o tipo dela é int(*)[2]!!!
Se você pensa que está ficando confuso, você está certo! Se você acha que existe muita probabilidade de um código baseado em matrizes não funcionar, acertou de novo! Vamos adicionar mais um pouco de confusão aqui. Eu disse que a matriz não pode ser armazenada como uma grade, vamos dar uma olhada como ela é guardada.

A variável multiarray tem 4 elementos, então deve se parecer com isso:
|  conteúdo em 0 || conteúdo em 1 || conteúdo em 2 || conteúdo em 3 |
   multiarray[0]    multiarray[1]   multiarray[2]     multiarray[3]

Como cada elemento de multiarray é uma matriz de 2 inteiros, que significa que “conteúdo em” são 2 inteiros consecutivos, assim:
memória:    |[int0] [int1]||[int0] [int1]||[int0] [int1]||[int0] [int1]|
multiarray:       [0]            [1]            [2]            [3]
multiarray:  [0][0] [0][1]  [1][0] [1][1]  [2][0] [2][1]  [3][0] [3][1] 

Isso significa que você pode lidar de duas formas, como 4 matrizes de 2 elementos, ou uma matriz simples de 8 elementos.

Vamos ver como utilizar as duas formas de acessar matrizes, utilizando funções.
void setup()
{
   Serial.begin(9600);
}
void setarray(int ma[][2],int size)
{
  for (int i=0;i<size;i++)
    for (int j=0;j<2;j++)
      ma[i][j] = 10*i+j;
}
void printarray(int* ma,int dim1, int dim2)
{
  for (int i=0;i<dim1;i++)
  {
    for (int j=0;j<dim2;j++) {
      Serial.print(*(ma+(i*dim2+j)));
 Serial.print(" ");
     }
    Serial.println(" ");
  }
}
void loop()
{
  int multiarray[4][2];
  setarray(multiarray,4);
  printarray(&multiarray[0][0],4,2);
   while(true); // fica parado
}


Na função setarray(), o tamanho da sub-matriz é fixa, ficando mais fácil de utilizar. O problema é que não é flexivel. Em contrapartida, printarray() é muito mais complicado de implementar, mas muito mais flexível também. Repare que printarray simplesmente pega o endereço do primeiro elemento e o explora de forma linear, da mesma forma que é armazenado na memória. Ao utilizar o código acima, temos o seguinte resultado:
0 1 
10 11 
20 21 
30 31 

Não é necessário dizer que matrizes de 3, 4 ou mais dimensões aumentam muito a complexidade quando utilizadas em parâmetros de funções. 

domingo, 1 de abril de 2012

Manifesto do Raduino

Pessoal,

Recebi um email do Marcelo Rodrigues, fundador do Laboratório de Garagem, me ameaçando de processo judicial por difamação.

Abaixo trechos do email enviado por Marcelo Rodrigues para Renato Aloi:

"...Você tem 24 horas para retirar do ar o tópico "Manifesto Raduino" do seu blog..."

e também:

"...onde você calunia e difama o meu nome e o da nossa instituição, ou vou entrar com uma ação contra você na justiça..."

Decidi então retirar o manifesto do ar, dentro do prazo que ele me deu de 24 horas.

Queria agradecer a todos que me apoiaram, mas eu sou um desenvolvedor independente de tecnologia e não tenho condições de ir adiante com o Manifesto e arcar com os custos gerados por processos judiciais.

Obrigado de coração a todos que acompanham meu trabalho... Por isso vou recuar nessa questão e continuar trabalhando, para que aqueles que acompanham meu trabalho não sejam prejudicados.

Abraços,
Renato Aloi

terça-feira, 13 de março de 2012

Portas Analógicas do Arduino

Uma descrição das portas analógicas de um chip Arduino (Atmega8, Atmega168, Atmega328, or Atmega1280).

Conversor A/D

Os microcontroladores Atmega usados para o Arduino contém embarcados 6 canais de conversão analógica-digital (A/D). O conversor do Arduino tem uma resolução de 10 bits, retornando inteiros entre 0 e 1023. Enquanto a função principal das portas analógicas para a maioria dos usuários do Arduino é ler sensores, as portas analógicas também tem a funcionalidade de entrada/saída de propósito geral (GPIO) (da mesma forma que as portas digitais 0~13).
Consequentemente, se o usuário precisar mais entradas/saídas de propósito geral, e todas as portas analógicas não estiverem em uso, estas podem ser usadas para GPIO.

Mapeamento de Portas

As portas analógicas podem ser usadas da mesma forma que portas digitais, utilizando apelidos A0 (para a porta analógica 0), A1 etc. Por exemplo, o código deverá parecer com o abaixo, configurando a porta analógica como saída (OUTPUT) e atribuindo o valor alto (HIGH):
pinMode(A0, OUTPUT);
digitalWrite(A0, HIGH);

Resistores de Elevação

As portas analógicas também tem resistores de elevação (pull-up), que funcionam exatamente da mesma forma que nas portas digitais. Eles são ativados por comandos como:
digitalWrite(A0, HIGH);  // set pullup on analog pin 0 
enquanto a porta for de entrada (INPUT).
Tome cuidado, entretanto, que ligar um resistor de elevação em uma porta analógica afetará os valores lidos pela função analogRead().

Detalhes e Avisos

O comando analogRead não funcionará direito se a porta não for corretamente configurada para saída (OUTPUT), então se esse é o caso, configure de volta a porta para entrada (INPUT) para usar a função analogRead. De forma similar, se a porta for configurada como HIGH e como saída, o resistor de elevação ficará ativado, mesmo voltando a porta para entrada.
O datasheet do Atmega também avisa sobre modular portas analógicas em uma proximidade temporal ao fazer leituras A/D (analogRead) em outras portas analógicas. Isso pode causar ruído elétrico e introduzir jiter no sistema analógico. Pode ser desejável, depois de manipular as portas analógicas (em modo digital), adicionar um atraso antes de começar a usar a função analogRead() para ler outras portas analógicas.

Traduzido do Original:

Para pt-BR por Renato Aloi


Arduino PWM

O Exemplo “Fading” (File>Example>Basics>Fade) demonstra o uso da saída analógica (PWM) para esvanecer um LED. Este exemplo está disponível no menu do Arduino: File->Sketchbook->Examples->Analog.

Modulação por Largura de Pulso, ou PWM (do inglês Pulse Width Modulation), é uma técnica de amostrar o sinal analógico em termos digitais. Controle digital é usado para criar uma onda quadrada, um sinal alternando entre ligado e desligado. Este padrão ligado/desligado pode simular voltagens entre totalmente ligado (5 Volts) e desligado (0 Volts), alternando a porção de tempo que o sinal gasta ligado contra o tempo que o sinal gasta desligado. A porção de tempo “ligada” é chamada de largura de pulso. Para variar valores analógicos, você muda, ou modula a largura de pulso. Se você repetir esse padrão ligado/desligado rápido suficiente com um LED, por exemplo, o resultado é como se o sinal fosse uma voltagem estável entre 0~5V, controlando o brilho do LED.
No gráfico abaixo, as linhas verdes representam um período regular de tempo. Esta duração, ou período, é o inverso da frequência do PWM. Em outras palavras, com a frequência do PWM do Arduino por volta de 500Hz, as linhas verdes devem medir 2 milissegundos, cada. Uma chamada na função analogWrite() está na escala de 0~255, tanto que analogWrite(255) aciona um ciclo de trabalho (duty cycle) de 100%, e analogWrite(127) é um duty cycle de 50% (na metade do tempo), por exemplo.

Uma vez que você executar esse exemplo, sacuda seu Arduino para frente e para trás. O que você está fazendo é essencialmente mapeando o tempo através do espaço. Para seus olhos, o movimento desfoca o piscar do LED em uma linha. No esvanecer do LED, ligando e desligando, essas linhas vão brilhar e encolher em comprimento. Agora você está vendo a largura de pulso.

Written by Timothy Hirzel

Traduzido para pt-BR por Renato Aloi

quinta-feira, 2 de fevereiro de 2012

Imprimir Valor de Porta Analógica Através da Serial


Este exemplo mostra como você pode ler uma porta digital usando um potenciômetro. Um potenciômetro é um dispositivo mecânico simples, que permite variar a resistência quando o êmbolo é girado. Ao passar voltagem através do potenciômetro e através de uma porta analógica do seu Arduino, é possível medir a quantidade de resistência produzida pelo potenciômetro, como um valor análogo. Neste exemplo você monitorará o estado do seu potenciômetro após estabelecer comunicação Serial entre o Arduino e o PC.



Material Necessário

  • Placa do Arduino
  • Potenciômetro de 10K ohms

Circuito

Conecte os três fios do potenciômetro na sua placa do Arduino. O primeiro fio vai no GND (0V), o pino central na porta analógica zero (A0) e o terceiro pino do potenciômetro vai no VCC (5V).


Ao girar o êmbolo do potenciômetro, você altera a quantidade de resistência em um ou outro lado da trilha na qual o pino central está montado. Isto muda a voltagem no pino central. Quando a resistência entre o pino central e o lado conectado no 5V está perto de zero (e a resistência do outro lado está perto de 10k ohms), a voltagem no pino central fica perto dos 5V. Quando o cenário é invertido, a voltagem no pino central se aproxima dos 0 volts, ou GND. Esta voltagem é a voltagem analógica que você está lendo como entrada.
O Arduino possui um circuito interno chamado conversor analógico-digital que efetua a leitura da variação de voltagem e a converte em um número entre 0 e 1023. Quando o êmbolo é girado em um sentido, teremos 0 volts entrando na porta analógica e o valor convertido é 0. Quando o êmbolo é girado completamente para o outro lado, teremos 5 volts entrando na porta e o valor convertido é 1023. Entre esses valores, a função analogRead() retorna um número entre 0 e 1023 que é a quantidade proporcional de voltagem sendo aplicada a porta.


Esquema Elétrico




Código

No programa abaixo, a única coisa que você precisa configurar na função setup() é a comunicação Serial, na velocidade de 9600 bauds (bits de dados por segundo), entre o Arduino e o PC, utilizando o comando abaixo:

Serial.begin(9600);

No laço principal do seu programa, na função loop() do seu código, você precisa estabelecer uma variável para armazenar o valor convertido da resistência do seu potenciômetro (que deve ser entre 0 e 1023, perfeito para o tipo int de variável).

int sensorValue = analogRead(A0);

Finalmente, você precisa imprimir essa informação para seu console Serial, convertido em decimal (DEC). Você pode fazer isso com o comando Serial.println() na sua última linha de código:

Serial.println(sensorValue, DEC)

Agora, quando você abrir o Monitor da Serial, no ambiente de desenvolvimento do Arduino (clicando no ícone exatamente ao lado do botão “Upload”, na barra de ferramentas), você deverá ver um fluxo constante de números entre 0-1023, correlacionados com a posição do êmbolo do potenciômetro. Ao girar o potenciômetro, esses números deverão refletir o valor convertido quase que instantaneamente.

/*
  AnalogReadSerial
 Reads an analog input on pin 0, prints the result to the serial monitor

 This example code is in the public domain.
 */


void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  Serial.println(sensorValue);
}