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

segunda-feira, 2 de dezembro de 2013

Configurando o Raspberry Pi

Durante a preparação do meu Pi fui registrando os sites onde encontrei as informações necessárias para configurá-lo. Não vou fazer uma manual aqui, pq ele se desatualizaria rapidamente. Em vez disso, vou botar os links onde vcs acham as informações e os softwares que usei para preparar o ambiente que eu gostaria de ter. O que eu fiz:

- Instalei o Raspbian (recomendado pelo povo do Rasspberry)
- Configurei a interface gráfica
- Configurei o teclado como ABNT2, que é o teclado que eu uso com ele.
- Configurei o PiFace
- Configurei o Scratch para usar o PiFace
- Instalei e configurei aplicativos para acessar remotamente o Pi.
- Etc

Aí vão dez dicas sobre o processo, com os links. Como uma impressão geral, achei trabalhoso mas foi mais fácil que eu esperava. Achei que dada a minha TOTAL falta de intimidade com Linux eu ia apanhar bem mais. Realmente, tem muito material legal na net, e o Raspbian me pareceu muito robusto (dãããããããã, dirão alguns de vocês...).

No tópico onde houver um Obs:, leia primeiro esse ponto.

Importante: os itens 2, 3 e 4 podem também ser feitos pelo raspi-config, programa que é executado na primeira vez que acessamos o Pi. Existem outras configurações importantes por lá também, e o programa pode ser executado também do terminal a qualquer instante.

1) NOOBS - instala SO
http://www.raspberrypi.org/archives/4100
Obs: Instalei o raspbian, então o que for feito a partir daqui diz respeito a ele.

Usr/pwd padrão: pi/raspberry

Para instalar, muito fácil: deszipe o arquivo que vc baixou para um diretório do seu micro. Em seguida, copie o conteúdo deszipado para um cartão SD recém formatado. Ligue o Pi com o cartão instalado nele e siga as instruções.

2) Mudando a senha do usuário pi
No prompt, dê o comando passwd. Siga as instruções.
Obs: anote a nova senha!

3) Executando a interface gráfica:
No prompt, comando startx.

4) Acionando o auto login e fazendo com que a interface gráfica entre na inicialização (sem precisar digitar startx)

6) Configura WiFi

Dê o comando:

sudo nano /etc/network/interfaces

Altere o conteúdo do arquivo para:


auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
#iface wlan0 inet manual
#wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
#iface default inet dhcp

iface wlan0 inet dhcp
wpa-ssid "<YOUR SSID>"
wpa-psk "<YOUR PASSPHRASE/KEY>"

Se não funcionar (prá mim funcionou), siga as instruções do link abaixo:


Para reiniciar o WiFi, use:

sudo ifup wlan0

6) Após instalar, obtenha as últimas atualizações do raspbian. Para isso, no LXTerminal, digite:

sudo apt-get update


7) Configura teclado em português (ABNT)

8) Instalando o PiFace:

Obs: Eu li que NOOBS 1.3 prá frente já vem com a lib para acessar o PiFace instalada, de modo que é só habilitar o SPI Kernel Module, como descrito no documento acima, e vai funcionar. Porém, comigo não funcionou, tive que rodar o script de instalação. Teste com o emulador como mostrado no mesmo documento. Tem como habilitar o SPI Kernel Module com o raspi-config também.

9) PiFace+scratch
Primeiro tem que habilitar a funcionalidade Mesh do Scratch (que permite a comunicação entre diferentes projetos Scratch ou do Scratch com outros devices): http://pi.cs.man.ac.uk/download/EnablingMeshInScratch.pdf

Em seguida, siga as instruções que encontrar em http://www.raspberrypi.org/phpBB3/viewtopic.php?f=48&t=10755

Procure pelo post GeekTeacher » Wed Aug 29, 2012 2:24 pm

Siga os passos a partir do 3 (os anteriores são para outra distribuição de Linux)

10) Backup/restore o SD do Raspberry

11) Acessando o Raspberry de outro micro na mesma rede
-Use o ThightVNC. Para instalar no Pi:
sudo apt-get install vnc-server

-Pra rodar:
vncserver

- Forneça a senha de acesso

Baixe e instale o client no PC: http://www.tightvnc.com/download.php

Execute o programa e conecte-se ao client.

11) Acessando o Raspberry pela internet
Bom, isso eu conto depois, na hora em que conseguir fazer funcionar... :)

O Primeiro Raspberry Pi...

Desde a última quinta-feira eu sou um feliz proprietário de um Raspberry Pi. Isso significa que o assunto do blog  se amplia (se bem que a regra sempre sempre foi "escrever o que me desse na telha", então não mudou tanto assim).

Como meu objetivo é usar o Pi em projetos de automação, resolvi comprar alguns acessórios, e montei o seguinte pacote:

