Usando Code Blocks e Arduino (From Scratch)

O Arduino é uma grande plataforma de software que abstrai diversos detalhes de hardware, isso possibilita que usuários iniciantes programem os microcontroladores da linha AVR sem praticamente nenhum conhecimento do mesmo. Esse tipo de abstração é extremamente útil na hora de criar uma aplicação ou resolver problemas rapidamente. Porém, algumas aplicações vão exigir mais do hardware e, nesses casos, a abstração e falta de conhecimento do mesmo pode dificultar o desenvolvimento. Por exemplo, utilizando o código com a abstração do arduino a seguir:

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
  digitalWrite(LED_BUILTIN, HIGH);  
  digitalWrite(LED_BUILTIN, LOW);   
}

A forma de onda observada na saída 13, através do AVR Simulator, altera seu estado de nível baixo para alto em ~3.44us. Enquanto que o código a seguir faz o mesmo mas com um tempo de ~0.18us:

#define PIN_B5_H PORTB |= 0b00100000
#define PIN_B5_L PORTB &= 0b11011111
#define LED_H PIN_B5_H
#define LED_L PIN_B5_L
#include <avr/io.h>
int main(void)
{
    DDRB = 0b11111111;
    for(;;) {
        LED_H;
        LED_L;
    }
    return 0;
}

Assim, neste Post será mostrado como configurar a IDE Code Blocks e o compilador avr-gcc para trabalhar “diretamente com os registradores do microcontrolador”.

Aqui a instalação será feita no OS Windows, mas para Linux, a instalação é similar. Exceto que o avr-gcc pode ser instalado diretamente por ferramentas como apt-get.

Instalação

  1. Baixe e instale o WinAvr
  2. Baixe e instale o CodeBlocks
  3. Para facilitar a configuração do CodeBlocks, já coloco aqui um projeto do codeblocks já testado: omic-serial-adc
    1. Descompacte esse zip e abra no CodeBlocks o arquivo omic.cbp. Esse “.cbp” é o arquivo de projeto do codeblocks, ele contem toda a configuração necessária para compilar o projeto
    2. Você pode explorar as configurações em Project->Build Options e também em Settings Compiler como na Figura abaixo:
Configuração do CodeBlocks em Settings->Compiler

Para compilar o código clique em Build->Build. Será gerado um arquivo omic.hex na pasta bin/Release/

Gravação

Para gravar o código compilado siga estes passos:

  1. Conecte seu arduino na porta USB;
  2. Descubra qual a porta COM do mesmo através do gerenciador de dispositivos;
  3. Edite o arquivo BURN.bat que veio junto no zip compactado. Mude a porta COM11 para a sua porta. Salve o arquivo;
  4. Clique duas vezes sobre o mesmo. A gravação deve iniciar e terminar com êxito.

Caso apareçam mensagens de falha em algum lugar, deixe um comentário ou me envie um email =]

Drivers

Alguns Arduinos podem vir com o componente CH340, como abaixo

Nesse caso, você vai precisar instalar o Driver desse componentes que está nesse link: https://pandoralab.com.br/arduino/driver-ch340-para-arduino/ (NOTA, Clique em INSTALL e aguarde aparecer a mensagem instalado com sucesso antes de fechar!!)

 

 

 

 

Scilab e Arduino – O Básico

Olá, esse material é um tipo de guia pra você ter um “pontapé” inicial no assunto: coletar dados com Arduino e Scilab. Conhecimentos básicos em eletrônica são desejáveis mas não obrigatórios. Você lerá a seguir algumas regras básicas quando mexemos com eletrônica. Quanto a programação, serão necessários mais conhecimentos se quiser incrementar o que colocarei aqui.

Os softwares mostrados aqui tratam apenas o sensor de temperatura e sem fazer conversão de valores. Completar os programas é a atividade que faço em sala de aula. Mas, se você não é da aula e quiser os programas completos, envie um e-mail para mim.

Eletrônica – Regras

