Ir ao conteúdo
  • Cadastre-se

Leitura analogica com PIC e colocar o valor da leitura no display


Ir à solução Resolvido por rodrigocirilo,

Posts recomendados

Ola senhores, gostaria da ajuda de vocês mais uma vez.

Estou tentando fazer o PIC16F877 ler o valor da saida de um acelerometro e jogar no display, isso inicialmente é apenas um teste pata eu ver que estou fazendo tudo certo. porém não sei se não estou fazendo a leitura de forma correta ou se estou errando na hora de colocar o valor direto no LCD.

 

segue codigo simples:

 

#include <16f877a.h>
#device ADC=10
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT,NOBROWNOUT,NOLVP,NOPROTECT
#include "c:\Flex_lcd_16x4_877.c"
 
 
int16 valor; // Variáveis do programa
 
void main()
 
{
 
setup_adc_ports(RA0_RA1_RA3_ANALOG);//Configura como entradas analogicas
setup_adc(ADC_CLOCK_INTERNAL);
 
 
lcd_init();
lcd_putc("Passo 2");
 
while(true)
{
set_adc_channel(0);//prepara o canal 
delay_us(10);//aguarda o tempo de estabilização
valor= read_adc(ADC_READ_ONLY);
 
 
lcd_gotoxy(1,2);
printf(lcd_putc,"Ivan Henrique");
 
lcd_gotoxy(1,3);
printf(lcd_putc,(valor));//PRECISO DO VALOR DA LEITURA AQUIIIIII
 
lcd_gotoxy(1,4);
printf(lcd_putc,"PIC16f877");//16 caracteres dentro das aspas
 
}
}

Tava lendo algo e vi que tenho q mudar a varialvel mas não entendi bem o porque disso.

Link para o comentário
Compartilhar em outros sites

@Ivan (eletronic)

 

Veja:

#include <16F877A.h>#device adc=10  #FUSES NOWDT                    //No Watch Dog Timer#FUSES XT                       //Crystal osc <= 4mhz#FUSES PUT                      //Power Up Timer#FUSES NOPROTECT                //Code not protected from reading#FUSES NODEBUG                  //No Debug mode for ICD#FUSES BROWNOUT                 //Reset when brownout detected#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O#FUSES NOCPD                    //No EE protection #use delay(clock=4000000) #include <lcd.c> int16 q1; int main() {   lcd_init();      setup_adc_ports(AN0);   setup_adc(ADC_CLOCK_DIV_8);     set_adc_channel(0);   delay_us (20);   while (TRUE)    {      q1 = read_adc();            printf (lcd_putc,"\fAD:%ld", q1);      delay_ms (200);   }}      
Link para o comentário
Compartilhar em outros sites

Tentei varias variações de codigos mas nada parece da certo, usando \f nessa biblioteca não fica legal por isso retirei.

 

Ultimo codigo testado abaixo, com este codigo parece tudo bem mas o resultado no display ta estranho o negocio vai inplementando sozinho de 10 em 10 despois decrementa no mesmo ritmo isso sem variação nenhuma na entrada. Fora que mesmo quando você aterra a entrada analogica ele mostra um valor x no display.

 

#include <16f877a.h>
#device adc=10
#use delay(clock=4000000)
#fuses XT,NOWDT,PUT,NOBROWNOUT,NOLVP,NOPROTECT
#include "c:\Flex_lcd_16x4_877.c"
 
 
int16 valor; // Variáveis do programa
 
void main()
 
{
 
setup_adc_ports(AN0_AN1_AN3); // Define as entradas analógicas
setup_adc(ADC_CLOCK_INTERNAL); // Define clock da conversão A/D
 
lcd_init();
lcd_putc("\f");
 
 
while(true)
{
 
set_adc_channel(0);//prepara o canal 
delay_us(20);//aguarda o tempo de estabilização
valor= read_adc();
 
lcd_gotoxy(1,3);
printf(lcd_putc,"AD:%ld",valor);
 
 
delay_ms(200);
 
}
}
Link para o comentário
Compartilhar em outros sites

Primeira pergunta, de qual accel estamos falando? ADXL3x? 


Você tem debug disponível ai? (simulador serve) Proteus? Ou um hard debugger como o PICKIT2? Se sim, uma sugestão é que você cheque o resultado da leitura da variavel valor logo após a conversão antes de enviar ao LCD para ver se a leitura e configuração do A/D está correta.


Aos conhecedores do CCS alguém poderia colocar o protótipo da função printf(); usada no nessa IDE, queria checar uma coisa e no momento estou sem acesso ao site.

Por enquanto é isso :)

Abs.

Felipe

Link para o comentário
Compartilhar em outros sites

Felipe_Eletronic

 

Não entendi sua primeira pergunta, ja quanto a segunda eu não tenho e por algum motivo estranho meu computador não aceita mais a instalação do proteus rsrsrrsrs.

 

 

Talvez você precisa calcular a media dos valores.

Verifique se este link te ajuda:

http://forum.clubedohardware.com.br/forums/topic/1014696-estabilizar-leitura-de-adc/?hl=%2Bleopuena#entry5690442

 

você acha que pode ser alguma coisa na alimentação oou matriz de contatos?

