Baixe o app para aproveitar ainda mais
Prévia do material em texto
AULA 6 LÓGICA E MICROCONTROLADORES Prof. Charles Way Hun Fung 2 TEMA 1 – FUNÇÕES E PROCEDIMENTOS Quando um programa é desenvolvido, é comum a ocorrência de repetição de código, seja por um cálculo ou por uma execução repetitiva de eventos. Um exemplo comum seria acender um LED por um tempo – os comandos para realizar essa tarefa são sempre praticamente os mesmos: digitalWrite(pino,HIGH); delay(tempo); digitalWrite(pino,LOW); Sempre que algum LED tiver que ser aceso no projeto, essas três linhas serão utilizadas, apenas alternando as variáveis pino e tempo. A modularização consiste em juntar trechos ou blocos de código que se repetem, diminuindo a complexidade do programa analisado. Seria muito mais simples, em vez de escrever as três linhas de código citadas, escrever ligaLED(pino,tempo), em que pino é o pino digital que o LED está conectado no Arduino e tempo é o tempo em milissegundos que o LED permanecerá aceso. Esses módulos são chamados de funções e aplicados em linguagens como C/C++ e Wiring, devido ao formato estruturado da linguagem em que todo código deve executar dentro de funções. O formato padrão é: <tipo de retorno> <nome da função>(<parâmetros>){ <comandos da função> <retorno> } Exemplo de função: int somaValores(int A, int B){ int resultado; resultado = A+B; return resultado; } Essa função realiza a soma de dois valores inteiros A e B, que são recebidos por parâmetro, e retorna o resultado dessa soma. A seguir, estão descritas as diversas partes de uma função, tendo como base um exemplo: 3 Tipo de retorno: é o tipo de dado que a função irá retornar. Pode ser atribuído qualquer tipo e ainda o void, que indica que não haverá retorno. No exemplo, foi usado o tipo inteiro, que corresponde ao resultado da soma das variáveis A e B. Parâmetros: são as variáveis colocadas entre parênteses. Devem ser declaradas com separação por vírgula, seguindo o padrão <tipo> <nome_parâmetro>. Exemplo: int A e int B. Essas variáveis receberão valor quando acontecer a chamada dessa função. Comandos da função: são os comandos na linguagem Wiring que ficam no escopo da função (entre chaves “{ }”). Pode existir declaração de variáveis, operações lógicas, aritméticas e relacionais, estruturas condicionais, repetição e retorno da função. Retorno da função: é um campo que é obrigatório se o tipo de retorno não for void. É composto da palavra return seguida do valor de retorno, que pode ser uma variável ou uma sentença que resulte nesse valor. O retorno deve ser do mesmo tipo que apresentado no tipo de retorno. No exemplo, o retorno da função é linha que tem o comando return, e, nesse caso, o retorno da função é a variável resultado. Após a execução do comando return, a função é finalizada, independentemente da quantidade de linhas após o return ou se estiver dentro de alguma estrutura de controle. É comum o uso de funções que não tenham retorno, as quais são conhecidas como procedimentos. Nesse caso, o campo retorno da função não será usado. O formato padrão de um procedimento é: void <nome do procedimento>(<parâmetros>){ <comandos do procedimento > } Exemplo de procedimento: void inicializaSerial(int taxaCom){ Serial.begin(taxaCom); Serial.println(“Comunicacao serial inicializada”); } Perceba que o exemplo não tem um retorno, são apenas comandos que serão usados para situações específicas. Nesse caso, inicializa a comunicação serial e envia uma mensagem dizendo que foi inicializada. Não é necessário 4 enviar nenhum retorno, apenas executar as instruções. O procedimento é um modo bastante comum de reduzir códigos repetidos e deixar de forma geral o código fonte mais legível. TEMA 2 – LOCALIZAÇÃO DAS FUNÇÕES No tema anterior, foram estudados o formato e as partes de uma função. Agora, a questão é onde colocar no código essas novas funções. Na verdade, há duas opções: antes ou depois das funções setup() e loop(). Há algumas observações para cada uma dessas situações. 2.1 Funções localizadas antes das funções-padrão Figura 1 – Implementação de função antes das funções-padrão Na Figura 1, há um Arduino com um botão conectado ao pino 2. Para detectar que o botão foi pressionado, o nível lógico do pino 2 deverá ser analisado. Valor lógico baixo ou LOW indica que não está pressionado. Caso contrário, o pino 2 estará em HIGH, e, nessa condição, o LED interno da placa acenderá. Para comportar essas condições, foi implementado o código a seguir: 5 Figura 2 – Código fonte com a função implementada antes das funções-padrão A Figura 2 apresenta um código fonte no qual existe uma função chamada botaoPress(), que foi implementada antes das funções setup() e loop(). Nesse caso, quando o código é executado, a primeira linha de código que é recebida pelo processador é a linha 16, ou seja, o começo da função setup(). Conforme estudado anteriormente, primeiro a função setup() e depois a função loop() são executas. Entretanto, o compilador, software que transforma o código fonte em código de máquina, para que o processador compreenda a linguagem de programação, computa toda a função botaoPress e a armazena na memória. Dessa forma, quando ocorrer a execução dessa função na linha 22, a ferramenta terá conhecimento sobre como executá-la. O registro das funções pelo compilador é essencial para a criação do código de máquina. 2.2 Funções localizadas depois das funções-padrão Na segunda situação, a função será colocada depois das funções-padrão: 6 Figura 3 – Código fonte com a função implementada depois das funções-padrão Na Figura 3, a função botaoPress() foi colocada depois das funções- padrão. Isso pode causar um erro na hora da compilação (nem sempre causa, depende do tamanho do programa), pois o compilador não conhecerá a função botaoPress() quando executar a linha 13. Para compreender melhor isso, finja que a linha 3 não existe (o significado disso será explicado depois). Suponha que o compilador irá ler linha por linha o código da Figura 3 e começará a executá-lo a partir da linha 5, na função setup(). Quando começar a executar a função loop(), irá se deparar com a linha 13, na qual há uma chamada para a função botaoPress(). Entretanto, o compilador não tem em sua memória a função botaoPress(), e isso causará um erro, afirmando que o compilador não conhece essa função. Esse erro pode ser resolvido inserindo uma linha antes das funções-padrão chamada cabeçalho da função. Esta consiste na primeira linha da função, a qual contém o tipo de retorno, o nome e os tipos dos parâmetros, seguidos de um ponto e vírgula (linha 3 da Figura 3). Isso é uma informação para o compilador, afirmando que existe essa função em alguma parte do código fonte. Com essa informação, o compilador pode procurar pelo código da função quando ocorrer a chamada. 7 TEMA 3 – CHAMADA DE FUNÇÃO A Figura 3 apresentou outro conceito sobre funções: a chamada da função. Esta consiste em chamar a função, passando os valores necessários nos parâmetros e recebendo o valor de retorno desta. Para ilustrar esse conceito, o exemplo ilustrado na Figura 4 apresenta uma função que faz a multiplicação de dois valores e o retorno do resultado dessa operação: Figura 4 – Chamada de função Na Figura 4, a função multiplica é definida nas linhas 4, 5 e 6. Os parâmetros dessa função são duas variáveis inteiras A e B, com um retorno do tipo inteiro. Logo, para utilizar essa função, é preciso colocar dois valores inteiros no lugar dos parâmetros (separados por vírgula) e uma variável inteira para receber o valor de retorno. A linha 14 da Figura 4 exemplifica uma chamada da função multiplica. Para isso, foram criadas as variáveis conta, x1 e x2. No caso desse programa, as variáveis x1 e x2 têm respectivamente os valores 3 e 6, que foram definidosnas linhas 12 e 13. A função multiplica executará a multiplicação do valor das variáveis x1 e x2, copiando esses valores para as variáveis locais A e B. O valor copiado segue a ordem dos parâmetros x1 A, x2 B, por isso, sempre que se analisa uma função, é preciso considerar os parâmetros como variáveis locais com valor já estabelecido. 8 A função multiplica realiza a operação de multiplicação de A com B na linha 5 e retorna o resultado. Retornar significa terminar a função e tornar, transformar o retorno da função com o valor equivalente ao do valor retornado – no exemplo da Figura 4, o valor de retorno é o conteúdo da variável resultado. Na linha 14, em que ocorre a chamada da função, a variável conta recebe o valor de resultado, e, dessa forma, a função é finalizada e o fluxo do código volta para onde a função foi chamada. 3.1 Chamadas de funções sem parâmetros Há possibilidade de as funções utilizadas não terem parâmetros, principalmente com o uso de variáveis globais. Nesse caso, não é preciso passar nenhum dado para a função para chamá-la. A Figura 5 apresenta um exemplo desse tipo de função: Figura 5 – Chamada de função sem parâmetro A função apresentada na Figura 5 é semelhante à mostrada na Figura 4, mas não recebe nenhum valor como parâmetro. Nesse caso, é feito o uso das variáveis globais: perceba que as variáveis x1 e x2 estão presentes tanto em multiplica() como em setup(). Quando é realizada a chamada da função na linha 14, o código da função multiplica é executado, fazendo a multiplicação entre x1 e x2 e armazenando esse 9 dado na variável resultado (linha 5). O retorno da função segue o mesmo procedimento descrito para a função da Figura 4. 3.2 Chamadas de funções sem retorno Outra variação de chamada de função é a chamada sem retorno, apresentada na Figura 3. A função botaoPress tem um tipo de retorno void (ver linha 17), o que indica que essa função não precisará ter a linha do comando return. A diferença na chamada dessa função é que basta chamar o nome da função, com os respectivos parâmetros, caso necessário, finalizando com um ponto e vírgula. Um exemplo dessa chamada se encontra na linha 13 da Figura 3, em que ocorre a chamada de uma função que não tem retorno nem parâmetros. TEMA 4 – FUNÇÕES PREDEFINIDAS NO ARDUINO Na IDE do Arduino, há diversas funções predefinidas que o desenvolvedor pode utilizar, não precisando declarar o código fonte. Segundo a Documentação de Referência da Linguagem Arduino ([S.d.]), serão listados a seguir os tipos e as funções definidas na ferramenta. 4.1 Entrada e saída digital Funções usadas para configurar, ler e escrever nos pinos digitais do Arduino (Quadro 1). Quadro 1 – Funções de entrada e saída digital digitalRead() Leitura digital de um pino. digitalWrite() Escrita digital de um pino. pinMode() Seleciona o pino e o modo de operação. 4.2 Entrada e saída analógica Funções usadas para receber e escrever dados analógicos nos pinos analógicos e digitais (Quadro 2). 10 Quadro 2 – Funções de entrada e saída analógica analogRead() Leitura de um pino analógico. analogWrite() Escrita de dados em formato analógico (PWM). analogReference() Configura a tensão de referência das entradas analógicas. 4.3 Funções temporizadas Funções usadas para contagem de tempo ou intervalos de tempo para o programa (Quadro 3). Quadro 3 – Funções temporizadas delay() Pausa o programa pelo tempo em milissegundos passado por parâmetro. delayMicroseconds() Pausa o programa pelo tempo em microssegundos passado por parâmetro. micros() Retorna a quantidade de microssegundos que passou desde que a placa do Arduino foi iniciada. millis() Retorna a quantidade de milissegundos que passou desde que a placa do Arduino foi iniciada. 4.4 Funções matemáticas Operações matemáticas utilizadas para resolução de equações (Quadro 4). Quadro 4 – Funções matemáticas abs() Retorna o valor absoluto do valor. constrain() Deixa um número no intervalo determinado. map() Remapeia um intervalo de números para outro intervalo. max() Retorna o maior número entre dois. min() Retorna o menor número entre dois pow() Função exponencial. sq() Retorna o quadrado do número. sqrt() Função raiz quadrada. 4.5 Funções trigonométricas Seguem a mesma ideia das operações matemáticas, mas para problemas de geometria que fazem uso de ângulos (Quadro 5). 11 Quadro 5 – Funções trigonométricas sin() Cálculo do seno do ângulo em radianos. cos() Cálculo do cosseno do ângulo em radianos tan() Cálculo da tangente do ângulo em radianos. 4.6 Números aleatórios Funções usadas para obter números aleatórios (Quadro 6). Quadro 6 – Funções trigonométricas Random() Retorna um número pseudoaleatório, limitado pelo valor máximo passado como parâmetro. randomSeed() Reinicializa o gerador de números pseudoaleatórios. Saiba mais Outras funções podem ser encontradas na Documentação de Referência da Linguagem Arduino. TEMA 5 – EXEMPLO DE FUNÇÕES COM O ARDUINO Para exemplificar o uso de funções, será apresentado um exemplo que tem um potenciômetro, um servo motor e dois LEDs. Nesse exemplo, o movimento do potenciômetro irá controlar a posição do servo motor. Quando estiver nos limites do valor do potenciômetro, os LEDs irão acender – o LED verde para o limite inferior e o LED vermelho para o limite superior. A Figura 6 apresenta o diagrama elétrico da implementação desse problema: 12 Figura 6 – Exemplo do uso de funções Na Figura 6, podemos ver que o motor e os LEDs se encontram nos pinos digitais 9, 3 e 2, respectivamente, enquanto o potenciômetro está no pino analógico zero do Arduino. A Figura 7 ilustra o código utilizado para controlar o servo motor a partir do potenciômetro: Figura 7 – Código do exemplo do uso de funções 13 No código apresentado na Figura 7, há diversos usos de funções, que serão explicados a seguir. Na linha 1, há uma inclusão da biblioteca Servo.h, que contém diversas funções e definições que auxiliam o programador a utilizar um servo motor, não precisando entender profundamente como este funciona. Essa biblioteca possibilita o uso do tipo Servo, definido na linha 3, como uma variável desse tipo. As linhas de 10 a 13 apresentam os cabeçalhos das funções que são usadas no programa, o que serve para o compilador reconhecer que essas funções existem. Na função setup(), são realizadas quatro chamadas de função: 1. servo.attach(9): indica que o servo motor está conectado no pino digital 9. 2. Serial.begin(9600): inicializa a serial com taxa de comunicação de 9600 bits por segundo. 3. pinMode(ledVerde, OUTPUT): indica que o pino 2, no qual está o LED verde, é uma saída de dados. 14 4. pinMode(ledVermelho, OUTPUT): indica que o pino 3, no qual está o LED vermelho, é uma saída de dados. Essas chamadas de função apresentam parâmetros, mas não produzem nenhum retorno. Isso pode ser percebido porque não há nenhuma variável recebendo algum valor de retorno dessas funções. Na função loop(), nas linhas 23 e 24, temos duas funções com retorno. A primeira função é analogRead, que retorna o valor lido no pino analógico que está conectado ao potenciômetro. O valor lido varia de 0 a 1023, devido aos 10 bits do conversor A/D. Na linha seguinte, a função map faz o remapeamento do valor que se encontra na variável val. O intervalo de valores de val é convertido de 0 a 1023 para 0 a 180, o que quer dizer que os valores lidos do potenciômetro serão convertidos em um ângulo de 0 a 180º. Na linha 25, o valor de ângulo obtido a partir da leitura do potenciômetro é transmitido para o servo motor por meio do comando servo.write. Entre as linhas 26 e 37, é apresentada a lógica para acender os LEDs verde e vermelho. O primeiro irá acender caso o valor do ângulo lido seja iguala zero, como mostrado na linha 26. Caso contrário, o LED verde estará apagado (linha 30). Da mesma forma que o LED verde, o LED vermelho irá acender quando o valor do ângulo lido for igual a 180. Caso o ângulo seja diferente de 180, o LED vermelho estará apagado (linha 36). As linhas de 44 a 55 informam a definição das funções que foram apresentadas como cabeçalho nas linhas de 10 a 13. As funções são compostas apenas da função digitalWrite, que é usada para trocar o nível lógico dos pinos digitais, para que, assim, os LEDs possam acender e apagar. 15 REFERÊNCIAS ALVES, W. P. Linguagem e Lógica de programação. 1. ed. São Paulo: Érica, 2014. ASCENCIO, A. F. G. Fundamentos da programação de computadores. 1. ed. São Paulo: Prentice Hall, 2002. DOCUMENTAÇÃO de Referência da Linguagem Arduino. Arduino, [S.d.]. Disponível em: <https://www.arduino.cc/reference/pt/ >. Acesso em: 6 nov. 2019. FORBELLONE, A. L. V. Lógica de programação: a construção de algoritmos e estrutura de dados. 3. ed. São Paulo: Prentice Hall, 2005. MCROBERTS, M. Arduino básico. 1. ed. São Paulo: Novatec, 2011. OLIVEIRA, C. L. V. Arduino descomplicado: aprenda com projetos de eletrônica e programação. 1. ed. São Paulo: Érica, 2017.
Compartilhar