Não colocarei aqui um tutorial sobre eletrônica básica, coloque esse tema numa busca na internet e terá material mais que suficiente. A ideia dessa seção é dar uma noção básica apenas. De como funciona e do que pode e não pode ser feito.

Regra 1: Todo dispositivo eletrônico funciona devido a um fluxo de elétrons (dos átomos). A esse fluxo, damos o nome de corrente elétrica. Existem duas formas desse fluxo ocorrer (sem muitos detalhes aqui):

  • Corrente contínua: O fluxo de elétrons parte de um pólo positivo e vai em direção ao negativo (foi convencionado que é assim, pois os cálculos tornam-se mais fáceis). Pegue uma bateria, nela temos o polo positivo e negativo. O lado positivo tem mais elétrons que o negativo, logo os lados tentam se equilibrar através do fluxo de elétrons. Quando tudo está equilibrado, então a bateria está descarregada.
  • Corrente alternada: O fluxo de elétrons muda de direção constantemente, não há um polo definido. É a corrente que temos nas tomadas de casa (110/220Vca). Dessa forma é mais fácil levar energia a longas distâncias, porém é mais perigosa, pois dá choque.

Usaremos aqui a corrente contínua.

Regra 2: Nunca conecte o positivo com o negativo diretamente (não cause um curto-circuito): Se você conectar o positivo e o negativo de uma pilha carregada usando apenas um pedaço de fio elétrico, vai perceber faíscas e aquecimento. Não faça isso por muito tempo (mais do que alguns milissegundos),  pois a pilha pode estourar e você se machucar.

Se a fonte de energia for outra, como a porta USB do computador, que contem 5 Vcc (Volts corrente contínua), você pode acabar estragando essa porta.

É obvio que não queremos um curto-circuito, mas acidentes acontecem. Por isso, ao revisar um circuito antes de ligá-lo, tenha como prioridade encontrar possíveis causas de curto circuito, depois vemos outras coisas.

Entre o positivo e o negativo deve sempre haver alguma carga. Isto é, alguma coisa que será ligada. Os elétrons saem do positivo, passam pela(s) carga(s) e daí encontram o negativo (fluxo).

Regra 3: Se ver fumaça, desligue da fonte de energia imediatamente.

Circuito Eletrônico

O circuito eletrônico para coletar os dados está na Figura abaixo. Você vai precisar de um Arduino, um LM35 (sensor de temperatura) e LDR (sensor de luminosidade) e um resitor de 10KOhms.

Observe o fluxo: O 5V da placa é levado (pelo fio vermelho) ao LDR, depois ele volta para o Arduino na porta de entrada A1 para leitura e também vai para o resistor. Passando por este, encontra-se o negativo (GND).

O 5V também é levado ao LM35, o qual contem um circuito interno para medição de temperatura.

Software para o Arduino

O software de leitura é bastante simples. Primeiro, inicializamos a porta serial para comunicação. Depois, implementamos a sequência de comandos em loop, a qual é: (a) Ler o sensor; (b) Imprimir “S:” para indicar inicio de transmissão; (c) Enviar o valor; (d) enviar “\n” para indicar término de transmissão; (e) aguardar 500ms. Terminada essa sequência, o processador volta a executar (a).

Nos microcontroladores, o programa é tal que permanece em loop infinito.

int sensorValue = 0; 

void setup() {
  //Inicializa a comunicacao serial
  Serial.begin(9600);
}

//Essa funcao permanece rodando em loop
void loop() {
  // le o sensor
  sensorValue = analogRead(A0);
  // escreve na serial
  Serial.print("S:");
  Serial.print(sensorValue);
  Serial.print("\n");
  //espera 500ms
  delay(500);
}

O programa começa a executar assim que energizamos o mesmo através da USB do computar (daí o cuidado com curtos-circuitos).

Copie o código acima para a IDE do Arduino, selecione a porta COM correta e a placa também. Clique em Carregar, o programa será compilado e carregado no Arduino.

