MCO018703 2024 2 AULA04: mudanças entre as edições

De MediaWiki do Campus São José
Ir para navegação Ir para pesquisar
Douglas (discussão | contribs)
Douglas (discussão | contribs)
 
(18 revisões intermediárias pelo mesmo usuário não estão sendo mostradas)
Linha 1: Linha 1:
=Comunicação Serial=
=Mapa das Entradas e Saídas do Arduino=
 


;OBJETIVOS
;OBJETIVOS
Linha 5: Linha 6:
O aluno será capaz de:
O aluno será capaz de:


:*Utilizar o monitor serial;
* Apresentar o mapa das entradas e saídas do Arduino;
:*Conhecer os operadores relacionais e lógicos;
* Saber utilizar as funções na linguagem do Arduino.
:*Identificar as funções para controle de fluxo;
:*Saber utilizar o comando de decisão ''if-else''.




;METODOLOGIA
;METODOLOGIA


:A aula será expositiva e dialogada, utilizando apresentação de texto base na Internet, onde serão mostrados exemplos executados programas para programação de microcontroladores. Na prática faremos testes de comunicação serial com o Arduino através da porta USB.
:A aula será expositiva e dialogada, utilizando apresentação de texto base na Internet, onde serão mostrados exemplos executados programas para programação de microcontroladores. Na prática utilizaremos os pinos digitais como entrada digital fazendo uso de ''pushbotton''.  


;INTRODUÇÃO


;INTRODUÇÃO: Apesar do Arduino ser gravado via porta USB, a comunicação se dá como serial padrão (USART). O ATmega328 permite comunicação serial no padrão UART TTL (5 V), que está disponível nos pinos digitais 0 (RX) e 1 (TX). Um chip FTDI FT232RL na placa encaminha esta comunicação serial através da USB e os drivers FTDI (incluído no software do Arduino) fornecem uma porta virtual para o software no computador. O software Arduino inclui um '''Monitor Serial''' que permite que dados simples de texto sejam enviados e recebidos à placa Arduino. Os LEDs RX e TX da placa piscam quando os dados estão sendo transferidos ao computador pelo chip FTDI e há conexão USB (mas não quando há comunicação serial pelos pinos 0 e 1). A biblioteca SoftwareSerial permite comunicação serial por quaisquer dos pinos digitais do Uno. O ATmega328 também oferece suporte aos padrões de comunicação  I2C (TWI) e SPI. Inclui uma biblioteca Wire para simplificar o uso do barramento I2C. Para usar a comunicação SPI, veja o manual do ATmega328. Assim, no Arduino existe uma parte do hardware especifica para a conversão Serial/USB. Disso resulta a criação de uma porta COM virtual no computador para a comunicação com o Arduino.
Nessa aula vamos aprender alguns conceitos básicos para começar a utilizar uma placa Arduíno. Este conteúdo mostrará como configurar e manipular as entradas e saídas digitais em uma placa Arduino, de modo que, no decorrer deste material você aprenderá a desenvolver programas capazes de utilizar as funções, por exemplo, de fazer com que o seu Arduíno realize o acionamento de um LED e também com que ele consiga saber se um botão foi pressionado.




[[imagem:Fig020_MCO18703.png|500px|center|border]]
[[imagem:Fig041_MCO018703.jpg|600px|center|border]]
<center>
<center>
Figura 1 - Porta COM virtual no computador para a comunicação com o Arduino.
Figura 1 - Mapa das Entradas e Saídas do Arduino.
</center>
</center>


;Pinos Digitais: São usados  para  detecção ou  transmissão  de controles digitais. 


Como a comunicação é a serial padrão, é fácil trocar informações entre o computador e o Arduino.
:Funções em C:
::pinMode( )
::digitalRead( )
::digitalWrite( )
::analogWrite( )
::attachInterrupt( )
::pulseIn( )


Existe uma ferramenta própria na IDE do Arduino para a comunicação serial.


[[imagem:Fig021_MCO18703.png|500px|center|border]]
;Pinos analógicos: São usados para leitura de sinais de sensores análogicos.
<center>
 
Figura 2 - Ferramenta da IDE do Arduino para a comunicação serial com o Arduino.
:Funções em C:
</center>
::analogRead( )




;Porta USB: É usada  para  comunicação  serial  com um computador.
:Funções em C:
::begin( )
::end( )
::available( )
::read( )
::print( )
::println( )


