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...

domingo, 17 de novembro de 2013

Carrinho segue-faixa I

Como projeto final de automação da criançada do projeto decolar resolvi construir um carrinho segue-faixa para que eles o programem. Peguei um kit emprestado com os amigos da Acrux e bolei um sensor de faixa, que encomendei ao amigo Euclas que o construiu. Aqui, imagens do carrinho e do sensor:

Carrinho visto de cima
Para quem não conhece, o segue-faixa é um carrinho que consegue seguir uma faixa preta pintada no chão, que define uma espécie de pista que o carrinho deve seguir. É um autômato clássico e simples, muito usado para ensinar automação e em competições de robótica.

Na foto acima, do lado esquerdo (parte traseira, fundo amarelo), o Arduino Mini. No meio do carrinho, o driver que comanda os dois motores (tração e direção) e na frente o sensor de faixa. A bateria está embaixo, dentro do chassis do carrinho.

Sensor de faixa, visto de cima

Detalhe do sensor de faixa, visto de baixo.

A foto acima mostra o sensor de faixa. Composto de 3 sensores de luminosidade tipo LDR e dois LEDs, ele funciona da seguinte forma: os LEDs, de cor branca, são acesos. O sensor LDR (esses com um desenho em ziguezague) tem a sua resistência variando de acordo com a quantidade de luz que incide sobre ele. Como a faixa preta reflete uma quantidade de luz diferente do piso, a ideia é que o programa use essa diferença de valores para detectar se a faixa está "escapando" para um ou outro lado, virando a direção do carrinho para corrigir a trajetória e "trazer a faixa" para o centro, alinhando o carrinho.

Acontece que o Arduino não "lê" (mede) resistência elétrica. A única grandeza que ele lê é variação de tensão, de 0 a 5V. Devemos então transformar uma variação de resistência em uma variação de tensão correspondente. Isso pode ser feito usando-se um circuito chamado divisor de tensão. Neste blog existem alguns posts que explicam a ideia, então não vou me repetir, basta vc clicar aqui e aprender como funciona a coisa.

Abaixo o esquema elétrico do sensor.


O esquema acima, feito no Fritzing, é só uma representação do circuito, já que não foi usada uma protoboard para montar o circuito. Os LEDs são alimentados pelo pino 11 do Arduino. Os divisores de tensão dos LDRs estão conectados aos pinos A0, A1 e A2 (analógicos).

No próximo post veremos os softwares de teste que foram feitos para testar os sensores e os motores.

Abracadabraço!

terça-feira, 12 de novembro de 2013

Palestra no Lightning Talks 2013 - Torturando números para que confessem o sumiço das cervejas

No domingo palestrei num evento, Lightning Talks, no ITA. Lá falei sobre mecanismos de tratamento de dados, filtragem, médias etc. Aqui o ppt da apresentação. Abaixo, o vídeo do projeto:


domingo, 3 de novembro de 2013

Controle Remoto para PC II - Comandando uma apresentação PowerPoint

Em novembro de 2011 eu fiz um post no meu outro blog, o de "variedades", que tratava do uso de um controle remoto com o Arduino. Como eu ainda estava começando com o Arduino, só mostrei "o que" eu fiz, mas não "o como". Por isso, volto ao assunto agora, para um post "comme il faut" (ui!).

Os aparelhos de controle remoto que a gente usa em casa se comunicam com os equipamentos que controlam através da luz infravermelha. Quando pressionamos uma tecla o controle emite uma série de pulsos (piscadas) correspondentes à tecla pressionada. Um sensor localizado no aparelho enxerga a informação e a converte para pulsos elétricos, que podem ser processados pelo Arduino. É usado o infravermelho e não a luz visível para que o sensor sofra menos influência da luz ambiente.

Para fazermos comunicação infravermelha temos duas alternativas:

1) Usarmos um LED infravermelho e um sensor tipo transistor, que conduz quando recebe um feixe de luz infravermelha. Criamos o nosso próprio protocolo e fazemos tanto a emissão quanto a recepção.

2) Usamos um sensor infravermelho desses que existem nos aparelhos eletrônicos e usamos um controle do mesmo aparelho ou de outro. Eles são razoavelmente compatíveis, então dá para trabalhar fácil, ainda que algumas teclas de um ou outro controle não possam ser identificadas no Arduino. Existem também controles e sensores proprietários, aí não rola.

O nosso projetim é do tipo 2. Como sensor usei um tal de F8483 do qual não achei nenhuma informação na net. Liguei o bicho conforme abaixo, baseado no datasheet de um semelhante:


O objetivo do projeto é controlar uma apresentação PowerPoint no PC, avançando e retornando slides com um controle remoto desses da Net. Para isso, basta:

- Ligar o sensor como visto acima;
- Baixar a lib de controle remoto, daqui;
- Copiar e colar o seguinte código no programa do Arduino;
- Baixar o código .Net C# aqui e compilar, ou baixar somente o executável zipado daqui e usar.

O controle que haqueei para criar esse programa foi esse aqui, muito comum nas nossas casas, usado pela Net.


Vc pode usar outro, claro. O programa permite que vc indique outros códigos, basta vc carregar a aplicação abaixo no Arduino, abrir o Serial Monitor, pressionar os códigos que quiser usar e digitá-los nos campos correspondentes do programa do PC.

Abaixo, o programa do Arduino.

// look for IR codes and print them as they are received

#include "NECIRrcv.h"
#define IRPIN 2    // pino onde o sensor está conectado

NECIRrcv ir(IRPIN) ;

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

void loop()
{
  unsigned long ircode ;
  
  while (ir.available()) 
  {
    ircode = ir.read() ;
    Serial.println(ircode,HEX) ;
  }
}

Esse programa, muito simples, lê o código fornecido pelo sensor e envia para a serial, em formato hexadecimal.

No PC, para que a gente possa comandar uma aplicação PowerPoint, as coisas são um pouquinho mais complicadas. Eu fiz uma aplicação em C# que:

1) Permite ao usuário indicar o arquivo ppt ou pptx que quer apresentar.

2) Permite também indicar o código da tecla que desempenhará cada função de comando da apresentação. Está pré-configurado para esse controle da Net aí de cima. Prometo que na versão 2.0 ele vai salvar a última configuração :);

3) Selecionado o arquivo o programa passa a "escutar" determinada porta serial, também indicada pelo usuário;

4) Uma vez acionado o botão Ok do controle remoto, a aplicação abre o arquivo no modo de apresentação.

5)  Ao receber dois comandos indicados passa a navegar pela apresentação. Vejamos como é feito isso, nesse caso com um bocado mais de código.

Taí a cara do bicho:




Abaixo, o código C#, devidamente comentado.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.Office.Interop.PowerPoint;
using System.Timers;

namespace pptRemote
{
    public partial class fMain : Form
    {
        // Serial port to receive information frorm Arduino
        System.IO.Ports.SerialPort sp = new System.IO.Ports.SerialPort();

        public fMain()
        {
            InitializeComponent();
            // Most of the times, Arduino port is the last one available, so we try to gess it.
            string[] ports = System.IO.Ports.SerialPort.GetPortNames();
            edPorta.Text = ports[ports.Length - 1];
        }

        // PPT access objects
        Microsoft.Office.Interop.PowerPoint.Application ppApp;
        Presentations ppPresens;
        Presentation objPres;

        // Open previously selected presentation
        private void openPresentation()
        {
            // As there are COM objects involved...
            GC.Collect();
        
            // Create PPT access objects
            ppApp = new Microsoft.Office.Interop.PowerPoint.Application();
            ppApp.Visible = Microsoft.Office.Core.MsoTriState.msoTrue;
            ppPresens = ppApp.Presentations;
            
            // Load presentation from disk
            objPres = ppPresens.Open(edFName.Text, Microsoft.Office.Core.MsoTriState.msoFalse,
                Microsoft.Office.Core.MsoTriState.msoTrue, Microsoft.Office.Core.MsoTriState.msoTrue);
            Slides objSlides = objPres.Slides;
            Microsoft.Office.Interop.PowerPoint.SlideShowWindows objSSWs;
            Microsoft.Office.Interop.PowerPoint.SlideShowSettings objSSS;

            objSSS = objPres.SlideShowSettings;

            // Show slideshow
            objSSS.Run();
            objSSWs = ppApp.SlideShowWindows;
        }

        private void process()
        {
            // Open communitation session
            try
            {
                if (sp.IsOpen)
                    sp.Close();
                sp.PortName = edPorta.Text;
                sp.BaudRate = 9600;
                sp.Open();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }

            bool navigation = true;
            DateTime now = DateTime.Now;
            string lastCmd = string.Empty;
            while (navigation)
            {
                string cmd = string.Empty;
                if (sp.BytesToRead > 0)
                {
                    // Get command sent by Arduino
                    cmd = sp.ReadLine().TrimEnd('\r');
                    // Avoid repetition
                    TimeSpan diff = DateTime.Now.Subtract(now);
                    if (diff.Milliseconds > 200)
                        now = DateTime.Now;
                    else
                        cmd = string.Empty;

                    // Process Arduino commands
                    if (cmd == cmdOpenPresentation.Text)
                        openPresentation();
                    else
                        if (cmd == cmdForward.Text)
                            ppPresens[1].SlideShowWindow.View.Next();
                        else
                            if (cmd == cmdBackward.Text)
                                ppPresens[1].SlideShowWindow.View.Previous();
                            else
                                if (cmd == cmdClosePresentation.Text)
                                    navigation = false;
                } 
                System.Windows.Forms.Application.DoEvents();
            }
            // Close stuff
            objPres.Close();
            ppApp.Quit();
        }
        