Link para o comentário
Compartilhar em outros sites

 

 

Pode sim,mas é boa pratica fazer a leitura pela media.

Nem sempre, isso depende muito do modelo do sinal a ser tratado, para sensores com função de transferência de baixa largura de banda, a utilização de um filtro como a popular média móvel pode vir a ser útil para deixar "vivo" no resultado do A/D apenas a banda de interesse, porém se a detecção de sinais for por meio de diferenciação (exemplo cáculo da aceleração a partir da derivada de velocidade) usar um filtro de média móvel pode causar um "damp" (amortecimento) excessivo das variações de valores do sinal eliminando inclusive a banda da interesse, e te entregando qualquer coisa no resultado da conversão, menos o valor desejado. Para conversão de dados de um domínio para outro (Analógico -> Digital) ainda uma das  melhores soluções consiste em conhecer o modelo do sinal de entrada, a banda de interesse e se possível um pouco do modelo estatístico dele, e projetar um bom filtro anti-aliasing na entrada para limitar a banda do sinal, e escolher adequadamente, a taxa de amostragem do conversor A/D. Da mais trabalho? Claro que dá, mas o que custa queimar um pouco mais os neurônios no projeto e em caso de bug retirar a conversão do sinal como suspeito de falha. 

Só lembrando, não sou contra o uso de média móvel, só não concordo com a generalização, e que a mesma é adequada para ALGUNS casos bem definidos (sinais quase que estáticos, pouco variam no tempo).

 

@Ivan (eletronic),

 

A minha pergunta se trata em saber qual o modelo do seu acelerômetro, eu suspeito da familia ADXL  que possui algumas particularidades antes de ligar sua saída na entrada do A/D.

Só para fins de debug, experimente conectar um potenciometro ou trimpot na entrada o A/D e o varie lentamente, veja se os valores são condizentes a posição do trimpot, isso pode ajudar a identificar o problema :)

Ah, antes que esqueça, qual a aplicação do acelerômetro(O que deseja calcular/ fazer com ele)?

Abs.

Felipe

Link para o comentário
Compartilhar em outros sites

 

Nem sempre, isso depende muito do modelo do sinal a ser tratado, para sensores com função de transferência de baixa largura de banda, a utilização de um filtro como a popular média móvel pode vir a ser útil para deixar "vivo" no resultado do A/D apenas a banda de interesse, porém se a detecção de sinais for por meio de diferenciação (exemplo cáculo da aceleração a partir da derivada de velocidade) usar um filtro de média móvel pode causar um "damp" (amortecimento) excessivo das variações de valores do sinal eliminando inclusive a banda da interesse, e te entregando qualquer coisa no resultado da conversão, menos o valor desejado. Para conversão de dados de um domínio para outro (Analógico -> Digital) ainda uma das  melhores soluções consiste em conhecer o modelo do sinal de entrada, a banda de interesse e se possível um pouco do modelo estatístico dele, e projetar um bom filtro anti-aliasing na entrada para limitar a banda do sinal, e escolher adequadamente, a taxa de amostragem do conversor A/D. Da mais trabalho? Claro que dá, mas o que custa queimar um pouco mais os neurônios no projeto e em caso de bug retirar a conversão do sinal como suspeito de falha. 

Só lembrando, não sou contra o uso de média móvel, só não concordo com a generalização, e que a mesma é adequada para ALGUNS casos bem definidos (sinais quase que estáticos, pouco variam no tempo).

Para aplicações profissionais é valido .

Creio eu que um 'filtro digital' é mais confiável que um filtro analogico.

PS:Só agora lo que ele esta usando acelerometro...

Link para o comentário
Compartilhar em outros sites

@vtrx

 

 

 

Creio eu que um 'filtro digital' é mais confiável que um filtro analogico

Sem se distanciar muito do foco do tópico, ambos os tipos de filtros tem vantagens mas tem seus males dado a suas naturezas de implementação, o que as vezes me incomoda é o fato que devido ao advento de processadores, com unidades DSP internas, ou mesmo os DSCs com seu elevado desempenho numérico combinado a ferramentas de design, filtro digital ante a um analógico hoje virou uma frase feita, e que os circuitos analógicos baseados em opamps ou mesmo malhas LC ficaram obsoletos. É valido lembrar que filtros digitais são imunes a muita coisa, mas ainda sofrem de dois males que podem mandar sua 'confiabilidade' para o espaço que são quantização e largura de banda bem limitada, e como todo bom filtro pode virar um belo oscilador digital se mal projetado (transformadas Z podem ser mapeadas em funções em S). Acho que existem aplicações bem definidas para cada um deles. O que está se fazendo hoje é a combinação de técnicas analógicas e digitais para projetos de filtros e outros circuitos comuns do domínio analógico.

Dê uma pesquisada por circuitos com capacitores chaveados (ou switching capacitors). 

 

E antes que esqueça, ainda não é possivel filtragem digital de sinais em banda de RF :)

De fato para aplicações profissionais ou não, ser bem feito deve ocorrer em ambos os casos(principalmente no segundo, onde o intuito é aprender), senão compensa comprar pronto... :)

Abs.

Felipe

Link para o comentário
Compartilhar em outros sites

@

 

Aos conhecedores do CCS alguém poderia colocar o protótipo da função printf(); usada no nessa IDE, queria checar uma coisa e no momento estou sem acesso ao site.

 

Não postei antes pois o forum ficou fora do ar um tempão.

 

Bom, quando chamados a função printf, o CCS utiliza a biblioteca LCD.C abaixo. Veja que a função printf chama a função void lcd_putc(char c) localizada na biblioteca mencionada.

 

LCD.C:

 

///////////////////////////////////////////////////////////////////////////////////                             LCD.C                                     ////////                 Driver for common LCD modules                         ////////                                                                       ////////  lcd_init()   Must be called before any other function.               ////////                                                                       ////////  lcd_putc(c)  Will display c on the next position of the LCD.         ////////                 \a  Set cursor position to upper left                 ////////                 \f  Clear display, set cursor to upper left           ////////                 \n  Go to start of second line                        ////////                 \b  Move back one position                            ////////              If LCD_EXTENDED_NEWLINE is defined, the \n character     ////////              will erase all remanining characters on the current      ////////              line, and move the cursor to the beginning of the next   ////////              line.                                                    ////////              If LCD_EXTENDED_NEWLINE is defined, the \r character     ////////              will move the cursor to the start of the current         ////////              line.                                                    ////////                                                                       ////////  lcd_gotoxy(x,y) Set write position on LCD (upper left is 1,1)        ////////                                                                       ////////  lcd_getc(x,y)   Returns character at position x,y on LCD             ////////                                                                       ////////  lcd_cursor_on(int1 on)   Turn the cursor on (on=TRUE) or off         ////////              (on=FALSE).                                              ////////                                                                       ////////  lcd_set_cgram_char(w, *p)   Write a custom character to the CGRAM.   ////////                                                                       ////////                                                                       ////////  CONFIGURATION                                                        ////////  The LCD can be configured in one of two ways: a.) port access or     ////////  b.) pin access.  Port access requires the entire 7 bit interface     ////////  connected to one GPIO port, and the data bits (D4:D7 of the LCD)     ////////  connected to sequential pins on the GPIO.  Pin access                ////////  has no requirements, all 7 bits of the control interface can         ////////  can be connected to any GPIO using several ports.                    ////////                                                                       ////////  To use port access, #define LCD_DATA_PORT to the SFR location of     ////////  of the GPIO port that holds the interface, -AND- edit LCD_PIN_MAP    ////////  of this file to configure the pin order.  If you are using a         ////////  baseline PIC (PCB), then LCD_OUTPUT_MAP and LCD_INPUT_MAP also must  ////////  be defined.                                                          ////////                                                                       ////////  Example of port access:                                              ////////     #define LCD_DATA_PORT getenv("SFR:PORTD")                         ////////                                                                       ////////  To use pin access, the following pins must be defined:               ////////     LCD_ENABLE_PIN                                                    ////////     LCD_RS_PIN                                                        ////////     LCD_RW_PIN                                                        ////////     LCD_DATA4                                                         ////////     LCD_DATA5                                                         ////////     LCD_DATA6                                                         ////////     LCD_DATA7                                                         ////////                                                                       ////////  Example of pin access:                                               ////////     #define LCD_ENABLE_PIN  PIN_E0                                    ////////     #define LCD_RS_PIN      PIN_E1                                    ////////     #define LCD_RW_PIN      PIN_E2                                    ////////     #define LCD_DATA4       PIN_D4                                    ////////     #define LCD_DATA5       PIN_D5                                    ////////     #define LCD_DATA6       PIN_D6                                    ////////     #define LCD_DATA7       PIN_D7                                    ////////                                                                       ///////////////////////////////////////////////////////////////////////////////////////        (C) Copyright 1996,2010 Custom Computer Services           //////// This source code may only be used by licensed users of the CCS C  //////// compiler.  This source code may only be distributed to other      //////// licensed users of the CCS C compiler.  No other use, reproduction //////// or distribution is permitted without written permission.          //////// Derivative programs created using this software in object code    //////// form are not restricted in any way.                               /////////////////////////////////////////////////////////////////////////////// #ifndef __LCD_C__#define __LCD_C__ // define the pinout.// only required if port access is being used.typedef struct  {                            // This structure is overlayed   int1 enable;           // on to an I/O port to gain   int1 rs;               // access to the LCD pins.   int1 rw;               // The bits are allocated from   int1 unused;           // low order up.  ENABLE will   unsigned int     data : 4;         // be LSB pin of that port.  #if defined(__PCD__)       // The port used will be LCD_DATA_PORT.   unsigned int    reserved: 8;  #endif} LCD_PIN_MAP; // this is to improve compatability with previous LCD drivers that accepted// a define labeled 'use_portb_lcd' that configured the LCD onto port B.#if ((defined(use_portb_lcd)) && (use_portb_lcd==TRUE)) #define LCD_DATA_PORT getenv("SFR:PORTB")#endif #if defined(__PCB__)   // these definitions only need to be modified for baseline PICs.   // all other PICs use LCD_PIN_MAP or individual LCD_xxx pin definitions./*                                    EN, RS,   RW,   UNUSED,  DATA  */ const LCD_PIN_MAP LCD_OUTPUT_MAP =  {0,  0,    0,    0,       0}; const LCD_PIN_MAP LCD_INPUT_MAP =   {0,  0,    0,    0,       0xF};#endif ////////////////////// END CONFIGURATION /////////////////////////////////// #ifndef LCD_ENABLE_PIN   #define lcd_output_enable(x) lcdlat.enable=x   #define lcd_enable_tris()   lcdtris.enable=0#else   #define lcd_output_enable(x) output_bit(LCD_ENABLE_PIN, x)   #define lcd_enable_tris()  output_drive(LCD_ENABLE_PIN)#endif #ifndef LCD_RS_PIN   #define lcd_output_rs(x) lcdlat.rs=x   #define lcd_rs_tris()   lcdtris.rs=0#else   #define lcd_output_rs(x) output_bit(LCD_RS_PIN, x)   #define lcd_rs_tris()  output_drive(LCD_RS_PIN)#endif #ifndef LCD_RW_PIN   #define lcd_output_rw(x) lcdlat.rw=x   #define lcd_rw_tris()   lcdtris.rw=0#else   #define lcd_output_rw(x) output_bit(LCD_RW_PIN, x)   #define lcd_rw_tris()  output_drive(LCD_RW_PIN)#endif // original version of this library incorrectly labeled LCD_DATA0 as LCD_DATA4,// LCD_DATA1 as LCD_DATA5, and so on.  this block of code makes the driver// compatible with any code written for the original library#if (defined(LCD_DATA0) && defined(LCD_DATA1) && defined(LCD_DATA2) && defined(LCD_DATA3) && !defined(LCD_DATA4) && !defined(LCD_DATA5) && !defined(LCD_DATA6) && !defined(LCD_DATA7))   #define  LCD_DATA4    LCD_DATA0   #define  LCD_DATA5    LCD_DATA1   #define  LCD_DATA6    LCD_DATA2   #define  LCD_DATA7    LCD_DATA3#endif #ifndef LCD_DATA4#ifndef LCD_DATA_PORT   #if defined(__PCB__)      #define LCD_DATA_PORT      0x06     //portb      #define set_tris_lcd(x)   set_tris_b(x)   #else     #if defined(PIN_D0)      #define LCD_DATA_PORT      getenv("SFR:PORTD")     //portd     #else      #define LCD_DATA_PORT      getenv("SFR:PORTB")     //portb     #endif   #endif   #endif #if defined(__PCB__)   LCD_PIN_MAP lcd, lcdlat;   #byte lcd = LCD_DATA_PORT   #byte lcdlat = LCD_DATA_PORT#elif defined(__PCM__)   LCD_PIN_MAP lcd, lcdlat, lcdtris;   #byte lcd = LCD_DATA_PORT   #byte lcdlat = LCD_DATA_PORT   #byte lcdtris = LCD_DATA_PORT+0x80#elif defined(__PCH__)   LCD_PIN_MAP lcd, lcdlat, lcdtris;   #byte lcd = LCD_DATA_PORT   #byte lcdlat = LCD_DATA_PORT+9   #byte lcdtris = LCD_DATA_PORT+0x12#elif defined(__PCD__)   LCD_PIN_MAP lcd, lcdlat, lcdtris;   #word lcd = LCD_DATA_PORT   #word lcdlat = LCD_DATA_PORT+2   #word lcdtris = LCD_DATA_PORT-0x02#endif#endif   //LCD_DATA4 not defined #ifndef LCD_TYPE   #define LCD_TYPE 2           // 0=5x7, 1=5x10, 2=2 lines#endif #ifndef LCD_LINE_TWO   #define LCD_LINE_TWO 0x40    // LCD RAM address for the second line#endif #ifndef LCD_LINE_LENGTH   #define LCD_LINE_LENGTH 20#endif unsigned int8 lcd_read_nibble(void); unsigned int8 lcd_read_byte(void){   unsigned int8 low,high;  #if defined(__PCB__)   set_tris_lcd(LCD_INPUT_MAP); #else  #if (defined(LCD_DATA4) && defined(LCD_DATA5) && defined(LCD_DATA6) && defined(LCD_DATA7))   output_float(LCD_DATA4);   output_float(LCD_DATA5);   output_float(LCD_DATA6);   output_float(LCD_DATA7);  #else   lcdtris.data = 0xF;  #endif #endif           lcd_output_rw(1);   delay_cycles(1);   lcd_output_enable(1);   delay_cycles(1);   high = lcd_read_nibble();         lcd_output_enable(0);   delay_cycles(1);   lcd_output_enable(1);   delay_us(1);   low = lcd_read_nibble();         lcd_output_enable(0);  #if defined(__PCB__)   set_tris_lcd(LCD_OUTPUT_MAP); #else  #if (defined(LCD_DATA4) && defined(LCD_DATA5) && defined(LCD_DATA6) && defined(LCD_DATA7))   output_drive(LCD_DATA4);   output_drive(LCD_DATA5);   output_drive(LCD_DATA6);   output_drive(LCD_DATA7);  #else   lcdtris.data = 0x0;  #endif #endif    return( (high<<4) | low);} unsigned int8 lcd_read_nibble(void){  #if (defined(LCD_DATA4) && defined(LCD_DATA5) && defined(LCD_DATA6) && defined(LCD_DATA7))   unsigned int8 n = 0x00;    /* Read the data port */   n |= input(LCD_DATA4);   n |= input(LCD_DATA5) << 1;   n |= input(LCD_DATA6) << 2;   n |= input(LCD_DATA7) << 3;      return(n);  #else   return(lcd.data);  #endif} void lcd_send_nibble(unsigned int8 n){  #if (defined(LCD_DATA4) && defined(LCD_DATA5) && defined(LCD_DATA6) && defined(LCD_DATA7))   /* Write to the data port */   output_bit(LCD_DATA4, bit_test(n, 0));   output_bit(LCD_DATA5, bit_test(n, 1));   output_bit(LCD_DATA6, bit_test(n, 2));   output_bit(LCD_DATA7, bit_test(n, 3));  #else         lcdlat.data = n;  #endif         delay_cycles(1);   lcd_output_enable(1);   delay_us(2);   lcd_output_enable(0);} void lcd_send_byte(unsigned int8 address, unsigned int8 n){  #if defined(__PCB__)   set_tris_lcd(LCD_OUTPUT_MAP);  #else   lcd_enable_tris();   lcd_rs_tris();   lcd_rw_tris();  #endif    lcd_output_rs(0);   while ( bit_test(lcd_read_byte(),7) ) ;   lcd_output_rs(address);   delay_cycles(1);   lcd_output_rw(0);   delay_cycles(1);   lcd_output_enable(0);   lcd_send_nibble(n >> 4);   lcd_send_nibble(n & 0xf);} #if defined(LCD_EXTENDED_NEWLINE)unsigned int8 g_LcdX, g_LcdY;#endif void lcd_init(void) {   unsigned int8 i;   unsigned int8 LCD_INIT_STRING[4] = {0x20 | (LCD_TYPE << 2), 0xc, 1, 6};                             // These bytes need to be sent to the LCD                             // to start it up.       lcd_output_enable(0);   lcd_output_rs(0);   lcd_output_rw(0);  #if defined(__PCB__)   set_tris_lcd(LCD_OUTPUT_MAP); #else  #if (defined(LCD_DATA4) && defined(LCD_DATA5) && defined(LCD_DATA6) && defined(LCD_DATA7))   output_drive(LCD_DATA4);   output_drive(LCD_DATA5);   output_drive(LCD_DATA6);   output_drive(LCD_DATA7);  #else   lcdtris.data = 0x0;  #endif   lcd_enable_tris();   lcd_rs_tris();   lcd_rw_tris(); #endif       delay_ms(15);   for(i=1;i<=3;++i)   {       lcd_send_nibble(3);       delay_ms(5);   }      lcd_send_nibble(2);   delay_ms(5);   for(i=0;i<=3;++i)      lcd_send_byte(0,LCD_INIT_STRING[i]);   #if defined(LCD_EXTENDED_NEWLINE)   g_LcdX = 0;   g_LcdY = 0;  #endif} void lcd_gotoxy(unsigned int8 x, unsigned int8 y){   unsigned int8 address;      if(y!=1)      address=LCD_LINE_TWO;   else      address=0;        address+=x-1;   lcd_send_byte(0,0x80|address);   #if defined(LCD_EXTENDED_NEWLINE)   g_LcdX = x - 1;   g_LcdY = y - 1;  #endif} void lcd_putc(char c){   switch (c)   {      case '\a'   :  lcd_gotoxy(1,1);     break;       case '\f'   :  lcd_send_byte(0,1);                     delay_ms(2);                    #if defined(LCD_EXTENDED_NEWLINE)                     g_LcdX = 0;                     g_LcdY = 0;                    #endif                     break;      #if defined(LCD_EXTENDED_NEWLINE)      case '\r'   :  lcd_gotoxy(1, g_LcdY+1);   break;      case '\n'   :         while (g_LcdX++ < LCD_LINE_LENGTH)         {            lcd_send_byte(1, ' ');         }         lcd_gotoxy(1, g_LcdY+2);         break;     #else      case '\n'   : lcd_gotoxy(1,2);        break;     #endif           case '\b'   : lcd_send_byte(0,0x10);  break;          #if defined(LCD_EXTENDED_NEWLINE)      default     :          if (g_LcdX < LCD_LINE_LENGTH)         {            lcd_send_byte(1, c);            g_LcdX++;         }         break;     #else      default     : lcd_send_byte(1,c);     break;     #endif   }} char lcd_getc(unsigned int8 x, unsigned int8 y){   char value;    lcd_gotoxy(x,y);   while ( bit_test(lcd_read_byte(),7) ); // wait until busy flag is low   lcd_output_rs(1);   value = lcd_read_byte();   lcd_output_rs(0);      return(value);} // write a custom character to the ram// which is 0-7 and specifies which character array we are modifying.// ptr points to an array of 8 bytes, where each byte is the next row of//    pixels.  only bits 0-4 are used.  the last row is the cursor row, and//    usually you will want to leave this byte 0x00.void lcd_set_cgram_char(unsigned int8 which, unsigned int8 *ptr){   unsigned int i;    which <<= 3;   which &= 0x38;    lcd_send_byte(0, 0x40 | which);  //set cgram address    for(i=0; i<8; i++)   {      lcd_send_byte(1, *ptr++);   }     #if defined(LCD_EXTENDED_NEWLINE)    lcd_gotoxy(g_LcdX+1, g_LcdY+1);  //set ddram address   #endif} void lcd_cursor_on(int1 on){   if (on)   {      lcd_send_byte(0,0x0F);           //turn LCD cursor ON   }   else   {      lcd_send_byte(0,0x0C);           //turn LCD cursor OFF   }} #endif