A biblioteca ''Serial()'' do [http://wiring.org.co/reference/Serial.html Wiring] tem todas as funções necessárias para se implementar comunicação serial entre o Arduino e o PC.
;Pinos de Alimentação: São usados para alimentação de circuitos externos e ''reset'' do Arduino.


A porta serial te permite ler e escrever facilmente dados de e para dispositivos externos.
==Funções das Portas de E/S==


Isto permite a duas máquinas se comunicarem através de portas seriais de 8 pinos, dos PCs, ou emulads através de um adaptador serial.
;PINOS DIGITAIS


Velocidades típicas de comunicação são:  2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 e 115200 BPS.
São 14 pinos marcados com o nome DIGITAL logo abaixo de duas barras de 8 pinos. São numerados de 0 a 13 da direita para a esquerda e podem ser configurados pela função
'''pinMode( )''' para detetarem ou transmitirem níveis lógicos digitais (verdadeiro/falso, 1/0 ou HIGH/LOW). A Figura 2 mostra o mapa de pinos Digitais do Arduino.


Apenas uma aplicação pode utilizar a porta serial, a cada vez.
[[imagem:Fig042_MCO018703.jpg|600px|center|border]]
<center>
Figura 2 - Mapa dos Pinos Digitais do Arduino.
</center>




As funções mais utilizadas são:
{| class="wikitable" style="background-color:#ffffff; text-align: center;"
 
! style="background:#2E8B57; color:white; font-weight:bold;" | Função
* ''begin()'' Abre a porta serial para leitura ou escrita.
! style="background:#2E8B57; color:white; font-weight:bold;" | Exemplo
* ''read()'' Retorna um número entre 0 e 255 para o próximo byte que está esperando no buffer. Retorna -1 se não há nenhum byte, embora isto possa ser evitado pelo uso da função ''available()'', que informa se há dado disponível
! style="background:#2E8B57; color:white;font-weight:bold;" | Notas
* ''write()'' Escreve um byte na porta serial.
* ''print()'' Escreve dados (int, float, byte, char, char[], números nas bases (DEC, BIN, OCT or HEX) ou textos na porta serial.
* ''println()'' O mesmo que a função ''print()'', exceto que acrescenta uma linha nova ao final da chamada.
* ''available()'' Retorna o número de bytes disponíveis.
* ''peek()'' Investiga o próximo byte de dados no buffer da porta serial. Não o recupera do buffer. Retorna -1 se não há dado disponível.
* ''flush()'' Descarrega o buffer da porta serial.
* ''end()'' Fecha a porta serial.
 
 
==Enviando texto para Monitor Serial==
 
;EXEMPLO 1:
 
<syntaxhighlight lang=vhdl>
void setup(){
  Serial.begin(9600);  //Inicia a comunicação serial a 9600 bauds
}
 
void loop(){
  Serial.println("Aprendendo a programar no arduino"); 
// Envia a string "Aprendendo a programar no arduino"     
//para a console
}
</syntaxhighlight>
 
 
Agora acesse o Monitor Serial, no menu do Arduino.
 
O resultado é uma sucessão de impressões da string “Aprendendo a programar no arduino”.
 
Vimos que iniciamos a comunicação serial através do comando serial.begin(9600) que colocamos dentro do setup(){} .
 
O  valor de 9600 pode variar dependendo da sua aplicação veja mais sobre velocidade da porta serial nesse post:
[[http://www.tech-faq.com/difference-between-bit-rate-and-baud-rate.html Baud Rates]]
 
O comando ''Serial.print(“string aqui”)'' que faz com que a informação seja impressa no serial monitor.
 
Adiante veremos outros exemplos do uso do Serial.print, mas por ora quero que reparem que todo comando que não constrói um bloco (não tem “chaves” como o setup e o loop), ou então que não e uma diretiva de pré-processador (#include, #define que veremos adiante também)  termina com ponto e vírgula, isso indica o fim do comando.
 
==Acionando o LED do Arduino, via Monitor Serial==
 
;EXEMPLO 2:
 
No segundo teste, vamos acionar, acender e apagar, o led do pino 13 através de comandos de teclado do PC, na interface '''Serial Monitor''', do Arduino.
 
A programação também é simples e bem interessante:  
 
 
<syntaxhighlight lang=c>
#define LED 13
byte estebyte = 35;
void setup() {
  pinMode(LED, OUTPUT);
  Serial.begin(9600);
}
void loop() {
  Serial.println(" Como enviar valores formatados: ");
  Serial.println("Formato ASCII do valor: ");
  Serial.write(estebyte);
  Serial.println(".");
  Serial.println("Formato DECIMAL:");
  Serial.print(estebyte, DEC);
  Serial.println(".");
  Serial.println("Formato HEXADECIMAL:");
  Serial.print(estebyte, HEX);
  Serial.println(".");
  Serial.println("Formato BINÁRIO:");
  Serial.print(estebyte, BIN);
  Serial.println(".");
  Serial.println("");
  Serial.println("Agora, digite 0 no Monitor para apagar o LED e 1, para acender!");
  while(true) {
      if(Serial.available() > 0) {
        estebyte = Serial.read();
        if(estebyte == '1') {    // Digitou 1 no Monitor Serial
            digitalWrite(LED, HIGH);
            Serial.println(" LED ACESO!");
        }
        if(estebyte == '0'){        // Digitou 0 no Monitor Serial
            digitalWrite(LED, LOW);
            Serial.println(" LED APAGADO!");
        }  //end if
      }    //end if
  }//end while
}//end loop
</syntaxhighlight>
 
;EXEMPLO 2-B
 
<syntaxhighlight lang=c>
byte estebyte;
void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  Serial.println("Digite 0 no Monitor para apagar o LED e 1 para acender!");
}
void loop() {
 
  if(Serial.available() > 0) {
    estebyte = Serial.read();
    if(estebyte == '1') {    // Digitou 1 no Monitor Serial
        digitalWrite(13, HIGH);
        Serial.println(" LED ACESO!");
    }
    if(estebyte == '0'){        // Digitou 0 no Monitor Serial
        digitalWrite(13, LOW);
        Serial.println(" LED APAGADO!");
    }
  }   
}
</syntaxhighlight>
 
=Operadores Relacionais e Lógicos=
 
Os operadores relacionais e lógicos são os mesmos vistos na aula anterior.
 
{| class="wikitable" text-align: center;background:white;"
! style="background:#2E8B57; color:white;" | Operador
! style="background:#2E8B57; color:white;" | Significado
! style="background:#2E8B57; color:white;" | Exemplo
|-
|-
!style="text-align: center;background:white;" | >
| '''pinMode(pino,modo)'''
| maior que
Serve para estabelecer a direção do
!style="text-align: center;background:white;" | A > B
fluxo de informações em qualquer dos 14
pinos digitais. Dois parâmetros devem
ser passados à função: o primeiro indica
qual pino vai ser usado; o segundo, se
esse pino vai ser entrada ou se vai ser
saída dessas informações.
| '''pinMode(2,OUTPUT);'''
Aqui o pino 2 é selecionado para
transmitir informações do Arduino
para um circuito externo qualquer. 
Para configurar esse pino como
entrada, o segundo parâmetro dessa
função deve ser INPUT.
| Essa função é sempre
escrita dentro da
função
setup( ).
|-
|-
!style="text-align: center;background:white;" | >=
|'''digitalRead(pino) '''
|maior ou igual que
Uma vez configurado um certo pino
!style="text-align: center;background:white;" | A >= -1
como entrada com a função
pinMode( ), a informação presente
nesse pino pode ser lida com a função
digitalRead( )  e armazenada
numa variável qualquer.
| '''int chave = digitalRead(3);'''
Nesse exemplo a variável inteira
‘chave’ vai guardar o estado lógico
(verdadeiro/falso) presente no
pino digital 3.
|  
|-
|-
!style="text-align: center;background:white;" | <
| '''digitalWrite(pino,valor) '''
| menor que
Para enviar um nível lógico para qualquer
!style="text-align: center;background:white;" | B < 2
pino digital do Arduino utiliza-se essa
função. Dois parâmetros são requeri
dos: o número do pino e o estado lógico
(HIGH/LOW ) em que esse pino deve
permanecer.
| '''digitalWrite(2,HIGH);'''
Aqui uma tensão de 5 volts é colo
cada no pino 2. Para enviar terra
para esse pino o segundo parâmetro
deverá ser LOW.
| É necessário configurar previamente o
pino como saída com a função
pinMode( ).
|-
|-
!style="text-align: center;background:white;" | <=
| '''analogWrite(pino,valor)'''
| menor ou igual que
O Arduino pode gerar tensões analógicas
!style="text-align: center;background:white;" | A <= B
em 6 de seus 14 pinos digitais com a função
'''analogWrite( )'''. Dois parâmetros devem
ser passados à função: o primeiro indica em
qual pino será gerada a tensão; o segundo
determina a amplitude dessa tensão, e
deve ter valores entre 0 (para 0 volt) e
255 (para 5 volts).
| '''analogWrite(10,128);'''
Com esses parâmetros uma
tensão analógica de 2,5 volts
vai aparecer no pino 10. Não é
necessário configurar um pino
PWM como saída com a função
'''pinMode( )'''  quando se chama
função '''analogWrite( )'''.
| Modulação por Largura de Pulsos, ou  
PWM (Pulse Width Modulation) na
língua inglesa,  é uma técnica usada
para gerar tensões analógicas a partir
de uma sequência de pulsos digitais.
|-
|-
!style="text-align: center;background:white;" | ==
| '''attachInterrupt(pino,função,modo)'''
| igual a  
Essa função é uma rotina de serviço de
!style="text-align: center;background:white;" | B == 0
interrupção, ou ISR (Interrupt Service
Routine) em inglês. Toda vez que ocorrer
uma interrupção por hardware no pino digi
tal 2 ou no 3 do Arduino uma outra função,
criada pelo programador, vai ser chamada.
O terceiro parâmetro, modo, informa
como a interrupção vai ser disparada, se
na borda de subida do pulso detetado no
pino do Arduino, se na borda de descida, se
quando o pulso for baixo ou se na mudança
de nível desse pulso.
| '''attachInterrupt(0,contador,RISING);'''
Nesse exemplo a função
‘contador’ vai ser chamada
quando o Arduino detetar uma
mudança do nível LOW para
o nível HIGH em seu pino 2.
Nessa ISR o parâmetro 0
monitora o pino 2, o parâmetro 1
monitora o pino 3.
| LOW - dispara a interrupção quando
o pino está em 0;
CHANGE - dispara sempre que o
pino muda de estado (de 0 para 1,
ou vice-versa);
RISING - somente quando o pino
muda de 0 para 1;
FALLING - somente quando o pino
muda de 1 para 0.
|-
|-
!style="text-align: center;background:white;" | !=
| '''pulseIn(pino,valor,espera)'''
|diferente de
Essa função mede a largura em microssegundos
!style="text-align: center;background:white;" | B != A
de um pulso em qualquer pino digital.
O parâmetro ‘valor’ diz à função que
tipo de pulso deve ser medido, se HIGH
ou LOW. O parâmetro ‘espera’ (time out) é
opcional e se passado à função faz com que
a medida do pulso só comece após o tempo
em microssegundos ali especificado.
| '''pulseIn(4,HIGH);'''
Aqui essa função vai monitorar
o pino 4, e quando o nível
nesse pino mudar de LOW
para HIGH a sua largura vai
ser medida até que seu nível
volte para LOW. Se, por
exemplo, for passado o valor 100
como terceiro parâmetro, a
medida da largura do pulso só
será disparada após 100 uS.
| Uma aplicação interessante para
essas duas últimas funções seria
o de montar um contador de dois dígitos
com mostradores de 7-segmentos.
|}
|}


;EXEMPLO


{| class="wikitable" style="background-color:#ffffff; text-align: center;"
! style="background:#2E8B57; color:white;" | Operador
! style="background:#2E8B57; color:white;" | Significado
! style="background:#2E8B57; color:white;" | Exemplo
|-
!style="text-align: center;background:white;" |&&
|AND (E)
!style="text-align: center;background:white;" |(A<B) && (B!=0)
|-
!style="text-align: center;background:white;" |<nowiki>||</nowiki>
|OR (OU)
!style="text-align: center;background:white;" |(B>1)<nowiki>||</nowiki>(A==0)
|-
!style="text-align: center;background:white;" |!
|NOT (NÃO)
!style="text-align: center;background:white;" |!(A<=B)
|}
* Atenção para o uso dos parênteses.
Ver [http://www.ead.cpdee.ufmg.br/cursos/C/c.html Operadores Relacionais e Lógicos]
=Funções para Controle de Fluxo - Decisão=


==if( )==
No programa abaixo essas três funções: pinMode(), digitalRead() e digitalWrite() são utilizadas para acender um LED no pino 2 toda vez que
 
uma chave normalmente aberta no pino 3 for pressionada.
É um controle de fluxo usado para selecionar uma ou mais instruções baseado no resultado de um teste de comparação. Todas as instruções entre as chaves { } são executadas somente se o resultado desse teste for verdadeiro; se não, essas instruções não são executadas. Verdadeiro é qualquer resultado, mesmo negativo, diferente de zero. Falso é um resultado zero. A Figura 1 mostra o controle de fluxo utilizando os comandos '''if''' e '''if...else'''.


<syntaxhighlight lang=c>
<syntaxhighlight lang=c>
if (expressão){
void setup()  
  bloco de instruções; // se "expressão" for verdadeira, "bloco de instruções" é executado
{
    pinMode(11,OUTPUT);
    // led no pino 11 como saída
    pinMode(5,INPUT);  // Pode-se definir um resistor interno de pull-up com INPUT_PULLUP 
    // chave no pino 5 como entrada
}
void loop()
{
    int chave = digitalRead(5);  
    // variável ‘chave’ guarda estado do pino 5
    if (chave==HIGH)
      digitalWrite(11,LOW); 
    else
      digitalWrite(11,HIGH); 
    // estado de ‘chave’ é passado para pino 11
}
}
</syntaxhighlight>
</syntaxhighlight>


[[imagem:Fig037_MCO018703.jpg|600px|center]]
A Figura 3 mostra como ficaria as ligações para acender o LED toda vez que a chave for pressionada.
 
[[imagem:Fig043_MCO018703.jpg|400px|center]]
<center>
<center>
Figura 3 - Controle de Fluxo com os comandos '''if''' e '''if...else'''.
Figura 3 - Fios vermelhos são 5V, fios pretos GND e fios verdes conexões com os Pinos de E/S.
</center>
</center>


==if( )...else==
O botão ''push-button'' também é chamado micro ''switch''. A Figura 4 ilustra o seu funcionamento.


Ao se acrescentar mais um bloco de instruções no loop do comando '''if''' pode-se criar o comando '''if...else''' (Figura 1), para fazer um novo teste quando o resultado da expressão for falsa.
[[imagem:Fig013_MCO18703.png|500px|center]]
 
<center>
<syntaxhighlight lang=c>
Figura 4 - ''Push-button'' de pólo simples com 2 ou 4 pinos de contato.
if (expressão) {
</center>
  bloco de instruções1; // se "expressão" for verdadeira, "bloco de instruções1" é executado
}
else {
  bloco de instruções2; // se "expressão" for falsa, "bloco de instruções2" é executado
}
</syntaxhighlight>
 
==if( )...else if( )==


E de novo ao se acrescentar agora o comando '''if...else''' no loop do comando '''if''' pode-se criar mais um outro comando, o '''if...else if'''. No exemplo abaixo se "expressão1" for verdadeira o "bloco de instruções1" é executado; se "expressão1" for falsa mas "expressão2" for verdadeira "bloco de instruções2" é executado; e se "expressão1" e "expressão2" forem falsas o "bloco de instruções3"  é executado. A Figura 2 mostra os comandos '''if( )...else if( )''' e '''switch...case'''.
LED, ou ''Light Emitter Diode'' é um diodo emissor de luz que, quando alimentado corretamente, permite o fluxo de energia apenas em um sentido. É um componente polarizado (com pólos positivo e negativo) e deve ser corretamente conectado para funcionar. Note que o polo positivo possui uma perna maior (terminal maior) que a outra (veja a figura abaixo). Já o polo negativo possui a menor perna (terminal menor).  


[[imagem:Fig038_MCO018703.jpg|600px|center]]
[[imagem:Fig004_MCO18703.jpg|500px|center]]
<center>
<center>
Figura 4 - Controle de Fluxo usando os comandos '''if( )...else if( )''' e '''switch...case'''.
Figura 5 - ''Diodo emissor de luz.
</center>
</center>


<blockquote style="background:#FAFAD2; border: 2px solid #2E8B57; margin-left: 200px; margin-right: 200px; padding: 2em;">
;Nota: Alguns LED's apresentam o polo negativo chanfrado (plano) no seu exterior.
</blockquote>


<syntaxhighlight lang=c>
==Enviando estado de chave para Monitor Serial==
if (expressão1) {
  bloco de comandos1;
}
else if (expressão2) {
  bloco de instruções2;
}
else {
  bloco de comandos3;
}
</syntaxhighlight>


==switch...case==
;EXEMPLO 2: Neste teste, o estado de uma chave externa será lido e enviado pro Monitor Serial.


É possível ir inserindo comandos  '''if...else '''na posição do segundo bloco de instruções de outro comando '''if...else '''e assim criar uma cadeia de comandos para testar dezenas de expressões até encontrar uma que retorne um resultado verdadeiro e executar um dos blocos de instruções; mas existe um comando próprio que simplifica bastante essa seleção, é o comando '''switch...case''' (Figura 2). Esse comando permite comparar uma mesma variável inteira, ou uma expressão que retorne um inteiro, com vários valores possíveis. 
;ESQUEMÁTICO


; switch..,case
<syntaxhighlight lang=c>
switch (expressão) {
  case 1:  bloco de instruções1;
          break;
  case 2:  bloco de instruções2;
          break;
  case 3:  bloco de instruções3;
          break;
  default: bloco de instruções4;
}
</syntaxhighlight>


=Exemplos=
[[imagem:Fig022_MCO18703.png|500px|center]]


[1] Acender o LED se digitar 1 no monitor serial.
;CÓDIGO FONTE


<syntaxhighlight lang=c>
<syntaxhighlight lang=c>
byte estebyte; // variável que vai receber o valor do monitor serial
int pushButton=2;
void setup() {
 
    pinMode(10, OUTPUT);
void setup()
    Serial.begin(9600);
{
  Serial.begin(9600);
  pinMode(pushButton, INPUT);
}
}


void loop() {
void loop()  
    Serial.println("Digite 1 no Monitor para acender o LED: ");
{
    while(true)
  int buttonState=digitalRead(pushButton);
    {  
      if(Serial.available() > 0)
      {
        estebyte = Serial.read();
        if(estebyte == '1') // Digitou 1 no Monitor Serial
        {
          digitalWrite(10, HIGH);
          Serial.println(" LED ACESO!");
        }
      }//end if
  }//end while
}//end loop


  Serial.println(buttonState);
  delay(1);
}
</syntaxhighlight>
</syntaxhighlight>


[[imagem:Fig046_MCO018703.png|500px|center]]
;No protoshield do laboratório:
<center>
Figura 5 - Código do bloco de programação Tinkercad.
</center>
 


[[imagem:Fig023_MCO18703.jpg|400px|center]]


;Quando pressiona a chave, efeito no Monitor Serial:


[[imagem:Fig024_MCO18703.png|500px|center]]


==Pushbutton como interruptor liga/desliga==


Criar um circuito para atribuir duas funções em um único botão (pushbutton). O botão servirá como um interruptor para ligar e desligar um componente eletrônico. Neste exemplo vamos ligar e desligar um led utilizando o pushbutton como interruptor.


[2] Acende o LED se digitar 1 no monitor serial senão for 1 apaga.
;EXEMPLO 3


<syntaxhighlight lang=c>
<syntaxhighlight lang=c>
byte estebyte; // variável que vai receber o valor do monitor serial
const int buttonPin = 6;
const int ledPin = 13;
 
int estado = 0; // variável para leitura do pushbutton
int guarda_estado = LOW; // variável para armazenar valores do pushbutton
 
void setup() {
void setup() {
     pinMode(10, OUTPUT);
     pinMode(ledPin, OUTPUT);
     Serial.begin(9600);
     pinMode(buttonPin, INPUT); // resistor de pullup -> pinMode(buttonPin, INPUT_PULLUP);
}
}
 
void loop(){
    estado = digitalRead(buttonPin);
    if (estado == LOW) {    // para pullup (estado==LOW)
        guarda_estado = !guarda_estado;  // inverte valor da variável variable_buttonEstado
        delay(500); //esperera o tempo de 500ms para evitar que haja várias vezes alterações
    }
    if (guarda_estado == HIGH) {
        digitalWrite(ledPin, HIGH);
    }
    else {
        digitalWrite(ledPin, LOW);
    }
}
</syntaxhighlight>


void loop() {
=Exercícios=
    Serial.println("Digite 1 no Monitor para acender o LED e qualquer outro para apagar: ");
    while(true)
    {
      if(Serial.available() > 0)
      {
        estebyte = Serial.read();
        if(estebyte == '1') // Digitou 1 no Monitor Serial
        {
          digitalWrite(10, HIGH);
          Serial.println(" LED ACESO!");
        }
        else
        {
          digitalWrite(10, LOW);
          Serial.println(" LED APAGADO!");
        }
      }//end if
  }//end while
}//end loop
 
</syntaxhighlight>


[3] Acende o LED se digitar 1 no monitor serial senão se for 2 apaga.
:1. Altere o programa Button para trocar o estado do LED quando o botão é pressionado.
:2. Explique e implemente o código abaixo:


<syntaxhighlight lang=c>
<syntaxhighlight lang=c>
byte estebyte; // variável que vai receber o valor do monitor serial
#define BOTAO 6
#define LED 13
void setup() {
void setup() {
    pinMode(10, OUTPUT);
  pinMode(LED, OUTPUT);
    Serial.begin(9600);
  pinMode(BOTAO, INPUT);
}
}


void loop() {
void loop() {
    Serial.println("Digite 1 no Monitor para acender o LED e digite 2 para apagar o LED: ");
  digitalWrite(LED, !digitalRead(BOTAO));
    while(true)
}
    {
      if(Serial.available() > 0)
      {
        estebyte = Serial.read();
        if(estebyte == '1') // Digitou 1 no Monitor Serial
        {
          digitalWrite(10, HIGH);
          Serial.println(" LED ACESO!");
        }
        else if(estebyte == '2') // Digitou 2 no Monitor Serial
        {
          digitalWrite(10, LOW);
          Serial.println(" LED APAGADO!");
        }
      }//end if
  }//end while
}//end loop
 
</syntaxhighlight>
</syntaxhighlight>


[4] Desafio: Acrescente mais um LED no seu experimento e, utilizando o comando '''switch..case''', crie todas as possibilidades de acender e apagar os dois LEDs.
;Nota: O operador !, em linguagem C, significa negação ('''NOT''') e tem como finalidade complementar a expressão que segue à sua direita.
 
 
</pre>


=Responda=
=Referências=


# Para que serve o monitor serial da IDE do Arduino?
[1] https://portal.vidadesilicio.com.br/entradas-e-saidas-digitais/
# Quais os controles de fluxo que você viu nessa aula?
# Dê um exemplo de uso do comando ''if...else'''.


[2] http://ordemnatural.com.br/pdf-files/CartilhadoArduino_ed1.pdf


[3] https://www.tinkercad.com/circuits


[4] http://www.um.pro.br/arduino/index.php?c=ArduinoUno


-----
-----

Edição atual tal como às 13h07min de 14 de novembro de 2024

1 Mapa das Entradas e Saídas do Arduino

OBJETIVOS

O aluno será capaz de:

  • Apresentar o mapa das entradas e saídas do Arduino;
  • Saber utilizar as funções na linguagem do Arduino.


METODOLOGIA
A aula será expositiva e dialogada, utilizando apresentação de texto base na Internet, onde serão mostrados exemplos executados programas para programação de microcontroladores. Na prática utilizaremos os pinos digitais como entrada digital fazendo uso de pushbotton.
INTRODUÇÃO

Nessa aula vamos aprender alguns conceitos básicos para começar a utilizar uma placa Arduíno. Este conteúdo mostrará como configurar e manipular as entradas e saídas digitais em uma placa Arduino, de modo que, no decorrer deste material você aprenderá a desenvolver programas capazes de utilizar as funções, por exemplo, de fazer com que o seu Arduíno realize o acionamento de um LED e também com que ele consiga saber se um botão foi pressionado.


Figura 1 - Mapa das Entradas e Saídas do Arduino.

Pinos Digitais
São usados para detecção ou transmissão de controles digitais.
Funções em C:
pinMode( )
digitalRead( )
digitalWrite( )
analogWrite( )
attachInterrupt( )
pulseIn( )


Pinos analógicos
São usados para leitura de sinais de sensores análogicos.
Funções em C:
analogRead( )


Porta USB
É usada para comunicação serial com um computador.
Funções em C:
begin( )
end( )
available( )
read( )
print( )
println( )
Pinos de Alimentação
São usados para alimentação de circuitos externos e reset do Arduino.

1.1 Funções das Portas de E/S

PINOS DIGITAIS

São 14 pinos marcados com o nome DIGITAL logo abaixo de duas barras de 8 pinos. São numerados de 0 a 13 da direita para a esquerda e podem ser configurados pela função pinMode( ) para detetarem ou transmitirem níveis lógicos digitais (verdadeiro/falso, 1/0 ou HIGH/LOW). A Figura 2 mostra o mapa de pinos Digitais do Arduino.

Figura 2 - Mapa dos Pinos Digitais do Arduino.


Função Exemplo Notas
pinMode(pino,modo)

Serve para estabelecer a direção do fluxo de informações em qualquer dos 14 pinos digitais. Dois parâmetros devem ser passados à função: o primeiro indica qual pino vai ser usado; o segundo, se esse pino vai ser entrada ou se vai ser saída dessas informações.

pinMode(2,OUTPUT);

Aqui o pino 2 é selecionado para transmitir informações do Arduino para um circuito externo qualquer. Para configurar esse pino como entrada, o segundo parâmetro dessa função deve ser INPUT.

Essa função é sempre

escrita dentro da função setup( ).

digitalRead(pino)

Uma vez configurado um certo pino como entrada com a função pinMode( ), a informação presente nesse pino pode ser lida com a função digitalRead( ) e armazenada numa variável qualquer.

int chave = digitalRead(3);

Nesse exemplo a variável inteira ‘chave’ vai guardar o estado lógico (verdadeiro/falso) presente no pino digital 3.

digitalWrite(pino,valor)

Para enviar um nível lógico para qualquer pino digital do Arduino utiliza-se essa função. Dois parâmetros são requeri dos: o número do pino e o estado lógico (HIGH/LOW ) em que esse pino deve permanecer.

digitalWrite(2,HIGH);

Aqui uma tensão de 5 volts é colo cada no pino 2. Para enviar terra para esse pino o segundo parâmetro deverá ser LOW.

É necessário configurar previamente o

pino como saída com a função pinMode( ).

analogWrite(pino,valor)

O Arduino pode gerar tensões analógicas em 6 de seus 14 pinos digitais com a função analogWrite( ). Dois parâmetros devem ser passados à função: o primeiro indica em qual pino será gerada a tensão; o segundo determina a amplitude dessa tensão, e deve ter valores entre 0 (para 0 volt) e 255 (para 5 volts).

analogWrite(10,128);

Com esses parâmetros uma tensão analógica de 2,5 volts vai aparecer no pino 10. Não é necessário configurar um pino PWM como saída com a função pinMode( ) quando se chama função analogWrite( ).

Modulação por Largura de Pulsos, ou

PWM (Pulse Width Modulation) na língua inglesa, é uma técnica usada para gerar tensões analógicas a partir de uma sequência de pulsos digitais.

attachInterrupt(pino,função,modo)

Essa função é uma rotina de serviço de interrupção, ou ISR (Interrupt Service Routine) em inglês. Toda vez que ocorrer uma interrupção por hardware no pino digi tal 2 ou no 3 do Arduino uma outra função, criada pelo programador, vai ser chamada. O terceiro parâmetro, modo, informa como a interrupção vai ser disparada, se na borda de subida do pulso detetado no pino do Arduino, se na borda de descida, se quando o pulso for baixo ou se na mudança de nível desse pulso.

attachInterrupt(0,contador,RISING);

Nesse exemplo a função ‘contador’ vai ser chamada quando o Arduino detetar uma mudança do nível LOW para o nível HIGH em seu pino 2. Nessa ISR o parâmetro 0 monitora o pino 2, o parâmetro 1 monitora o pino 3.

LOW - dispara a interrupção quando

o pino está em 0; CHANGE - dispara sempre que o pino muda de estado (de 0 para 1, ou vice-versa); RISING - somente quando o pino muda de 0 para 1; FALLING - somente quando o pino muda de 1 para 0.

pulseIn(pino,valor,espera)

Essa função mede a largura em microssegundos de um pulso em qualquer pino digital. O parâmetro ‘valor’ diz à função que tipo de pulso deve ser medido, se HIGH ou LOW. O parâmetro ‘espera’ (time out) é opcional e se passado à função faz com que a medida do pulso só comece após o tempo em microssegundos ali especificado.

pulseIn(4,HIGH);

Aqui essa função vai monitorar o pino 4, e quando o nível nesse pino mudar de LOW para HIGH a sua largura vai ser medida até que seu nível volte para LOW. Se, por exemplo, for passado o valor 100 como terceiro parâmetro, a medida da largura do pulso só será disparada após 100 uS.

Uma aplicação interessante para

essas duas últimas funções seria o de montar um contador de dois dígitos com mostradores de 7-segmentos.

EXEMPLO


No programa abaixo essas três funções: pinMode(), digitalRead() e digitalWrite() são utilizadas para acender um LED no pino 2 toda vez que uma chave normalmente aberta no pino 3 for pressionada.

void setup() 
{
    pinMode(11,OUTPUT);
    // led no pino 11 como saída
    pinMode(5,INPUT);   // Pode-se definir um resistor interno de pull-up com INPUT_PULLUP  
    // chave no pino 5 como entrada
}
void loop() 
{
    int chave = digitalRead(5); 
    // variável ‘chave’ guarda estado do pino 5
    if (chave==HIGH)
       digitalWrite(11,LOW);   
    else
       digitalWrite(11,HIGH);   
    // estado de ‘chave’ é passado para pino 11 
}

A Figura 3 mostra como ficaria as ligações para acender o LED toda vez que a chave for pressionada.

Figura 3 - Fios vermelhos são 5V, fios pretos GND e fios verdes conexões com os Pinos de E/S.

O botão push-button também é chamado micro switch. A Figura 4 ilustra o seu funcionamento.

Figura 4 - Push-button de pólo simples com 2 ou 4 pinos de contato.

LED, ou Light Emitter Diode é um diodo emissor de luz que, quando alimentado corretamente, permite o fluxo de energia apenas em um sentido. É um componente polarizado (com pólos positivo e negativo) e deve ser corretamente conectado para funcionar. Note que o polo positivo possui uma perna maior (terminal maior) que a outra (veja a figura abaixo). Já o polo negativo possui a menor perna (terminal menor).

Figura 5 - Diodo emissor de luz.

Nota
Alguns LED's apresentam o polo negativo chanfrado (plano) no seu exterior.

1.2 Enviando estado de chave para Monitor Serial

EXEMPLO 2
Neste teste, o estado de uma chave externa será lido e enviado pro Monitor Serial.
ESQUEMÁTICO


CÓDIGO FONTE
int pushButton=2;

void setup()
{
   Serial.begin(9600);
   pinMode(pushButton, INPUT);
}

void loop() 
{
   int buttonState=digitalRead(pushButton);

   Serial.println(buttonState);
   delay(1);
}
No protoshield do laboratório
Quando pressiona a chave, efeito no Monitor Serial

1.3 Pushbutton como interruptor liga/desliga

Criar um circuito para atribuir duas funções em um único botão (pushbutton). O botão servirá como um interruptor para ligar e desligar um componente eletrônico. Neste exemplo vamos ligar e desligar um led utilizando o pushbutton como interruptor.

EXEMPLO 3
const int buttonPin = 6; 
const int ledPin = 13; 

int estado = 0; // variável para leitura do pushbutton
int guarda_estado = LOW; // variável para armazenar valores do pushbutton
  
void setup() {
    pinMode(ledPin, OUTPUT);
    pinMode(buttonPin, INPUT); // resistor de pullup -> pinMode(buttonPin, INPUT_PULLUP);
}
  
void loop(){
    estado = digitalRead(buttonPin);
 
    if (estado == LOW) {    // para pullup (estado==LOW)
        guarda_estado = !guarda_estado;  // inverte valor da variável variable_buttonEstado
        delay(500); //esperera o tempo de 500ms para evitar que haja várias vezes alterações
    }
    if (guarda_estado == HIGH) {
        digitalWrite(ledPin, HIGH);
    }
    else {
        digitalWrite(ledPin, LOW);
    }
}

2 Exercícios

1. Altere o programa Button para trocar o estado do LED quando o botão é pressionado.
2. Explique e implemente o código abaixo:
#define BOTAO 6
#define LED 13
void setup() {
   pinMode(LED, OUTPUT);
   pinMode(BOTAO, INPUT);
}

void loop() {
   digitalWrite(LED, !digitalRead(BOTAO));
}
Nota
O operador !, em linguagem C, significa negação (NOT) e tem como finalidade complementar a expressão que segue à sua direita.

3 Referências

[1] https://portal.vidadesilicio.com.br/entradas-e-saidas-digitais/

[2] http://ordemnatural.com.br/pdf-files/CartilhadoArduino_ed1.pdf

[3] https://www.tinkercad.com/circuits

[4] http://www.um.pro.br/arduino/index.php?c=ArduinoUno