Problema na implementação - PIC 16F877A

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Problema na implementação - PIC 16F877A

Mensagempor hsena » 29 Out 2008 09:57

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.
hsena
Bit
 
Mensagens: 7
Registrado em: 08 Ago 2008 13:14

Mensagempor Djalma Toledo Rodrigues » 29 Out 2008 10:39

Remova o contrôle do motor de passo e teste o LCD enviando uma mensagem qualquer.

Funcionou ?
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor hsena » 29 Out 2008 12:48

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.
hsena
Bit
 
Mensagens: 7
Registrado em: 08 Ago 2008 13:14

Mensagempor saulo.wulhynek » 29 Out 2008 12:59

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
Saulo Wulhynek
http://saulo.890m.com
saulo.wulhynek
 
Mensagens: 2
Registrado em: 03 Jul 2008 19:48

Mensagempor hsena » 29 Out 2008 13:34

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
hsena
Bit
 
Mensagens: 7
Registrado em: 08 Ago 2008 13:14

Mensagempor hsena » 29 Out 2008 13:52

Aqui está o circuito que estou testando:
http://hsena.files.wordpress.com/2008/10/layout_circuito.jpg
hsena
Bit
 
Mensagens: 7
Registrado em: 08 Ago 2008 13:14

Mensagempor saulo.wulhynek » 29 Out 2008 15:29

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
Saulo Wulhynek
http://saulo.890m.com
saulo.wulhynek
 
Mensagens: 2
Registrado em: 03 Jul 2008 19:48

Mensagempor hsena » 29 Out 2008 15:58

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.
hsena
Bit
 
Mensagens: 7
Registrado em: 08 Ago 2008 13:14

Mensagempor Djalma Toledo Rodrigues » 29 Out 2008 17:57

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.
Avatar do usuário
Djalma Toledo Rodrigues
Dword
 
Mensagens: 2334
Registrado em: 03 Ago 2008 13:22

Mensagempor vtrx » 29 Out 2008 19:35

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...).
Avatar do usuário
vtrx
Dword
 
Mensagens: 2240
Registrado em: 20 Abr 2008 21:01

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

Mensagempor amboni » 30 Out 2008 15:42

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...
amboni
Nibble
 
Mensagens: 50
Registrado em: 23 Abr 2008 08:26
Localização: Içara - SC

RESOLVIDO

Mensagempor hsena » 01 Nov 2008 16:57

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.
hsena
Bit
 
Mensagens: 7
Registrado em: 08 Ago 2008 13:14


Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x