CanaKit: kit contendo o basicão para se brincar com o Pi: a plaquinha, fonte de alimentação com 1A de capacidade (o Pi é bem mais exigente em termos de consumo energético do que o Arduino), caixinha, cabo HDMI e um cartão SD de 8 giga com o NOOBS instalado.

PiFace: essa placa funciona como um shield do Arduino, agregando funcionalidades de automação ao Pi. Ela vem com dois relés 240Vx5A, oito LEDs, quatro push-buttons, além de conectores com parafusos que podemos usar para conectar as portas do Pi aos nossos circuitos. A placa é muito bem acabada e vai merecer um post especial sobre ela no futuro.

Edimax Adptador WiFi USB: segundo os caras, é o "menor adaptador WiFi do mundo", funciona a 150 Mbps;

Câmera digital 5MP Raspberry Pi: como tenho vontade de brincar um pouco com visão computacional, essa câmera certamente será útil. Como achei que ela era muito frágil, comprei também um case prá ela, só que esse não chegou a tempo de ser trazido dos EUA pela minha gentlíssima portadora. Pena... vou ter que improvisar algo, já que ela é realmente muito delicada.

Acho que fiz uma boa escolha, tenho tudo o que preciso para começar a diversão. Me aguardem!

domingo, 1 de dezembro de 2013

Automação no Parque, 30/11/2013

Ontem tivemos mais um de nossos Automação no Parque.

Como sempre acontece no fim do ano (já é nosso terceiro fim de ano, o Automação no Parque começou ali por novembro de 2011) o nosso evento fica melhor. Como vários projetos de alunos que apoiamos durante o ano vão ficando prontos, e o prazo vai-se esgotando, a turma aparece em peso .

Nesse sábado tivemos também os alunos do Projeto Decolar que são apoiados pelo Automação no Parque, que fizeram atividades em outro local durante o semestre mas ontem se juntaram a nós nos trabalhos do sabadão.

Por fim, tivemos a ilustríssima presença do amigo Luciano Ramalho, um guru de programação já com suas décadas de estrada em TI e educação, uma das maiores autoridades em Pyton do Brasil. Nos conhecemos no TDC 2013 e trocamos ideia sobre nosso trabalho por lá. Ele participou de um evento em SJC na sexta e resolveu ficar no sábado para conhecer as nossas iniciativas nerdísticas, Automação no Parque e o Hacker Clube SJC.

Abaixo, imagens das atividades de ontem:

Esse é um TCC muito interessante, que usa Computação Visual. A ideia é fotografar, com uma webcam, uma garrafa de Coca de 600 ml, e em seguida usar a foto para descobrir se o nível da foto está dentro do padrão determinado.

Usamos a biblioteca Open CV para processar a imagem, intensificando os contrastes de maneira a identificar o nível do refri na garrafa.

Como vcs podem ver na foto ao lado, foi feita uma plataforma onde está presa a webcam e tem uma marcação para colocação da garrafa. Foi colocado um anteparo (fundo) branco para aumentar o contraste entre o líquido e a parte vazia da garrafa. Abaixo vcs podem ver vídeos do processamento da foto:





Um projeto que esteve no Parque durante semanas foi esse, que implementa duas maneiras distintas de se abrir uma porta: uma com o uso de reconhecimento de voz (a pessoa fala uma palavra chave para abrir a fechadura da porta, outra para fechar) e também com uma sequencia de toques (batida) na porta.

Ao lado, mecanismo construído pelo aluno. Essa maquininha vai presa à porta. Ela é composta por:

- um Arduino
- um break de comando de voz (similar  a esse)
- um sensor tipo piezo (na realidade um buzzer ligado "ao contrário", quer dizer, um buzzer colado à porta para sentir as batidas e gerar um pulso elétrico a partir delas)
- um motor CC com uma redução para dar bastante torque, de modo a conseguir acionar a fechadura
- uma ponte H para comandar o motor.


Ao lado, detalhe do buzzer colado na madeira.

Abaixo, vídeo do acionamento por voz funcionando. O acionamento por voz foi a parte fácil, já que o break é que compara a palavra dita com um pequeno banco de palavras previamente armazenado. Se bateu com algum comando, ele retorna um número correspondente.

Já a sensibilidade ao toque é feita inteiramente pelo Arduino, processando o sinal enviado pelo buzzer. Dia desses escrevo um post a respeito, mas nesse link vcs tem já um projeto semelhante, no qual este se baseou.


Outro projeto legal que andou por lá foi um de uma grua para movimentação de peças baseadas em suas cores.

Esse projeto ainda está com a parte mecânica sendo feita ainda, de modo que voltaremos a ele quando estiver mais pronto.











O Luciano, com a generosidade que é própria daqueles que sabem, resolveu contemplar os presentes com uma keynote a respeito da tabela ASCII e outras formas de se representar caracteres dos diversos idiomas nos computadores. Inspirado pelo sucesso que a prosa dele fez, me ocorreu introduzir algumas palestras nos nossos encontros sabáticos, a partir de 2014.



