LusoRobótica - Robótica em Português

Sistemas específicos => Arduino / AVR => Tópico iniciado por: Cynary em 10 de Setembro de 2010, 01:06

Título: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 10 de Setembro de 2010, 01:06
Recentemente, tenho andado a espreitar alguns tutoriais, e a datasheet de alguns AVRs (inclusive o presente no Arduino), e a programar o Arduino com base nisso.
Para atingir a performance máxima, podia programar em assembly, mas com as optimizações no máximo, o código em C, é apenas cerca de 10% menos eficiente, e mais simples de fazer debug e prorgamar.
A maioria dos tutoriais que li estavam em inglês, o que pode ser uma limitação para alguns, e outros não cobriam o AVR presente no arduino, o que levava a que houvesse alguns erros nos registers usados (facilmente corrigidos observando a datasheet).
Então, para facilitar as coisas para outros iniciantes, decidi começar a escrever alguns tutoriais também :), em português
Para já, ainda não tenho nada pronto, mas neste post já deixo umas coisas:
Um tutorial de iniciante muito bom: http://lusorobotica.com/index.php?topic=1069.0 (http://lusorobotica.com/index.php?topic=1069.0)
Neste fórum, encontram vários tutoriais também, em inglês (foram esses que li): http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewforum&f=11&sid=bc063b8fce44bb602023706af59cf38b (http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewforum&f=11&sid=bc063b8fce44bb602023706af59cf38b)

Estes tutoriais têm dois objectivos principais: facilitar a entrada de iniciantes no mundo da programação em baixo nível de microcontroladores e também facilitar a minha aprendizagem desse mesmo mundo.

Outro bónus, neste primeiro post: como fazer um simples programa de comunicação em serial.
Versão baixo nível (estive horas à procura do motivo para não estar a funcionar bem ... aconteceu que li mal a datasheet, e pus mal a configuração para enviar 8 bits por caracter, e estava a enviar 7 XD):

Código: (c) [Seleccione]
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define B9600 103 // F_CPU = 16000000 -- valor no datasheet

volatile char c = 'A'; // Volátil porque a interrupção pode alterá-lo (coisas que o optimizador de C não pode prever).
char output = 0;

int main() {
  DDRB |= (1<<PB5); // Configurar o pino digital 13 (PB5) para output

  UCSR0B |= (1<<RXEN0) | (1<<TXEN0); // Começar a comunicação USART. TXEN0 -- transmissão; RXEN0 -- recepção
  UCSR0C &= ~(1<<UCPOL0);
  UCSR0C &= ~((1<<UMSEL01) | (1<<UMSEL00)); // Estes dois bits selccionam o tipo de comunicação serial -- assíncrona.
  UCSR0C &= ~((1<<UPM01) | (1<<UPM00)); // Não queremos paridade

  // Os dados enviados/recebidos têm 8 bits.
  UCSR0B &= ~(1<<UCSZ02);
  UCSR0C |= (1<<UCSZ01) | (1<<UCSZ00);
 
  UCSR0A &= ~((1<<U2X0) | (1<<MPCM0)); // Estamos aqui a certificar-nos que a velocidade do serial não é duplicada (U2X0) e que o serial não é configurado para multiprocessador (MPCM0).
 
  UBRR0L = B9600;
  UBRR0H = B9600>>8; // 9600 baud
 
  // 1 STOP BIT
  UCSR0C &= ~(1<<USBS0);
 
  UCSR0B |= (1<<RXCIE0); // Ligar a interrupção local do USART, que ocorre quando se recebe dados; vector: USART, RX
  sei(); // Ligar interrupções a nível global.
 
  for(;;) {
    if(UCSR0A&(1<<UDRE0)) { // Só enviamos dados quando a flag (UDRE0) que nos indica que o buffer está vazio está "ligada"
      // Enviar o carácter c e nova linha.
      UDR0 = c;
      while(!(UCSR0A&(1<<UDRE0)));
      UDR0 = '\n';
      _delay_ms(1000); } } } // Uma vez por segundo

ISR(USART_RX_vect) { // Interrupção quando recebe dados -- alterar o carácter c para o recebido, e caso seja para o 'A', mudar o estado do pino digital 13 (PB5 -- OUTPUT)
  output = ~output; // Alterar o estado do bit do pino 13
  c = UDR0; // Guardar os dados recebidos em c
  if(c=='A') {
    PORTB &= ~(1<<PB5);
    PORTB |= ((output&1)<<PB5); } } // Alterar o estado do pino digital 13.

Versão alto nível (linguagem do arduino):
Código: (c) [Seleccione]
void setup() {
  Serial.begin(9600);
  pinMode(13, OUTPUT); }

char c = 'A';
int output = 0;

void loop() {
  if(Serial.available()) {
    c = Serial.read();
    if(c == 'A') {
      output = 1-output;
      digitalWrite(13, output); } }
  Serial.println(c);
  delay(1000); }