        private void button2_Click(object sender, EventArgs e)
        {
            // Ask for PPT presentation file name
            if (ofd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                // if selected, process it
                edFName.Text = ofd.FileName;
                process();
            }
        }

        private void fMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            // Close stuff
             try
             {
               if (sp.IsOpen)
                   sp.Close()
             }
             catch{}
        }
    }
}


O código é um pouco longo, mas fácil de entender. Na sessão using temos a referência à assembly que faz a interface com o PPT. Ela encapsula chamadas chamadas COM, que é (ainda) o protocolo de comunicação com o Office. Quando o Office é instalado ele geralmente instala essas assemblies. O nome que a Microsoft dá a esse troço atualmente PIA, Primary Interop Assemblies, então se quiser saber mais, clique aqui.

Uma observação necessária é que a Microsoft costuma mexer nessas interfaces de uma versão do Office para a outra. Isso tem diminuído, mas se esse programa não funcionar com Office diferente do 2010, é culpa do Steve, não minha.

Voltado ao nosso código acima: dentro do construtor tem as instruções:

string[] ports = System.IO.Ports.SerialPort.GetPortNames();
edPorta.Text = ports[ports.Length - 1];

Esse trecho de código, de minha própria lavra, tenta "adivinhar" qual a porta que o Arduino está usando. 99% das vezes ele escolhe a última disponível, então é essa que a gente indica, e geralmente acerta.

Em seguida temos, logo abaixo do construtor do form, as instruções:

Microsoft.Office.Interop.PowerPoint.Application ppApp;
Presentations ppPresens;
Presentation objPres;

Elas definem os objetos necessários para se comandar uma apresentação PPT de dentro de uma aplicação .Net.

Em seguida vem a rotina openPresentation() que, uma vez indicado o arquivo a ser exibido, faz o carregamento deste para a memória "dentro" dos objetos correspondentes.A instrução:

   objPres = ppPresens.Open(edFName.Text, Microsoft.Office.Core.MsoTriState.msoFalse,
                Microsoft.Office.Core.MsoTriState.msoTrue, Microsoft.Office.Core.MsoTriState.msoTrue);

carrega o arquivo para a memória. Em seguida são criados outros objetos mas o que importa é que, após a última instrução da rotina a apresentação será exibida no modo apresentação, ou seja, pronta para que a gente possa comandá-la pelo Arduino.

Em seguida vem a rotina Process(), que é quem vai receber e processar os comandos vindos do Arduino.

A primeira parte estabelece a comunicação serial com o Arduino. Depois criam-se alguns objetos necessários e aí vem o comando while, que forma o loop de processamento dos comandos.

A rotina fica esperando que haja bytes a ser lidos, então os lê e coloca em cmd. Observe que tem uma rotininha de threshold, que busca evitar que, caso o usuário fique com a mão por muito tempo no botão esse seja indefinidamente repetido. Ocorre que a rotina que lê os códigos do Arduino já elimina as repetições, então seria dispensável esse cuidado, mas... vai que, né?

Por fim o ninho de ifs que processa as instruções enviadas pelo controle. Os comandos que eu escolhi usar para comandar a apresentação foram: o botão Ok, que mostra a apresentação, os botões ao lado do Ok para navegar pela apresentação e o botão Sair para encerrar.

Bom, é isso. Divirtam-se! Aqueles que usarem, por favor, me mandem um email dizendo o que acharam. Se tiverem sugestões, prometo que as implemento ASAP.

sábado, 2 de novembro de 2013

Teclado "chiclete" no Arduino

Toda vez que eu tenho que ligar aquele teclado clássico do Arduino (esse aí da foto abaixo) eu apanho da prá achar como conectar, procurando net afora.


Eu tenho a impressão que isso pode variar, mas esse teclado aí da foto é assim:

- O pino 8 é o mais próximo da tecla # e, claro, o pino 1 fica mais perto do 0.

Conectei-o assim:

Arduino        Teclado
----------------------
5                   8
6                   7
7                   6
8                   5
9                   4
10                 3
11                 2
12                 1

Abaixo, o "pograminha" correspondente. Se prá vc as teclas aparecerem diferentes, altere a tabela de teclas no programa.


#include "Keypad.h"

const byte ROWS = 4;
const byte COLS = 4;
char keys[ROWS][COLS] = {
  {'D','C','B','A'},
  {'#','9','6','3'},
  {'0','8','5','2'},
  {'*','7','4','1'}
};

byte rowPins[ROWS] = {5, 6, 7, 8};
byte colPins[COLS] = {9, 10, 11, 12}; 

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

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

void loop(){
  char key = keypad.getKey();

  if (key){
    Serial.println(key);
  }
}


É isso.