Observem que a criançada do Decolar colou no nosso visitante ilustre.













Resumindo: um sábado "daqueles", foi o que tivemos no Parque Santos Dumont. Fui-me embora às 12:30 porque tinha um compromisso mas a galera ficou por lá, se divertindo.

Semana que vem teremos a despedida do semestre da criançada do Decolar, com direito a demo dos projetos que eles fizeram no ano. Aí vou fazer um balanço geral do que foi o nosso Automação no Parque em 2013.



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.

quarta-feira, 30 de outubro de 2013

Expandindo a memória do Arduino I

A memória do Arduino é curta. O certo seria inclusive escrever "as memórias", já que existe mais de um tipo de memória:

Memória flash: é a memória que armazena os nossos programas. O Arduino pode ser desligado e o programa não se perde. A memória disponível para os nossos programas é um pouco menor do que a disponibilizada pelo processador do Arduino. O motivo é que nessa memória existe também o bootloader do Arduino, que é um programa que vem gravado nessa memória para receber o nosso programa enviado pela serial. Mas tergiverso, voltemos às memórias.

Memória SRAM: é um tipo de memória que serve para guardar as nossas variáveis. Ela é volátil, ou seja, quando a energia é cortada ou a paquinha é resetada, baubau, perdeu, playboy.

Memória EEPROM: é uma memória não volátil que serve para guardar dados.

Nos dois Arduinos mais comuns, Uno e Mega, temos:


Memória Uno  Mega
Flash 32k 256k
SRAM 2k 8k
EEPROM 1k 4k

Ou seja, é um recurso escasso.

Para aumentar o tamanho da memória para código não há recurso. Pode-se otimizar o seu uso, programando de maneira mais minimalista. No caso da memória para dados, aí existem algumas alternativas. A que a gente mais usa é o cartão SD, já que existem alguns breaks que são fáceis de encontrar e usar. Tem também alguns shields, como os de MP3 e Ethernet, que costumam ter suporte a cartões SD e MiniSD.

Uma outra alternativa é usar chips EEPROM, que são muito baratos e estão ficando fáceis de achar (no Mercado Livre tem). Porém não se acha muita coisa na net sobre o seu uso, por isso resolvi escrever a respeito.

O chip que estou usando é o Atmel AT24C512, mas tem outros fabricantes que fornecem equivalentes.

Ele é um chip de 512k bits de memória não volátil, o que significa que ele tem 64k bytes de memória EEPROM. Para a gente se comunicar com ele usa-se a interface I2C, que é implementada pela lib wire.h. Uma coisa interessante é que vc pode ligar até quatro deles em cascata (ou em "cadeia de margaridas", como dizem nossos irmãos lá do norte). Aí eles vão funcionar como uma só memória de 256k bytes.

Abaixo, uma imagem do bicho já devidamente conectado ao Arduino:

Dá prá ver que ele é bem pequeno, desses de oito pinos. As conexões são as seguintes:

Pinos 1* a 4: GND
Pino  5: SDA - conectado à porta A4 do Arduino
Pino  6: SCL - conectado à porta A5 do Arduino
Pino  7: GND
Pino  8: Vcc - pode ser conectado aos pinos 3V3 ou 5V do Arduino.

Para ler e gravar no bicho temos a lib EEPROM24LC256_512.h, que pode ser baixada aqui.

Eu peguei um exemplo que vem com a lib e dei uma simplificada (achei-o um tanto confuso).

Abaixo vcs podem vê-lo. Divirtam-se!




#include "Wire.h"
#include "EEPROM24LC256_512.h"

unsigned int randomNum=0;
 
//define eeprom chip (1 per chip)
EEPROM256_512 mem;
 
void test512ByteBounds()
{
  byte d;
  mem.writeByte(0, 0b10111101);
  d=mem.readByte(0);
   
  Serial.print(" Address: 0");
  Serial.print(" Read Data: "); Serial.println(d, BIN);
      
  mem.writeByte(65535, 0b10111101);
  d=mem.readByte(65535);
   
  Serial.print(" Address: 65535");
  Serial.print(" Read Data: "); Serial.println(d, BIN);
}
 
void test512ByteSequence()
{
    int i=0;
    byte d;
   //get 512 random bytes... write to them.  read them
   Serial.println("Testing Corner Cases");
   test512ByteBounds();
    
   randomSeed(analogRead(0));
   Serial.println("Testing Byte Sequence (24LC512) - 512 random bytes");
   for(i=0; i<512;i++)
   {
     randomNum = random(0,65535);//get random byte number
     mem.writeByte(randomNum, 0b10111101);
     d=mem.readByte(randomNum);
     Serial.print("Seq: "); Serial.print(i);
     Serial.print(" Address: "); Serial.print(randomNum);
     Serial.print(" Read Data: "); Serial.println(d, BIN);
   }
}
 