Considerações ao programar para microcontroladores:

  • As variáveis não costumam ter o mesmo tamanho que no computador. Ex.: Um “int” no Arduino pode armazenar apenas valores entre -32,768 até 32,767.
    • Se precisar mais do que isso e apenas positivo use: unsigned int, que vai de 0 a 65535;
    • Se precisar de mais ainda: Variáveis no Arduino

Software do Scilab

O Arduino envia os dados para o computador através de uma porta serial, emulada pela conexão USB. Para ler esses dados, o Scilab precisa se conectar a porta serial correspondente, que é a mesma utilizada para carregar o programa.

Antes de começar, é necessário ter instalado o plugin de comunicação serial no Scilab. Vá no menu Aplicativos->Gerenciador de módulos – ATOMS. Vá na categoria Contributed Scilab Builds e instale o módulo Serial communication. Reinicie o Scilab para ativar o módulo.

O programa a seguir é executado pelo Scilab no computador. Execute este programa após programar o Arduino. Lembre de selecionar a porta correta, no exemplo abaixo estamos usando a porta COM5.

//Abrir porta serial COM5
h = openserial(5,"9600,n,8,1")
tic()
while %t
    [n, v] = msscanf(readserial(h),"S:%d\n");
    if(n>0) then
        printf("Valor = %d\n", v);
        plot([toc()],[v],"-ro")
        sleep(250);
    end
end
closeserial(h); //fecha a serial, devido ao loop infinito nunca será executado
                //execute manualmente este comando para fechar a porta serial
                //Não será possível executar o programa novametne se a porta já estiver aberta

Esse programa recebe um valor do Arduino e plota num gráfico. A função toc() é usada para saber em que momento (em segundos) a informação chegou, então você verá um gráfico valor X tempo.

Note o uso de msscanf. Note ainda:

  1. O primeiro parâmetro é a função readserial(h), que retorna um valor lido da serial;
  2. O segundo parâmetro é “S:%d\n”. Note que coincide com o que o Arduino envia. Apenas passamos o formato para o msscanf dizendo que começa com S:, tem um inteiro no meio (%d) e termina com “\n”. Cada %d colocado, o msscanf entende que você quer o valor que estiver alí, no nosso caso é onde o Arduino coloca o valor da leitura. Então, ele é retornado. No retorno [n,v], n é a quantidade de itens retornados, nesse caso será 1; e v é o valor desse item.
    1. readserial pode retornar vazio se nada tiver para ser lido, por isso, após a leitura testamos se n > 0 (tem leitura)

Tendo um valor v válido, plotamo-o no gráfico.

Se você interromper o programa, e quando reexecutar ele mostrar um erro de que a porta já está sendo usada, execute closeserial(h) e tente novamente. O erro acontece porquê esse programa abre a porta serial no começo, mas fica no loop e nunca a fecha. E quando interrompemos, a porta pode continuar aberta pelo Scilab. Não é permitido abrir a porta mais de uma vez, seja pelo mesmo programa ou programas diferentes.

 

Utilizando a IDE Code::Blocks com SDCC

Após muito tempo de pesquisas e tentativas, finalmente consegui configurar o Code::Blocks para usar o SDCC de forma satisfatória.

Então, neste post vamos configurar o Code::Blocks para utilizar o compilador SDCC (Small Device C Compiler). Além de todas as vantagens do uso de uma IDE, como auto-completar, o Code::Blocks compila automaticamente todas as bibliotecas necessárias e gera o arquivo .hex pronto para utilizar com apenas 1 clique.

Após instalar o Code::Blocks, vamos configurar o compilador SDCC:

  1. Acesse Settings→Compiler;
  2. Selecione o Compilador: Small Device C Compiler;
  3. Na aba “Compiler settings”, deixe tudo desmarcado;
  4. Na aba “Linker Settings”, deixe tudo em branco, remova qualquer biblioteca se tiver;
  5. Faça o mesmo na aba “Search directories” e suas sub-abas;
  6. Na aba “Toolchain executables”, corrija o diretório do compilador, no meu caso é “C:\Program Files\SDCC”;
  7. Na aba “Other Settings”, clique em “Avanced Options” e Yes;
    1. Na aba “Commands”, selecione o comando “Link object files to executable” e, no campo “Command line macro”, remova “-o $exe_output”;
    2. Faça o mesmo para “Link object files to console executable”
    3. Faça o mesmo para “Link object files to native executable”;
  8. Você pode clicar em “Set as default” se só usa o sdcc;

Feita a configuração do compilador, criamos um novo projeto. Nesse novo projeto fazemos as configurações locais.

Para não ter que fazer toda a configuração a seguir, você pode baixar um modelo de projeto. Assim, basta abrir e alterar/compilar. Mas, se quiser entender como funciona, siga os passos abaixo.

Aqui temos algumas ressalvas:

workspace1

  • Você deve ter uma pasta de trabalho, a qual contem os seus projetos, um em cada pasta, e as bibliotecas compartilhadas numa outra pasta, assim:
    • workspace (minha pasta de trabalho)libs (bibliotecas compartilhadas)
      • projeto_1
      • projeto_2

 

Parte 2

Vamos criar um projeto. No Code::Blocks, vá em File→New Project:

  1. Selecione “Empty project”;
  2. Clique em Go e em Next;
  3. Dê um nome, de preferência sem espaços e outros caracteres que não sejam letras, números e underline;
  4. Selecione a pasta “workspace”. Não crie uma pasta para seu projeto lá, o Code::Blocks irá fazer isso usando o nome que você deu ao projeto;
  5. Clique em Next;
  6. Desmarque a opção ‘Create “Debug” configurations’ e clique em Finish;
  7. Adicione um novo arquivo ao seu projeto em File→New→Empty File ou usando o ícone “New File”. A IDE perguntará se deseja salva, clique em Yes e salve na mesma pasta do projeto. Salve como main.c, pois usaremos esse nome novamente depois.
  8. Crie outros dois arquivos, picsetup.c e picsetup.h;
  9. Vá em Project→Properties;
    1. Na aba “Build targets”
      1. Altere Type para Native;
      2. Apague o Output filename (deixe em branco);
      3. Desmarque “Auto-generate filename extension;
      4. Clique OK;
  10. Vá em Project→Build Options;
    1. Na aba Compiler Settings e na sub-aba Compiler Flags, marque PIC 16-bit (p18f452…). Use PIC 14-bit se seu pic for da Familia 16F;
    2. Na sub-aba Other compiler options acrescente: –use-non-free -p18f4550 -I ../libs. Veja que incluímos o diretório de bibliotecas compartilhadas ‘libs’. Também indicamos qual é o pic a ser programado.
    3. Na aba “Linker settings” acrescente “main.c” no campo “Other linker options”;
  11. Abra o Arquivo main.c e vá em File→Properties, na aba Build, desmarque “Compile File” e “Link File”

Coloque o código de exemplo nos arquivos que foram criados:

main.c

#include "picsetup.h"

#pragma config FOSC = HSPLL_HS
#pragma config PWRT = OFF, BOR = OFF
#pragma config WDT = OFF
#pragma config DEBUG = OFF
#pragma config PLLDIV = 5
#pragma config USBDIV = 1
#pragma config CPUDIV = OSC1_PLL2
#pragma config XINST = OFF

#define LOOPS_PER_MS 820
#include <delays.h>
#define LED PORTEbits.RE1
#define LED2 PORTEbits.RE2

void main()
{
    hdw_setup();
    LED = 0;
    delay_ms(500);
    LED = 1;
    delay_ms(500);
    LED=0;
    delay_ms(500);
    while(1)
    {
        LED = 1;
        delay_ms(100);
        LED = 0;
        delay_ms(100);
    }
}

NOTA: evite LED = !LED, por algum motivo, o SDCC não gera o código corretamente.

picsetup.h

#include <pic18fregs.h>

void hdw_setup();

 

picsetup.c

#include "picsetup.h"

void hdw_setup(){

	TRISA = 0b00000011;
	TRISB = 0b00000000;
	TRISC = 0b10000000;
	TRISD = 0b00000000;
	TRISE = 0b00000000;

	PORTA = 0;
	PORTB = 0b00000000;
	PORTC = 0;
	PORTD = 0;
	PORTE = 0;
}

 

Salve os arquivos e clique em Build→Rebuild.

Prefira usar sempre o Rebuild, pois o Code::Blocks pode não detectar alterações das bibliotecas.

O resultado deve ser o seguinte:

-------------- Clean: Release in protest (compiler: Small Device C Compiler)---------------

Cleaned "protest - Release"

-------------- Build: Release in protest (compiler: Small Device C Compiler)---------------

sdcc.exe  -mpic16 --use-non-free -p18f4550 -I ../libs     -c picsetup.c -o obj\Release\picsetup.o
sdcc.exe    -mpic16 --use-non-free -p18f4550 -I ../libs    main.c   obj\Release\picsetup.o
message: Using default linker script "C:\Program Files (x86)\gputils\lkr\18f4550_g.lkr".
Output file is main.hex with size 1.35 KB
Process terminated with status 0 (0 minute(s), 1 second(s))
0 error(s), 0 warning(s) (0 minute(s), 1 second(s))

 

Os passos que envolvem o arquivo main.c foram necessários para que o Code::Blocks executasse a seguinte linha de comando:

sdcc.exe    -mpic16 –use-non-free -p18f4550 -I ../libs    main.c   obj\Release\picsetup.o

De outro modo, o compilador iria primeira gerar um arquivo objeto (-c main.c -o main.o) e depois tentar linkar. E, quando você precisar usar bibliotecas como stdio (para printf, por exemplo), obteria um erro dizendo que falta a biblioteca. Executando a linha acima, o compilador encontra as bibliotecas corretas automaticamente.

Dúvidas, entre em contato ou deixe um comentário.

Utilizando o Tiny Multi Bootloader+ com Microcontrolador PIC18F4550 a 48MHz

Nesse post mostrarei os passos necessários para utilizar o Tiny Multi Bootloader+.

Tentarei detalhar ao máximo os passos necessários para possibilitar que mesmo iniciantes possam utilizar esse bootloader.

A primeira coisa a fazer é gravar o arquivo .hex do bootloader no Microcontrolador PIC. Para isso será necessário um gravador como o ICD2, ICD3, entre outros que estão disponíveis no mercado.

O arquivo a ser gravado e o código fonte estão compactados aqui: boot18f4550

A versão para PIC18F4550 48MHz foi feita por mim, a partir de uma versão original para 20Mhz que o Tiny Bootloader. Se preferir outra configuração ou outro microcontrolador, veja os disponíveis no site do Tiny Multi Bootloader+.

Depois, você vai precisar de um circuito para conectar o PIC ao PC via RS232. Como boa parte dos notebooks já não possuem mais uma porta RS232 (até os desktop novos já não possuem mais), então decidi utilizar o componente FT232RL, ele funciona como um conversor USB-SERIAL e é muito fácil de utilizar. O único porém é o fato de ser SMD, no pacote SSOP28, cujo espaçamento entre os pinos é muito pequeno.

Existem vários módulos disponíveis nos quais esse componente já vem soldado.

picft232
Circuito PIC18F4550 e FT232RL com foto real.

Se tiver uma porta serial RS232 disponível, basta utilizar o MAX232, o qual possui muitos exemplos na internet. As conexões TX e RX são as mesmas. Apenas deve-se verificar o pino RTS, pois o TinyMB o utiliza para reiniciar o microcontrolador na hora de gravar.

Esse circuito pode ser alimentado pela própria USB, que fornece 5V. Para usar o FT232RL, o usuário deve instalar o driver que está disponível no site do fabricante.

Agora, com o circuito conectado ao computador, basta abrir o TinyMB, escolher o arquivo .hex a ser gravado, selecionar a porta COM e Clicar em “Write Device“. Deve-se também selecionar o baudrate correto, para o hex disponibilizado aqui, o correto é 115200.

fototinybl
Tela do TinyMB

 

 

Utilizando SDCC com Microcontrolador PIC 18F4550 (48Mhz)

Olá,

Nesse post vou escrever um pouco sobre como programar microcontroladores PIC, especificamente o PIC18F4550, com o compilador SDCC (Small Device C Compiler).

Aqui faremos uso apenas da linha de comando, se você procura algo como uma IDE, veja este POST: utilizando-a-ide-codeblocks-com-sdcc

Primeiro, a utilização de um bootloader é interessante. Veja esse Post para gravar um bootloader compatível com esse programa.

O primeiro passo é instalar o compilador SDCC e o GPUTILS.

Em seguida, crie uma pasta para trabalhar em algum local de seu computador. Vamos começar com um pequeno programa exemplo, mas o qual já vai nos dar a estrutura para trabalhar com qualquer projeto posterior. Essa é apenas uma forma de trabalhar, existem muitas outras.

Crie um arquivo chamado “config.h” e coloque nele o seguinte código:

#include <pic18fregs.h>
#define LED PORTBbits.RB0

Esse será o único local no qual o processador será especificado. Assim, quando precisar mudar de processador, basta alterar esse arquivo. Aqui também serão colocadas configurações globais do código, como a pinagem do microcontrolador, assim pode-se alterar os pinos facilmente. No nosso exemplo, um led foi colocado no pino B0.

Num outro arquivo, agora chamado “picconfig.h”, coloque o seguinte:

#ifndef _CONFIG_H_
#define _CONFIG_H_ 1

#include "config.h"

#pragma config FOSC = HSPLL_HS
#pragma config PWRT = OFF, BOR = OFF
#pragma config WDT = OFF
#pragma config DEBUG = OFF
#pragma config XINST = OFF
#pragma config PLLDIV = 5
#pragma config USBDIV = 1
#pragma config CPUDIV = OSC1_PLL2

#endif

Aqui vão as configurações do microcontrolador. Nesse arquivo alteramos as configurações dos chamados “fusíveis” do pic. Seria muito extenso explicar cada um deles aqui, esse trabalho já está feito no datasheet. Mas, qualquer coisa você pode perguntar aqui.

Agora, vamos criar o arquivo principal desse mini projeto, esse arquivo chama-se main.c:

#include "picconfig.h"

void hdw_setup(){
	ADCON1= 0x06;
	TRISA = 0b00000011;
	TRISB = 0b00000000; //0b00001000;
	TRISC = 0b10000000; //0b10000000;
	TRISD = 0b00000000;
	TRISE = 0b00000000;
}

void main(){
	hdw_setup();
	LED = 1;
	while(1){

	}
}

A ideia é muito simples. Criamos a função hdw_setup() para inicializar o hardware e, na função main(), fazemos com que o led acenda. A inicialização consiste em configurar os pinos do PIC como saída.

Agora vamos compilar esse código. Crie uma pasta chamada “obj” na sua pasta de trabalho. Essa nova pasta servirá apenas para organizarmos melhor os arquivos compilados do projeto.

Na sua pasta de trabalho, crie o arquivo “COMPILAR.bat” com o seguinte conteúdo:

@echo off
del obj/*.o
del obj/*.asm
del obj/*.lst
del *.hex
sdcc --use-non-free -mpic16 -p18f4550 main.c
del *.o
del *.asm
del *.lst
del *.cod
PAUSE

Execute esse arquivo para executar a compilação (pode simplesmente clicar duas vezes sobre ele). Como resultado você verá o arquivo main.hex na sua pasta de trabalho.

Agora plugue o seu circuito e baixe o arquivo main.hex nele. A princípio, o LED deve acender.

Se você não conseguiu criar todos os arquivos ou não entendeu alguns passos, segue um zip com todos esses arquivos: blog1