A do arduino é obviamente muito mais simples. No entanto, enquanto a de baixo nível só ocupa ~0,4kB, a do arduino ocupa ~2.8kB! (~7 vezes mais!). E estive a ver a biblioteca de Serial do arduino ... basicamente é tudo feito a nível de software, o que põe um grande stress no processador ...
O que este programa faz é basicamente enviar um carácter por Serial, a cada segundo, e quando recebe um carácter por Serial, passar a enviar esse carácter. Quando o carácter recebido é o A, faz toggle do pin 13 (que nalguns arduinos recentes traz um LED).

O primeiro tutorial que colocarei aqui será sobre interrupções. O primeiro tutorial que coloquei mais acima, escrito por Njay explica bastante bem os GPIOs, logo considerarei os mesmos explicados :P
Para compilar os programas, será sempre suficiente usar os seguintes comandos:
Citar
avr-gcc -Wall prog.c -Os -mcall-prologues -mmcu=atmega328 -o prog.out -DF_CPU=16000000
avr-objcopy -O ihex -R .eeprom prog.out prog.hex
(alterar prog.c para o nome do ficheiro; caso isto não seja suficiente, mencionarei isso nos tutoriais)

Para enviar os programas para o arduino, é suficiente usar:
Citar
avrdude -p m328p -c avrisp -P /dev/ttyUSB0 -b 57600 -F -U flash:w:prog.hex
(alterar /dev/ttyUSB0 pela porta série correspondente).

Para os que usem Windows, é provavelmente mais simples configurar o AVR Studio. Como nunca usei, não me arrisco a explicar, mas deixo aqui este tutorial (como também contém um mapping dos pinos do arduino para o seu nome no microcontrolador, aconselho a todos a ler):
http://www.smileymicros.com/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=70&MMN_position=117:117 (http://www.smileymicros.com/index.php?module=pagemaster&PAGE_user_op=view_page&PAGE_id=70&MMN_position=117:117)

Vou assumir que todos os interessados têm alguma experiência em programação de C (vou tentar explicar como se fossem muito burros xD, mas é a primeira vez que faço uma coisa assim :/ -- tentarei responder qualquer dúvida ... agradeço no entanto que chegue à programação da interface serial antes de fazerem perguntas acerca do código acima -- o meu objectivo é que nessa altura já o percebam :P).

EDIT: Código low-level alterado para coincidir com as sugestões do senso, e do Tyran. Obrigado :)
EDIT2: Senso, por alguma razão, o ~output não funciona bem :S com bools. Por isso passei a usar chars, e esqueço os bools :P

EDIT3: PDF publicado! A partir de agora para manter o tópico limpo, todos os tutoriais serão colocados neste PDF, havendo apenas um post de aviso de actualização. Os posts com os tutoriais serão apagados. PDF em anexo.
EDIT4: PDF editado de acordo com sugestões de Njay. E guardado num host mais permanente, caso haja problemas com actualização do fórum.
EDIT5: Secção I²C actualizada. Separei os vários tópicos em PDFs diferentes, mais pequenos, e manti tudo junto num PDF grande.

Documento completo: http://netexplorers.org/AVR/AVR_C.pdf (http://netexplorers.org/AVR/AVR_C.pdf)
Pequenos conceitos necessários acerca de programação em C: http://netexplorers.org/AVR/uC_C.pdf (http://netexplorers.org/AVR/uC_C.pdf)
Introdução/GPIO (contribuições do Njay): http://netexplorers.org/AVR/Njay.pdf (http://netexplorers.org/AVR/Njay.pdf)
Interrupções: http://netexplorers.org/AVR/interrupts.pdf (http://netexplorers.org/AVR/interrupts.pdf)
Timers - Parte 1: http://netexplorers.org/AVR/timers.pdf (http://netexplorers.org/AVR/timers.pdf)
Timers - Parte 2: http://netexplorers.org/AVR/timers2.pdf (http://netexplorers.org/AVR/timers2.pdf)
Analog-to-Digital Converter: http://netexplorers.org/AVR/ADC.pdf (http://netexplorers.org/AVR/ADC.pdf)
Comunicação Serial no AVR (contribuições do senso): http://netexplorers.org/AVR/serial.pdf (http://netexplorers.org/AVR/serial.pdf)
Comunicação por I²C: http://netexplorers.org/AVR/I2C.pdf (http://netexplorers.org/AVR/I2C.pdf)
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 10 de Setembro de 2010, 01:42
O teu outuput=1-output não podia ser simplesmente output = ~output?
Acho que devias ter o teu código mais comentado, quem nunca viu isto á frente não sabe o que querem dizer todas aquelas siglas.
Continuas com alguns maus habitos do arduino, por exemplo usar ints, ainda por cima para usar como variavel que guarda dados para meter num porto que tem no máximo 8 bits, habitua-te a usar uint8_t e int8_t, char, unsigned char, e coisas assim para poupar no que é desnecessário.
Apesar de tudo parabens pela iniciativa, ando a fazer o mesmo, brincar com c a sério e deixar o ide do arduino, já usava c em vez do estupido c++ no ide do arduino, mas como quero passar para outros atmegas vou virar-me só para avr-gcc e nada de c++ e de todo o bloat que o core do arduino tem e do consumo estupidamente excessivo de ram e de flash que o mesmo origina.
Quando tiver tempo e não te importares da concorrencia acho que tambem vou escrever um pequeno tutorial.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 10 de Setembro de 2010, 01:52
O teu outuput=1-output não podia ser simplesmente output = ~output?
Acho que devias ter o teu código mais comentado, quem nunca viu isto á frente não sabe o que querem dizer todas aquelas siglas.
Continuas com alguns maus habitos do arduino, por exemplo usar ints, ainda por cima para usar como variavel que guarda dados para meter num porto que tem no máximo 8 bits, habitua-te a usar uint8_t e int8_t, char, unsigned char, e coisas assim para poupar no que é desnecessário.
Apesar de tudo parabens pela iniciativa, ando a fazer o mesmo, brincar com c a sério e deixar o ide do arduino, já usava c em vez do estupido c++ no ide do arduino, mas como quero passar para outros atmegas vou virar-me só para avr-gcc e nada de c++ e de todo o bloat que o core do arduino tem e do consumo estupidamente excessivo de ram e de flash que o mesmo origina.
Quando tiver tempo e não te importares da concorrencia acho que tambem vou escrever um pequeno tutorial.

~output pode dar resultados indefinidos (neste caso não faria diferença no entanto, visto estarmos a mexer com PORTB), já que todos os bits da variável são alterados, e arriscas-te a mexer noutros bits do register.
Tens razão, devia ser ~output, e não vale a pena usar um int. Aliás, no início tinha um bool, e fazia simplesmente output=!output.
No entanto, como estava a ter problemas no programa, e não sabia o que estava a causar, e visto que nunca percebi se bool é um char/int ou um bit (no primeiro caso, !output não é exactamente 1, o que pode dar comportamentos indefinidos no código, mas foi mesmo de desespero que tentei xD), tentei com int :P
Quanto aos comentários, o meu objectivo é ir depois explicando o código ao longo dos tutoriais, pois explicar aquilo tudo com alguns comentários é mesmo impossível xD
Quanto à competição, agradecia, facilitaria um pouco o meu trabalho hehe.
Estava a pensar guardar tudo num PDF, quando tivesse um número razoável de trabalhos. Importas-te que use os teus no mesmo (claro, crédito atribuído onde é merecido ;))?

EDIT: Decidi seguir as tuas sugestões, e comentar e optimizar mais um pouco. O pormenor do (output&1) não é estritamente necessário neste caso, visto que não nos importamos com os outros pinos, mas mesmo assim é um bom hábito a obter, pois se não o fizéssemos, podíamos alterar outros pinos na porta B.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 10 de Setembro de 2010, 02:19
bool assim sem mais nada não existe, ou fazes por exemplo '#define bool char' ou fazes um include que já não me recorda qual é... e ocupa claro 8bits. Se só quiseres mesmo utilizar 1 bit também dá mas deixa isso para depois.

E já agora se quiseres manter o ~ em vez de ~(....) usa (bool)~(...) pois caso contrário o compilador vai gerar código para 16bits... Tens esta e outras particularidades explicadas no avr-gcc libc.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 10 de Setembro de 2010, 02:36
bool assim sem mais nada não existe, ou fazes por exemplo '#define bool char' ou fazes um include que já não me recorda qual é... e ocupa claro 8bits. Se só quiseres mesmo utilizar 1 bit também dá mas deixa isso para depois.

E já agora se quiseres manter o ~ em vez de ~(....) usa (bool)~(...) pois caso contrário o compilador vai gerar código para 16bits... Tens esta e outras particularidades explicadas no avr-gcc libc.

No mínimo uma variável ocupa 1 byte, visto que é um valor na memória ... podemos é usar cada bit de uma variável, ou então aceder a um registo de uso geral para isso ...
Quanto ao bool, tinha-me esquecido :S hábito do C++ xD. E o pormenor do ~ não sabia, obrigado pela dica ;) No entanto, não vou incluir nos exemplos, pois de acordo com o que li, aplica-se a todas as operações ao nível de bits, e é código, que apesar de optimizar um pouco o programa, não faz realmente muita diferença (até fico admirado que o compilador não optimize isso por si só com as flags de optimização ...).
Já alterei o código no post original. O bool está no stdbool.h

EDIT: Fiz um teste, e o casting não fez diferença ... só se depender da implementação da libc ...
O compilador normalmente optimiza certos detalhes como esse, entre outros.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 10 de Setembro de 2010, 09:41
Podes sempre criar uma estrutura com várias flags de um bit, isso de usar assim cruelmente uma variável e ter lá várias flags nunca me deu muito interesse. Até ao momento ainda não precisei de ser assim tão poupado também, mas de facto traz saudades a área endereçável ao bit do 8051 :D

