Esquemático:
As placas do protótipo montado:
Demonstração da tela do pc no momento da gravação de firmware:
Engenheiro eletricista - Desenvolvedor de hardware. Protótipos e projetos. Desenvolvimento de software de interface.(aguivone@gmail.com)
////////////////////////////////////////////////////////////////////////////////
// Projeto: Girando motor de passo unipolar (28byj-48) nos dois sentidos. //
// Nome: Renato Lôbo Rodrigues //
// Data: 29/11/17 //
// Email: lobosoft@oi.com.br //
////////////////////////////////////////////////////////////////////////////////
//http://giocarduino.altervista.org/e19-motore-passo-passo.pdf
//dois botões pulsadores no pino 3 e 4 do pic e GND
//0 pino 4 do pic (A3) deve ter um resistor de pull-up
//pino 7 do pic em 1N1 da placa que acompanha o motor 28byj-48
//pino 6 do pic em 1N2
//pino 5 do pic em 1N3
//pino 2 do pic em 1N4
//GND em - da placa
//12V em + da placa
//Configuração PIC
#include <12f675.h>
//inicializando os fusiveis
#fuses INTRC_IO, NOMCLR, NOWDT,PROTECT,PUT,BROWNOUT,CPD
#use delay(clock=4Mhz) //clock interno de 4mhz
#byte tris_portA = 0x85 //sentido dos pinos do portA
#bit bot1= 0x05.3 //botão sentido horario
#bit bot2= 0x05.4 //botão sentido anti-horario
#bit bob_A1 = 0x05.0 //terminais do motor de passo bobina A e B
#bit bob_A2 = 0x05.1 //
#bit bob_B1 = 0x05.2 //
#bit bob_B2 = 0x05.5 //
//se 5 fios lique o center type no GND
//se 6 fios ligue os dois center type no GND
int1 roda = false; //iniciando a variaval roda como falsa
int1 dir = false; //iniciando a variaval dir como falsa
int8 pulso =0; //iniciando a pulso com zero
void motor(int8 num) //configuração de giro do motor em 0.5 passo
{
switch(num)
{
case 0: bob_A1=1;
bob_A2=0;
bob_B1=0;
bob_B2=0;
break;
case 1: bob_A1=1;
bob_A2=1;
bob_B1=0;
bob_B2=0;
break;
case 2: bob_A1=0;
bob_A2=1;
bob_B1=0;
bob_B2=0;
break;
case 3: bob_A1=0;
bob_A2=1;
bob_B1=1;
bob_B2=0;
break;
case 4: bob_A1=0;
bob_A2=0;
bob_B1=1;
bob_B2=0;
break;
case 5: bob_A1=0;
bob_A2=0;
bob_B1=1;
bob_B2=1;
break;
case 6: bob_A1=0;
bob_A2=0;
bob_B1=0;
bob_B2=1;
break;
case 7: bob_A1=1;
bob_A2=0;
bob_B1=0;
bob_B2=1;
break;
case 8: bob_A1=0; //motor desligado
bob_A2=0;
bob_B1=0;
bob_B2=0;
break;
}
}
#int_timer1
void rotina_t1() //na frenquência de 1khz esse motor gira a 20 rpm
{
if(roda)
{
if(dir)
{
if(pulso < 7)pulso++;else pulso=0; //gira anti-horário
}else{
if(pulso > 0)pulso--;else pulso=7; //gira horário
}
motor(pulso); //gira 0.5 passo a cada chamada
roda=false; //avisa que terminou 0 0.5 passo
}
else
{
motor(8);
}
set_timer1(64536 + get_timer1()); //preset de contagem do timer1
}
void main ()
{
int1 st1 = false,st2 = false; //status do botão
setup_comparator(NC_NC_NC_NC); //comparadores desligados
setup_vref(FALSE); //sem valor de referencia
port_a_pullups(0b00010000); //pull-up para pino A3
tris_portA=0b11011000; //entrada e saidos dos pinos
bob_A1=0; //todos pinos do motor inicia em zero
bob_A2=0;
bob_B1=0;
bob_B2=0;
// Timer1 para estouro a cada 1 ms.(Frequência do Ocilador 4Mhz)
enable_interrupts(global);
setup_timer_1(t1_internal | t1_div_by_1);
Enable_interrupts(int_timer1);
set_timer1(64536);
while (TRUE)
{
if(!roda)
{
if( bot1) st1 = false;
if(!bot1 && !st1) //gira horário
{
dir=false;
roda=true;
}
if( bot2) st2 = false;
if(!bot2 && !st2) //gira anti-horário
{
dir=true;
roda = true;
}
}
}
}
- Pic16F628 da Microchip
- Placa com display duplo de 7 segmentos de catodo comum
- Capacitor de 100nf para desacoplamento
- Cabinhos para ligação
- Matriz de contato
- Fonte de 5v
//////////////////////////////////////////////////////////////////////////////// // Projeto: Usando Varredura no acionamento de display de 7 segmentos. // // Nome: Renato Lôbo Rodrigues // // Data: 20/08/17 // // Email: lobosoft@oi.com.br // //////////////////////////////////////////////////////////////////////////////// #include <16F628A.h> #use delay (clock = 4Mhz) //Configure os fusíveis em acordo com o pic selecionado #fuses NOWDT #fuses PUT #fuses NOBROWNOUT #fuses NOMCLR #fuses INTRC_IO #fuses PROTECT #byte tris_portA = 0x85 #byte tris_portB = 0x86 #bit display0 = 0x05.0 //pino A0 #bit display1 = 0x05.1 //pino A1 #bit SegA = 0x06.1 //pino B1 #bit SegB = 0x06.2 //pino B2 #bit SegC = 0x06.3 //pino B3 #bit SegD = 0x06.4 //pino B4 #bit SegE = 0x06.5 //pino B5 #bit SegF = 0x06.6 //pino B6 #bit SegG = 0x06.7 //pino B7 void digito(int8 num) { switch(num) { case 0: SegA=1;// AAAA SegB=1;// F B SegC=1;// F B SegD=1;// SegE=1;// E C SegF=1;// E C SegG=0;// DDDD break; case 1: SegA=0;// SegB=1;// B SegC=1;// B SegD=0;// SegE=0;// C SegF=0;// C SegG=0;// break; case 2: SegA=1;// AAAA SegB=1;// B SegC=0;// B SegD=1;// GGGG SegE=1;// E SegF=0;// E SegG=1;// DDDD break; case 3: SegA=1;// AAAA SegB=1;// B SegC=1;// B SegD=1;// GGGG SegE=0;// C SegF=0;// C SegG=1;// DDDD break; case 4: SegA=0;// SegB=1;// F B SegC=1;// F B SegD=0;// GGGG SegE=0;// C SegF=1;// C SegG=1;// break; case 5: SegA=1;// AAAA SegB=0;// F SegC=1;// F SegD=1;// GGGG SegE=0;// C SegF=1;// C SegG=1;// DDDD break; case 6: SegA=1;// AAAA SegB=0;// F SegC=1;// F SegD=1;// GGGG SegE=1;// E C SegF=1;// E C SegG=1;// DDDD break; case 7: SegA=1;// AAAA SegB=1;// B SegC=1;// B SegD=0;// SegE=0;// C SegF=0;// C SegG=0;// break; case 8: SegA=1;// AAAA SegB=1;// F B SegC=1;// F B SegD=1;// GGGG SegE=1;// E C SegF=1;// E C SegG=1;// DDDD break; case 9: SegA=1;// AAAA SegB=1;// F B SegC=1;// F B SegD=1;// GGGG SegE=0;// C SegF=1;// C SegG=1;// DDDD break; } } //___________________________________________ //Rotina principal void main() { int1 d = false; int8 dig0 = 0; int8 dig1 = 0; int8 valor = 0; int16 conta = 0; tris_portA = 0b11111100; tris_portB = 0b00000001; //DEFINE display0 e TODOS SEGMENTOS LIGADOS PARA TESTE DURANTE 1 SEGUNDO display0=1;display1=0; SegA=1;// AAAA SegB=1;// F B SegC=1;// F B SegD=1;// GG SegE=1;// E C SegF=1;// E C SegG=1;// DDDD //aguarda 1 segundo delay_ms(1000); //DEFINE display1 e TODOS SEGMENTOS LIGADOS PARA TESTE DURANTE 1 SEGUNDO display0=0;display1=1; SegA=1;// AAAA SegB=1;// F B SegC=1;// F B SegD=1;// GG SegE=1;// E C SegF=1;// E C SegG=1;// DDDD //aguarda 1 segundo delay_ms(1000); while(true) //laço infinito { if(!d) //se d é falso { display0=1;display1=0; //seleciona display0 digito(dig0); //chama rotina para digitos de 0 a 9 d=1; //troca para display1 }else{ //se falso display0=0;display1=1; //seleciona display1 digito(dig1); //chama rotina para digitos de 0 a 9 d=0; //troca para display0 } conta++; //incremento de contagem para acertar um tempo de +/- 1S if(conta>=100) //testa se ja venceu o tempo { if(valor<100){ //testa se o valor e maior que 100 valor++; //se verdadeiro incrementa o valor }else{ valor=0; // se falso atribui zero } dig0=valor%10; //extrai o resto da divisão para o display0 dig1=valor/10; //extrai o inteiro da divisão para o display1 conta=0; //atribui zero para iniciar a contagem de tempo } delay_ms(10); //tempo de espera para troca de display } }
Material para montagem em matriz de contato:
- Pic16F883 da Microchip
- Cristal de 20Mhz
- LCD de 16 x 2
- 2 Trimpot de 10K
- Resistencia de 180R
- Resistencia de 1k
- Resistencia de 10k
- Resistencia de 100k
- Resistencia de 1M
- Capacitor de 100nf
- 2 Capacitores de 15pF
- Vários capacitores para teste
- Cabinhos para licação
- Matriz de contato
- Fonte de 5v
Imagem do esquemático no simulador:
Protótipo do projeto:
O código Fonte: //////////////////////////////////////////////////////////////////////////////// //Projeto:Capacimetro.c // //data:27/07/2017 // //créditos: http://www.eletronite.com.br/projetos/capacimetro-com-arduino // //Convertido de arduino para pic: Renato Lobo Rodrigues // // // //lobosoft@oi.com.br // //////////////////////////////////////////////////////////////////////////////// #include <16F883.h> #DEVICE ADC=10 #use delay (clock = 20Mhz) //Configura os fusiveis #fuses HS #fuses NOWDT #fuses PUT #fuses BROWNOUT #fuses NOMCLR #fuses PROTECT #bit carga_Pin1 =0x05.5 //pin_A5 pino para carga do capacitor com resistor de 1k #bit carga_Pin1_tris =0x85.5 #bit carga_Pin10 =0x05.4 //pin_A4 pino para carga do capacitor com resistor de 10k #bit carga_Pin10_tris =0x85.4 #bit carga_Pin100 =0x07.0 //pin_C0 pino para carga do capacitor com resistor de 100k #bit carga_Pin100_tris =0x87.0 #bit carga_Pin1000 =0x07.1 //pin_C1 pino para carga do capacitor com resistor de 1M #bit carga_Pin1000_tris =0x87.1 #bit descarga_Pin =0x07.2 //pin_C2 pino para descarregar capacitor atraves de resistor de 1k #bit descarga_Pin_tris =0x87.2 #define Valor_resistor1 1000.0F // valor do resistor de 1k #define Valor_resistor10 10000.0F // valor do resistor de 10k #define Valor_resistor100 100000.0F // valor do resistor de 100k #define Valor_resistor1000 1000000.0F // valor do resistor de 1M #define auto_Capacitance 0.000228F // Variáveis globais unsigned int32 inicio_tempo; unsigned int32 Tempo_total; float microFarads; float nanoFarads; float picoFarads; unsigned char carga_Pin = 0; float Valor_resistor; void descarregaCap(); #include "lcd-4.c" //Rotina de interrupção #int_rtcc void rotina_t0() { set_timer0(255) + get_timer0(); inicio_tempo++; } void main() { LCD_init(); //inicializa o LCD //configura a interrupção do timer0 enable_interrupts(global); setup_timer_0(rtcc_internal | rtcc_ext_l_to_h); setup_timer_0(rtcc_8_bit | rtcc_div_1); Enable_interrupts(int_timer0); set_timer0(255); //configura o ADC do pic canal 0 setup_adc(ADC_CLOCK_INTERNAL); setup_adc_ports(sAN0); // Configura pinos como entrada carga_Pin10_tris = 1; carga_Pin100_tris = 1; carga_Pin1000_tris = 1; carga_Pin1_tris = 1; // imprime texto estático na tela lcd_gotoxy(1,1); printf (lcd_putc,"Lobosoft Ltda. "); lcd_gotoxy(1,2); printf (lcd_putc,"Cap = "); while(true) { // Seleciona melhor resistor para capacitor a ser medido carga_Pin = 0; do { descarregaCap(); switch (carga_Pin) { case 0: carga_Pin10_tris = 1; carga_Pin100_tris = 1; carga_Pin1000_tris = 1; carga_Pin1_tris = 0; carga_Pin1 = 1; Valor_resistor = Valor_resistor1; break; case 1: carga_Pin1_tris = 1; carga_Pin100_tris = 1; carga_Pin1000_tris = 1; carga_Pin10_tris = 0; carga_Pin10 = 1; Valor_resistor = Valor_resistor10; break; case 2: carga_Pin1_tris = 1; carga_Pin10_tris = 1; carga_Pin1000_tris = 1; carga_Pin100_tris = 0; carga_Pin100 = 1; Valor_resistor = Valor_resistor100; break; case 3: carga_Pin1_tris = 1; carga_Pin10_tris = 1; carga_Pin100_tris = 1; carga_Pin1000_tris = 0; carga_Pin1000 = 1; Valor_resistor = Valor_resistor1000; break; } //seleciona canal zero do ADC para leitura set_adc_channel(0); delay_us(10); inicio_tempo = 0; //aguarda carga de 63.2% do capacitor para calculo while (read_adc() < 648); // 647 é 63.2% de 1023 (valor máximo da entrada analógica) //calcula tempo de carga com 39.82% de correção Tempo_total = (inicio_tempo*1.3982)*39.82; carga_Pin++; } while (Tempo_total < 1000 && carga_Pin != 4); // Converte valor de capacitor medido para unidade de engenharia e imprime no display LCD microFarads = ((float)Tempo_total / Valor_resistor) - auto_Capacitance; if(microFarads >0) { lcd_gotoxy(7,2); printf (lcd_putc," "); lcd_gotoxy(7,2); if (microFarads > 1) { printf (lcd_putc,"%fuf",microFarads); } else { nanoFarads = microFarads * 1000.0; if (nanoFarads > 1) { printf (lcd_putc,"%fnf ",nanoFarads); } else { picoFarads = nanoFarads * 1000.0; printf (lcd_putc,"%fpf",picoFarads); } } descarregaCap(); delay_ms(500); } else { //Se o capacitor não estiver conectado diz que esta ausente lcd_gotoxy(7,2); printf (lcd_putc,"Ausente "); } } } // Função para descarregar capacitor void descarregaCap() { carga_Pin10_tris = 1; carga_Pin100_tris = 1; carga_Pin1000_tris = 1; carga_Pin1_tris = 1; descarga_Pin_tris = 0; descarga_Pin = 0; //Aguarda a descarga total do capacitor while (read_adc() > 0); descarga_Pin_tris = 1; } Biblioteca para LCD alfanumérico //////////////////////////////////////////////////////////////////////////////// // BIBLIOTECA DO LCD // // data:27/07/2017 // // // // // //////////////////////////////////////////////////////////////////////////////// // Modifique os pinos o quanto Quiser. #define LCD_DB4 PIN_b4 #define LCD_DB5 PIN_b5 #define LCD_DB6 PIN_b6 #define LCD_DB7 PIN_b7 #define LCD_RS PIN_b0 #define LCD_E PIN_b1 // Se voce quiser uma interface de 6 pinos para seu LCD, então // conecte o pino R/W do LCD ao terra, e comente a seguinte linha //#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 #define lcd_line_1 0x00 //LCD RAM address for the 1 line #define lcd_line_2 0x40 //LCD RAM address for the 2 line #define lcd_line_3 0x10 //LCD RAM address for the 3 line #define lcd_line_4 0x50 //LCD RAM address for the 4 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(60); #endif } } /*------------duas linhas---------------- 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); } */ //------------quatro linhas---------------- void lcd_gotoxy(int8 x, int8 y) { int8 address; switch(y) { case 1: address = lcd_line_1; address += x-1; break; case 2: address = lcd_line_2; address += x-1; break; case 3: address = lcd_line_3; address += x-1; break; case 4: address = lcd_line_4; address += x-1; break; default: address = lcd_line_1; address += x-1; break; } 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 //implementado por Renato Lôbo Rodrigues #separate void lcd_cursor_on() { lcd_send_byte(0,0x0E); } #separate void lcd_cursor_blink() { lcd_send_byte(0,0x0F); } #separate void lcd_cursor_off() { lcd_send_byte(0,0x0C); } #separate void lcd_shift_left() { lcd_send_byte(0,0x18); } #separate void lcd_shift_right() { lcd_send_byte(0,0x1C); }
* * Compilador : MPlabXC8 * Microcontrolador: 16F628A * Autor: aguivone * Versão: 1 * Data : 06 de julho de 2017 * * intruções: * a programação deve ser feita usado #SXX* ; onde S=o ciclo que se quer alterar(1 a 7) e XX é um valor de 00 a 99 * note que a programação será por multiplos de 10s * * * mapa de endereços * posição de memoria - descrição. * * 0 - posição de memoria rom que indica se houve gravação * 1 a 7 - relativo ao modo de funcionamento 1 a 7. * */ #include <stdio.h> #include <string.h> //para usar funçoes de string deve se adicionar este header #include <stdlib.h> #define _XTAL_FREQ 4000000 // vou usar o oscilador interno #include <xc.h> /////////////////////////////////////////////////////////configuraçôes////////////////////////////////////////////////// //#pragma config FOSC = INTOSCIO // Oscillator Selection bits (INTOSC oscillator: I/O function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN) #pragma config FOSC = HS ///se for de 20mhz deve ser HS #pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled) #pragma config PWRTE = ON // Power-up Timer Enable bit (PWRT enabled) #pragma config MCLRE = OFF // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is digital input, MCLR internally tied to VDD) #pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled) #pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming) #pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off) #pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off) #define BOT_CONFIG RA4 #define RL_GERAL RB7 #define RL_1 RB4 #define RL_2 RB5 #define RL_3 RB6 #define LED_STATUS RB0 ////////////////////////////////////////////////variaveis globais/////////////////////////////////////////////////////////// int modo=0;//modo de funcionamento int tempo[7];//para guardar os tempos int pos_prog=6;//posição inicial //usadas na serial char rs232[6];//guarda pacote recebido char caracter; int pos_serial=0; bit flag_interrupcao = 0; /////////////////////////////////funçoes usadas pela uart ////////////////////////////////////////////////////// //void inicializa_RS232(long velocidade,int modo) void inicializa_RS232() {////por padrão é usado o modo 8 bits e sem paridade, mas se necessario ajuste aqui a configuração desejada. //verifique datasheet para ver a porcentagem de erro e se a velocidade é possivel para o cristal utilizado. RCSTA = 0X90;//habilita porta serial,recepção de 8 bit em modo continuo,assincrono. TXSTA = 0X24;//modo assincrono,trasmissao 8 bits./alta velocidade SPBRG = 25;//9600 RCIE = 1;//habilita interrupção de recepção TXIE = 0;//deixa interrupção de transmissão desligado(pois corre se o risco de ter uma interrupção escrita e leitura ao mesmo tempo) } void escreve(char valor) { TXIF = 0;//limpa flag que sinaliza envio completo. TXREG = valor; while(TRMT==0);//resolvi usar este flag em vez de TXIF // while(TXIF ==0);//espera enviar caracter//alterei para 1 para testar 18/07/17 // __delay_us(20); } void imprime(const char frase[]) { char indice = 0; char tamanho = strlen(frase); while(indice < tamanho ) ///veja que o programa pode travar se aqui não tiver as duas aspas { escreve(frase[indice]); indice++; } } void int_to_char(int quant) {//converte para inteiro e imprime unsigned char ucDez='0', ucUn='0'; while(quant>=10) { quant -= 10; ucDez++; } while(quant>=1) { quant -= 1; ucUn++; } escreve(ucDez); escreve(ucUn); } void delay_ms(long valor)//resolve um erro do conmpilador { while(valor>0) { __delay_ms(1); valor--; } } void delay_seg(long valor)//rotina de 1s { while(valor>0) { __delay_ms(1000); //__delay_ms(100); //pra simular LED_STATUS = ~LED_STATUS; valor--; } //para simular pode reduzir o tempo } void ler_dados() { imprime(" \n\r tempos="); int var_auxi=0; while(var_auxi<7) { tempo[var_auxi] = eeprom_read(var_auxi+1); int_to_char(tempo[var_auxi]); escreve('0'); escreve('|'); var_auxi++; } } ///////////////////////////////////////////////////interrupção////////////////////////////////////////////////////////////// void interrupt RS232(void)//vetor de interrupção { if(RCIF) {//se pacote for de tamanho diferente ele descarta o pacote. formato #XXX* caracter = RCREG; if(flag_interrupcao == 0) {//verifica se está liberado para ler dados if(pos_serial>0) { if(caracter == '*') {//pacote aceito if(pos_serial == 4) { flag_interrupcao = 1; rs232[pos_serial]=caracter; pos_serial = 0;//pra evitar que escreva antes de ler } else {//descarta pois é menor que o esperado pos_serial = 10;//faz zerar tudo } } else { rs232[pos_serial]=caracter; pos_serial++; } } if(pos_serial>4) { //erro no tamanho zera tudo rs232[0]='0'; rs232[1]='0'; rs232[2]='0'; rs232[3]='0'; rs232[4]='0'; pos_serial = 0; } if(caracter == '#') { pos_serial = 1; rs232[0]='#'; } } RCIF = 0;// limpa flag de interrupção de recepção } } //////////////////////////////////////////////////////Rotina principal/////////////////////////////////////////////////////////////// void main(void) { TRISB = 0X02;//configura portB como saida, B1 (pino RX) como entrada PORTB = 0; // limpar as portas que estão configuradas como saidas TRISA = 0XFF;//configura portA como entrada inicializa_RS232();//modo de alta velocidade PEIE = 1;//habilita interrupção de perifericos do pic GIE = 1; //GIE: Global Interrupt Enable bit __delay_ms(200); imprime("Sistema de irrigação V.1.0.0 \n\r"); //pega valores da memoria if(eeprom_read(0) != 'G') {//nunca foi gravada, então coloca valor padrão eeprom_write(0X00,0); eeprom_write(0X01,1);//endereço/valor eeprom_write(0X02,1); eeprom_write(0X03,1); eeprom_write(0X04,1); eeprom_write(0X05,1); eeprom_write(0X06,1); eeprom_write(0X07,1); } ////leitura modo=1; if(BOT_CONFIG == 0) { delay_ms(1000); if(BOT_CONFIG == 0) { imprime("Modo configuração \n\r"); modo=0; // eeprom_write(0X00,'G');//indica que houve gravação na memoria LED_STATUS =1; } } if(modo == 1) { RCIE = 0;//desabilita interrupção de recepção TXIE = 0;//desabilita interrupção de transmissao ler_dados(); LED_STATUS =0; } ////////////// for(;;) { if(modo==0) { if(flag_interrupcao == 1) {//tem dados para ler LED_STATUS =0; escreve(rs232[0]); escreve(rs232[1]); escreve(rs232[2]);//retorna o valor lido escreve(rs232[3]); escreve(rs232[4]); //////processa dados///// if((rs232[2]>0X2F)&&(rs232[2]<0X40)&&(rs232[3]>0X2F)&&(rs232[3]<0X40))//indica que foi recebido um numero valido {//trata pacote if((rs232[1]>0X30)&&(rs232[1]<0X38))//indica que foi recebido um modo valido(entre 1 e 7) {//verifica se o modo de programação tem caracter valido int valor = (((rs232[2] - 0X30)*10)+(rs232[3] - 0X30));//converte pra int int posicao = (rs232[1] - 0X30);//converte pra int eeprom_write(posicao,valor);//altera o valor na de memoria; imprime("\n\r Alterado:\n\r"); for(int i=1;i<8;i++) {//imprime valores da memoria int_to_char(eeprom_read(i)); escreve('|'); } eeprom_write(0X00,'G');//indica que houve gravação na memoria; } } pos_serial = 0; flag_interrupcao = 0;//libera pra pegar outro pacote LED_STATUS =1; } } else { //a sequencia foi pensada de forma que cada valvula tenha pelo menos 1 ciclo de descanso a cada 2 ciclos(execto se o tempo for zero para uma das posicoes) switch(pos_prog) { case 0: { //fim de programa RL_1=0; RL_2=0; RL_3=0; delay_ms(500); RL_GERAL=0; }break; case 1: { if(tempo[0]>0) { RL_1=1; RL_2=0; RL_3=0; } pos_prog=3;//vai para proxima posição delay_seg(tempo[0]*10); }break; case 2: { if(tempo[1]>0) { RL_1=0; RL_2=1; RL_3=0; } pos_prog=7;//vai para proxima posição delay_seg(tempo[1]*10); }break; case 3: { if(tempo[2]>0) { RL_1=1; RL_2=1; RL_3=0; } pos_prog=4;//vai para proxima posição delay_seg(tempo[2]*10); }break; case 4: { if(tempo[3]>0) { RL_1=0; RL_2=0; RL_3=1; } pos_prog=5;//vai para proxima posição delay_seg(tempo[3]*10); }break; case 5: { if(tempo[4]>0) { RL_1=1; RL_2=0; RL_3=1; } pos_prog=2;//vai para proxima posição delay_seg(tempo[4]*10); }break; case 6: {//como o programa inicia aqui é preciso ter uma atenção diferente neste ponto RL_GERAL=1; //rele principal, mantem a placa energizada if(tempo[5]>0) { RL_1=0; RL_2=1; RL_3=1; } else { RL_1=0; RL_2=0; RL_3=0; } pos_prog=1;//vai para proxima posição delay_seg(tempo[5]*10); }break; case 7: { if(tempo[6]>0) { RL_1=1; RL_2=1; RL_3=1; } pos_prog=0;//vai para proxima posição delay_seg(tempo[6]*10); }break; } } }//loop infinito }
O esquemático de simulação no proteus ficou:
//////////////////////////////////////////////////////////////////////////////// // Projeto: Aparelho de som com modulo DFPlayer Mini // // Nome: Renato Lôbo Rodrigues // // Data: 12/07/17 // // Email: lobosoft@oi.com.br // //////////////////////////////////////////////////////////////////////////////// #include "config_pic675.h" void main() { int1 st1=false, st2 = false, st3=false, st4 = false, play = true, di = false; int8 equ = 1,disp = 1; tris_bot1 = 1; tris_bot2 = 1; tris_bot3 = 1; tris_bot4 = 1; tris_bot5 = 1; GPPU = 0; delay_ms(2000); Uart_SendCMD(0x06 , 0 , 0x16 ) ; //volume inicial delay_ms(200); sorteia(); delay_ms(200); Tocar(); delay_ms(200); Proxima_trilha(); delay_ms(500); while(true) { if( bot1) st1 =false; //Equalizador delay_ms(50); if(!bot1 && !st1) { st1 = true; equ++; if(equ>5)equ=1; if(equ==1)equaliza(1); if(equ==2)equaliza(2); if(equ==3)equaliza(3); if(equ==4)equaliza(4); if(equ==5)equaliza(5); delay_ms(1000); } if( bot2) st2 =false; //troca o dispositivo: Memoria/Pendrive delay_ms(50); if(!bot2 && !st2) { st2 = false; di=~di; if(di) disp=2; else disp=1; dispositivo(disp); delay_ms(500); } if(!bot3) st3 =false; //toca tudo altomaticamente delay_ms(50); if( bot3 && !st3 && play) { st3 = true; Proxima_trilha(); delay_ms(200); } if( bot4) st4 =false; //tocar/pausa delay_ms(50); if(!bot4 && !st4) { st4 = true; play = ~play; if (play)Tocar();else Pausa(); delay_ms(500); } } } Configuração do PIC 12F675 //////////////////////////////////////////////////////////////////////////////// // Projeto: configuração de cabeçalho de projeto com pic12F675 // // Nome: Renato Lôbo Rodrigues // // Data: 12/07/17 // // Email: lobosoft@oi.com.br // //////////////////////////////////////////////////////////////////////////////// #include "12F675.h" #use delay(clock=4Mhz) #include "DFPlayer.h" //======================================================================= //Configurando fusiveis //======================================================================= #fuses NOWDT #fuses PUT #fuses NOBROWNOUT #fuses NOMCLR #fuses INTRC_IO #fuses PROTECT //======================================================================= //Configurando I/O de direção dos pinos //======================================================================= #bit bot1 = 0x05.0 #bit bot2 = 0x05.2 #bit bot3 = 0x05.3 #bit bot4 = 0x05.4 #bit bot5 = 0x05.5 #bit tris_bot1 = 0x85.0 #bit tris_bot2 = 0x85.2 #bit tris_bot3 = 0x85.3 #bit tris_bot4 = 0x85.4 #bit tris_bot5 = 0x85.5 #bit GPPU = 0x81.7 Biblioteca do DSPlayer Mini //////////////////////////////////////////////////////////////////////////////// // Projeto: Biblioteca para acessar o DFPlayer Mini // // Nome: Renato Lôbo Rodrigues // // Data: 12/07/17 // // Email: lobosoft@oi.com.br // //////////////////////////////////////////////////////////////////////////////// #use rs232(baud=9600,xmit=PIN_A1,rcv=PIN_A2, ERRORS) static unsigned INT8 Send_buf[10] = {0} ; void SendCmd(unsigned INT8 leng) { INT8 i = 0 ; putc(0x7E); for(i=0; i<leng; i++)//dados { putc(Send_buf[i]); } putc(0xEF); } void DoSum( unsigned INT8 *Str, unsigned INT8 len) { unsigned INT16 xorsum = 0; unsigned INT8 i; for(i=0; i<len; i++) { xorsum = xorsum + Str[i]; } xorsum = 0 -xorsum; *(Str+i) = (unsigned INT8)(xorsum >>8); *(Str+i+1) = (unsigned INT8)(xorsum & 0x00FF); } void Uart_SendCMD(unsigned INT8 CMD ,unsigned INT8 feedback , unsigned INT16 dat) { Send_buf[0] = 0xFF; //bytes reservados Send_buf[1] = 0x06; //comprimento Send_buf[2] = CMD; //instruções de controle Send_buf[3] = feedback; //A necessidade de feedback Send_buf[5] = (unsigned INT8)(dat); //datal Send_buf[4] = (unsigned INT8)(dat >> 8); //datah DoSum(&Send_buf[0],6); //Verifique SendCmd(8); //Esta transmissão da trama de dados } void Arquivo_musica(int8 pasta,int8 numero) { int16 pasta_numero; pasta_numero = (pasta * 256) | numero ; Uart_SendCMD(15 , 0, pasta_numero); } void Proxima_trilha() { Uart_SendCMD(1 , 0, 0); } void Trilha_anterior() { Uart_SendCMD(2 , 0, 0); } void Diminuir_volume() { Uart_SendCMD(5 , 0, 0); } void Aumentar_volume() { Uart_SendCMD(4 , 0, 0); } void Volume(int8 vol) { Uart_SendCMD(6 , 0, vol); } void Equaliza(int8 equa) { Uart_SendCMD(7 , 0, equa); } Void Pausa() { Uart_SendCMD(14 , 0, 0); } Void Tocar() { Uart_SendCMD(13 , 0, 0); } void dispositivo(int8 disp) { Uart_SendCMD(9 , 0, disp); } void sorteia() { Uart_SendCMD(24 , 0, 3); } void sequencia() { Uart_SendCMD(24 , 0, 1); }