Link para o comentário
Compartilhar em outros sites

To usando o MMA7361 como sensor, ele sera usado para detectar a inclinação de determinada estrutura de um projetando em andamento.

 

O problema esta ai, eu ja troquei a fonte de alimentação por uma mais estavel. Agora to usando uma fonte ajustavel da Agilent e ja retirei o sensor e coloquei pot e ate uma outra fonte ajustavel com intuito de verificar uma possivel incompatibilidade entre o acelerometro e o PIC. Entretanto o resultado foi o mesmo, e quanto mais pesquiso menos entendo o porque esta dando errado o codigo.

 

Não sei se muda muito mas a biblioteca que estou usando para o LCD é a seguinte:

 

 
// Flex_LCD416.c 
// Mude os pinos abaixo conforme pinagem do seu projeto
 
#define LCD_DB4   PIN_B4 
#define LCD_DB5   PIN_B5 
#define LCD_DB6   PIN_B6 
#define LCD_DB7   PIN_B7 
 
#define LCD_RS    PIN_B1 
#define LCD_RW    PIN_B2 
#define LCD_E     PIN_B3 
 
#define USE_RW_PIN   1      
 
// Estes são os endereços de linha para a maioria dos LCDs 4x16. 
#define LCD_LINE_1_ADDRESS 0x00 
#define LCD_LINE_2_ADDRESS 0x40 
#define LCD_LINE_3_ADDRESS 0x10 
#define LCD_LINE_4_ADDRESS 0x50 
 
//======================================== 
 
#define lcd_type 2   // 0=5x7, 1=5x10, 2=2 lines(or more) 
 
int8 lcd_line; 
 
int8 const LCD_INIT_STRING[4] = 
 0x20 | (lcd_type << 2),  // Set mode: 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); 
 
//----------------------------------- 
// Esta sub-rotina só é chamada pela lcd_read_byte().
// Ela não é uma sub-rotina isolada.  Por exemplo, o pino
// R/W é setado high pelo lcd_read_byte() antes de chamar
// esta sub-routina.
 
#ifdef USE_RW_PIN 
int8 lcd_read_nibble(void) 
int8 retval; 
// Cria bit variaveis que podem ser facilmente modificados
// bits individuaisna variavel retval.
#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_us(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); 
delay_us(1); 
    
return(retval);    
}    
#endif 
 
//--------------------------------------- 
// Lê um byte do LCD e retorna seu valor. 
 
#ifdef USE_RW_PIN 
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 
 
//---------------------------------------- 
//Envia um byte para o LCD. 
void lcd_send_byte(int8 address, int8 n) 
output_low(LCD_RS); 
 
#ifdef USE_RW_PIN 
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_RW_PIN 
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; 
 
lcd_line = 1; 
 
output_low(LCD_RS); 
 
#ifdef USE_RW_PIN 
output_low(LCD_RW); 
#endif 
 
output_low(LCD_E); 
 
 // Alguns LCDs exigem 15 ms de atraso mínimo após ligado.
 // Outros exigem 30 ms. Vou configurá-lo para 35 ms.
 // por isso deve trabalhar com todas elas.
 
delay_ms(35);          
 
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]); 
    
    // Se o pino R/W não é usado, então o bit busy bit não pode ser setado. Um dos
    // comandos init deve demorar mais do que a espera de 50 us, nesse
    // caso, devemos fazer uma espera de 5 ms depois de todos os 4. 
    
    #ifndef USE_RW_PIN 
        delay_ms(5); 
    #endif 
   } 
 
 
//---------------------------- 
 
void lcd_gotoxy(int8 x, int8 y) 
int8 address; 
 
 
switch(y) 
  { 
   case 1: 
     address = LCD_LINE_1_ADDRESS; 
     break; 
 
   case 2: 
     address = LCD_LINE_2_ADDRESS; 
     break; 
 
   case 3: 
     address = LCD_LINE_3_ADDRESS; 
     break; 
 
   case 4: 
     address = LCD_LINE_4_ADDRESS; 
     break; 
 
   default: 
     address = LCD_LINE_1_ADDRESS; 
     break; 
      
  } 
 
address += x-1; 
lcd_send_byte(0, 0x80 | address); 
 
//----------------------------- 
void lcd_putc(char c) 
 switch© 
   { 
    case '\f': 
      lcd_send_byte(0,1); 
      lcd_line = 1; 
      delay_ms(2); 
      break; 
    
    case '\n': 
       lcd_gotoxy(1, ++lcd_line); 
       break; 
    
    case '\b': 
       lcd_send_byte(0,0x10); 
       break; 
    
    default: 
       lcd_send_byte(1,c); 
       break; 
   } 
 
//------------------------------ 
#ifdef USE_RW_PIN 
char lcd_getc(int8 x, int8 y) 
char value; 
 
lcd_gotoxy(x,y); 
 
// Espera a FLAG de busy flag estar low.
while(bit_test(lcd_read_byte(),7));  
 
output_high(LCD_RS); 
value = lcd_read_byte(); 
output_low(LCD_RS); 
 
return(value); 
#endif 
[/code][/spoiler]
Link para o comentário
Compartilhar em outros sites

@Ivan (eletronic)

 

Primeiro, antes de tudo. Quando for colocar um código aqui no forum, utilize as tags

  seu código aqui [.code]. Substitua o ponto por barra.

 

Isso deixa o código mais fácil de ler, mantém sua formatação (indentaçao) e fica mais bonito.

 

Outra coisa. Quando postar um código grande, como a biblioteca LCD acima, tente colocar além das tags [code]. As tags [spoiler]. Isso colocará um botão para que possamos mostrar o código só quando necessário. Se o código é muito grande, demos que dar muito scrool na tela e fica chato.

 

Resumindo, se o código for muito grande, fica:

 

[spoiler][code] seu código aqui [.code][.spoiler]. Sbstitua os pontos(.) por barra (/).

 

 

 

 

Voltando ao assunto do tópico. você disse:

 

 

Agora to usando uma fonte ajustavel da Agilent e ja retirei o sensor e coloquei pot e ate uma outra fonte ajustavel com intuito de verificar uma possivel incompatibilidade entre o acelerometro e o PIC. Entretanto o resultado foi o mesmo,

 

Bom, você disse que trocou de fonte, colocou potenciômetro no lugar e o resultado foi o mesmo. Mas você não especificou qual resultado foi o mesmo.

 

você trocou a fonte e usou o acelelômetro de novo e o erro continua ou você trocou a fonte, colocou o potenciômetro e mesmo com ele, o pot, o erro continua?

 

Falou

Link para o comentário
Compartilhar em outros sites

@Ivan (eletronic)

 

Primeiro, antes de tudo. Quando for colocar um código aqui no forum, utilize as tags

  seu código aqui [.code]. Substitua o ponto por barra.

 

Isso deixa o código mais fácil de ler, mantém sua formatação (indentaçao) e fica mais bonito.

 

Outra coisa. Quando postar um código grande, como a biblioteca LCD acima, tente colocar além das tags [code=auto:0]. As tags [spoiler]. Isso colocará um botão para que possamos mostrar o código só quando necessário. Se o código é muito grande, demos que dar muito scrool na tela e fica chato. Resumindo, se o código for muito grande, fica: [spoiler][code=auto:0] seu código aqui [.code][.spoiler]. Sbstitua os pontos(.) por barra (/).  

Como  pode ver no post 13, eu tentei fazer o que você mencionou aparentemente isso não deu certo. Ou fiz algo errado?

 

Bom, você disse que trocou de fonte, colocou potenciômetro no lugar e o resultado foi o mesmo. Mas você não especificou qual resultado foi o mesmo.

 

você trocou a fonte e usou o acelelômetro de novo e o erro continua ou você trocou a fonte, colocou o potenciômetro e mesmo com ele, o pot, o erro continua?

 

O resultado é uma contagem louca, sem nexo nenhum que em determinado momento apareceu o valor de 2900 no display.

Eu troquei a fonte de alimentação por uma mais estavel, e nada adiantou então tentei colocar no lugar do acelerometro um pot e o problema se mantem.

Link para o comentário
Compartilhar em outros sites

@Ivan (eletronic)

 

Sobre o problema das tags, deixo na mão de algum moderador poder ver o que está ocorrendo, @Bcpetronzio

 

Se mesmo com o potenciômetro ocorre isso, pode ser mau contato na sua protoboard.

 

Se você está utilizando o código básico que você postou lá em cima, não poderia, nunca aparecer o valor de 2900 com o potenciômetro. Nem com o acelerômetro. O ADC é limitado em 10 bits. Por isso, o número limite que aparece é 1024.

 

Veja o seu código com um mudança mínima:

 

#include <16f877a.h>#device adc=10#use delay(clock=4000000)#fuses XT,NOWDT,PUT,NOBROWNOUT,NOLVP,NOPROTECT#include "c:\Flex_lcd_16x4_877.c"  int16 valor; // Variáveis do programa void main(){ setup_adc_ports(AN0_AN1_AN3); // Define as entradas analógicassetup_adc(ADC_CLOCK_DIV_8); // Define clock da conversão A/D lcd_init();lcd_putc("\f"); set_adc_channel(0);//prepara o canal delay_us(20);//aguarda o tempo de estabilização  while(true){valor = read_adc();  printf(lcd_putc,"\fAD:%ld",valor);  delay_ms(200); }}
Link para o comentário
Compartilhar em outros sites

Uma pergunta besta que eu gostaria de fazer:

"Checou se o potenciometro ou acelerometro estão ligados na entrada analógica correspondente ao canal que esta a ler?"

Por exemplo na função:
 

 

set_adc_channel(0);

Nessa função você irá configurar o MUX interno do A/D para ler o canal analógico zero, que corresponde ao terminal do PIC chamado de AN0, comumente nos PIC16 de 40 terminais o AN0 está no mesmo terminal chamado de RA0.

Estou desconfiando que voce esta a ler um canal analógico mas que o trimpot está em outro terminal do PIC e resulta nessa leitura estranha (como se o terminal nao estivesse ligado em nada).

No código do @Matheus_LPS a conversão deveria funcionar perfeitamente SE e somente SE o potenciometro estiver ligado no terminal RA0/AN0, que se bem me lembro no 877A deve ser o pino 2.

Boa sorte, :)

Felipe

Link para o comentário
Compartilhar em outros sites

Bom senhores consegui upar um video, porém consegui corrigir um erro mas agora esta assim:

 

 

com usando trimpot.

 

e Matheus eu ja tentei esse codigo e um dos prblemas dele é o seguinte termo:

 

printf(lcd_putc,"\fAD:%ld",valor);

 

onde o \f limpa o display a todo momento o que gera grande desconforto 

Link para o comentário
Compartilhar em outros sites

Ivan coloquei assim

printf(lcd_putc,"\ AD:%04Ld",valor);

o que eu vi que ocorreu neste video é que quando o valor do AD cai abaixo de 1000 ( 4 digitos) ele mantem o ultimo digito por isso que parece que o numero tem 4 digitos, mas não tem, tem só os 3 primeiros. com a adição do numero 04 entre % e Ld você diz que o numero tem que ter 4 digitos então ele vai mante o numero exibido corretamente na tela.. sem precisar ficar limpando o lcd o tempo todo.

 

testa ai...

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

@rodrigocirilo

 

Eu tinha pensado nisso. Por isso coloquei o \f. Justamente para limpar o display e ele não manter caracters da última escrita.

 

@Ivan (eletronic)

 

Realmente quando se usa o \f, ele pode piscar, desde que o tempo seja baixo. Como há um delay de 200 ms entre cada leitura/escrita, imaginei que não ocorreria isso.

 

Sobre a pergunta do @, vale a pena conferir. Mas acho difícil você ter colocado no pino errado.

 

Bem possível ser o que o colega @rodrigocirilo disse.

 

Aí, depois de ter colocado para funcionar com o potenciômetro. Ligue seu acelerômetro de novo e continua o desenvolvimento de sua aplicação.

 

Normalmente é assim mesmo. Damos 3 passos para trás para encontrar um erro. Mas é a forma mais fácil de encontrar o mesmo. Utiliza-se de um programa básico e hardware mais básico ainda. E vai aumentando a complexidade até encontrar o erro. 

 

Falou

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

O amigo @Matheus_LPS está correto, e a observação do @rodrigocirilo também é pertinente.

Uma outra abordagem pra validar se a conversão A/D está correta, seria transmitir diretamente a variável "valor" pela porta serial e exibir em um terminal num PC e observar se o valor que chega é condizente com a posição do potenciômetro, com isso elimina - se de vez a desconfiança do canal A/D.

Boa sorte.

Felipe.

Link para o comentário
Compartilhar em outros sites

printf(lcd_putc,"\ AD:%04Ld",valor);

 

O funcionou finalmente tanto com o pot qto com o acelerometro. Mas como estou a aprender muito nesse topico peço a gentileza dos colegas que puderem me explicar o que esse termo faz:

 

"\fAD:%04ld"

 

aprendi aqui que o "\f" limpa o display, 

também que o 04 é digamos a quantidade de digitos mas o que é o ld?

 

Outra coisa, como posso tentar estabilizar um pouco mais a conversão de forma a deixar """mais preciso""".

 

Desde ja agradeço o auxilio de todos

O amigo @Matheus_LPS está correto, e a observação do @rodrigocirilo também é pertinente.

Uma outra abordagem pra validar se a conversão A/D está correta, seria transmitir diretamente a variável "valor" pela porta serial e exibir em um terminal num PC e observar se o valor que chega é condizente com a posição do potenciômetro, com isso elimina - se de vez a desconfiança do canal A/D.

Boa sorte.

Felipe.

Pretendo fazer algo parecido com isso mais essa é uma outra luta  rsrrsrsrsrsrs

Link para o comentário
Compartilhar em outros sites

  • Solução

Que bom que deu certo, o Ld significa que você quer exibir uma variavel do tipo  Long Signed Int veja a tabela abaixo

 

Formato de string Tipo de dado a ser enviado
%c                            Caractere
%s                            String
%u                            Unsigned int
%d                            Signed int
%Lu                          Long unsigned int
%Ld                          Long signed int   --- A sua é essa pois usa uma variavel do tipo int16
%x                            Hexadecimal (por exemplo: ab)
%X                            Hexadecimal (por exemplo: AB)
%Lx                          Long Hexadecimal (por exemplo: abcd)
%LX                         Long Hexadecimal (por exemplo: ABCD)
%f                            Float (ponto flutuante com decimais truncados)
%g                           Float (ponto flutuante com decimais arredondados)
%e                           Float no formato exponencial
%w                           Unsigned int com ponto decimal especificado
 
 
se quisesse exibir um numero com virgula tipo 1.20 usaria assim por exemplo AD=%f, variavel
  • Curtir 1
Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

Ebook grátis: Aprenda a ler resistores e capacitores!

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!