void Test512()
{
  //print page size
  Serial.print("24LC512 Page Size: ");
  Serial.println(mem.getPageSize());
   
  //exercise byte write/read
  test512ByteSequence();
}
 
void setup() {
  Wire.begin();
  mem.begin(0,0);
  Serial.begin(9600);
  Test512();
}
 
void loop() {}

domingo, 27 de outubro de 2013

Projeto Decolar, segundo semestre de 2013

Nesse semestre o Programa Decolar São José dos Campos está funcionando de uma forma conturbada. O novo Secretário de Educação da cidade, Célio da Silva Chaves, vem esvaziando o programa. O discurso é que o programa será mantido, mas será reformulado. Porém, a coordenadora pedagógica foi exonerada sem reposição, o telefone exclusivo do programa foi desativado, algumas sedes usadas pelo programa foram destinadas a outros fins, enfim, um programa sucesso absoluto entre pais, facilitadores e voluntários vai-se acabando. Isso se depender a vontade dos caras, a gente ainda vai lutar para que o programa não se acabe.

Toda essa zorra fez com que os alunos que eu atendia na minha atividade voluntária diminuísse de 10 alunos semestre passado para 5 esse semestre. Uma pena, pois estamos agora abordando programação com a criançada, usando o Scratch, ferramenta desenvolvida pelo MIT para ensinar a programar crianças e jovens. A ideia é ensinar a turma a programar para que possam depois desenvolver robôs programados por eles próprios. Durante quatro sessões eles fizeram programas diversos com o Scratch: histórias, games simples e outros foram programados pela criançada com essa ferramenta fantástica que é o Scratch.

Ontem eles começaram a lidar com o Arduino. Para isso fiz uma introdução aos circuitos elétricos, bem simples. Em seguida eles passaram a usar o S4A, ou Scratch for Arduino. Essas fotos são da última prática que a turma fez. Queimaram alguns LEDs (um até explodiu!), mas no fim deu tudo certo.

Será que a turma da Secretaria da Educação de São José dos Campos vai mesmo dar fim a um programa como o Decolar?

Abaixo, imagens da turma se divertindo e aprendendo.























































domingo, 25 de agosto de 2013

Reportagem na Veja Online

Sexta feira passada foi publicada uma matéria na Veja Online para a qual dei uma entrevista. No fim só sobrou uma frase e o meu rostinho bonito, mas o cara captou o espírito da coisa. O que importa é que o recado Arduínico foi dado: http://veja.abril.com.br/noticia/vida-digital/hardware-aberto-incentiva-amadores-e-especialistas-a-criar-dispositivos-eletronicos#Texto.

Automação no Parque, 24/08/2013 - Projeto Rover 5

Nesse sabadão lidamos com dois projetos: um carrinho de esteiras, o Rover 5, muito popular nos EUA para diversão com o Arduino. O outro fiu um tacômetro baseado em dois encoders, visando determinar a velocidade e a direção de giro de um disco. Nesse projeto a único resultado que obtivemos foi queimar os dois encoders, graças à minha teimosia em ligar LED sem resistor. Semana que vem tem mais...

Já no outro projeto tivemos bastante sucesso.


Esse é o Rover 5. Fabricado pela Dagu, é vendido em muitas lojas on-line dos EUA. Você o acha por aqui, também, mas prá variar custa uma grana.

Tem duas versões: uma com dois motores CC e a outra com quatro. Cada motor tem seu próprio encoder, o que deve possibilitar um controle muito preciso de posicionamento. Esse que estamos hackeando tem quatro motores. É de um ex-aluno da FATESF o Ângelo, que vai comandá-lo a partir de um celular.

Ele comprou o jipinho nos EUA. Quando chegou aqui descobriu que um dos eixos estava completamente empenado, o que fazia com que a esteira simplesmente saísse fora quando os motores eram acionados. Nada complicado prá um sujeito que trabalha na Embraer.

Nesse sábado a ideia ela simplesmente acionar os motores através do driver, já ele só havia sido testado ligando-se os motores direto na bateria.

O Ângelo comprou esse driver de acionamento de motores aqui:


Ele funciona com até quatro motores CC, cada um com seu encoder. As conexões estão descritas no diagrama acima. Basicamente,à esquerda são ligados os pinos do Arduino que comandam os motores, respectivamente:

- Pino terra (GND)

- Pino PWM: ligado a um pino PWM do Arduino, controla a velocidade do motor.

- Pino Direction: controla a direção de giro, sinal do Arduino HIGH roda numa direção, LOW na outra. Uma coisa interessante no carrinho é que os motores são montados em oposição em termos de giro. Isso significa que se vc aplicar HIGH num motor da parte dianteira do carrinho e ele girar prum lado, ao aplicar o mesmo HIGH a um motor da parte traseira (ou na parte oposta, já que ele é simétrico, então vc tem que escolher a frente) ele vai girar na direção contrária. Nada que não possa ser corrigido por software.

