Postagem em destaque

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

Este post é o primeiro de uma série de seis que escrevi tratando de controle de potência e PID (controle proporcional, integral e derivativo...

sexta-feira, 26 de julho de 2013

Cinquenta!


Nós, humanos que somos, gostamos de efemérides. Prá quem não sabe o que é, efeméride é uma data comemorativa, como o nosso aniversário, ou o 9 de julho, data em que São Paulo perdeu uma guerra mas ganhou um feriado.

Daí que outro dia eu me lembrei de que esse blog estaria prestes a fazer um ano. Fui conferir a data e vi que ele nasceu no dia 12/06/2012, portanto coincidente com uma outra efeméride das mais valorizadas por essas bandas, o Dia dos Namorados. Ou seja, já era.

Aí fui olhar o número de acessos: quem sabe vai dar um número redondo por esses dias? Nova decepção: há pouco tempo passamos pelos 20.000 acessos, ou seja, vai demorar meses para chegar aos 30.000.

Ocorre que... cheguei ao post de número 50! Então taí a procurada efeméride, até porque o cinquenta anda em alta: 50 tons de Arduino & Automação.

A "filosofia" do automatoBr é muito simples: relatar projetos de automação desenvolvidos ou apoiados por mim bem como outras atividades do Automação no Parque. Tudo com os fontes, diagramas etc, possibilitando a quem quiser repetir a experiência toda a informação necessária.

A criação do blog me levou ao Parque Santos Dumont para o Automação no Parque, que por sua vez levou a juntar a turma do Hacker Clube por lá. Trouxe também algumas amizades virtuais e até algum serviço, na forma de projetos em que prestei consultoria para pessoas que me descobriram através do blog.

Um abracadabraço aos amigos e frequentadores do automatoBr. E que venham os próximos 50 posts...

Sensor refletivo com filtro polarizado e Aduino - usando pullup interno

Dia desses apareceu uma turma de alunos com um projeto de um detetor que, funcionando em cima de uma esteira, detectasse num engradado de cerveja onde não houvesse garrafas. A partir daí, o sistema vai colocar garrafas para completar o engradado.

Começamos a trabalhar no projeto do jeito que eu normalmente faço: um curso de Arduino & programação e a partir daí começamos a estudar os detalhes do projeto. Avaliamos o uso de sensores de ultrassom para detectar as posições vazias e parece que vai dar certo. Parece que vão servir, eu avaliei os dois tipos de sensores que analisei em um post anterior.

Outro teste que fizemos foi com um sensor reflexivo com vidro polarizado. Esse sensor será usado para detectar a passagem das caixas pela esteira. Aqui  informações sobre ele.

É um sensor feito para a indústria, robusto e pode ser alimentado com 12 a 240 Vcc ou Vca.
Ligamos o bicho numa fonte de 24 Vcc e ele funcionou. Liguei então o relé ao Arduino. Normalmente, eu faria isso ligando o relé através de um circuito pull down, conforme explico aqui em outro post. Acontece que dia desses eu descobri que o Arduino tem internamente resistores PULLUP, então resolvi testar essa feature. E não é que funcionou?

Sensor de frente:



 De lado:



De cima, mostrando LEDs de controle (POWER e acionamento) e dip-switch de configuração.



















Aqui, o dito ligado ao Arduino. A conexão é simples: conecta-se um pino digital do Arduino a um fio do relé e o outro fio ao terra do Arduino, ou seja, não tem mais o resistor pull down. E a fonte industrial de 24V, claro, para alimentar o sensor.



Abaixo, o fonte do programa de testes:

void setup()
{
  pinMode(5,INPUT_PULLUP);
  Serial.begin(9600);
}

void loop()
{
  Serial.println(digitalRead(5));
}


Observe a definição do pinMode como INPUT_PULLUP, que indica que, além de usar o pino como INPUT deve ser ligado o resistor de pullup.

O efeito do resistor é o seguinte: se o relé está aberto, ou seja, o pino do Arduino não está conectado ao terra, o resistor "pull up" (empurra prá cima) o valor da porta, ou seja, ela será levada a 5V. Assim, quando o o sensor não estiver detectando nada, já que ele é normalmente aberto, o Serial.println irá imprimir o valor 1, correspondente aos 5V lidos no pino. Quando o sensor detectar algo entre ele e o espelho ele fechará o relé, conectando o pino 5 à terra, ou seja, a porta lerá 0V, ou o valor zero.

Por fim, vídeo do sensor funcionando. Essa é uma prova de que o Arduino pode perfeitamente ser conectado a sensores usados pela indústria, não só sensores de "brinquedo" ou desenhados especificamente para ele.


domingo, 21 de julho de 2013

Curso de Arduino e Automação, um tapa no visual do Hacker Clube SJC

Algumas fotos de atividades recentes. Primeiro, um curso de Arduino e Automação que eu dei para a primeira turma duas semanas atrás. Eu bolei esse curso para alunos de engenharia, principalmente o pessoal de Automação e Controle, mas também para os alunos de Engenharia de Produção e Elétrica. Um curso de 16 horas, prática pura, com conceitos de controle inteligente como o PID (ver posts aqui no blog). Modéstia às favas, ficou muito bom. Abaixo, fotos das práticas montadas e operadas pelos alunos:

 




Controle de motor de passo com o 74HC595.















Mesa para estudo de PID: controle de temperatura. Dia desses eu faço um post sobre esse dispositivo,que ficou bem didático.

"Sapassado", como diz o mineiro, demos um tapa no visual da sala de hardware do Hacker Clube. Abaixo, fotos do antes, do durante e do depois.

Como a janela se abre para fora, tivemos que colocar uma grade por dentro prá reforçar a segurança.
 Sucata a espera de reaproveitamento.

 Tava bem sujinha a sala...
Primeiro, tivemos que mover a tralha para a sala...























depois lixar...

e pintar.



Lavoro finito!

quarta-feira, 17 de julho de 2013

Explorando sensores de ultrassom - sensor de estacionamento



Nove de julho, feriado paulista (Revolução Constitucionalista de 1932), tarde fria, 'bora Arduinar. Tinha que testar dois sensores de distância do tipo ultrassom para um projeto, então montamos dois circuitos, eu e o meu ajudante da ocasião, Pedro, um para testar cada sensor.

Esses sensores funcionam da seguinte forma: eles emitem som numa frequência que não escutamos (muito aguda) e em seguida espera pelo eco do som emitido, enviando a informação da chegada do eco para o Arduino, que aí calcula a distância. Sabendo-se que o som percorre 340 m/s (isso no ar, ao nível do mar), pode-se calcular a distância percorrida pelo som até o obstáculo multiplicando-se o tempo decorrido entre a emissão e a detecção do eco e dividindo-se por dois. Para ver uma animação explicando como esse tipo de sensor funciona, clique aqui.

Esses são os sensores. O primeiro, HC-SCR04, é bom e barato: acha-se até por R$ 9,90 no Mercado Livre.
Sensor Ultra Sonico Distancia Hc-sr04 Ultrassom Pic Arduino

Abaixo, montado no circuito. O Vcc é 5V, os pinos de trigger e echo são ligados a pinos digitais do Arduino.




O segundo sensor é o LV-EZ1, da MaxBotix. A primeira coisa que chama a atenção é a diferença de preços entre os dois sensores: este custa R$ 129,00 no Lab de Garagem. Taí o datasheet.
Sensor de distância por ultrassom - LV-EZ3
Ele é de fato menor, e tem três formas de conexão com o circuito externo: analógica, largura de pulso (PW) ou serial.

Na analógica vc liga o pino de saída AN do sensor a um dos pinos analógicos do Arduino. A sensibilidade é de Vcc/512 por polegada. Em 5V no Arduino, temos: 5V/512/pol = 9.8 mV/pol. Como a saída do Arduino varia de 0 a 1023, temos que dividir por dois o valor da saída analógica, ou seja, o código fica:

int v = analogRead(0)/2; // a saída A do sensor está ligada ao pino 0
float distcm = v * 2.54;

Na conexão como largura de pulso, o funcionamento é análogo ao HC-SCR04: conecta-se os pinos PW e BW a dois pinos digitais do Arduino. O código eu colocarei como exemplo no fim desse artigo.

Por fim, a conexão via serial, onde o sensor fornece o valor diretamente a uma conexão serial (RX/TX).

Para testar os sensores, montamos um circuito de um sensor de estacionamento, onde um LED e um buzzer darão aviso visual e sonoro da aproximação de um obstáculo. Esse sensor funciona exatamente como um sensor de estacionamento como os encontrados nos veículos hoje. Abaixo, fotos do circuito.



Aqui, vídeo dos dois circuitos funcionando e o código (o mesmo código) correspondente.

IMPORTANTE: no código abaixo existe a seguinte instrução:

    long distancia = duration /29 / 2 ;  

De onde vem esse 29???

Do seguinte: a instrução

    long duration = pulseIn(echoPin,HIGH);

coloca na variável duration o tempo, em microssegundos, que o pulso leva para ir até o obstáculo e voltar até o sensor.

Sabemos que a velocidade média do som no ar é de aprox. 340 m/s, então em 1.000.000 microssegundos o som percorre 340 m.

Isso significa que, para saber a distância, devemos fazer a seguinte conta:

distancia =  duration * 1.000.000 ms / 340 m/s / 2 (porque o duration dá o tempo de ida e volta)

1.000.000 / 340 = 2.94, o que dá a distância em metros. Como a maioria das medidas que se faz com esse sensor é em centímetros (o alcance dele é pequeno), a gente multiplica a constante por 100, o que nos dá o valor 29.

Obrigado ao leitor jkampus que me fez fazer essa alteração.






#define echoPin 13 //Pino 13 recebe o pulso do echo  
#define trigPin 12 //Pino 12 envia o pulso para gerar o echo  

void setup()  
{  
   Serial.begin(9600); //inicia a porta serial  
   pinMode(echoPin, INPUT); // define o pino 13 como entrada (recebe)  
   pinMode(trigPin, OUTPUT); // define o pino 12 como saida (envia)  
   pinMode(4, OUTPUT); // define o pino 12 como saida (envia)  
}  
  
void loop()  
{  
  //seta o pino 12 com um pulso baixo "LOW" ou desligado ou ainda 0  
    digitalWrite(trigPin, LOW);  
  // delay de 2 microssegundos  
    delayMicroseconds(2);  
  //seta o pino 12 com pulso alto "HIGH" ou ligado ou ainda 1  
    digitalWrite(trigPin, HIGH);  
  //delay de 10 microssegundos  
    delayMicroseconds(10);  
  //seta o pino 12 com pulso baixo novamente  
    digitalWrite(trigPin, LOW);  
  //pulseInt lê o tempo entre a chamada e o pino entrar em high  
    long duration = pulseIn(echoPin,HIGH);  
  //Esse calculo é baseado em s = v . t, lembrando que o tempo vem dobrado  
  //porque é o tempo de ida e volta do ultrassom  
    long distancia = duration /29 / 2 ;  
  
    Serial.print("Distancia em CM: ");  
    Serial.println(distancia);  
    if (distancia < 5)
    { 
      digitalWrite(4,  HIGH);
      tone(8,440);
      delay(50);
      noTone(8);
      delay(50);
    }
    else
       if (distancia < 10)
       {
         digitalWrite(4,  HIGH);
         tone(8,440);
         delay(100);
         noTone(8);
         delay(100);
       }
    digitalWrite(4, LOW);
    delay(100); //espera 1 segundo para fazer a leitura novamente  
}  

segunda-feira, 8 de julho de 2013

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();
      }
      
  }

domingo, 7 de julho de 2013

Automação no Parque, fim de junho

Dias atrás, tivemos mais um dia de desmonte com as crianças no nosso automação no parque. Espiem as fotos, e vejam o tamanho da festa: