Nesse post vou mostrar os passos efetuados no desenvolvimento do elevador microcontrolado, que foi tema de um trabalho da faculdade. O objetivo do trabalho era entender o funcionamento de um microcontrolador. Em cima desse objetivo e muitas discussões optamos (eu e minha equipe) em fazer um elevador comercial.
Obs: Todo o desenvolvimento foi efetuado em ambiente Windows :(
Ferramentas Utilizadas:
Software:
Compilador: CCS PCWH v4.074
Simulador: Proteus Asis 7
Gravador: PICkit 2 V2.55.01
PCB Design : Proteus Ares 7
Hardware
Gravador: MicroICD ZIF da Microgenios
Microcontrolador PIC 16F877A
LCD de 16x2
Motor de passo
Display de 7 Segmentos Ânodo Comum
O desenvolvimento inicio-se com a resolução e entendimento do problema, onde o procedimento a ser tomado pelo elevador era:
1 - Conter 3 andares 2 - A prioridade de chamada é dada aos usuários internos do elevador 3 - A chamada externa é guardada em memoria e atendida conforme o andar 4 - A prioridade de andar e feita por proximidade 5 - O controle de andar sendo efetuado pelo controle de passo do motor 6 - Um LCD 16x2 mostrando a informação de que andar está e pra onde vai 7 - Temporizador de 30 segundos, para verificação de tempo de uso 8 - Display de informação de andar 9 - Sistema de desligamentoDepois de montado o layout de resolução foi efetuado o algoritmo em C.
[sourcecode language="css"]
//Elevador.h
#include
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT //No Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#use delay(clock=4000000)
</pre>
<pre class="brush:c">//Elevador.c
//ELEVADOR MICROCONTROLADO
//Trabalho de SDM II - Engenharia de Controle e Automação e Telecomunicação
//Equipe: Hamilton Sena
// André Fazione
// Leandro Rossi
// Robson Molgaro
#include "Elevador.h"
#include
#define MAX_PASSO 3 // 0-3 (Total de 4 passos)
//Variaveis Globais
char Passos[4]={8,4,2,1}; //Full Step 1
int index=0;//indice para matriz de passos
int TempoPasso=75;//Tempo de cada passo
int viAndar = 0;
int vaPinosPassado[7];
static int viContador;
int viSegundos;
int viPino5;
int viPino4;
int viPino3;
#int_timer0
//Essa função conta até 125 formando 1 segundo
void ControleTimer(){
//Se tiver no terreo ou 1 andar e for chamado no 2 andar
if(input(PIN_A5) == 1){
viPino5 = 1;
output_high(pin_c7);//2 Andar
}
//Se tiver no terreo ou 2 andar e for chamado no 1 andar
if(input(PIN_A4) == 1){
viPino4 = 1;
output_high(pin_c6);//1 Andar
}
//Se tiver no 1 andar ou 2 andar e for chamado no terreo
if(input(PIN_A3) == 1){
viPino3 = 1;
output_high(pin_c5);//Terreo
}
set_timer0(131-get_timer0());
viContador++;
}
//Função que controla o display de 7 segmentos
int ControlaDisplay(int vaPinos[]){
output_bit(pin_c0,vaPinos[0]);
output_bit(pin_c1,vaPinos[1]);
output_bit(pin_c2,vaPinos[2]);
output_bit(pin_c3,vaPinos[3]);
output_bit(pin_e2,vaPinos[4]);
output_bit(pin_e1,vaPinos[5]);
output_bit(pin_e0,vaPinos[6]);
return 0;
}
//Função Responsavel de girar o motor em sentido horario ou anti-horario
int MovimentaMotor(int nibble, int viSentido){
if (viSentido == 0){
//Testa um bit determinado da variavel passada, onde nibble é a
//variavel passada e o outro algarismo é o bit testado
output_bit(pin_b3,bit_test(nibble,0));
output_bit(pin_b2,bit_test(nibble,1));
output_bit(pin_b1,bit_test(nibble,2));
output_bit(pin_b0,bit_test(nibble,3));
return 0;
}else{
output_bit(pin_b3,bit_test(nibble,3));
output_bit(pin_b2,bit_test(nibble,2));
output_bit(pin_b1,bit_test(nibble,1));
output_bit(pin_b0,bit_test(nibble,0));
return 0;
}
}//FIM FUNÇÃO MOVIMENTA MOTOR
//Função que faz Girar o motor e modificar o display de 7 segmentos quando passa no 1 andar
int MovimentaElevador(int viQtdPassos, int viSentidoAndar, int viAndarSentido, int viMostraPasso ){
int viControle = 0;
while(viControle = MAX_PASSO){//Controla os passos (indice da matriz)
index=0;
}else{
index++;//incrementa para proximo passo
viControle++; //Incrementa os passos
}
}//FIM WHILE
return 0;
}//FIM MOVIMENTA ELEVADOR
int vFuncAndar_T(){
output_low(pin_c5);//Não pode ser feito chamada no terreo
viPino3 = 0;
lcd_putc("\f -> Terreo");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
vaPinosPassado[0] = 1;
vaPinosPassado[1] = 1;
vaPinosPassado[2] = 1;
vaPinosPassado[3] = 1;
vaPinosPassado[4] = 1;
vaPinosPassado[5] = 1;
vaPinosPassado[6] = 0;
ControlaDisplay(vaPinosPassado);
if (viPino4 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
delay_ms(2000);
//move motor para andar 1
MovimentaElevador(82,0,0,0);
viAndar = 1;
viPino4 = 0;
output_low(pin_c6);
return 0;
}
if (viPino5 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
delay_ms(2000);
//move motor para andar Comercial
//Quando chamar no Comercial passa o valor 1 viAndarSentido e o valor 82 para viQtdPassos
MovimentaElevador(168,0,1,82);
viAndar = 2;
viPino5 = 0;
output_low(pin_c7);
return 0;
}
while(viAndar == 0){
output_low(pin_c5);//Não pode ser feito chamada no terreo
viPino3 = 0;
if (viPino4 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
delay_ms(2000);
//move motor para andar 1
MovimentaElevador(82,0,0,0);
viAndar = 1;
viPino4 = 0;
output_low(pin_c6);
return 0;
}
if (viPino5 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
delay_ms(2000);
//move motor para andar Comercial
MovimentaElevador(168,0,1,82);
viAndar = 2;
viPino5 = 0;
output_low(pin_c7);
return 0;
}
//Se desligar o sistema retorna para o MAIN()
if(input(PIN_B4) == 0){
return 0;
}
if ((input(PIN_A1) == 1) & (input(PIN_A0) == 0)){
lcd_putc("\f Subindo para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
//move motor para andar 1
MovimentaElevador(82,0,0,0);
viAndar = 1;
return 0;
}
if ((input(PIN_A1) == 0) & (input(PIN_A0) == 1)){
lcd_putc("\f Subindo para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
//move motor para andar 2
MovimentaElevador(168,0,1,82);
viAndar = 2;
return 0;
}
if ((input(PIN_A1) == 1) & (input(PIN_A0) == 1)){
lcd_putc("\f Subindo para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
//move o motor para o andar 1
MovimentaElevador(82,0,0,0);
viAndar = 1;
return 0;
}
if (input(PIN_A4) == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
//move o motor para o andar 1
MovimentaElevador(82,0,0,0);
viAndar = 1;
viPino4 = 0;
return 0;
}
if (input(PIN_A5) == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
//move o motor para o andar 2
MovimentaElevador(168,0,1,82);
viAndar = 2;
viPino5 = 0;
return 0;
}
}//FIM WHILE
}//FIM FUNÇÃO vFuncAndar_T
int vFuncAndar_1(){
output_low(pin_c6);//Não pode ser feito chamada no 1 andar
viPino4 = 0;
viSegundos = 0;
lcd_putc("\f -> 1 Andar");
lcd_gotoxy(1,2);
printf(lcd_putc, " R.H.");
vaPinosPassado[0] = 0;
vaPinosPassado[1] = 1;
vaPinosPassado[2] = 1;
vaPinosPassado[3] = 0;
vaPinosPassado[4] = 0;
vaPinosPassado[5] = 0;
vaPinosPassado[6] = 0;
ControlaDisplay(vaPinosPassado);
if (viPino3 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
delay_ms(2000);
//move motor para o terreo
MovimentaElevador(82,1,0,0);
viAndar = 0;
viPino3 = 0;
output_low(pin_c5);
return 0;
}
if (viPino5 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
delay_ms(2000);
//move motor para andar terreo
MovimentaElevador(85,0,0,0);
viAndar = 2;
viPino5 = 0;
output_low(pin_c7);
return 0;
}
while(viAndar == 1){
output_low(pin_c6);//Não pode ser feito chamada no 1 andar
viPino4 = 0;
if (viPino3 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
delay_ms(2000);
//move motor para o terreo
MovimentaElevador(82,1,0,0);
viAndar = 0;
viPino3 = 0;
output_low(pin_c5);
return 0;
}
if (viPino5 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
delay_ms(2000);
//move motor para andar terreo
MovimentaElevador(85,0,0,0);
viAndar = 2;
viPino5 = 0;
output_low(pin_c7);
return 0;
}
//Mostra contador de segundos
if(viContador == 125){
viSegundos++;
viContador = 0;
lcd_gotoxy(1,2);
printf(lcd_putc, " R.H. -> %i",viSegundos);
}
//Se desligar o sistema retorna para o MAIN()
if(input(PIN_B4) == 0){
return 0;
}
if ((input(PIN_A2) == 1) & (input(PIN_A0) == 0)){
lcd_putc("\f Descendo para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
//move motor para andar Terreo
MovimentaElevador(82,1,0,0);
viAndar = 0;
return 0;
}
if ((input(PIN_A2) == 0) & (input(PIN_A0) == 1)){
lcd_putc("\f Subindo para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
//move motor para andar 2
MovimentaElevador(85,0,0,0);
viAndar = 2;
return 0;
}
if ((input(PIN_A2) == 1) & (input(PIN_A0) == 1)){
lcd_putc("\f Descendo para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
//move o motor para o andar Terreo
MovimentaElevador(82,1,0,0);
viAndar = 0;
return 0;
}
if (input(PIN_A3) == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
//move o motor para o andar terreo
MovimentaElevador(82,1,0,0);
viAndar = 0;
viPino3 = 0;
return 0;
}
if (input(PIN_A5) == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Comercial");
//move o motor para o andar 2
MovimentaElevador(85,0,0,0);
viAndar = 2;
viPino5 = 0;
return 0;
}
//viTempoControle = viTempoControle + 1;
if(viSegundos == 30){
lcd_putc("\f Descendo...");
lcd_gotoxy(1,2);
lcd_putc("Tempo Esgotado");
MovimentaElevador(82,1,0,0);
viAndar = 0;
return 0;
}
}//FIM WHILE
}//FIM FUNÇÃO vFuncAndar_1
int vFuncAndar_2(){
output_low(pin_c7);//Não pode ser feito chamada no 2 andar
viPino5 = 0;
viSegundos = 0;
lcd_putc("\f -> 2 Andar");
lcd_gotoxy(1,2);
printf(lcd_putc, " Comercial");
vaPinosPassado[0] = 1;
vaPinosPassado[1] = 1;
vaPinosPassado[2] = 0;
vaPinosPassado[3] = 1;
vaPinosPassado[4] = 1;
vaPinosPassado[5] = 0;
vaPinosPassado[6] = 1;
ControlaDisplay(vaPinosPassado);
if (viPino4 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
delay_ms(2000);
//move motor para andar 1
MovimentaElevador(83,1,0,0);
viAndar = 1;
viPino4 = 0;
output_low(pin_c6);
return 0;
}
if (viPino3 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
delay_ms(2000);
//move motor para andar terreo
//Quando chamar no Terreo passa o valor 2 viAndarSentido e o valor 83 para viQtdPassos
MovimentaElevador(166,1,2,83);
viAndar = 0;
viPino3 = 0;
output_low(pin_c5);
return 0;
}
while(viAndar == 2){
output_low(pin_c7);//Não pode ser feito chamada no 2 andar
viPino5 = 0;
if (viPino4 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
delay_ms(2000);
//move motor para andar 1
MovimentaElevador(83,1,0,0);
viAndar = 1;
viPino4 = 0;
output_low(pin_c6);
return 0;
}
if (viPino3 == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
delay_ms(2000);
//move motor para andar terreo
MovimentaElevador(166,1,2,83);
viAndar = 0;
viPino3 = 0;
output_low(pin_c5);
return 0;
}
//Mostra contador de segundos
if(viContador == 125){
viSegundos++;
viContador = 0;
lcd_gotoxy(1,2);
printf(lcd_putc, " Comercial -> %i",viSegundos);
}
//Se desligar o sistema retorna para o MAIN()
if(input(PIN_B4) == 0){
return 0;
}
if ((input(PIN_A1) == 1) & (input(PIN_A2) == 0)){
lcd_putc("\f Descendo para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
//move motor para andar 1
MovimentaElevador(83,1,0,0);
viAndar = 1;
return 0;
}
if ((input(PIN_A1) == 0) & (input(PIN_A2) == 1)){
lcd_putc("\f Descendo para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
//move motor para andar terreo
MovimentaElevador(166,1,2,83);
viAndar = 0;
return 0;
}
if ((input(PIN_A1) == 1) & (input(PIN_A2) == 1)){
lcd_putc("\f Descendo para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
//move o motor para o andar 1
MovimentaElevador(84,1,0,0);
viAndar = 1;
return 0;
}
if (input(PIN_A4) == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" R.H.");
//move o motor para o andar 1
MovimentaElevador(84,1,0,0);
viAndar = 1;
viPino4 = 0;
return 0;
}
if (input(PIN_A3) == 1){
lcd_putc("\f Chamada para...");
lcd_gotoxy(1,2);
lcd_putc(" Engenharia");
//move o motor para o andar terreo
MovimentaElevador(167,1,2,83);
viAndar = 0;
viPino3 = 0;
return 0;
}
//viTempoControle = viTempoControle + 1;
if(viSegundos == 30){
lcd_putc("\f Descendo...");
lcd_gotoxy(1,2);
lcd_putc("Tempo Esgotado");
MovimentaElevador(167,1,2,83);
viAndar = 0;
return 0;
}
}//FIM WHILE
}//FIM FUNÇÃO vFuncAndar_2
//Programa Principal
void main(){
//------- Codigo gerado pelo Compilador
setup_adc_ports(NO_ANALOGS);
setup_adc(ADC_OFF);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
//Configura timer0 para clock interno e prescaler dividido por 64
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_64);
set_timer0(131);//inicia o timer 0 em 131
enable_interrupts(global | int_timer0);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
//--------------------------------------
//Definindo as porta do MCU
set_tris_b(0b00010000);//Coloca o pino RB4 como entrada e os outros pino RB como saida
set_tris_a(0b11111111);//Coloca todos os pino RA como entrada
set_tris_e(0b00000000);//Coloca todos os pino RE como Saida
set_tris_c(0b00000000);//Coloca todos os pinos RC como saida
//Definido estado dos pinos
output_b(0b00000000);//todos os pinos de saida da porta b desligados
//output_e(0b00000000);
//output_c(0b00000000);
//output_low(pin_b5);//Deixa desligado o Backlite do LCD
//Iniciliaza o LCD
lcd_init();
vaPinosPassado[0] = 0;
vaPinosPassado[1] = 0;
vaPinosPassado[2] = 0;
vaPinosPassado[3] = 0;
vaPinosPassado[4] = 0;
vaPinosPassado[5] = 0;
vaPinosPassado[6] = 0;
ControlaDisplay(vaPinosPassado);
//Loop infinito do Programa
while(true){
if (input(PIN_B4) == 1){//Sistema ligado
//output_high(PIN_B5);//Liga o BackLith do LCD
if (viAndar == 0){
vFuncAndar_T();
}
if (viAndar == 1){
vFuncAndar_1();
}
if (viAndar == 2){
vFuncAndar_2();
}
}else{
//Caso o pino de ativação do sistema estive desligado inicializa/desliga o sistema
vaPinosPassado[0] = 0;
vaPinosPassado[1] = 0;
vaPinosPassado[2] = 0;
vaPinosPassado[3] = 0;
vaPinosPassado[4] = 0;
vaPinosPassado[5] = 0;
vaPinosPassado[6] = 0;
ControlaDisplay(vaPinosPassado);
switch(viAndar){
case 0:
lcd_putc("\f ");//Apaga se tiver alguma coisa escrita no LCD
output_low(pin_c7);
output_low(pin_c6);
output_low(pin_c5);
viPino3 = 0;
viPino4 = 0;
viPino5 = 0;
break;
case 1:
lcd_putc("\f Desligando...");
MovimentaElevador(82,1,0,0);
lcd_putc("\f");//Apaga se tiver alguma coisa escrita no LCD
viAndar = 0;
output_low(pin_c7);
output_low(pin_c6);
output_low(pin_c5);
viPino3 = 0;
viPino4 = 0;
viPino5 = 0;
break;
case 2:
lcd_putc("\f Desligando...");
MovimentaElevador(167,1,0,0);
lcd_putc("\f");//Apaga se tiver alguma coisa escrita no LCD
viAndar = 0;
output_low(pin_c7);
output_low(pin_c6);
output_low(pin_c5);
viPino3 = 0;
viPino4 = 0;
viPino5 = 0;
break;
}//SWITCH
}//FIM ELSE PIN_B4
}//FIM WHILE PRINCIPAL
}//FIM Função MAIN
[/sourcecode]
Abaixo segue o layout do simulador,
Abaixo o layout do circuito impresso, O final da historia foi a aprovação direta para o próximo período e mais conhecimento. Abaixo deixo os arquivos a serem compilados e testados. Acesso aos arquivos
Abaixo segue um video com o funcionamento do elevador http://www.youtube.com/watch?v=n49V2sRLX9k