Mudanças entre as edições de "MCO018703 2021 1 AULA04"

De MediaWiki do Campus São José
Ir para: navegação, pesquisa
(Objetivos)
(Comunicação Serial)
Linha 1: Linha 1:
 
=Comunicação Serial=
 
=Comunicação Serial=
 +
 +
;Objetivos:
 +
 +
*Aprender a utilizar o monitor serial;
 +
*Aprender sobre funções para controle de de fluxo;
 +
*Utilizar o comando de decisão ''if else''.
 +
 +
  
 
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.
 
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.

Edição das 16h25min de 17 de maio de 2021

Comunicação Serial

Objetivos
  • Aprender a utilizar o monitor serial;
  • Aprender sobre funções para controle de de fluxo;
  • Utilizar o comando de decisão if else.


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.

Fig020 MCO18703.png


Como a comunicação é a serial padrão, é fácil trocar informações entre o computador e o Arduino.

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

Fig021 MCO18703.png

A biblioteca Serial() do Wiring tem todas as funções necessárias para se implementar comunicação serial entre o Arduino e o PC.

A porta serial te permite ler e escrever facilmente dados de e para dispositivos externos.

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.

Velocidades típicas de comunicação são: 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600 e 115200 BPS.

Apenas uma aplicação pode utilizar a porta serial, a cada vez.


As funções mais utilizadas são:

  • begin() Abre a porta serial para leitura ou escrita.
  • 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
  • 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
  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
   }


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: [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 tambem) 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:


 
 #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

Funções para Controle de Fluxo - Decisão

if( )

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

if (expressão){
   bloco de instruções; // se "expressão" for verdadeira, "bloco de instruções" é executado
}
Fig037 MCO018703.jpg

Figura 1 - Controle de Fluxo com os comandos if e if...else.

if( )...else

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.

if (expressão) {
   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 
}

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.

Fig038 MCO018703.jpg

Figura 2 - Controle de Fluxo usando os comandos if( )...else if( ) e switch...case.


if (expressão1) {
   bloco de comandos1; 
}
else if (expressão2) {
   bloco de instruções2; 
}
else {
   bloco de comandos3; 
}

switch...case

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

switch..,case
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; 
}

Operadores Relacionais e Lógicos

Vamos recordar os principais operadores relacionais e lógicos vistos nas aulas anteriores.

Relacionais
Operador Significado
> maior que
>= maior ou igual que
< menor que
<= menor ou igual que
== igual a
!= diferente de


Lógicos
Operador Significado
&& AND (E)
|| OR (OU)
! NOT (NÃO)

Ver Operadores Relacionais e Lógicos

Exemplos

[1] Acender o LED se digitar 1 no monitor serial.

byte estebyte; // variável que vai receber o valor do monitor serial
void setup() {
    pinMode(10, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    Serial.println("Digite 1 no Monitor para acender o LED: ");
    while(true)
    { 
      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

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

byte estebyte; // variável que vai receber o valor do monitor serial
void setup() {
    pinMode(10, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    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

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

byte estebyte; // variável que vai receber o valor do monitor serial
void setup() {
    pinMode(10, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    Serial.println("Digite 1 no Monitor para acender o LED e digite 2 para apagar o LED: ");
    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

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




Icone voltar.png Icone menu.png Icone prox.png