funciones-con-retorno-bitbloq

Os espelhos deveriam pensar duas vezes antes de devolver uma imagem…

Jean Cocteu

Na lição anterior aprendemos o que era uma função e para que se utilizava. Também nomeamos um tipo de função: as funções com retorno, que são as que aprofundaremos neste post. Estás pronto para dominar um pouco mais a arte das funções? Queres ser um mago do fluxo de programação? Ou simplesmente queres fazer os programas mais bonitos da comunidade bitbloq? Vamos a isso! bitbloq con margarita Para realizar os exemplos de hoje, necessitarás:

  • 1 x ZumBloq Miniservo
  • 1 x ZumBloq Potenciómetro
  • 1 x ZumBloq Sensor de luz
  • 1 x ZumBloq Buzzer
  • 1 x ZumBloq LCD
  • Uma placa controladora ZUM BT 328 ou compatível com Arduino UNO
  • Um cabo USB

O bloco função com retorno e o bloco chamar a função com retorno

As funções com retorno são muito parecidas com as funções sem retorno mas a sua diferença está na sua aplicação.

As funções com retorno criam um “mini-programa” que se encarrega de obter, preparar ou modificar uma variável. A função com retorno devolve-nos esse valor assim que o pedirmos, sem necessitar de dizer uma e outra vez ao programa como obter esse dado que necessitamos. Um exemplo poderia ser uma função que se encarregue de mapear o valor de um potenciómetro e depois devolva o valor já mapeado do mesmo componente, ou também se poderia fazer uma função que conforme a distância que o sensor de ultrassons devolver, te dirá se estás mais ou menos perto do objeto que tens à tua frente. (um programinha destes poderia ter salvo o Titanic, por exemplo).

As variáveis que utilizamos nas nossas funções com retorno podem ser de qualquer tipo: numéricas, de texto ou também vectores (essas variáveis com três compartimentos que explicávamos na lição do Joystick).

Consegues ver o espaço que existe no bloco função com retorno? Aí deve estar a variável que a função vai devolver quando a chamarmos. Coloca um bloco de variável para indicar-lhe que é o que tem que devolver, ainda que por vezes poderá ser útil colocar um número ou um texto que seja sempre o mesmo (usando um bloco número ou texto) como veremos mais adiante.

Já reparaste que  os blocos chamar a função com retorno tem a mesma forma que o bloco  usar uma variável?

Exacto! Têm a mesma forma porque o bloco de chamar a função com retorno encaixa em qualquer sítio onde encaixaria uma variável. Na verdade, ao entenderes as variáveis, entendes que as funciones com retorno poderiam ser como uma variável que, antes de ver o que têm dentro da caixa… mesmo antes de abrir a caixa, ocorrem coisas dentro de ela que já te permitem ver o conteúdo.

Vamos ver se já entendeste estes novos blocos:

Exemplo com os blocos de funções com retorno

Programa que move o miniservo com o potenciómetro, neste caso usando uma função

Lembras-te como funcionava o bloco mapear? Dá uma vista de olhos ao exemplo do link, porque te ajudará a entender como funciona o exemplo.

Como podes ver, temos novamente duas colunas de blocos: o programa principal em cima e a declaração da função receber_valor_potenciometro em baixo. Esta função tem o objectivo indicado no seu nome: quando a chamamos (com o bloco chamar uma função com retorno do programa principal) vai criar uma variável que armazenará o valor actual do potenciómetro. Depois vai criar outra variável para guardar o valor mapeado da variável potenciómetro entre 0 e 180 (que são os graus em que pode girar o miniservo) e por último, indicámos que tem que devolver-nos o valor da variável que tem o mapeamento guardado. De esta forma, quando no programa principal, usarmos o bloco receber_valor__potenciometro,  executa-se rapidamente a função de cima a abaixo e colocamos o valor  mapeado no valor do servo Graus(0-180)

O bloco Se…devolve…

E se quisermos que uma mesma função nos devolva algo diferente dependendo de, por exemplo, a luz que exista numa sala ou se tivermos pressionado um botão? Da mesma forma que no bloco de controlo Se…executar, temos um bloco para dotar de inteligência as nossas funções, para conseguir que decidam algo em função de outro valor. Este é o bloco “Se…devolve…”

Este bloco só pode ser utilizado dentro de uma função com retorno (fica tranquilo, pois o bitbloq recorda-te disso se te esqueceres). No primeiro espaço temos de colocar uma expressão lógica (dos blocos de lógica), e se esta for verdadeira, a função terminará imediatamente e devolverá o valor que tinhas inserido no segundo bloco em forma de variável ou um número ou texto fixo (digo um número ou texto fixo porque com este bloco tem um montão de aplicações).

Seguimos com o seguinte exemplo para ver uma destas aplicações muito úteis.

Exemplo com o bloco “Se…devolve”

Antes de analisar o exemplo, explicaremos a aplicação deste programa.

Suponhamos que estamos a usar um sensor de iluminação que não é o do Meu Primeiro Kit de Robótica (visto que já sabemos que este devolve valores entre 0 e 500 em função da luz que incide sobre o sensor), mas, não conhecemos esse valor?

Agora suponhamos que se te enganasses e o valor do sensor desse mais de 500, o servo que estiveres a usar, entrasse em curto-circuito e tivesses que despedir-te do teu precioso servo? Não achas que seria perfeito criar uma função que confirmasse este valor antes de usar o servo? Vamos desenvolver um exemplo que já usamos na lição do miniservo.

Programa com sensor de luz e confirmação de erros

func_com_ret_4Comecemos a estudar a pequena função em baixo. Muito simples, não? Se o sensor de luz der um valor maior ou igual a 500, a função devolverá a palavra Erro e se não for assim, não executará el bloque Si…devolve e passará a devolver o que lhe corresponde por defeito: Correcto. Seguidamente, no programa principal, podemos ver como consta apenas um bloco Se…executar… senão…executar e o que existe nas confirmações dos blocos de lógica são chamadas na função de confirmacao_valor_luz, assim que quando o programa chegue a este bloco, função vai executar-se e irá devolver Correcto ou Erro, entrando assim no ciclo que nos interessa: se for correcto, moverá o servo, se não, avisará com o buzzer. Como supomos que vocês claro que têm um sensor de luz bué fixe do nosso kit de robótica, para testar este exemplo podem usar o potenciómetro (que devolverá valores de entre 0 e 1023).

O bloco Devolver…

Este bloco tem a mesma função que a anterior. No entanto, não inclui a expressão lógica, o que lhe dá um pouco mais de versatilidade. Desta forma, podemos colocar o bloco dentro de uma condição Se..executar, mas fazer muitas mais coisas antes de devolver o valor que nos interessa. Vamos ver um exemplo no qual criámos uma função para saber se temos um objeto perto, a meia distância ou longe do sensor de ultrassons.

Programa para aviso de marcha atrás dos carros

Neste exemplo criámos uma função com retorno que primeiro lê a distância do sensor de ultrassons e armazena o valor numa variável. Depois disto, inicia um ciclo com um bloco Se…executar na qual, conforme a distância que esteja indicada na variável, acende um LED se estiver muito perto ou apaga se estiver mais longe. Além disso, quando estiver perto devolve a palavra “Perto”, se estiver a media distância devolve a palavra “Médio” e se estiver longe, não entra na condicional e executa simplesmente a função, devolvendo “Longe”.

No programa principal temos unicamente um bloco buzzer, que vai soar duma forma intermitente, esperando um tempo entre medias. Este tempo dependerá da palavra que nos devolver a função anterior.

Melhorando as funções: Funções com parâmetros de entrada

Estou certo que já reparaste nessa estrelinha que acompanha os blocos função com retorno e função sem retorno, assim como nos restantes blocos de controlo. Ela não está ali somente para enfeitar. A estrelinha permite-nos melhorar os blocos de função para torná-los ainda mais potentes. Com ela podemos adicionar parâmetros de entrada.

– O que é que está para aí a dizer? Que é isso de “parâmetros de entrada”? Isso soa-me a magia negra!

– Calma! Sei que soa a algo complicado e difícil, mas vamos já ver que não é muito.

Um parâmetro de entrada é uma variável do nosso programa principal que deixamos ser usada pela função. Desta forma podemos criar uma função muito inteligente e reutilizável. Por exemplo, podemos criar uma função que faça várias operações matemáticas a partir de dois valores que inserimos como parâmetros de entrada. Ou uma função que se lhe dermos como parâmetro de entrada um 3, pisque um LED 3 vezes. Quando criamos um parâmetro de entrada no bloco função com retorno ou função sem retorno, aparece um espaço para colocarmos uma variável ou número no bloco chamar a função (do tipo correspondente). Este será o que vamos adicionar à função para que possa ser usada. Por sua vez, uma variável associada com o parâmetro de entrada é criada, e terá o mesmo valor que inserires no espaço que falámos agora mesmo.

É importante saber que estas variáveis que se criaram com os parâmetros de entrada, só podem ser usadas dentro da função.

Quando criamos um parâmetro de entrada, devemos dar-lhe um nome que tenha a ver com o que vai fazer esse parâmetro na função e temos que dizer-lhe se o parâmetro de entrada vai ser um número (int) ou texto (string). Vamos ver um exemplo para entender melhor.

Exemplo com funções com parâmetros de entrada

Programa que faz operações com dois parâmetros de entrada e mostra o resultado no LCD

Neste exemplo, podemos ver como foi criada uma função com retorno com parâmetros de entrada. Os parâmetros de entrada são entrada_1 e entrada_2 e foram colocados nos espaços, duas variáveis: dado 1 e dado 2. Agora, entrada_1 vale o mesmo que o dado 1 e entrada_2 vale o mesmo que o dado 2, mas agora podemos usar entrada_1 e entrada_2 dentro da função para realizar operações matemáticas com elas.

No final, a função devolve o valor final da operação ao programa principal e imprime o valor no LCD. (para ver como funciona esta última, clica aquí)

Agora que já sabemos a teoria, só nos resta practicar para domina-las. Tenta usá-las sempre que poderes e vais ver que vais começar a vê-las como uma grande ajuda.