- Pino Current: é conectado a um sensor de corrente, com sensibilidade de 1V/A, até o máximo de 5V. isso significa que vc pode legá-lo diretamente a um pino analógico do Arduino e monitorar a corrente, de modo a ver se tem algo errado. Esses motores não devem operar acima de 1,5A, ou menos até.

À direita são conectados os encoders, suas entradas e alimentação (pinos que vem dos encoders) na parte externa da placa e as saídas na parte interna. São dois encoders, que juntos permitem que a gente determine não só a velocidade e consequentemente a distância mas também a direção de giro. Como fazer isso? Fica para um próximo post. Por agora, a tarefa é acionar os motores na mesma direção, controlando a velocidade.

No mais, tem a conexão para a fonte de alimentação dos motores. Já que o Arduino não consegue prover a corrente necessária, é preciso ter uma outra fonte para isso. Essa pode ser seis pilhas AA, ligadas em série de maneira a prover 9Vcc. Tem também uma conexão para alimentação da parte eletrônica da placa, que vc pode "pegar" da saída Vcc do Arduino. E por fim, as conexões para os quatro motores.

Os camaradas já trouxeram o carrinho com s conexões elétricas prontas entre motores, encoders, driver e Arduino, então foi fazer um "pograminha" de teste e botar prá rodar.

À esquerda, o  driver conectado.











E abaixo, o carrinho montado. Dá prá ver as seis baterias dos motores e uma de 9V para alimentação do Arduino.


/*************************************************************
Automação no Parque - 25/08/2013
Controle do Dagu Rover 5
assismauro@hotmail.com
**************************************************************/

#define FRENTE 1
#define RE 0

// O array abaixo define o controle dos  motores
// Indica onde está ligado cada pino do Arduino
// correspondente a um motor (0,1,2,3)
//                  CUR DIR PWM FWD MSK 
int motor[4][4] = {{A0, 4,  5,  HIGH}, // motor 0
                   {A1, 7,  6,  HIGH}, // motor 1
                   {A2, 10, 11, LOW},  // motor 2
                   {A3, 8,  9,  LOW}}; // motor 3
/*    
Diagrama do posicionamento dos motores no carrinho   

      Frente
      _____
    0|     |1
     |     |
     |     |
    2|_____|3

Pino     Função
--------------------------------------------------
CUR      Sensor de corrente
DIR      Direção
PWM      Velocidade
FWD MASK indica qual o sinal que o motor deve receber para acionar o motor prá frente.
*/

// Essa rotina é a que conta os sinais enviados pelo encoder.
// A saída de um dos encoders está ligada ao pino 2 do Arduino,
// fazendo que count seja incrementado. Quanto mais veloz, mais 
// "counts" por unidade de tempo.
volatile unsigned int count = 0;
void encoderInt()
{
  count++;
}

// Set os modos dos pinos que serão usados
void setPinsMode()
{
  for(int i=0;i<4;i++)
  {
    for (int j=1;j<3;j++)
    {
      pinMode(motor[i][j],OUTPUT);
      pinMode(motor[i][j],OUTPUT);
    }
  }
}

// Comanda cada motor individualmente. Recebe como parâmetro o número do motor,
// a direção e a velocidade
void setMotor(int no, int dir, int speed)
{
  // Aqui ocorre a inversão do sinal de direção de acordo com a posição do motor
  if (dir)
    digitalWrite(motor[no][1], motor[no][3]);
  else
    digitalWrite(motor[no][1], !motor[no][3]);
  analogWrite(motor[no][2], speed);
}

// Aqui se aciona o carrinho "como um todo" (argh!).
// Tem dois dir e duas speed, porque comanda-se individualmente
// cada lado do rover, de maneira a fazer curvas, por exemplo.
void rover(int dirEsq, int dirDir, int speedEsq, int speedDir)
{
  setMotor(0,dirDir,speedDir);
  setMotor(1,dirEsq,speedEsq);
  setMotor(2,dirDir,speedDir);
  setMotor(3,dirEsq,speedEsq);
}

//Para o rover (dãããã...)
void roverParado()
{
  rover(FRENTE,FRENTE,0,0);
}

void setup()
{
  Serial.begin(9600); 
  setPinsMode();
// Conecta a interupção do encoder
  attachInterrupt(0,encoderInt,RISING);
}

void loop()
{
  // Move o rover à frente, com velocidade 50 (vai até 255)
  rover(FRENTE,FRENTE,50,50);
  // Mostra a contagem do encoder a cada segundo, ou seja, indica a velocidade.
  // Depois vai-se calibrá-lo para m/min.
  delay(1000);
  Serial.println(count);
  count=0;
}


Por fim, vídeo do resultado. Sabadão tem mais com o jipinho.



quinta-feira, 22 de agosto de 2013

Porque existem displays de anodo comum?



