Página 1 de 1

Problema na implementação - PIC 16F877A

MensagemEnviado: 29 Out 2008 09:57
por hsena
Olá pessoal, sou novo por aqui e na utilização de microcontroladores,
e estou tendo alguns problemas na hora da implementação de um projeto na protoboard.
Vamos lá,
Meu ambiente de desenvolvimento:
Compilador: CCS PCWH versão 4.074
Simulador: Protheus ISIS Professional versão 7.2 SP2
Microcontrolador: PIC 16F877A
Gravador: MIicroICD ZIF da Microgenios

Objetivo do projeto:
Controlar o sentido de um motor de passo e mostrar em um LCD o seu sentido.

1º Teste
Fiz o programa para controlar o motor, o mesmo funcionou perfeitamente, até fiz um video
com o seu funcionamento, que pode ser visto nesse link -> http://www.youtube.com/watch?v=vjyRC8xzqeM

2º Teste
Após fazer funcionar o motor, partir para o funcionamento do LCD. Dai é que começou meus
problemas, comprei um LCD 16x2 e adicionei no programa do motor a biblioteca lcd.c que
já vem no compilador CCS. Montei o LCD na protoboard e tentei testar, acontece que quando
está adicionado os comandos de escrita no programa o sistema inteiro para de funcionar, dai
simulei o sistema no Proteus e funcionou perfeitamente.

O que poderia ser a causa do problema?????

O código fonte e design do Proteus pode ser baixado -> Projeto_LCD_Motor_Passo.rar


Desde já, agradeço a ajuda.

MensagemEnviado: 29 Out 2008 10:39
por Djalma Toledo Rodrigues
Remova o contrôle do motor de passo e teste o LCD enviando uma mensagem qualquer.

Funcionou ?

MensagemEnviado: 29 Out 2008 12:48
por hsena
Olá Djalma, vc diz retirar do codigo ou fisicamente, se for do codigo eu já retirei e o LCD nem deu sinal de vida.
Um detalhe, esse LCD que estou colocando é novo (comprei ontem), pois eu estava usando outro LCD que eu tinha, mas não sabia se estava funcionando. Pra ser sincero ainda não consegui colocar nenhum LCD para funcionar na protoboard, só pelo Proteus.

MensagemEnviado: 29 Out 2008 12:59
por saulo.wulhynek
Olá hsena,

Realmente vc não disse como implementou o controle do motor de passo nem do LCD. Porém, ambos precisam de tempos de espera (Laços de tempo) para que possam receber os comandos corretamente. Assim, as duas rotinas devem estar implementadas originalmente com laço de tempo e não deverão funcionar juntas. Elas precisam ser reescritas implementando as temporizações pelos timers.

Será que ajudei?

Saulo

MensagemEnviado: 29 Out 2008 13:34
por hsena
Olá Saulo,
Saulo não sei se vc deu uma olhada no arquivo que coloquei para download, la tem o código e layout feito no Proteus, mas para facilitar vou ja deixar postado aqui para uma verificação mais pratica.
Em questão do tempo de espera, se o programa funcionou no simulador ele não teria que funcionar na pratica???
E se for necessário temporizar pelos timers, quando eu acionar o LCD ele não vai para de movimentar o motor???

Abaixo o código, como dito anteriormente compilado com o CCS
----------------------------------------

Código: Selecionar todos
#include <16F877A.h>
#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)
#include <lcd.c>

#define MAX_PASSO 3 // 0-3 (Total de 4 passos)


 //Gira Motor no sentido horario
 void MotorHorario(int nibble)
 {
    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));

 }
 
  //Gira Motor no sentido anti-horario
 void MotorAntiHorario(int nibble)
 {
    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));

 }
 
char Passos[4]={12,6,3,9}; //Passo Completo
int index=0;//indice para matriz de passos
int TempoPasso=100;//Tempo de cada passo
int viControle1 = 0;
int viControle2 = 0;
   

void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   
   set_tris_b(0b00000000);//Coloca todos os pino RB como saida
   set_tris_a(0b00000011);//Coloca o pino RA0 e RA1 como entrada
   
   output_b(0b0000000);//todos os pinos de saida da porta b desligados
   lcd_init();//Iniciliza o LCD
   
   while(true){
   
   if (input(pin_a1) == 1){//Liga o motor e depois verifica para que sentido ele vai
   
      if(input(pin_a0) == 1){
     
         viControle2 = 0;
         lcd_putc("\fSentido Horario\n");
         printf(lcd_putc, "Passo -> %i",viControle1);
         delay_ms(TempoPasso); // aguarda um tempo entre cada passo
         MotorHorario(Passos[index]);

         if(index >= MAX_PASSO){//Controla os passos (indice da matriz)
            index=0;
         }else{
            index++;//incrementa para proximo passo
         }
         
         viControle1++;
      }else{
         
         viControle1 = 0;
         lcd_putc("\fSentido Anti-horario\n");
         printf(lcd_putc, "Passo -> %i",viControle2);         
         delay_ms(TempoPasso); // aguarda um tempo entre cada passo
         MotorAntiHorario(Passos[index]);

         if(index >= MAX_PASSO){//Controla os passos (indice da matriz)
            index=0;
         }else{
            index++;//incrementa para proximo passo
         }
     
         viControle2++;
      }//FIM ELSE AntiHorario
   
   
   
   }else{
   
      output_b(0b0000000);
      lcd_putc("\f");
     
   }//FIM ELSE LIGADO DESLIGADO

}//FIM WHILE

}//FIM MAIN