Deve depender do nível de optimização...
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 11 de Setembro de 2010, 16:48
Mais uma vez parabens pelo esforço, só uma coisa, nunca se usam delays numa interrupção, é uma convenção por questões de segurança e fiabilidade do programa.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 11 de Setembro de 2010, 17:14
Delays não é de todo recomendável numa interrupção, ela deve ser o mais rápida possível para que outras possam também ocorrer. Todo o código pesado duma interrupção deve ser passado para fora da mesma.

Esse método não é o melhor e pode nem funcionar, imagina que apanhavas um bounce mas que mais tarde estabilizava para 0, isto é, apenas apanhaste um ruído e não um pressionar do botão... O que podes fazer é pegar num dos algoritmos usados como por exemplo testar se o nível de input continua no mesmo valor durante 10 leituras com x milisegundos de intervalo entre as mesmas. Deves apanhar várias técnicas espalhadas pela net...

Outra coisa, não precisas de inicializar as variáveis globais a 0 pois isso acontece na secção .init

Já não usas o bool? Eu costumo fazer num ponto h common.h:
Código: [Seleccione]
#define bool unsigned char
#define false 0
#define true !false

Mas pelo que tu queres fazer podes usar uma operação XOR...
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 11 de Setembro de 2010, 17:20
Eu menciono no tutorial que os delays não são recomendáveis :P
Como disse, apenas usei para demonstrar um método básico de debouncing (e também explico que só uso porque não tenho nada no código principal).
Além disso, também serviu para mostrar como as interrupções funcionam através das flags.
O bool do stdbool.h não funcionou para o que estava a fazer ... por alguma razão, o ~output não dava o resultado esperado quando era bool, por isso manti-me pelos chars :P não me confunde e funcionam xD
Estou a tentar desenvolver uma técnica mais sofisticada de debouncing, que envolve contar o tempo que passa entre a transição para o estado low e o estado high. Mas como envolve timers, vou deixar para um tutorial futuro.
Quanto a inicializar as variáveis globais a 0, tens razão, só quis ser o mais claro possível.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 11 de Setembro de 2010, 17:47
Talvez trocar o '~'  por '!'

Com o xor numa expressão fazias tudo sem precisar de variáveis auxiliares.

Sim compreendo o que dizes e parabéns pelo esforço para a comunidade ;) Era interessante ter algum feedback, vamos dar tempo e esperar que alguém queira também enveredar por isto :D

Qualquer ajuda que precises para fazer algo apita :)
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 11 de Setembro de 2010, 17:52
Talvez trocar o '~'  por '!'

Com o xor numa expressão fazias tudo sem precisar de variáveis auxiliares.

Sim compreendo o que dizes e parabéns pelo esforço para a comunidade ;) Era interessante ter algum feedback, vamos dar tempo e esperar que alguém queira também enveredar por isto :D

Qualquer ajuda que precises para fazer algo apita :)

Obrigado!
Não troco o ~ pelo ! devido a uma particularidade: o comportamento do '~' está bem definido (mudar todos os bits da variável ... o tipo bool deve ter alguma particularidade ou optimização que faz com que isto não funcione exactamente dessa forma). O '!' altera o valor lógico da variável, mas exactamente como, não está bem definido, dependendo do compilador (pode por exemplo, para alterar de falso para verdadeiro só mexer num dos bits, ou em bits random). Ao usar o !, estaria a arriscar que o bit menos significativo da variável ficasse igual ao estado anterior (caso fosse uma transição de falso para verdadeiro), não mexendo assim na porta de output, e apenas alterando as outras.
O XOR funcionaria perfeitamente claro, e nesta aplicação é mais do que razoável utilizá-lo. Para outras aplicações, tem no entanto o risco de alterar o estado das outras portas, por isso prefiro não apanhar muito esse hábito.

Gostaria era de ver mais pessoas a tentar isto, pois o controlo directo do microcontrolador dá-nos muito mais opções do que o IDE do arduino.
Talvez depois do tutorial acerca de timers, coloque um sobre coisas básicas (manipulação de bits, registers, etc.), a ver se mais "novatos" espreitam isto xD
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 11 de Setembro de 2010, 19:26
Era simples, em vez de fazer a lógica com o 1 fazias == true por exemplo :)

Não altera desde que só faças ao bit que desejares, não ias fazer ao porto todo.

Pois, mas até ao momento somos apenas 3 a ter postado lol vamos dar tempo :p
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 12 de Setembro de 2010, 01:34
Era simples, em vez de fazer a lógica com o 1 fazias == true por exemplo :)

Não altera desde que só faças ao bit que desejares, não ias fazer ao porto todo.

Pois, mas até ao momento somos apenas 3 a ter postado lol vamos dar tempo :p

Então estás a sugerir implementar um if? Funcionaria, mas aí seria muito mais pesado para o processador do que um ~ (claro, neste caso não notaríamos diferença, em grandes programas sim).
E quanto ao == true, não sei se é uma boa ideia, tendo em conta as definições que fizeste do true false e bool ...
Como disse, o comportamento do ! não está completamente definido quando se converte de falso para verdadeiro, logo, podes estar a comparar dois valores inteiros (de 8 bits) com valores lógicos iguais, mas diferentes valores, resultando aí num false (a forma correcta seria com um "&& true").

Mencionei no meu post anterior que o XOR não funcionaria bem devido ao risco de alterar outras portas ... esqueçam o que eu disse xD
Tinha-me esquecido exatamente de como o XOR funcionava -.- Pensava que dois 0s no XOR davam 1, afinal dão 0 xD
Logo, um XOR funcionaria perfeitamente :P peço desculpa pela confusão que isto gerou.
Tentarei complicar com um tutorial impecável sobre timers ainda esta semana :)
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 12 de Setembro de 2010, 01:59
Não dizia um if... por exemplo (flag==true)<<X...

A flag vai estar sempre a fazer 1 0 1 0 1 0, e um 1 está dentro do range do meu !false, isto é, true... eu apenas deixou assim porque às vezes dá-me jeito ter outros valores como true, mas senão pode ficar o true como apenas sendo 1 e mesmo assim funciona esta maneira...

Em vez desse ==true podes fazer um &&true ou manter o &1
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 12 de Setembro de 2010, 02:54
Penso que não percebeste bem o que estava a dizer :S
Não vejo como o exemplo que deste:

(flag==true)<<X

poderia funcionar sempre.
A forma como os operadores lógicos (!, ==, ...) funcionam depende da forma como o compilador os trata.
A forma como definiste true (!false), não significa que true seja obrigatoriamente 1. E não significa que true seja sequer um valor constante! (no entanto, o mais provável é que o compilador optimize de forma a que seja). Assim, ao usares o ==, não estás a possibilitar o uso de vários valores como true. Por exemplo, se o compilador optimizar o !false que definiste como sendo igual a 1, então ao comparares com um 5, dar-te-ia false. Só podes garantir resultados correctos se usares o &&.
Mas o maior erro, está ao fazeres (flag==true)<<X, pois o == pode não devolver obrigatoriamente um 1. Pode devolver um 2 ou 4 ou um 6, ... e nesses casos, estarias a alterar o valor de outros pinos (no caso de 4, o pino X+1, ...), e não estarias a tocar no valor do teu pino (o mesmo problema ocorre ao usar o &&true).
Para fazer toggle de pinos, a melhor solução é mesmo um xor ... se uma variável de estado é necessária, usar operadores lógicos, como o !, para manipular o seu valor, não é aconselhável, visto a não terem comportamentos definidos (imagina que alguém decide programar um compilador em que o operador '!', quando aplicado a algo com o valor 0, corresponde a copiar todo o conteúdo de um register, com pelo menos um bit indubitavelmente igual a 1, e com os outros bits indefinidos, podendo ser alterados, ficas com um valor desconhecido).
Nos testes que fiz no gdb, esse tipo de operações deu-me sempre 1 como resultado ... no entanto, visto não ser obrigatório, pode não funcionar em alguns casos :P.
(esta discussão sobre o funcionamento da linguagem C, e formas de usar bools e fazer toggles a bits está a ficar interessante xD. No entanto, penso que o ideal, seria mover essa parte para outro tópico, possivelmente na secção de software e programação ... visto que está a tirar o foco dos tutoriais aqui :S -- sugeriria criar um novo tópico acerca disto, e mudar para lá as mensagens relevantes, e eliminar as nossas mensagens aqui, ou condensar tudo num só post, e eliminar os outros).
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 12 de Setembro de 2010, 11:00
Estranho que nos testes que fiz calhou sempre de dar direito, mas pode ter sido de já ser muito tarde e tava cheio de sono :D

Como disse no outro post facilmente se altera o true para 1... o que aliás é como o tenho definido agora para teste :)

Isso do '==' bem visto pois sempre tive na ideia que dava 0 ou 1 hmm logo vou fazer umas pesquisas xD

Neste caso sim como disse antes era um XOR mas pode nem sempre ser possível, depende... imagina que estavas a conduzir um transístor na gate, ora o valor alto que iria ter seria 0,7 que é visto pelo uC como 0 também, então já precisas de lógica.
E quanto ao '!', estamos a falar de C standard +-, julgo que haverá uma norma a seguir, mas é questão de investigar :)


De facto torna-se mesmo interessante debater estes e outros assuntos, é pena mais ninguém participar... mas olha aprendemos nós nunca pior :p

Título: Re: Programar Arduino/AVR -- low level.
Enviado por: fre_deri_co em 12 de Setembro de 2010, 11:18
desculpem a minha falta de compreensão, mas este tópico destina-se a ensinar a programar AVR comparando com arduino e não Arduino correcto?!

p.s.  os parabéns pela dedicação que toma para com a partilha de conhecimentos!!! ^^
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 12 de Setembro de 2010, 13:33
desculpem a minha falta de compreensão, mas este tópico destina-se a ensinar a programar AVR comparando com arduino e não Arduino correcto?!

p.s.  os parabéns pela dedicação que toma para com a partilha de conhecimentos!!! ^^

O objectivo deste tópico é ensinar a programar em AVRs, mas em todos os exemplos, assumo que o contacto que o leitor tem com AVRs é no arduino, logo estou a fazer código destinado ao mesmo (e os comentários usam o nome dos pinos de acordo com a norma do arduino, e o código para transferir o programa no primeiro post espera o bootloader do arduino). De qualquer forma, os mesmos conceitos aplicam-se para qualquer AVR, e as diferenças que se podem encontrar estão nos números de pinos, nome de registers e pouco mais :P
E ainda bem que temos mais um a comentar! :)

Citar
Estranho que nos testes que fiz calhou sempre de dar direito, mas pode ter sido de já ser muito tarde e tava cheio de sono

Como disse no outro post facilmente se altera o true para 1... o que aliás é como o tenho definido agora para teste

Isso do '==' bem visto pois sempre tive na ideia que dava 0 ou 1 hmm logo vou fazer umas pesquisas xD

Neste caso sim como disse antes era um XOR mas pode nem sempre ser possível, depende... imagina que estavas a conduzir um transístor na gate, ora o valor alto que iria ter seria 0,7 que é visto pelo uC como 0 também, então já precisas de lógica.
E quanto ao '!', estamos a falar de C standard +-, julgo que haverá uma norma a seguir, mas é questão de investigar


De facto torna-se mesmo interessante debater estes e outros assuntos, é pena mais ninguém participar... mas olha aprendemos nós nunca pior :p

Não percebi bem o exemplo do transístor na gate :/ xD
O '!', realmente é C standard, mas de todas as referências que li, a única coisa que podemos esperar do '!' é que transforme um valor diferente de 0 em 0, e o 0 num valor diferente de 0, sem nunca definir que valor é esse.
Atenção que posso estar a dizer disparates aqui xD e já terem definido um standard em que esses valores estão todos definidos ... apenas me estou a basear nas referências que tenho. Nunca fiz muitas experiências no sentido de testar isto a sério (com vários compiladores e diferentes níveis de optimização), mas pelo que percebi, não é um comportamento definido.
Acredito que tenha dado sempre certo, pois a implementação usada é capaz de funcionar.
Quanto a usar para o true o 1, depende do que vai fazer com o valor do bool ... se só usar para testes lógico, 1 e !false vão dar ao mesmo, mas outros tipos de testes, podem dar comportamentos indefinidos (por exemplo, o '==').

Hoje ou amanhã, já temos a primeira parte do tutorial sobre timers hehe (vou dividir em duas partes: Modos normal e CTC, e modos com PWM).
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 12 de Setembro de 2010, 17:49
Foi só para tentar explicar que o xor pode nem sempre resultar pois o valor lido pelo pino pode não ser alto o suficiente para ser considerado um high (1), então tens de usar flags para controlares.

Bem apenas vi que em C false é 0 e true é diferente de 0, não consegui encontrar efectivamente o que faz o ! Vou ter de procurar num livrito que tenha talvez hmm

Mas para superar essa questão, em vez de brincar com o true pode-se sempre brincar com o false, por exemplo, != false, aí já não falha :)
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 12 de Setembro de 2010, 19:19
Foi só para tentar explicar que o xor pode nem sempre resultar pois o valor lido pelo pino pode não ser alto o suficiente para ser considerado um high (1), então tens de usar flags para controlares.

Bem apenas vi que em C false é 0 e true é diferente de 0, não consegui encontrar efectivamente o que faz o ! Vou ter de procurar num livrito que tenha talvez hmm

Mas para superar essa questão, em vez de brincar com o true pode-se sempre brincar com o false, por exemplo, != false, aí já não falha :)

Ah ok xD
A ideia que estava a dar para o xor, seria por exemplo:
Código: (c) [Seleccione]
PORTB ^= (1<<BIT);com o pino posto em output. Aí, não interessa o valor lido pelo pino, mas sim se está ligado ou desligado, e que queremos alterar isso (tinha a ideia que esta instrução poderia alterar os outros pinos pois pensava que 0^0 = 1, mas estava enganado).
O != false funciona, mas aconselho a que, em vez de usares o == ou != quando estás a trabalhar com valores em que interessa apenas o seu valor lógico, uses operadores lógicos (substituir o && por ==, etc. pois aí retiras o problema de comportamentos indefinidos.

EDIT: Oops, alterei o XOR xD estava distraído quando fiz :P Senão nunca fazia o toggle, ficava sempre desligado.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Tyran em 12 de Setembro de 2010, 19:41
Basta fazeres: PORTB ^= (1<<BIT);
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 21 de Setembro de 2010, 09:43
Todos os tutoriais foram compilados numa ordem mais lógica num PDF!
Esse PDF encontra-se anexo ao post inicial.
Para manter o tópico mais limpo, os comentários servirão para comentar os tutoriais e outras discussões, enquanto os tutoriais estarão exclusivamente no PDF.
Para isso, eliminei os tutoriais que estavam em posts separados.

Comentários, críticas e sugestões são bem vindos :)
Obrigado ao Njay por me ter deixado usar o seu micro-tutorial.