Eu sempre me perguntei porque a maioria dos displays com os quais trabalhei são anodo comum e não catodo comum. Para quem não sabe, anodo é o terminal positivo e catodo o negativo. Na minha cabeça fazia mais sentido o catodo comum, quer dizer, o terra comum . Assim, quando eu quisesse ligar um segmento, era só mandar 5V para o pino correspondente e o bicho acenderia. No caso do anodo comum é o contrário, ou seja, +5V para desligar o LED.


Não que isso faça alguma diferença, tanto faz ligar com +5V ou 0V, mas não é esquisito?

Acima, um esquema de display com anodo comum.

Bom, aí resolvi investigar e descobri porque usa-se o anodo comum: é que os CIs de controle, para serem pequenos, tem capacidade de fornecer apenas alguns miliamperes de corrente por pino. Porém esses mesmos CIs tem a capacidade de "aterrar" 20+ mA por pino, ou seja, se o display for anodo comum exige-se menos do CI, e pode-se usar uma corrente por segmento maior => maior brilho.

Sacou?

sexta-feira, 2 de agosto de 2013

Mais sobre displays de LED com 74HC595 - Parte II

Na parte inicial deste artigo, vimos a parte de hardware de uma montagem com 12 displays de LED conectados ao Arduino via três CIs 74HC595.

Agora vamos discutir os fontes da aplicação:

#include "Arduino.h"
/*****************************************************************
 Controle de "n" displays de LED 3x8 tipo Para Light A-573H 
 http://automatobr.blogspot.com.br
******************************************************************/

// Este programa funcionará com qualquer número de dígitos
#define nDigits 12 // número de dígitos a serem usados
#define nCIs    3  // número de CIs 595 existentes no
                   // circuito, no mínimo 2.

// pinos para comunicação com o CI 74HC595
#define latchPin 8
#define clockPin 12
#define dataPin  11 

/* máscara de bits para os dígitos, conforme diagrama abaixo:
     A 
    --- 
  F|   |B
   | G | 
    ---
  E|   |C
   | D | 
    --- *d
*/
byte digits[] = 
//  dGFEDCBA - segmentos
  {B00111111, // 0
   B00000110, // 1
   B01011011, // 2
   B01001111, // 3
   B01100110, // 4
   B01101101, // 5
   B01111101, // 6
   B00000111, // 7
   B01111111, // 8
   B01101111, // 9
   B10000000, // dot
   B00000000}; // blank  

// valor apresentado no display
uint64_t displayValue = 0;

// rotina que envia um byte para o 595 de maneira serial, 
// um bit de cada vez

void shiftOut(byte dataOut) 
{
  boolean pinState; 
// prepara o envio
  digitalWrite(dataPin, LOW); 
  digitalWrite(clockPin, LOW);
  for (int i=0; i<=7; i++) 
  { 
    digitalWrite(clockPin, LOW); 
// se o bit "i" está ligado, envia para o pino de dados um byte com 
// só o primeiro bit ligado (HIGH), se não, envia 0 (LOW)
    if ( dataOut & (1 << i) ) 
      pinState = HIGH;
    else 
      pinState = LOW;
// envia o bit
    digitalWrite(dataPin, pinState);
// informa ao chip que terminou o envio
    digitalWrite(clockPin, HIGH); 
    digitalWrite(dataPin, LOW);
  }
  digitalWrite(clockPin, LOW); 
}

// "desenha" um determinado dígito (digit) no display 
// (display). O número 1 é o menos significativo
// (primeiro da direita) e assim por diante.
void displayDigit(int display, int digit)
{
// primeiro montamos o endereço do display, quer dizer, 
// vamos indicar qual display será
// habilitado e mostrará o dígito.
  int data1, data2;
  if(display <= 8)
  {
    data1 = B00000001 << (8-display);
    data2 = B00000000;
  }
  else
  {
    data1 = B00000000;
    data2 = B00000001 << (16-display);
  } 
  // prepara o envio
  digitalWrite(latchPin, LOW);
  // envia o dígito para o CI 3
  shiftOut(digits[digit]);
  // envia o endereço (máscara de bits) indicando 
  // o display a ser ativado
  shiftOut(data1);
  // se tiver mais de 1 CI de endereçamento, envia 
  // a outra parte do endereço
  if (nCIs > 2)
    shiftOut(data2);
  // termina o envio
  digitalWrite(latchPin, HIGH);
}

// exibe um número inteiro
void display(uint64_t number)
{
    for (int i = 1;i <= nDigits && number != 0;i++) 
    {
      // pega o i-ésimo dígito
      int digit = number % 10LL;
      // envia para exibição
      displayDigit(i,digit);
      // trunca o número, eliminando o último 
      // dígito exibido
      number /= 10LL;
    }
}

void setup()
{
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin,  OUTPUT);  
  // "inverte" a máscara de bits, porque os displays são 
  // anodo comum => o bit "1" desliga o LED.
  // Se os seus displays forem catodo comum, 
  // delete as próximas duas linhas.
  for(int i=0; i < sizeof(digits)/sizeof(digits[0]);i++)
    digits[i]=~digits[i];
}

