Introduction: YourCoffe - ​Simulador De Uma Máquina De Café - PIC18F4520

    Como Projeto Final da disciplina prática de sistemas embarcados da Universidade Federal de Itajubá – UNIFEI (https://www.linkedin.com/school/unifei/), desenvolvi o projeto “YourCoffe”. O objetivo é utilizar o microcontrolador PIC18f4520 da Microchip Technology Inc. (https://www.linkedin.com/company/microchip-technology/) representada pela Artimar Ltda no Brasil (https://www.linkedin.com/company/artimar-ltda/) para desenvolver um sistema que utiliza os periféricos LCD, LED's, Displays de sete segmentos e o Teclado.

    O projeto foi testado e está funcionando utilizando o simulador PICSimLab do Luis Claudio Gambôa Lopes (https://www.linkedin.com/in/luis-claudio-gamb%C3%B4a-lopes-6bbbb6182/).

    Os códigos referentes a este projeto estão disponíveis na minha conta do github (https://github.com/em4noel-dev/your-coffe). O projeto funcionando pode ser visto através do vídeo no (https://youtu.be/eWicd-miBo4).

    Os professores responsáveis pela condução da disciplina foram:

    - O professor Otávio Gomes (https://www.linkedin.com/in/otavio-gomes/)

    - O professor Rodrigo Almeida (https://www.linkedin.com/in/rmaalmeida/)

    Este projeto apresenta uma interface de controle e programação para uma máquina de café, onde por meio dela o usuário poderá selecionar sua bebida e acompanhar o seu preparo. Assim que o usuário finaliza a escolha, o programa executará os comandos relacionados à opção, simulando assim uma máquina de café real.

    Características:

    -- > LCD:

    Ele será utilizado para exibir ao usuário da máquina de café as seguintes informações:

    - Menu de escolha:

    - Opções de escolha do café desejado: (1) café expresso, (2) café puro, (3) capuccino, (4) latte, etc.;

    - Opções da quantidade de café desejado: (1) 300 ml, (2) 500 ml, etc.

    - Mensagens de aviso:

    - confirmação de escolha;

    - informando o preparo;

    - informando que o café está pronto.

    -- > LEDs:

    Os Leds serão acionados para simular uma sensação de carregamento durante o preparo do café escolhido. O acionamento dos led´s neste projeto indica uma adaptação afim de executar as tarefas reais: moagem, ferver a água, motor da água, etc.;

    -- > Displays de sete segmentos:

    Eles serão utilizados como um cronômetro informando o tempo restante para o fim da preparação do café escolhido.

    -- > Teclado:

    O teclado será utilizado para selecionar uma das opções fornecidas pelo LCD, navegação entre os menus e também para iniciar/cancelar o preparo do café caso desejado.

Step 1: Hardware: PIC18F4520

O PIC18F4520 é um microcontrolador que opera entre 2.0V a 5.5V, possui 40 pinos com encapsulamento Dual In Line, 10 bits de conversor A/D, nanoWatt Technology e memória flash. Possui uma estrutura de oscilador flexível com quatro módulos de cristais de até 40MHz, quatro circuitos PLL (Phase Lock Loop), cristais osciladores internos, dois módulos externos RC de até 4MHz, dois módulos de Clock externos de até 40MHz e um bloco de oscilador interno.

Sobre os periféricos, o microcontrolador tem uma alta corrente Sink/Source 25 mA possibilitando alimentar leds diretamente, três módulos externos de interrupção programáveis, quatro entradas de mudança de interrupção, dois módulos de captura CCP (Capture/Compare/PWM), canais de conversão A/D com resolução de 10 bits implicando em varias entradas analógicas nesse processador, módulos comparadores e programação de baixa tensão.

Algumas características especiais do PIC18F4520 é uma arquitetura otimizada para o compilador em C, 100000 escritas e leituras na memória flash, 1000000 de escritas e leituras na memória EEPROM e uma grande novidade da família 18F em relação a 16F é presença de níveis de prioridade de interrupção. A tabela fornecida acima mostra algumas informações sobre os microcontroladores da família 18F, sendo que a ultima linha é sobre o PIC18F4520.

O Aspecto físico do PIC18F4520 juntamente com seus 40 pinos está ilustrado na figura acima.

Na imagem, os pinos cuja seta aponta para dentro só podem ser utilizados para entrada e, em contrapartida, uma seta dupla, significa que pode ser usado para entrada e também para saída. É importante ressaltar que é imprescindível ter sempre em mãos o Data Sheet de todos os componentes utilizados em um projeto, para obter o total conhecimento dos seus funcionamentos e especificações técnicas.

Step 2: Software - Bibliotecas Utilizadas

No desenvolvimento do projeto, foram utilizadas as seguintes bibliotecas:

#include "config.h"
#include "pic18f4520.h"
#include "delay.h"
#include "lcd.h"
#include "teclado.h"
#include "yourcoffe.h"
#include <string.h>

As bibliotecas "config.h", "pic18f4520.h", "delay.h", "lcd.h" e "teclado.h" foram desenvolvidas pelo professor Rodrigo Maximiano para manipulação do microcontrolador PIC18F4520 e seus periféricos.

A biblioteca "yourcoffe.h" foi desenvolvida pela equipe do projeto para realizar as funções mais importantes da máquina de café.

A sua definição é:

#ifndef YOURCOFFE_H<br>#define YOURCOFFE_H

void tempoPreparo(int segundos);
char opcaoDesejada(char menu); 
void scrollDisplay(char *linha1, char *linha2);

#endif /* YOURCOFFE_H */

A função "tempoPreparo(int segundos)" é responsável por mostrar o valor restante no display de sete seguimentos do tempo de preparo do café escolhido pelo usuário. Além disso, ela também realiza uma animação nos LED's do PORTB simulando um carregamento.

A função "opcaoDesejada(char menu)" é responsável por retornar a leitura da tecla pressionada no teclado para o programa principal. Seu parâmetro char representa o menu para qual a o retorno será utilizado:

  • "1" > Tipo de café
  • "2" > Tamanho do café
  • "3" > Confirmação

A função "scrollDisplay(char *linha1, char *linha2)" é responsável pelo movimento horizontal do texto no display LCD a fim de uma melhor visualização. Ela recebe dois parâmetros, que são as frases que devem ser escritas na primeira e na segunda linha do LCD.

A biblioteca "string.h" foi utilizada no programa principal para manipulação de strings.

Step 3: Software - a Função TempoPreparo

O código da função está escrito abaixo:

void tempoPreparo(int segundos)
{    
    BitClr(INTCON2, 7); //liga pull up
    ADCON1 = 0x0E;      //config AD
    TRISD = 0x00;       //config. a porta D
    TRISA = 0x00;       //config. a porta A
    TRISB = 0x00;
    PORTB = 0x00;
    const char valor[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
    const char leds[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
    char aux = 0;
    unsigned int k, delay = 1000, i;
    while(1)
    {
        PORTB = leds[aux++]; if(aux == 8) aux = 0;
        for(i = 0; i < 50; i++) // for para ficar um pouco mais lento a aparição do número
        {
            PORTD = valor[(segundos / 1) % 10];
            BitSet(PORTA, 5);
            BitClr(PORTA, 4);
            BitClr(PORTA, 3);
            BitClr(PORTA, 2);
            for(k = 0; k < delay; k++);
            PORTD = valor[(segundos / 10) % 10];
            BitClr(PORTA, 5);
            BitSet(PORTA, 4);
            BitClr(PORTA, 3);
            BitClr(PORTA, 2);
            for(k = 0; k < delay; k++);
            PORTD = valor[(segundos / 100) % 10];
            BitClr(PORTA, 5);
            BitClr(PORTA, 4);
            BitSet(PORTA, 3);
            BitClr(PORTA, 2);
            for(k = 0; k < delay; k++);
            PORTD = valor[(segundos / 1000) % 10];
            BitClr(PORTA, 5);
            BitClr(PORTA, 4);
            BitClr(PORTA, 3);
            BitSet(PORTA, 2);
            for(k = 0; k < delay; k++);
       
        }
        
        segundos--;
        
        if(segundos == -1) break;
    }   
    
    BitClr(PORTA, 5);
    BitClr(PORTA, 4);
    BitClr(PORTA, 3);
    BitClr(PORTA, 2);
    PORTB = 0x00;
  
}

Essa função basicamente faz a multiplexação do tempo para exibição dos valores corretos no displays de sete segmentos. Além disso, também é utilizado os LED's do PORTB para simular uma sensação de carregamento. Essas duas etapas foram realizadas utilizando os vetores auxiliares "valor[10]" e "leds[8]". A função fica em loop até que se passe aproximadamente o tempo fornecido como parâmetro.

Significados de algumas instruções utilizadas:

Configuração para exibição do valor do tempo no display de sete segmentos juntamente com um delay para realização da multiplexação:

PORTD = valor[(segundos / 1000) % 10];<br>BitClr(PORTA, 5);
BitClr(PORTA, 4);
BitClr(PORTA, 3);
BitSet(PORTA, 2);
for(k = 0; k < delay; k++);

Mudança nos LED's acessos para o efeito de carregamento:

PORTB = leds[aux++]

Step 4: Software - a Função OpcaoDesejada

O código da função está escrito abaixo:

char opcaoDesejada(char menu)
{
    char tmp;
    if(menu != '3'){
        lcd_cmd(L_CLR);
        lcd_cmd(L_L1);
        lcd_str("  PRESSIONE A");
        lcd_cmd(L_L2);
        lcd_str(" OPCAO DESEJADA ");
    }

    while(1) // ler
    {
        TRISD = 0x0F;
        tmp = tc_tecla(0) + 0x30;
        TRISD = 0x00;
        if(menu == '1' && (tmp == '1' || tmp == '2' || tmp == '3' || tmp == '4')) // cafés
            break;
        else if((tmp == '1' || tmp == '2')) // tamanhos e confirmção
            break;

    }
    
    return tmp;
}

Essa função utiliza o LCD para imprimir na tela uma mensagem solicitando que o usuário pressione a tecla correspondente a opção desejada. O parâmetro da função tem como objetivo informar qual etapa de menu o programa está, para permitir corretamente as teclas que poderão ser pressionadas.

A função fica em loop até que o usuário pressione uma tecla adequada.

Os tipos de menus com suas respectivas quantidades de opção de seleção que a função recebe como parâmetro são:

  • "1" > Tipo de café (4 opções)
  • "2" > Tamanho do café (4 opções)
  • "3" > Confirmação (2 opções)

Significados de algumas instruções utilizadas:

lcd_cmd(L_CLR); // Limpa a tela do LCD

lcd_cmd(L_L1); // Move o cursor para a primeira linha do LCD

lcd_str("str"); // Escreve uma mensagem no LCD

lcd_cmd(L_L2); // Move o cursor para a segunda linha do LCD

A leitura da tecla pressionada juntamente com sua conversão para o char equivalente ocorre na seguinte instrução:

tmp = tc_tecla(0) + 0x30;

A variável TRISD é utilizada para a configuração do teclado.

Step 5: Software - a Função ScrollDisplay

O vídeo acima é um exemplo do movimento do display.

O código da função está escrito abaixo:

void scrollDisplay(char *linha1, char *linha2)
{   
    int i;
    lcd_cmd(L_CLR);
    lcd_cmd(L_L1);
    lcd_str(linha1);
    lcd_cmd(L_L2);
    lcd_str(linha2);
    atraso_ms(atrasoMax);

    for (i = 0; i < 14; i++) {
        atraso_ms(atrasoMed);
        lcd_cmd(0x18);
    }

    for (i = 0; i < 22; i++) {
        atraso_ms(atrasoMed);
        lcd_cmd(0x1C);
    }

    for (i = 0; i < 15; i++) {
        atraso_ms(atrasoMed);
        lcd_cmd(0x18);
    }

    atraso_ms(atrasoMax);
}

O objetivo dessa função é deslocar horizontalmente a mensagem do LCD para o usuário conseguir visualizar totalmente a informação fornecida pela máquina de café.

Significado de algumas instruções:

Deslocamento da mensagem 14 caracteres para esquerda:

for (i = 0; i < 14; i++) {<br>   atraso_ms(atrasoMed);
   lcd_cmd(0x18);
}

Deslocamento da mensagem 22 caracteres para direita:

for (i = 0; i < 22; i++) {<br>   atraso_ms(atrasoMed);
   lcd_cmd(0x1C);
}

Step 6: Software - O Programa Principal

O código do método main está escrito abaixo:

#include "config.h"
#include "pic18f4520.h"
#include "delay.h"
#include "lcd.h"
#include "teclado.h"<a href="https://www.instructables.com/editInstructable/edit/E5HTHY7KI1PELQK/step/6#" rel="nofollow"></a>
#include "yourcoffe.h"
#include <string.h>

void main(void) 
{
    unsigned char i, tempo;
    unsigned char cafe, tamanho, corfirmar;
    unsigned char cafes[5][10] = {"EXPRESSO", "AMERICANO", "CAPUCCINO", "LATTE"};
    unsigned char tamanhos[2][8] = {"90ml" , "150ml"};
    
    //configuração das entradas
    ADCON1 = 0x06;
    TRISD = 0x00;
    TRISE = 0x00;
    TRISB = 0x01;

    //Teclado numérico
    TRISB = 0xF8;
    
    lcd_init();
    
    for(;;)
    { 
        ADCON1 = 0x06;
        TRISD = 0x00;
        TRISE = 0x00;
        TRISB = 0x01;
        
        TRISB = 0xF8;
        
        lcd_cmd(L_CLR);
        lcd_cmd(L_L1);
        lcd_str("   Y0URC0FF3 ");
        lcd_cmd(L_L2);
        lcd_str("ESCOLHA SEU CAFE");
        atraso_ms(2000);
        
        do
        {
            scrollDisplay("(1) expresso  (2) americano", "(3) capuccino (4) latte       ");
            cafe = opcaoDesejada('1');

            char frase[50];
            
            switch (cafe)
            {
                case '1':
                    strcpy(frase, "TAMANHO DO EXPRESSO");
                    tempo = 30;
                    break;
                case '2':
                    strcpy(frase, "TAMANHO DO AMERICANO");
                    tempo = 50;
                    break;
                case '3':
                    strcpy(frase, "TAMANHO DO CAPUCCINO");
                    tempo = 60;
                    break;
                case '4':
                    strcpy(frase, "TAMANHO DO LATTE");
                    tempo = 40;
                    break;       
            }

            scrollDisplay(frase, "(1)90 ml (2)150 ml            ");

            tamanho = opcaoDesejada('2');
            
            strcpy(frase,cafes[(cafe - '0') - 1]);
            strcat(frase," ");
            strcat(frase, tamanhos[(tamanho - '0')- 1]);
            
            lcd_cmd(L_CLR);
            lcd_cmd(L_L1);
            lcd_str(frase);
            lcd_cmd(L_L2);
            lcd_str("(1)OK (2)CANCEL ");
            
            corfirmar = opcaoDesejada('3');
            
        }while(corfirmar == '2');    
            
        
        if(tamanho == '2') // se a opção escolhido for 150 ml o tempo demora + 20%
        tempo *= 1.2;


        lcd_cmd(L_CLR);
        lcd_cmd(L_L1);
        lcd_str("PREPARANDO O ");
        lcd_cmd(L_L2);
        lcd_str("CAFE DESEJADO    ");

        tempoPreparo(tempo);

        scrollDisplay("SEU CAFE ESTA PRONTO", "Mais delicioso impossivel      ");
            
    }
}<br>

Passo a passo do funcionamento do programa:

  • Declarações de variáveis e configurações inicias:
    // Declarações da variáveis utilizadas:
    unsigned char i, tempo;<br>    unsigned char cafe, tamanho, corfirmar;
    unsigned char cafes[5][10] = {"EXPRESSO", "AMERICANO", "CAPUCCINO", "LATTE"};
    unsigned char tamanhos[2][8] = {"90ml" , "150ml"};
    
    //configuração iniciais
    ADCON1 = 0x06;
    TRISD = 0x00;
    TRISE = 0x00;
    TRISB = 0x01;
    TRISB = 0xF8;
    lcd_init();<br>
  • Inicio do loop infinito do programa, exibição da mensagem inicial "Y0URC0FF3 ESCOLHA SEU CAFE" e um delay de 2 segundos de espera.
	for(;;)<br>    	{ 
           ADCON1 = 0x06;
           TRISD = 0x00;
           TRISE = 0x00;
           TRISB = 0x01;
           TRISB = 0xF8;
        
           lcd_cmd(L_CLR);
           lcd_cmd(L_L1);
           lcd_str("   Y0URC0FF3 ");
           lcd_cmd(L_L2);
           lcd_str("ESCOLHA SEU CAFE");
           atraso_ms(2000);

	...
	...
  • Inicio de um loop para caso o usuário cancele o pedido, exibição dos tipos de cafés disponíveis e leitura da opção desejada pelo teclado.
        do<br>        {
            scrollDisplay("(1) expresso  (2) americano", "(3) capuccino (4) latte       ");
            cafe = opcaoDesejada('1');

            ...
            ...
  • Definição do tempo total de preparo e da mensagem de exibição de acordo com o café escolhido.
            char frase[50];<br>            
            switch (cafe)
            {
                case '1':
                    strcpy(frase, "TAMANHO DO EXPRESSO");
                    tempo = 30;
                    break;
                case '2':
                    strcpy(frase, "TAMANHO DO AMERICANO");
                    tempo = 50;
                    break;
                case '3':
                    strcpy(frase, "TAMANHO DO CAPUCCINO");
                    tempo = 60;
                    break;
                case '4':
                    strcpy(frase, "TAMANHO DO LATTE");
                    tempo = 40;
                    break;       
            }
  • Exibição no LCD dos tamanhos disponíveis para o café escolhido e leitura da opção desejada pelo teclado:
	    scrollDisplay(frase, "(1)90 ml (2)150 ml            ");
            tamanho = opcaoDesejada('2');
  • Exibição do menu de confirmação.
  1. Caso o usuário selecione "OK", a cafeteira irá iniciar o processo de preparação.
  2. Caso o usuário selecione "CANCEL", o programa irá voltar para o menu inicial de escolha do café.
            strcpy(frase,cafes[(cafe - '0') - 1]);<br>            strcat(frase," ");
            strcat(frase, tamanhos[(tamanho - '0')- 1]);
            
            lcd_cmd(L_CLR);
            lcd_cmd(L_L1);
            lcd_str(frase);
            lcd_cmd(L_L2);
            lcd_str("(1)OK (2)CANCEL ");
            
            corfirmar = opcaoDesejada('3');
            
        }while(corfirmar == '2');
  • Exibição da mensagem no LCD "Preparando o café desejado", inicio da contagem do tempo no display de sete seguimentos e inicio da utilização dos LEDs para sensação de carregamento.
  • Caso o usuário escolher o tamanho de 150 ml, o tempo de preparação irá aumentar em 20%
        if(tamanho == '2') // se a opção escolhido for 150 ml o tempo demora + 20%<br>             tempo *= 1.2;lcd_cmd(L_CLR);
        lcd_cmd(L_L1);
        lcd_str("PREPARANDO O ");
        lcd_cmd(L_L2);
        lcd_str("CAFE DESEJADO    ");
        tempoPreparo(tempo);
  • Após o tempo de preparação acabar, uma mensagem avisando ao usuário que o café está pronto irá aparecer no LCD.
        scrollDisplay("SEU CAFE ESTA PRONTO", "Mais delicioso impossivel      ");
  • Por fim, o programa repete todo o procedimento do início.

Step 7: Dificuldades E Soluções Encontradas

A grande dificuldade na realização desse projeto foi o período de pandemia, que não permitiu as aulas presenciais da disciplina na universidade. Porém, graças as aulas dos professores, suas disposições de tempo para tirar dúvidas dos alunos e os documentos fornecidos, todas as soluções que o projeto necessitava foi encontrado.

Step 8: Vídeo Da Apresentação Do Projeto