arduino bÁsico lição v -...

81
15/08/14 Frederico Möller 1 ARDUINO BÁSICO Lição V Frederico José Dias Möller

Upload: vungoc

Post on 24-Nov-2018

221 views

Category:

Documents


0 download

TRANSCRIPT

15/08/14 Frederico Möller 1

ARDUINO BÁSICOLição V

Frederico José Dias Möller

15/08/14 Frederico Möller 2

Sumário

● Memória Volátil● Memória Permanente● EEPROM● EEPROM.read()● Exemplo IX● Exercício IX

● EEPROM.write()● Exemplo X● Armazenamento de

valores int e float● Função itoa()● Função atoi()

15/08/14 Frederico Möller 3

Sumário

● Conversão de valores float

● Exercício Final● Problemas dessa

forma de conversão● Operações de bitshift

15/08/14 Frederico Möller 4

Memória volátil

● Uma variável nada mais é que um endereço de memória que armazena um dado.

● Em todos os programas que fizemos até agora, neste curso, o Arduíno foi capaz de armazenar e acessar dados armazenados em sua memória.

● Tais dados no entanto, eram perdidos assim que o Arduíno era desligado, ou seja, estavam armazenados na memória volátil.

15/08/14 Frederico Möller 5

Memória volátil

● Muitos dos projetos feitos em arduíno não precisam de que o mesmo guarde os dados toda vez que é desligado. Podemos dizer que pelo propósito do Arduino, a maioria de seus projetos está bem servida com a memória volátil, ou seja aquela que morre junto com o fornecimento de energia da plataforma de prototipagem.

15/08/14 Frederico Möller 6

Memória permanente

● A memória permanente começa a se mostrar necessária no Arduino, principalmente quando temos que guardar configurações , mapeamentos de robôs , rotas e protocolos de comunicações.

● E é obvio que a plataforma possui uma memória permanente. Os programas carregados no Arduino são gravados em uma memória flash.

15/08/14 Frederico Möller 7

EEPROM

● Existe no entanto a memória EEPROM, no Arduino. E nela o usuário pode comandar a leitura e armazenamento de dados de forma permanente.

● Os dados gravados na memória EEPROM não são perdidos nem quando se grava um novo programa no Arduino. Uma vez gravado dado só é perdido (normalmente), quando um programa grava um novo dado em cima do antigo

15/08/14 Frederico Möller 8

EEPROM

● A memória EEPROM do Arduino é própria do seu microcontrolador e portanto sua capacidade vai depender do ATmega utilizado.

● No nosso caso, temos um ATmega328 sua memória EEPROM tem 1kB (kilobyte dividos em 1024 endereços de 1 byte.

● Mais informações sobre a memória EEPROM em geral se encontram na seção de leitura complementar.

15/08/14 Frederico Möller 9

EEPROM

● Para gravar e ler dados na memória EEPROM, o programa precisa ter a biblioteca EEPROM.h inclusa.

● Essa biblioteca é canônica da IDE do Arduino e portanto não precisa ser instalada separadamente. A IDE vem inclusivecom 3 exemplos prontos.

15/08/14 Frederico Möller 10

EEPROM.read()

● Normalmente os endereços da EEPROM de um Arduino vem com o valor 255 em cada. O endereço 0 pode vir com um valor diferente.

● A leitura de um endereço da memória EEPROM é feito atravéz do comando EEPROM.read(add)

● Add é o endereço de memória, no nosso caso um valor de 0 a 1023.

15/08/14 Frederico Möller 11

EEPROM.read()

● Normalmente os endereços da EEPROM de um Arduino vem com o valor 255 em cada. O endereço 0 pode vir com um valor diferente.

● A leitura de um endereço da memória EEPROM é feito atravéz do comando EEPROM.read(add)

● Add é o endereço de memória, no nosso caso um valor de 0 a 1023.

15/08/14 Frederico Möller 12

Exemplo IX

● Vamos a um exemplo bem simples. Vamos ler o que tem gravado no endereço 12 dos nossos arduinos.

● Uma vez que desejamos obter apenas uma leitura, a função loop não será utilizada

15/08/14 Frederico Möller 13

Exemplo IX

● Notem a inclusão da biblioteca EEPROM, da construção do programa na função setup, na função EEPROM.read() e na função loop sem nada em seu escopo.

15/08/14 Frederico Möller 14

Exemplo IX

● A variável a poderia ser do tipo char, no entanto isso resultaria na impressão de um valor da tabela ASCII ao invés de um numérico quando a função Serial.print(a) fosse chamada.

15/08/14 Frederico Möller 15

Exercício IX

● Durante a construção deste curso pelo menos um arduíno foi utilizado para testar as funções da biblioteca EEPROM.

● Usando o que foi aprendido até agora, descubram se o seu arduino é o que foi usado como cobaia, ou pelo menos se alguém deixou algo gravado na memória dele.

● Para facilitar, apenas os endereços iniciais foram usados nos testes.

15/08/14 Frederico Möller 16

Exercício IX

● Durante a construção deste curso pelo menos um arduíno foi utilizado para testar as funções da biblioteca EEPROM.

● Usando o que foi aprendido até agora, descubram se o seu arduino é o que foi usado como cobaia, ou pelo menos se alguém deixou algo gravado na memória dele.

● Para facilitar, apenas os endereços iniciais (0 a 32) foram usados nos testes.

15/08/14 Frederico Möller 17

Exercício IX

● O problema proposto pode até ter parecido complicado, no entanto se eu tivesse pedido "varra a memória em busca de alterações" estaria na cara que o que foi proposto pouco difere do exemplo passado

15/08/14 Frederico Möller 18

Exercício IX

● A diferença é que dessa vez temos uma variável de endereço, esta varia de valor dentro de um ciclo for.

● Coloquei aqui de 0 a 32, mas ela poderia variar dentro de qualquer intervalo de 0 a 1023

15/08/14 Frederico Möller 19

Exercício IX

● Dentro do ciclo for, o endereço é lido, o valor é armazenado na variável "a" e então é impresso na saída serial.

● Temos um delay para que seja possível acompanhar visualmente o valor armazenado em cada endereço.

15/08/14 Frederico Möller 20

EEPROM.write(add,val)

● A função EEPROM.write serve para armazenarmos um valor na memória EEPROM do arduino.

● Em add, colocamos o endereço de memória, que no nosso caso é um valor inteiro de 0 a 1023.

● Em val, vai o valor a ser armazenado, que é um byte, ou seja, um valor de 0 a 255.

15/08/14 Frederico Möller 21

Exemplo X

● Vamos fazer agora, um programa que leia o 3º endereço de memória (2), se este for maior que 100, ou então igual a 0, ele vai alterar esse valor para 1, se não, ele vai multiplicar esse valor por 2.

● Essa operação deve ser executada apenas uma vez, quando o arduino for ligado.

● O valor armazenado na memória deve ser exibido após a atualização.

15/08/14 Frederico Möller 22

Exemplo X

● Uma vez que as ações devem ocorrer apenas quando o arduino for ligado, nenhuma linha de código deve ser escrita dentro da função loop.

15/08/14 Frederico Möller 23

Exemplo X

● Inicialmente chamamos a biblioteca EEPROM.

● No setup, começamos por ligar a comunicação serial.

● Em seguida lemos o 3º endereço de memória.

15/08/14 Frederico Möller 24

Exemplo X

● O principal desse programa não é nem a leitura e gravação da memória EEPROM, mas sim o teste condicional.

15/08/14 Frederico Möller 25

Exemplo X

● Na excessão, ou seja, se val for diferente de zero e menor que 100 o valor de val vai ser multiplicado por 2.

● Atualizado, val é gravado no endereço 2 e depois é exibido via serial.

15/08/14 Frederico Möller 26

Armazenando valoes int e float

● O que aconteceria se tentassemos armazenar um valor inteiro em um endereço ROM?

● De acordo com o exemplo anterior, vimos que o fato da variável ser inteira não impede com que ela seja armazenada. Se o tamanho dela for o mesmo de um char, ou seja, um byte (0 a 255) ela vai ser armazenada sem problemas. Mas o que aconteceria se tentássemos armazenar um int maior que 255? Ou um valor float?

15/08/14 Frederico Möller 27

Armazenando valoes int e float

● O que aconteceria se tentassemos armazenar um valor inteiro em um endereço ROM?

● De acordo com o exemplo anterior, vimos que o fato da variável ser inteira não impede com que ela seja armazenada. Se o tamanho dela for o mesmo de um char, ou seja, um byte (0 a 255) ela vai ser armazenada sem problemas. Mas o que aconteceria se tentássemos armazenar um int maior que 255? Ou um valor float?

15/08/14 Frederico Möller 28

Armazenando valoes int e float

15/08/14 Frederico Möller 29

Armazenando valoes int e float

● Se observarem, ao invés de 1996, o arduino lê o valor de 204... Ao invés de 15.56, ele lê o valor 15.

● Por que isso acontece?● Variaveis int e float em geral, reservam 4 bytes

na memória para armazenar valores, no caso do arduino uno e similares, 2 bytes. Como os endereços de memória tem apenas um byte, apenas o byte menos significativo é armazenado.

15/08/14 Frederico Möller 30

Armazenando valores int e float

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0

0 0 0 0 0 1 1 1

1 1 0 0 1 1 0 0

1996Embinário

Apenas o byte menosSignificativo é armazenado

196 em binário

15/08/14 Frederico Möller 31

Armazenando valores int e float

● Infelizmente, na maioria das vezes, nos interessa armazenar valores int ou float, estes com mais de um byte de tamanho.

● Felizmente exitem diversas formas de contornar esse problema.

15/08/14 Frederico Möller 32

Armazenando valores int e float

● Infelizmente, na maioria das vezes, nos interessa armazenar valores int ou float, estes com mais de um byte de tamanho.

● Felizmente exitem diversas formas de contornar esse problema.

15/08/14 Frederico Möller 33

A função itoa(valor int,vetor char*,base)

● Essa é uma função da biblioteca stdio.h.

● Ela converte um valor inteiro em uma string.

● Ela faz essa conversão transformando cada dígito em um caracter, portanto 1996 tem 4 dígitos e precisará de uma string de 4 posições.

● Com essa string, basta chamar a função itoa, colocar o valor inteiro e a string dentro dos parenteses e a função fará a conversão.

● É preciso colocar também a base desejada, 10 para decimal, 16 para hexadecimal...

15/08/14 Frederico Möller 34

A função atoi(vetor char*)

● Essa é outra função da biblioteca stdio.h.● Ela converte uma string em um valor inteiro.● Diferente da itoa, nessa função, devemos

associar uma variável ao seu resultado.● Portanto a sitaxe correta será:

– Variável inteira=atoi(string)

15/08/14 Frederico Möller 35

Conversão de valores float

● A conversão de valores float já não é tão simples. Apesar de existir a função atof, a função ftoa não é canônica do C.

● Alguns programadores recomendam o uso da função sprintf, que imprime a saída de uma função printf em uma string, no entanto ela não costuma funcionar corretamente, pelo menos no arduino, para valores float.

15/08/14 Frederico Möller 36

Conversão de valores float

● Existe uma função chamada to_string, mas seu uso exige a importação de mais bibliotecas e por isso nós não veremos ela aqui.

● É interessante notar que qualquer valor numérico armazenado no arduino é racional.

● Sabendo disso é perfeitamente possível armazenar valores de ponto flutuante usando as funções atoi e itoa...

15/08/14 Frederico Möller 37

Exercício Final

● Este vai ser nosso último exercício nesse curso. Implementar uma função que armazene e uma que leia números de ponto flutuante na memória EEPROM do arduino.

● Não é uma tarefa fácil, mas ela pode ser executada de diversas formas.

● Lembrem-se que a função deve permitir que outros floats sejam armazenados sem apagar os que já foram armazenados.

15/08/14 Frederico Möller 38

Exercício Final

● Para facilitar, vamos nos limitar duas casas decimais e números de no máximo ordem 2 (ou seja, nada maior que 99.99, ou menor que -99.99)

● Como foi dito, é necessário poder armazenar vários números, pelo menos 10 floats devem ser armazenados sem que algum deles tenha que ser deletado.

15/08/14 Frederico Möller 39

Exercício Final

● Vamos ter que incluir, além da biblioteca EEPROM a biblioteca stdlib, para podermos usar as funções itoa e atoi.

● A primeira função implementada vai ser a responsável por armazenar o valor float na memória EEPROM.

15/08/14 Frederico Möller 40

Exercício Final

● Essa função deverá ser do tipo void, uma vez que ela não retorna valor algum, apenas armazena o valor na memória.

● Ela recebe um inteiro como endereço de memória e um float como valor a ser armazenado

15/08/14 Frederico Möller 41

Exercício Final

● É interessante observar que o endereço aqui não corresponde ao endereço real de memória. Como o valor vai ser convertido em uma string, vários endereços serão usados para armazenar um float.

15/08/14 Frederico Möller 42

Exercício Final

● Para evitar que se tenha que calcular o primeiro endereço, ou que a função tenha 6 entradas, reservamos a faixa de endereços do 512 ao 571 para armazenamento de floats.

15/08/14 Frederico Möller 43

Exercício Final

● Cada seqüência de 6 endereços equivale a um endereço "float". Por exemplo, os endereços do 512 ao 517 equivalem ao endereço 0 dessa função. Do 518 ao 513 temos o endereço 1 e assim por diante.

15/08/14 Frederico Möller 44

Exercício Final

● Inicialmente temos duas variáveis int declaradas, a i, que servirá como contadora de um ciclo for, e a valor_conv que é o valor float multiplicado por 100.

● Temos um vetor char de 6 posições chamado buffer declarado logo em seguida.

15/08/14 Frederico Möller 45

Exercício Final

● Quando multiplicamos o valor float por 100 obtemos um inteiro com no máximo 4 dígitos e um sinal.

● Esse inteiro é convertido para um vetor de char pela função itoa.

15/08/14 Frederico Möller 46

Exercício Final

● Em seguida cada posição do vetor é armazenada em um endereço de memória.

● Aqui é que entra a conversão do endereço da função para o endereço real.

15/08/14 Frederico Möller 47

Exercício Final

● Em cada passagem no ciclo for o endereço real de memória é atualizado dentro da função EEPROM.write pela expressão 512 + 6*add +i

15/08/14 Frederico Möller 48

Exercício Final

● 512 é onde começamos nossa "faixa reservada"

● 6*add é o endereço da função. É multiplicado por 6 por causa do tamanho da variável buffer [6]

● O i é cada posição do buffer.

15/08/14 Frederico Möller 49

Exercício Final

● A função seguinte é a ler_float, como o nome diz, ela lê um valor float armazenado na memória.

● É uma função tipo float, pois vai retornar um valor desse tipo.

15/08/14 Frederico Möller 50

Exercício Final

● A função recebe um valor inteiro, é o endereço de memória onde ela vai buscar o float.

● O endereço dado à função não corresponde aos endereços reais onde o valor float está armazenado.

15/08/14 Frederico Möller 51

Exercício Final

● Dentro da função são declarados um vetor de char, que vai futuramente receber cada byte do float armazenado na memória EEPROM.

15/08/14 Frederico Möller 52

Exercício Final

● Um inteiro i, que será usado como contador em um ciclo for.

● Um inteiro val_int, que vai receber a conversão string para inteiro realizado pela função atoi.

15/08/14 Frederico Möller 53

Exercício Final

● Uma variável float val_float que vai receber a conversão do valor inteiro para o valor flutuante.

● Essa variável poderia ser suprimida. Ela só está aqui para facilitar a visualização da lógica do exercício.

15/08/14 Frederico Möller 54

Exercício Final

● Após a declaração de variáveis, temos um ciclo for onde cada posição do buffer recebe o valor armazenado em um endereço de memória EEPROM.

15/08/14 Frederico Möller 55

Exercício Final

● A regra de conversão também foi usada aqui. Se o endereço na função for 3, o ciclo for fará com que os endereços 530,531,532,533,534 e 535 sejam lidos.

15/08/14 Frederico Möller 56

Exercício Final

● Ao término do ciclo, o buffer, já contendo todos os caracteres armazenados em uma determinada faixa da memória EEPROM é convertido em um inteiro pela função atoi.

15/08/14 Frederico Möller 57

Exercício Final

● A variável val_int é convertida em float e dividida por 100 (uma vez que na função de armazenamento, multiplicamos por 100)

● O valor convertido é a saída desta função.

15/08/14 Frederico Möller 58

Exercício Final

● Por fim um pequeno programa para demonstrar o funcionamento das funções

● Temos as variáveis float a e b, valendo 15.56 e 99.99 respectivamente.

15/08/14 Frederico Möller 59

Exercício Final

● As variáveis float c e d são declaradas, mas não tem valor definido.

● Usando a função armazena_float, armazenamos a no endereço 0 e b no endereço 1.

15/08/14 Frederico Möller 60

Exercício Final

● Ou seja, "a" está disposta nos endereços 512,513,514,515,516,517... e b do 518 ao 525.

15/08/14 Frederico Möller 61

Exercício Final

● Com a função ler_float recuperamos o valor desses endereços e os atribuimos às variáveis c e d.

● Por fim os valores são impressos. Os resultados podem ser facilmente conferidos no serial monitor.

15/08/14 Frederico Möller 62

Problemas dessa forma de conversão

● Já de cara podemos ver alguns problemas com esse tipo de método.

● Ao multiplicarmos o float por uma constante e salvar o resultado em um int, restringimos muito os valores float a serem lidos, se tivessemos que salvar o número 999.87, não conseguiríamos, pois 99987 está fora dos limites int do arduino uno.

15/08/14 Frederico Möller 63

Problemas dessa forma de conversão

● Já de cara podemos ver alguns problemas com esse tipo de método.

● Ao multiplicarmos o float por uma constante e salvar o resultado em um int, restringimos muito os valores float a serem lidos, se tivessemos que salvar o número 999.87, não conseguiríamos, pois 99987 está fora dos limites int do arduino uno.

15/08/14 Frederico Möller 64

Problemas dessa forma de conversão

● Podemos, claro, aprimorar esse método.● Um método válido seria, por meio de if-elses,

descobrir qual o tamanho da parte inteira do float, converter cada dígito dela em char e armazenar e depois multiplicar por 10 a parte fracionária, converter a parte inteira do novo número para caracter, subtrair o novo valor de sua parte inteira, multiplicar por 10 de novo...

15/08/14 Frederico Möller 65

Problemas dessa forma de conversão

● No entanto, isso iria requerer, além do espaço de memória para cada caracter do valor float, um para endereçar (dizer onde começa e onde termina o valor armazenado) e outro para dizer quantas casas decimais tinha a parte fracionária.

● As operações bit a bit no entanto resolvem muito bem esse problema.

15/08/14 Frederico Möller 66

Operações de bitshift

● Os operadores << e >> são os operadores de bitshift e são capazes de empurrar os bits de variáveis byte, int, ou long int (desde que o tamanho seja menor ou igual a 32 bits) para a esquerda ou para a direita.

● Por exemplo, o int 19800... ele pode ser escrito em binário como:

0 0 1 10 1 0 1 0 1 1 00 1 0 0

15/08/14 Frederico Möller 67

Operações de bitshift

● Realizando o bitshift de 4 casas para a esquerda, obtemos:

● Que equivale ao int 54656● Enquanto o bitshift de 4 casas para a direita

nos dá:

● Que equivale ao int 1237

0 0 1 11 0 1 0 10 0 1

1 1 0 1 0 1 10 1 0 0 0 0 0 0

0 0 0

15/08/14 Frederico Möller 68

Operadores bitshift

● O código ao lado exemplifica a utilidade do uso de bitshift para a conversão de dados.

● Podemor ir "shiftando" uma variável int de 8 em 8 bits de forma a pegarmos cada byte dela.

15/08/14 Frederico Möller 69

Operadores bitshift

● Esses bytes podem ser armazenados em posições de uma string, ou em endereços da memórita EEPROM.

● Depois, fazendo o bitshifting no sentido reverso, podemos reaver o valor decomposto.

15/08/14 Frederico Möller 70

Bitshift para floats

● Operadores de bitshift não funcionam com valores float e double, para armazenar esses valores é necessário fazer primeiro uma conversão para int (usando multiplicadores para eliminar a parte fracionária).

● A vantagem é que conseguimos usar, em geral, menos bytes para converter floats em um vetor de char, usando bitshift do que converter cada dígito em um caracter.

15/08/14 Frederico Möller 71

A melhor alternativa para floats

● Mesmo usando operadores bitshift, passar floats para um vetor de chars, principalmente se estivermos focando no armazenamento em endereços da EEPROM é um processo chato.

● A melhor alternativa para lidar com valores float, nesse caso é: EVITA-LOS.

● As entradas analógicas do arduino recebem valores inteiros, as digitais, booleanos.

15/08/14 Frederico Möller 72

A melhor alternativa para floats

● É perfeitamente possível manter os valores nesses estados, ou converter desses para char e armazenar na memória.

● Um bom programa deve deixar para fazer as conversões matemáticas que resultarão em valores float somente quando estes forem imprenscindíveis, como por exemplo, na hora de exibi-los para o usuário.

15/08/14 Frederico Möller 73

O Fim deste curso

● Esse curso é uma mera introdução da ferramenta Arduino. Muita coisa, como o uso de servo-motores, displays lcd, a biblioteca wire, o interfaceamento do Arduino com outros dispositivos, não foi explorada aqui.

● Alguns desses itens poderão ser vistos em cursos futuros, mas dificilmente vocês encontrarão um curso que aborde tudo o que o Arduino pode oferecer.

15/08/14 Frederico Möller 74

O Fim deste curso

● O domínio sobre essa plataforma só pode ser conseguido com seu constante uso.

● Uma das grandes vantagens do Arduino é o seu número de tutoriais na internet, façam bom uso deles, assim como os de fóruns de discussões, apostilas e livros sobre a plataforma.

15/08/14 Frederico Möller 75

Revisão

● Nessa lição, aprendemos sobre:– Memória volátil e memória permanente– A biblioteca EEPROM do Arduino.– Gravar e ler dados na memória EEPROM do

Arduino– Converter variaveis maiores para vetores de

variáveis menores

15/08/14 Frederico Möller 76

Leitura complementar

● Todos os operadores em c++– http://www.cplusplus.com/doc/tutorial/operators/

● História das memórias ROM– http://etcbinaria.wordpress.com/2011/01/21/evolucao-memoria-rom/

● Duas formas de converter int para vetor char:– http://sapiensmechatronicus.blogspot.com.br/2013/

05/comunicacao-serial-do-msp430-via-xbee.html

15/08/14 Frederico Möller 77

Referências bibliográficas

● MCROBERTS Micheal, Beginning Arduino, 1ªED

● SCHILDT Hebert, C completo e total, 3ªED● http://www.arduino.cc/

15/08/14 Frederico Möller 78

Informações adicionais

● Esses slides são a 1ª versão deste curso e sofrerão alterações

● Uma apostila está sendo feita e será disponibilizada em breve.

● Novas versões desses slides, a apostila, os códigos dos exercícios e dos exemplos feitos aqui poderão ser baixados nos seguintes links:

15/08/14 Frederico Möller 79

Informações adicionais

● Site do PET Mecatrônica/BSI:– http://sites2.jf.ifsudestemg.edu.br/?q=downloads

● Blog Homo Sapiens-Mechatronicus:– http://sapiensmechatronicus.blogspot.com.br/

● Blog projetos de jogos:– http://fredericomollerped.blogspot.com.br/

15/08/14 Frederico Möller 80

Dúvidas???

15/08/14 Frederico Möller 81

Obrigado e até o próximo curso!!!