void loop()
{
  displayValue=188459823945LL;
  while(displayValue < 9999999999999LL)
  {
    display(displayValue);
    displayValue++;
  }
}

O fonte está todo comentado acima.

As constantes nDigits e nCIs servem para vc adaptar o programa ao seu circuito, informando quantos CIs 595 vc tem e o número de dígitos que vc usou. Para usar mais ou menos CIs (e dígitos, consequentemente) vc deve adaptar o circuito que publiquei, não é difícil. Se forem, por exemplo, seis displays, vc pode usar 2 CIs, um para controlar os segmentos e outro para multiplexar (selecionar) os displays. Nesse caso a diferença é que vc não terá o CI 1 e consequentemente nenhuma de suas conexões e o pino de dados do CI 2 (pino 14) será conectado ao Arduino (pino 11). Mas nada impede que vc controle menos displays com algum CI sobrando, ou seja, os números são "quase" independentes ou seja: para controlar 10 displays vc é obrigado a ter no mínimo 3 CIs, já para controlar 4 displays apenas 2 são necessários, mas se vc tiver ligado 3 o programa funcionará.

Uma curiosidade desse sketch é que eu usei o tipo de dado uint64_t, que é um inteiro 64 bits suportado pelo Arduino. Usando-se esse tipo de dados podemos manipular um decimal até 20 dígitos.

É isso. Vou fazer ainda mais um post com outras brincadeiras com esse mesmo circuito.

Obrigado pela força do Euclides e do César, nosso "associado remoto".


Mais sobre displays de LED com 74HC595 - Parte I




Outro dia apareceu no nosso Sabugosa (apelido do Hacker Clube de São José dos Campos) um monte de displays de oito segmentos e três dígitos, desses daí ao lado.


Aqui no blog existe uma série de posts com projetos envolvendo o chip 74HC595. Aqui vai mais um. O resultado você pode ver no vídeo abaixo.



Clique para ver o datasheet.


Na figura à esquerda, o esquema  visual do display. O dígito mais à esquerda é o 1, os segmentos são identificados por letras de A a G e o ponto decimal é o DP (Dot Point). Essa identificação aparece em 100% dos displays que vi até hoje.



Essa outra figura é o esquema elétrico do display O display é de anodo comum, ou seja, o terminal positivo é conectado em comum para cada display (pinos 8,9,10).

Isso significa que, para ligar um determinado segmento, temos que conectar o pino do segmento correspondente ao terra. Para desligar o segmento, é só alimentar o pino correspondente com a mesma tensão do anodo, 5V no caso de nosso circuito. Isso vai contra o senso comum. que é 5V liga, 0V desliga, mas é assim mesmo.

Temos então um pino que é o anodo de todos os segmentos de um determinado display. O catodo é comum aos segmentos iguais dos diferentes displays, e os segmentos são conectados aos pinos 7,6,3 etc. Observe que eles são interconectados nos três displays, quer dizer, se eu conecto +5V ao pino 8 e 0V aos pinos 6 e 3 vai aparecer o número 1 nos três displays.

Como faço então para mostrar números diferentes nos displays? É só alternar o número a ser mostrado com o display ligado. Supondo que temos que mostrar o número 1,2,3 temos que fazer assim:

1) Habilito o display 1 (5V pino 10).
2) Desenho o número 3 (0V em 7,6,3,2,4)
3) Desligo o display 1 (0V em 10)
4) Ligo o display 2 (5V pino 9)
5) Desenho o número 2 (0V em 7,6,2,1,4)
6) Desligo o display 2 (0V pino 9)
7) Ligo o display 3 (5V pino 8)
8) Desenho o número 1 (5V pinos 6,3)
9) Volto ao passo 1.

E para que é feito dessa forma? Porque não ter um pino para cada segmento? R: Para diminuir o número de conexões necessárias ao acionamento do display. Se fosse um para cada seriam 25 pinos a serem comandados, um para cada segmento mais um anodo comum. No display que usamos temos apenas 11 conexões.

Na minha montagem, para diminuir ainda mais o número de pontos eu conectei todos os segmentos iguais dos quatro displays que usei. Assim se ativamos todos os displays e mostramos um 4, o que aparece é o que vc vê aí do lado.
Temos então 8 segmentos mais 1 pino para cada chip a comandar, o que dá "apenas" 20 pinos para comandar 12 displays, muito menos que os exatos 100 que seriam necessários caso fossem ligados a todos os pinos (96 LEDs mais 1 catodo comum para cada conjunto de 3 displays).


De toda forma, 20 pinos digitais é o limite máximo do Arduino Uno (14 digitais "verdadeiros" mais os 6 analógicos que podem ser usados como digitais), ou seja, se ligarmos o display direto no Arduino não dá para usar o Arduino prá mais nada. Temos que diminuir mais ainda o número de portas necessárias. Aí entra o 74HC595.