MensagemEnviado: 29 Out 2008 13:52
por hsena
Aqui está o circuito que estou testando:
http://hsena.files.wordpress.com/2008/10/layout_circuito.jpg

MensagemEnviado: 29 Out 2008 15:29
por saulo.wulhynek
Olá Hsena

Realmente eu não havia olhado o Prog. Vamos por partes. Dou aula de PIC mas uso assembler, até mesmo por questões didáticas. Sei programar em C, mas ainda não tive tempo para ver isso no PIC (tb gosto mais do assembler, hehehehe)

Pelo programa que vc postou, o tempo entre os passos do motor é feito pela função delay_ms, porém não fica claro como é a temporização do display (intena lib lcd.c). Não me parece motivo suficiente para não funcionar. Talvez o motor ficasse um tempo maior parado enquanto vc escreve no display, pois dessa forma não dá para fazer as duas coisas ao mesmo tempo.

Seria interessante colocar o motor pelo timer. Assim o motor não para e o LCD não deve mostrar muita diferença.

Nesse momento parece que o seu problema é no uso do LCD. Recomendo testar o LCD em separado primeiro.

Com relação ao simulador, esse têm sido um grande problema para mim na sala de aula. Simulador é ambiente controlado. Nem sempre as coisas que funcionam no simulador vão funcionar na prática. Alguns detalhes o simulador pode passar por cima.

Att,

Saulo

MensagemEnviado: 29 Out 2008 15:58
por hsena
Beleza Saulo,
vou tentar colocar pra funcionar o LCD primeiro, e depois integrar como o motor.
Quando terminar os testes volta pra informar o resultado.

Obrigado até agora.

MensagemEnviado: 29 Out 2008 17:57
por Djalma Toledo Rodrigues
saulo.wulhynek escreveu:...tb gosto mais do assembler, hehehehe...


Eu também , eu também.

O Asm tem o 'efeito colateral' de nos obrigar a conhecer bem o uC e o
hardware também.

MensagemEnviado: 29 Out 2008 19:35
por vtrx
O bom do assembler é que se pode implementar praticamente qualquer coisa e não tem como não solucionar um problema(pelo menos pra mim...).

Re: Problema na implementação - PIC 16F877A

MensagemEnviado: 30 Out 2008 15:42
por amboni
olá...
tbm ja tive esse problema... e acabei achando uma rotina no fórum da ccs.. que me vei a calhar... e estou usando ela há alguns meses no meu controlador do ar condicionado aqui da minha sala... ehehe

segueee

Código: Selecionar todos
// flex_lcd.c

// These pins are for the Microchip PicDem2-Plus board,
// which is what I used to test the driver.  Change these
// pins to fit your own board.

/// bla bla bla... interessa esse aqui oh
//************************************************************
//             COMANDOS DO DISPAY LCD - LM016L                   //
//  Não esquecer de include <FLEX_LCD.c>                                         
//  lcd_init()   Inicia LCD, deve se inserido no MAIN()          //
//  lcd_putc(c)  Escreve no display.                             //
//                     Comandos Adicionais ao lcd_putc(c)        //
//                      '\f'  Limpa Display                      //
//                      '\n'  Vai par a segunda linha            //
//                      '\b'  Move back one position             //
//                                                               //
//  lcd_gotoxy(x,y) Posiciona cursor no LCD (x,y)                //
//                                                               //
//  lcd_getc(x,y)   Returns character at position x,y on LCD     //
//************************************************************//

#define LCD_DB4   PIN_B4
#define LCD_DB5   PIN_B5
#define LCD_DB6   PIN_B6
#define LCD_DB7   PIN_B7

#define LCD_E     PIN_B3
#define LCD_RS    PIN_B1
#define LCD_RW    PIN_B2

// If you only want a 6-pin interface to your LCD, then
// connect the R/W pin on the LCD to ground, and comment
// out the following line.

#define USE_LCD_RW   1     

//========================================

#define lcd_type 2        // 0=5x7, 1=5x10, 2=2 lines
#define lcd_line_two 0x40 // LCD RAM address for the 2nd line


int8 const LCD_INIT_STRING[4] =
{
 0x20 | (lcd_type << 2), // Func set: 4-bit, 2 lines, 5x8 dots
 0xc,                    // Display on
 1,                      // Clear display
 6                       // Increment cursor
 };
                             

//-------------------------------------
void lcd_send_nibble(int8 nibble)
{
// Note:  !! converts an integer expression
// to a boolean (1 or 0).
 output_bit(LCD_DB4, !!(nibble & 1));
 output_bit(LCD_DB5, !!(nibble & 2)); 
 output_bit(LCD_DB6, !!(nibble & 4));   
 output_bit(LCD_DB7, !!(nibble & 8));   

 delay_cycles(1);
 output_high(LCD_E);
 delay_us(2);
 output_low(LCD_E);
}

//-----------------------------------
// This sub-routine is only called by lcd_read_byte().
// It's not a stand-alone routine.  For example, the
// R/W signal is set high by lcd_read_byte() before
// this routine is called.     

#ifdef USE_LCD_RW
int8 lcd_read_nibble(void)
{
int8 retval;
// Create bit variables so that we can easily set
// individual bits in the retval variable.
#bit retval_0 = retval.0
#bit retval_1 = retval.1
#bit retval_2 = retval.2
#bit retval_3 = retval.3

retval = 0;
   
output_high(LCD_E);
delay_cycles(1);

retval_0 = input(LCD_DB4);
retval_1 = input(LCD_DB5);
retval_2 = input(LCD_DB6);
retval_3 = input(LCD_DB7);
 
output_low(LCD_E);
   
return(retval);   
}   
#endif

//---------------------------------------
// Read a byte from the LCD and return it.

#ifdef USE_LCD_RW
int8 lcd_read_byte(void)
{
int8 low;
int8 high;

output_high(LCD_RW);
delay_cycles(1);

high = lcd_read_nibble();

low = lcd_read_nibble();

return( (high<<4) | low);
}
#endif

//----------------------------------------
// Send a byte to the LCD.
void lcd_send_byte(int8 address, int8 n)
{
output_low(LCD_RS);

#ifdef USE_LCD_RW
while(bit_test(lcd_read_byte(),7)) ;
#else
delay_us(60); 
#endif

if(address)
   output_high(LCD_RS);
else
   output_low(LCD_RS);
     
 delay_cycles(1);

#ifdef USE_LCD_RW
output_low(LCD_RW);
delay_cycles(1);
#endif

output_low(LCD_E);

lcd_send_nibble(n >> 4);
lcd_send_nibble(n & 0xf);
}

//----------------------------
void lcd_init(void)
{
int8 i;

output_low(LCD_RS);

#ifdef USE_LCD_RW
output_low(LCD_RW);
#endif

output_low(LCD_E);

delay_ms(15);

for(i=0 ;i < 3; i++)
   {
    lcd_send_nibble(0x03);
    delay_ms(5);
   }

lcd_send_nibble(0x02);

for(i=0; i < sizeof(LCD_INIT_STRING); i++)
   {
    lcd_send_byte(0, LCD_INIT_STRING[i]);
   
    // If the R/W signal is not used, then
    // the busy bit can't be polled.  One of
    // the init commands takes longer than
    // the hard-coded delay of 60 us, so in
    // that case, lets just do a 5 ms delay
    // after all four of them.
    #ifndef USE_LCD_RW
    delay_ms(5);
    #endif
   }

}

//----------------------------

void lcd_gotoxy(int8 x, int8 y)
{
int8 address;

if(y != 1)
   address = lcd_line_two;
else
   address=0;

address += x-1;
lcd_send_byte(0, 0x80 | address);
}

//-----------------------------
void lcd_putc(char c)
{
 switch(c)
   {
    case '\f':
      lcd_send_byte(0,1);
      delay_ms(2);
      break;
   
    case '\n':
       lcd_gotoxy(1,2);
       break;
   
    case '\b':
       lcd_send_byte(0,0x10);
       break;
   
    default:
       lcd_send_byte(1,c);
       break;
   }
}

//------------------------------
#ifdef USE_LCD_RW
char lcd_getc(int8 x, int8 y)
{
char value;

lcd_gotoxy(x,y);

// Wait until busy flag is low.
while(bit_test(lcd_read_byte(),7)); 

output_high(LCD_RS);
value = lcd_read_byte();
output_low(lcd_RS);

return(value);
}
#endif


valeu... podeprocurar aqui no forum que tem varios outros drives de displyas da galera...

RESOLVIDO

MensagemEnviado: 01 Nov 2008 16:57
por hsena
oh galera obrigado pela ajuda, conseguir resolver o problema.
A pinagem do LCD não estava correto na minha protoboard e os resistores que coloquei no pino 3 do LCD não deu o brilho correto, então coloquei um potenciômetro de 10K e ficou OK, e em relação a minha rotina que coloque acima, funcionou beleza em conjunto com o motor, sem a necessidade de utilizar o TIMER.

Obrigado a todos, isso que faz esse fórum ser referencia no assunto.