Quando ocorrerem actualizações, avisarei num post.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 21 de Setembro de 2010, 19:16
Acho que devias ter mantido aqui os tutoriais todos, assim era menos um download e o pdf pode sempre desaparecer em actualizações ao forum.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 21 de Setembro de 2010, 20:23
Acho que devias ter mantido aqui os tutoriais todos, assim era menos um download e o pdf pode sempre desaparecer em actualizações ao forum.

Quanto ao PDF desaparecer, estou a ver se o movo para um host permanente (ou pelo menos que tenha confiança que vá durar muito tempo xD), para evitar isso.
Mas isto estava a ficar um pouco desorganizado :S
Os tutoriais e a discussão acerca do funcionamento de C estavam a ficar um pouco misturados demais lol.
Quanto a mais um download, posso sempre separar os vários tutoriais em diferentes ficheiros, assim podem ler o que for mais conveniente, mas penso que não é uma urgência grande.
No entanto, posso sempre repostar tudo. Mas gostaria primeiro de saber a opinião de mais pessoas.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 21 de Setembro de 2010, 23:38
O mais um download é que no forum era só abrir o forum e ler, assim tens de sacar e passar para o pdf e tal, mas isso é coisas minimas.
Tenho uma sugestão ou duas quanto ao pdf em si, eu não usaria espaçamento de linha e meia em todo o pdf e procurava uma fonte mono-espaçada e outra cor de texto para o código, e dava uma revisão em termos de espaçamentos e isso que alguns estão meio estranhos.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 26 de Setembro de 2010, 19:57
Documento alterado no primeiro post.
Adicionei um tutorial sobre ADC.
Peço desculpa pela demora.
Para o próximo fim-de-semana, em princípio coloco um tutorial sobre comunicação em serial.
Se tiver tempo, ainda experimento comunicação entre dois micro-controladores, e será o exemplo usado ;).
Quanto às mudanças de formatação, tive em conta a vossa opinião, e fiz algumas alterações. Penso que ficou mais apresentável.

senso: Mantive o espaçamento de 1,5, penso que é mais legível assim. No entanto, tinhas razão quanto a espaçamentos esquisitos. Estavam a acontecer pois estava a editar o documento total e os tutoriais separados em documentos separados. Os tutoriais não tinham rodapé, logo quando copiava para o principal com rodapé, as imagens por vezes chateavam um pouco, mas resolvi tirando o rodapé do principal. Também não fazia nada a mais do que a capa já fazia :P. Quanto ao código, alterei a fonte, tens razão, fica melhor. No entanto, testei com várias cores, e não pensei que ficasse muito bem, acho que já fica bastante destacado do resto do texto com o espaçamento e fonte diferentes e o itálico. Tens alguma ideia para uma cor?

Uma questão: Para destacar o código do texto, ponho-o em itálico. Acham que fica bem, ou está destacado o suficiente sem isso?

Se quiserem, posso colocar também os tutoriais individuais em PDF, em vez de estar tudo junto. Se pelo menos uma pessoa achar uma boa ideia, coloco.

Um pedido: Se alguém tiver tempo e disponibilidade, agradecia que pegassem nas imagens desenhadas à mão, e tentassem fazer uma versão digital mais bonita xD. Para edição de imagens não tenho muito jeito :S
Assim que tiver tempo, vou ver se uso o eagle para fazer os circuitos mais bonitos. Os gráficos é que não sei bem que programa usar para os fazer.

EDIT: Quando postei isto originalmente, tinha-me esquecido de um tópico sobre o ADC -- o termómetro interno. Além disso, estava em falta uma pequena descrição da diferença entre sinal digital e analógico. Já actualizei o documento com essas informações que estavam em falta.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Capeleiro em 27 de Setembro de 2010, 20:22
Eu tenho uma dúvida:
Como é que a biblioteca Servo.h consegue controlar servos em tantos pins do ATMega?
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 27 de Setembro de 2010, 20:47
Funciona por interrupção e cria sinais pwm por software em vez de recorrer só a timers.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Capeleiro em 27 de Setembro de 2010, 20:53
Funciona por interrupção e cria sinais pwm por software em vez de recorrer só a timers.
Bem me parecia... Obrigado.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 03 de Outubro de 2010, 20:02
Esta semana não irá haver tutorial.
Estava a pensar fazer um sobre comunicação serial, mas visto que o senso já fez um excelente, tornou-se desnecessário xD
Depois pensei fazer um sobre I2C, mas ainda não tive tempo para estudar esse protocolo a 100%, e visto que estou à espera de alguns dispositivos que usam I2C, vou deixar o tutorial para a semana, de forma a ter mais exemplos :P
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: GnGz em 03 de Outubro de 2010, 20:11
Digital In ... Analog in ... Analog out(pwm)
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 03 de Outubro de 2010, 20:16
Digital In ... Analog in ... Analog out(pwm)

O que queres dizer com isso?
PS: recebeste a minha PM?
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: GnGz em 03 de Outubro de 2010, 20:22
Recebi .. podias ensinar isso ... Nao consigo ir ao msn :S
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 03 de Outubro de 2010, 22:16
Já te disse que digital in é fazer minha_variavel=PORTx sendo x a porta que queres ler, escrever é fazer PINx=minha_variavel, quando tiver tempo junto isso ao tutorial.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Njay em 03 de Outubro de 2010, 23:49
Já te disse que digital in é fazer minha_variavel=PORTx sendo x a porta que queres ler, escrever é fazer PINx=minha_variavel, quando tiver tempo junto isso ao tutorial.

Trocaste o PIN com o PORT.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 03 de Outubro de 2010, 23:52
Estou sempre a troca-los  :-[ obrigado pela correcção  ;)
Mas nos avr's mais recentes pode-se usar o PIN para tudo.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Njay em 04 de Outubro de 2010, 00:27
Tanto quanto sei, nos mais recentes, escrever para o PIN faz com que o pino faça toogle do estado.

Também podes ler do PORT, mas aí estás a ler o valor que lá mandaste colocar (assumindo que é uma saída), e não aquele que realmente lá está (esse é o PIN que dá).
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 05 de Outubro de 2010, 20:11
Tutorial actualizado!
Obrigado ao senso por me ter autorizado a utilizar o seu tutorial sobre comunicação serial, com algumas alterações.
Njay: obrigado pela dica, as páginas já têm números no rodapé e a data da última revisão.
Adicionei destaque de sintaxe ao código também :D
Espero que gostem.
Se facilitar, posso separar cada tutorial num PDF separado.

Quaisquer críticas ou dúvidas são bem-vindas.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 10 de Outubro de 2010, 16:18
Tutorial actualizado!
Adicionada parte sobre I²C, com AVR como Master.
Penso que ficou um pouco confuso ... se acharem que o I²C não ficou bem explicado, posso tentar arranjar tempo para rever o texto e tentar explicar melhor.
No entanto, já ficam com funções que vos permitem usar o I²C :)
Quaisquer comentários e/ou dúvidas são bem-vindos.
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: Cynary em 21 de Dezembro de 2010, 03:56
Estive sem tempo para actualizar isto por causa de escola e outros compromissos.
No entanto, agora estou de férias :D, e tenho finalmente tempo hehe.
Estive a mexer novamente com o I²C, e finalmente penso que tenho uma boa compreensão de como utilizar este tipo de comunicação no AVR (infelizmente penso que ainda não sei explicar a 100% :S). Por isso, alterei completamente a secção do I²C no AVR, pois estava muito confusa, na minha opinião (apenas manti a introdução ao protocolo).
Além disto, dividi o documento em várias partes, de acordo com o tema de que falam. Irei manter o primeiro post actualizado com essas diferentes partes.
O tutorial sobre I²C pode ser encontrado aqui: http://netexplorers.org/AVR/I2C.pdf (http://netexplorers.org/AVR/I2C.pdf)
O próximo será sobre SPI. Já estive a ler um pouco sobre este protocolo, e como usar no AVR, e parece bastante simples :D, pelo menos mais simples e eficiente que o I²C xD
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: doiga em 01 de Julho de 2013, 16:13
Boas,
peço desculpa desenterrar o tópico, mas, os link's dos PDF'S estão em baixo.
Agora que tinha tempo queria começar a estuda-los e a aprender a programar em low level!

Cumps, Diogo
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: senso em 01 de Julho de 2013, 18:12
A origem dos pdf's estão aqui no fórum, os tutoriais é que nunca mais foram acabados, ver se os acabo este ano, estão aqui:
http://lusorobotica.com/index.php?topic=2838.0 (http://lusorobotica.com/index.php?topic=2838.0)
Título: Re: Programar Arduino/AVR -- low level.
Enviado por: doiga em 01 de Julho de 2013, 18:18
A origem dos pdf's estão aqui no fórum, os tutoriais é que nunca mais foram acabados, ver se os acabo este ano, estão aqui:
http://lusorobotica.com/index.php?topic=2838.0 (http://lusorobotica.com/index.php?topic=2838.0)

Muito obrigado!