Em 2012 eu fiz alguns posts sobre o uso desse chip para controlar LEDs RGB. Lá eu descrevo detalhadamente o funcionamento dele: Parte I, Parte II. Tem também outros posts sobre a conexão de displays de oito segmentos isolados, então não vou repetir a descrição do bicho. Vou apenas dizer que ele é um conversor serial-paralelo, ou seja, com apenas 3 pinos eu comando oito pinos de saída. Além disso eles podem ser interconectados, o que faz com que eu possa controlar, teoricamente, "n" pinos com apenas três pinos do Arduino.

No nosso caso, usamos 3 chips 595: um deles comanda os segmentos e os outros dois selecionam cada um dos displays. Observem que a gente poderia então ter mais quatro displays sendo comandados pelos mesmos três chips, já que estou usando apenas 12 dos 16 possíveis na saída de dois 595. Não coloquei mais porque simplesmente não coube na protoboard e eu não tinha outra.

Abaixo, um vídeo do sistema funcionando, só que com 100 ms entre cada exibição de display:


Dá para ver "em câmera lenta" os dígitos sendo exibidos. Observe que, como é um contador, o primeiro dígito (à direta, claro) vai mudando.

Quando a gente acelera (retira o delay), tem-se o resultado do primeiro vídeo.

Não vou postar o esquema (Fritzing) do circuito por razão óbvia: a preguiça de desenhar esse "aranzel", como se diz em minha terra. Mas dá para explicar como fiz. Identifique os CIs na figura logo abaixo.

Os dois 595 à esquerda (chamarei de 1 e 2) são responsáveis pela seleção do display corrente, e o do direita, o 3, comanda os segmentos.





Para conectar os CIs entre si são ligados os pinos 11 e 12 de cada CI entre si. O pino 9 do CI 1 é ligado ao pino 14 do CI 2. Essa conexão é a que será usada pelo CI 1 para "exportar" os dados para o CI 2. Da mesma forma, conectamos o CI 2 ao 3.

Abaixo um esquema com dois 595 conectados. O nome dessa conexão em inglês e "daisy chain (seriam "margaridas encadeadas"???), em português se usa "cascata".




Os pinos de saída do chip são conectados aos displays, da seguinte forma:

Vamos chamar os displays de 1 a 4 do menos significativo ao mais significativo, ou seja, da direita para a esquerda.

O esquema de ligação dos CIs está descrito na tabela abaixo:
   
       
           CI
                        Pino                  Display                  Pino            CI       Pino Arduino        Pino Função
1 1 4 9 Seleciona display 2
1 2 4 8 Seleciona display 3
1 3 3 10 Seleciona display 4
1 4 3 9 Seleciona display 5
1 5 3 8 Seleciona display 6
1 6 2 10 Seleciona display 7
1 7 2 9 Seleciona display 8
1 8 GND GND
1 9 2 14   Daisy chain
1 10 Vcc Vcc
1 11 2 11  12   Clock
1 12 2 12  8   Latch
1 13 GND GND
1 14 11  Data
1 15 4 10 Seleciona display 1
1 16 Vcc
2 1 1 10 Seleciona display 10
2 2 1 9 Seleciona display 11
2 3 1 8 Seleciona display 12
2 4 Não usado
2 5 Não usado
2 6 Não usado
2 7 Não usado
2 8 GND GND
2 9 3 14   Daisy chain
2 10 Vcc Vcc
2 11 3 11   Clock
2 12 3 12   Latch
2 13 GND GND
2 14 1 9   Data
2 15 2 8 Seleciona display 9
2 16 Vcc Vcc
3 1 1 6 Segmento B
3 2 1 3 Segmento C
3 3 1 2 Segmento D
3 4 1 1 Segmento E
3 5 1 5 Segmento F
3 6 1 4 Segmento G
3 7 1 11 dot
3 8 GND GND
3 9 2 14   Daisy chain
3 10 Vcc Vcc
3 11 2 11   Clock
3 12 2 12   Latch
3 13 GND GND
3 14 Data
3 15 1 7 Segmento A
3 16 Vcc Vcc









Observe que tem pinos que são conectados a mais de um ponto simultãneamente, ex: os pinos 9, 11 e 12 do CI 1 estão também conectados ao Arduino.

Além dessas conexões é necessário ligar os segmentos correspondentes da seguinte forma: conecte os pinos 7,6,3,2,1,5,4,11 dos quatro chips aos seus correspondentes, ou seja o pino 7 do display 1 ao pino 7 do display 2, o pino 7 do display 2 ao pino 7 do display 3, o pino 6 do display 1 ao pino 6 do display 2 e assim por diante. Uma sugestão: faça PRIMEIRO essa conexão entre os displays, acho que deve ser mais fácil assim.

No próximo post, o software.