snis Posted April 5, 2012 at 04:21 PM Report #447806 Posted April 5, 2012 at 04:21 PM // Lcd pinout settings sbit LCD_RS at RB0_bit; sbit LCD_EN at RB1_bit; sbit LCD_D4 at RB2_bit; sbit LCD_D5 at RB3_bit; sbit LCD_D6 at RB4_bit; sbit LCD_D7 at RB5_bit; // Pin direction sbit LCD_RS_Direction at TRISB0_bit; sbit LCD_EN_Direction at TRISB1_bit; sbit LCD_D4_Direction at TRISB2_bit; sbit LCD_D5_Direction at TRISB3_bit; sbit LCD_D6_Direction at TRISB4_bit; sbit LCD_D7_Direction at TRISB5_bit; char *test = "Hello LCD"; unsigned int adc_rd; unsigned long u; unsigned char ch; void main() { ADCON1 = 0x009f; trisa = 0XFF; // portA input trisd = 0; // todas portas D output trisb = 0; // todas portas B output Lcd_Init(); Lcd_Cmd(_Lcd_CLEAR); Lcd_Cmd(_Lcd_CURSOR_OFF); Lcd_Out(1, 1, "OLA"); Lcd_Out(2, 1, "Benvindo"); delay_ms(2000); UART1_Init(9600); UART1_Write_text("Ola\r"); while(1) { adc_rd = adc_read(0); // ler valor mv do lm35 u = (long)adc_rd * 5000; // converter mv u = u / 1023 - 40; // 0..1023 -> 0-5000 mv ch = u/1000; // tirar digitol em volt // caracter ascii UART1_Write_text(48+u); UART1_Write_text("\r"); Lcd_Out(2, 1, 48+u); delay_ms(500); } } estou com o problema que , apenas consigo ler caracteres , aumento a temp e muda de caracter.. alguma ajuda' ?
bsccara Posted April 5, 2012 at 05:26 PM Report #447818 Posted April 5, 2012 at 05:26 PM A linguagem C não converte directamente caracteres em strings. Uma string (em C) é um conjunto de caracteres com um zero no final. Na tua chamada UART1_Write_text(48+u); estás a usar um 'unsigned long' (u+48) como sendo um ponteiro. O compilador deve-te dar um aviso por isso. Tens de declarar um array de caracteres com tamanho suficiente. Se tens a garantia que 'u' só vai variar entre 0 e 5 (1 digito) podes fazer : char valor[2]; valor[1] = 48 + u; valor[2] = 0; UART1_Write_text(valor);
snis Posted April 5, 2012 at 06:13 PM Author Report #447830 Posted April 5, 2012 at 06:13 PM mesmo que use apenas UART1_Write_text(u); deveria dar um valor lido em lm35 em RA0. desta forma nem dá nada sabes dizer me se adcon1 está bem configurado para ler do lm35? datasheet: http://ww1.microchip.com/downloads/en/devicedoc/39582b.pdf
bsccara Posted April 5, 2012 at 07:36 PM Report #447849 Posted April 5, 2012 at 07:36 PM mesmo que use apenas UART1_Write_text(u); deveria dar um valor lido em lm35 em RA0. Não estás a perceber: se usas a função assim 'UART1_Write_text("Ola\r")' significa que a função estará declarada como 'UART1_Write_text(char *)', o que significa que está à espera dum ponteiro para uma string terminada a zero como argumento. Quando lhe passas 'u' ou 'u + 48' estás a forçar o compilador a fazer uma conversão dum 'unsigned long' para um 'char *', ou seja a usar o valor da expressão como um ponteiro (endereço) para a string. Isso não funciona, pois o ponteiro passado assim provavelmente aponta para o início da memória do PIC. sabes dizer me se adcon1 está bem configurado para ler do lm35? Não me parece: 0x9F no ADCON1 significa: Bit 7 = 1 (ADFM Right justified) 0 (ADCS2 off) 0 (Não implementado) 1 (Não implementado, bit inválido) 1 | (Entrada analógica no AN0, todas outras AN como digitais, 1 | Vref+ no AN3 e Vref- no AN2) 1 | Bit 0 = 1 | Como não tens nada ligado ao AN3 e AN2 não vais ter tensão de referência para o ADC. Para além disso não estás a inicializar o ADCON0, que fica com os valores de power-on, o que desliga o ADC. Acho que devias inicializar os dois assim: ADCON0 = 0x81; ADCON1 = 0xCE; para um clock do ADC de Fosc / 64. Isso partindo do principio que o preprocessador transforma isto em instruções para configurar os registos (0x9F é o endereço do ADCON1 no PIC). Para além disso o LM35 dá-te cerca de 250mV para uma temperatura de 25C, ou seja com os teus cálculos nunca vais passar de zero. Vê : Escala máxima do ADC = Vcc=5V ADC(5V) = 1023 ADC(250mv) = 51 (51 * 5000 / 1023 - 40) / 1000 = 0.21 ch = 0 A divisão por mil está a mais e o código para mostrar no LCD e enviar pela UART tem de lidar com números de mais dígitos. Também não percebo o -40. No site existe um Zip com exemplos, incluindo com o LM35: http://www.mikroe.com/eng/downloads/get/1708/easypic_v7_examples_v100.zip
snis Posted April 5, 2012 at 10:03 PM Author Report #447872 Posted April 5, 2012 at 10:03 PM Antes de mais, um muito obrigado. Neste momento nao posso testar. Assim que puder dou noticias xxxxxxxxxxxxx EDIT xxxxxxxxxxxxxxxxxxxx com a tua ajuda e dos exemplos que me deste, consegui chegar a qualquer coisa. // Lcd pinout settings sbit LCD_RS at RB0_bit; sbit LCD_EN at RB1_bit; sbit LCD_D4 at RB2_bit; sbit LCD_D5 at RB3_bit; sbit LCD_D6 at RB4_bit; sbit LCD_D7 at RB5_bit; // Pin direction sbit LCD_RS_Direction at TRISB0_bit; sbit LCD_EN_Direction at TRISB1_bit; sbit LCD_D4_Direction at TRISB2_bit; sbit LCD_D5_Direction at TRISB3_bit; sbit LCD_D6_Direction at TRISB4_bit; sbit LCD_D7_Direction at TRISB5_bit; char *test = "Hello LCD"; const unsigned short VREF = 5; unsigned int adc_rd = 0; float temp; char txt[15]; void main() { ADCON0 = 0x81; ADCON1 = 0xCE; trisa = 0XFF; // portA input trisd = 0; // todas portas D output trisb = 0; // todas portas B output adc_init(); Lcd_Init(); Lcd_Cmd(_Lcd_CLEAR); Lcd_Cmd(_Lcd_CURSOR_OFF); Lcd_Out(1, 1, "Temperatura"); Lcd_Chr(2, 8, 223); Lcd_Chr(2,9,'C'); delay_ms(2000); UART1_Init(9600); UART1_Write_text("Temperatura:\r"); adc_rd = 0; while(1) { adc_rd = ADC_Get_Sample(0); temp = (adc_rd * VREF)/10.240; floatToStr(temp, txt); txt[4] =0; UART1_Write_text(txt); UART1_Write_text("\r"); Lcd_Out(2, 3, txt); delay_ms(500); } }
snis Posted April 13, 2012 at 10:33 AM Author Report #448916 Posted April 13, 2012 at 10:33 AM boas, estou com problemas em por uma fan funcionar conforme o valor de temperatura // Lcd pinout definições sbit LCD_RS at RB0_bit; sbit LCD_EN at RB1_bit; sbit LCD_D4 at RB2_bit; sbit LCD_D5 at RB3_bit; sbit LCD_D6 at RB4_bit; sbit LCD_D7 at RB5_bit; // Direcção Pin sbit LCD_RS_Direction at TRISB0_bit; sbit LCD_EN_Direction at TRISB1_bit; sbit LCD_D4_Direction at TRISB2_bit; sbit LCD_D5_Direction at TRISB3_bit; sbit LCD_D6_Direction at TRISB4_bit; sbit LCD_D7_Direction at TRISB5_bit; //char *test = "Hello LCD"; //Declaração de variaveis globais const unsigned short VREF = 5; unsigned int adc_rd = 0; float temp; char txt[15]; int i=0; void main() { //Declaração de variaveis adc_rd = 0; //Declaração de info das portas ADCON0 = 0x81; ADCON1 = 0xCE; T2CON = 0x04; CCP1CON = 0x0F; PR2=0xFF; trisa = 0XFF; // portA input trisc = 0; trisd = 0; // todas portas D output trisb = 0; // todas portas B output PORTC = 0; PWM1_Init(5000); pwm1_start(); PWM1_Set_Duty(200); exemplo com 200 //Iniciar adc adc_init(); //Iniciar Lcd Lcd_Init(); //Iniciar Uart1 UART1_Init(9600); Lcd_Cmd(_Lcd_CLEAR); Lcd_Cmd(_Lcd_CURSOR_OFF); Lcd_Out(1, 1, "Aguarde"); Lcd_Out(2, 2, "Teste aos Led's"); UART1_Write_text("Aguarde:\r"); UART1_Write_text("Teste aos Led's\r"); delay_ms(1000); //Testar se Led estão bons do { portd.f0=1; //verde portd.f1=1; //amarelo portd.f2=1; //2x vermelho delay_ms(1000); portd.f0=0; portd.f1=0; portd.f2=0; delay_ms(1000); i++; }while(i!=3); Lcd_Cmd(_Lcd_CLEAR); Lcd_Out(1, 1, "Aguarde"); Lcd_Out(2, 2, "Led's Bons"); UART1_Write_text("Led's em bom estado\r"); //mensagem não certa delay_ms(2000); Lcd_Cmd(_Lcd_CLEAR); //Leitura do LM35 while(1) { adc_rd = ADC_Get_Sample(0); temp = (adc_rd * VREF)/10.240; floatToStr(temp, txt); txt[4] =0; UART1_Write_text(txt); UART1_Write_text("\r"); Lcd_Out(1, 1, "Temperatura:"); Lcd_Chr(2, 8, 223); Lcd_Chr(2,9,'C'); Lcd_Out(2, 3, txt); delay_ms(500); //indicação dos led's perante temp if (temp <30) { portd.f0=1; portd.f1=0; } if (temp >30) { portd.f0=1; portd.f1=1; portd.f2=0; } if (temp >90) { portd.f0=1; portd.f1=1; portd.f2=1; } } }
bsccara Posted April 13, 2012 at 02:59 PM Report #448972 Posted April 13, 2012 at 02:59 PM Um concelho: evita cálculos em virgula flutuante em microcontroladores. Forças a inclusão de grande quantidade de código para suportar isso, o que não é aconselhável com as pequenas quantidades de memória nesses ICs. O teu cálculo deve ser refeito de: temp = (adc_rd * VREF)/10.240; para: temp = ((unsigned long)adc_rd * VREF * 100)/1024; ou temp = ((unsigned long)adc_rd * VREF * 100) >> 10; Obviamente a variável 'temp' deve passar a ser 'unsigned int'. Em vez da função 'FloatToStr' usa uma para converter inteiros em strings, que será muito mais pequena, também. Quanto ao teu problema, terás de usar a função 'PWM1_Set_Duty' dentro do ciclo de leitura do LM35. Qual é o teu problema exactamente ?
snis Posted April 16, 2012 at 01:24 PM Author Report #449403 Posted April 16, 2012 at 01:24 PM // Lcd pinout definições sbit LCD_RS at RB0_bit; sbit LCD_EN at RB1_bit; sbit LCD_D4 at RB2_bit; sbit LCD_D5 at RB3_bit; sbit LCD_D6 at RB4_bit; sbit LCD_D7 at RB5_bit; // Direcção Pin sbit LCD_RS_Direction at TRISB0_bit; sbit LCD_EN_Direction at TRISB1_bit; sbit LCD_D4_Direction at TRISB2_bit; sbit LCD_D5_Direction at TRISB3_bit; sbit LCD_D6_Direction at TRISB4_bit; sbit LCD_D7_Direction at TRISB5_bit; //char *test = "Hello LCD"; //Declaração de variaveis globais //unsigned short current_duty; const unsigned short VREF = 5; unsigned int temp, adc_rd = 0; //float temp; char txt[15]; int i=0; void main() { //Declaração de variaveis //current_duty = 16; adc_rd = 0; //Declaração de info das portas ADCON0 = 0x81; ADCON1 = 0xCE; trisa = 0XFF; // portA input trisc = 0; trisd = 0; // todas portas D output trisb = 0; // todas portas B output PORTC = 0; T2CON = 0x04; CCP1CON = 0x0F; PR2=0xFF; PWM1_Init(5000); //Iniciar adc adc_init(); //Iniciar Lcd Lcd_Init(); //Iniciar Uart1 UART1_Init(9600); Lcd_Cmd(_Lcd_CLEAR); Lcd_Cmd(_Lcd_CURSOR_OFF); Lcd_Out(1, 1, "Aguarde"); Lcd_Out(2, 2, "Teste aos Led's"); UART1_Write_text("Aguarde:\r"); UART1_Write_text("Teste aos Led's\r"); delay_ms(1000); Lcd_Cmd(_Lcd_CLEAR); Lcd_Out(1, 1, "Aguarde"); Lcd_Out(2, 2, "Led's Bons"); UART1_Write_text("Led's em bom estado\r"); delay_ms(2000); Lcd_Cmd(_Lcd_CLEAR); pwm1_start(); //Leitura do LM35 while(1) { adc_rd = ADC_Get_Sample(0); //temp = (adc_rd * VREF)/10.240; //temp = ((unsigned long)adc_rd * VREF * 100)/1024; temp = ((unsigned long)adc_rd * VREF * 100) >> 10; floatToStr(temp, txt); //com intToStr não funciona txt[4] =0; UART1_Write_text(txt); UART1_Write_text("\r"); Lcd_Out(1, 1, "Temp || Potencia"); Lcd_Chr(2, 5, 223); Lcd_Chr(2,6,'C'); Lcd_Out(2, 1, txt); delay_ms(500); PWM1_set_Duty(temp); } } já estou usar PWM1_Set_duty , mas nao tenho qualquer sinal. mesmo com um osc na saida ccp1 não tenho nada
bsccara Posted April 16, 2012 at 03:20 PM Report #449432 Posted April 16, 2012 at 03:20 PM Vários pontos: temp = ((unsigned long)adc_rd * VREF * 100) >> 10; O ADC do 877 é de 10 bits pelo que o resultado da função adc_rd irá variar entre 0 e 1023. Assim a variável 'temp' irá variar entre 0 e 499.512. A função 'PWM1_set_Duty' recebe um byte, que pode variar entre 0 e 255. Portanto se o valor de 'temp' exceder 255 vai provocar um 'wraparound' e subtrair 256 (256 será passado como 0). A escala do cálculo tem de ser reduzida. floatToStr(temp, txt); //com intToStr não funciona Se não funciona (não vejo porque) é preferível escrever uma rotina para converter a 'temp' numa string, pois a utilização de funções de virgula flutuante implicam o potencial acréscimo de vários KB de código na flash, que é limitada a 14KB. PWM1_set_Duty(temp); Dependendo da aplicação, o controlo contínuo do 'duty cycle' pode não ser a melhor solução. É preciso estabelecer a relação temperatura / duty cycle do PWM. Tenta escrever um código mínimo, só para iniciar o PWM e depois vai juntando o resto aos poucos.
snis Posted April 17, 2012 at 10:46 AM Author Report #449509 Posted April 17, 2012 at 10:46 AM // Lcd pinout definições sbit LCD_RS at RB0_bit; sbit LCD_EN at RB1_bit; sbit LCD_D4 at RB2_bit; sbit LCD_D5 at RB3_bit; sbit LCD_D6 at RB4_bit; sbit LCD_D7 at RB5_bit; // Direcção Pin sbit LCD_RS_Direction at TRISB0_bit; sbit LCD_EN_Direction at TRISB1_bit; sbit LCD_D4_Direction at TRISB2_bit; sbit LCD_D5_Direction at TRISB3_bit; sbit LCD_D6_Direction at TRISB4_bit; sbit LCD_D7_Direction at TRISB5_bit; unsigned int temp; void main() { trisc=0; portc=0; T2CON = 0x04; CCP1CON = 0x0F; PR2=0xFF; //Iniciar PWM PWM1_Init(5000); //Iniciar Lcd Lcd_Init(); //PWM Start pwm1_start(); while(1) { temp=254; PWM1_set_Duty(temp); } } tenho so um proj. novo com o 16f877a e a saida do ccp1. como o codigo esta nao da sinal. se trocar para portc.f2=1 a fan roda, logo o esquena deve estar bem feito.
snis Posted April 17, 2012 at 04:15 PM Author Report #449559 Posted April 17, 2012 at 04:15 PM https://docs.google.com/open?id=0BwoM1EQQ2ZAzRlZzb0N0Qm04X00
albertoice Posted August 16, 2012 at 12:55 AM Report #472408 Posted August 16, 2012 at 12:55 AM gostei amigo ta de paraben era o que eu procurava
snis Posted August 16, 2012 at 10:54 AM Author Report #472430 Posted August 16, 2012 at 10:54 AM tenho aqui o projecto concluido se precisares de ajuda abraço
Guerra Lacerda Posted February 20, 2014 at 12:41 AM Report #545902 Posted February 20, 2014 at 12:41 AM Amigo poderia disponibilizar este projeto?
snis Posted February 20, 2014 at 06:14 PM Author Report #545973 Posted February 20, 2014 at 06:14 PM olas tenho q ver onde tenho isso. sinceramente nao sei onde o guardei 😞
Guerra Lacerda Posted February 23, 2014 at 09:26 PM Report #546412 Posted February 23, 2014 at 09:26 PM ok, caso encontre ficarei muito agradecido.
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now