Follow along with the video below to see how to install our site as a web app on your home screen.
Nota: This feature currently requires accessing the site using the built-in Safari browser.
hola Airoa Airon...me interasa mucho esa respuesta que dejaste en lenguaje c, estaria muy agradacido si pudieras explicar un poco mas lo de variar el duty y la frecuencia... pues exactamente es lo que tengo que hacer con un teclado matricial.....de antemno muchas gracias....Es algo mas complicado en ensamblador.
Primero que nada ten en mente que frecuencias vas a utilizar,
y el tiempo de encendido (duty cycle), de cuanto es tu oscilador
y ve por cuanto mas o menos tendrias que dividir el timer 2(tabla en la hoja de datos)
luego con la formula de PR2 sacas el valor y ya lo que queda es seguir los pasos
Esto lo saque de la hoja de datos. Busca en la seccion PWM.
15.4.4 SETUP FOR PWM OPERATION
The following steps should be taken when configuring
the CCP module for PWM operation:
1. Para ajustar el periodo de PWM tienes que cargarle un valor al registro PR2 del pic
2. Luego para ajustar el ciclo de encendido escribes en los registros
CCPRxL y CCPxCON<5:4>
3. Tienes que poner algun pin de CCPx como salida, borrando algun TRIS bit(ponerlo a 0) yo he usado RC2
4. Le asignas un valor para iniciar el TMR2
Luego un valor de preescale(division + o -) a los bits (T2CKPS1:T2CKPS0)
00 = Prescaler is 1
01 = Prescaler is 4
1x = Prescaler is 16
TMR2ON: Timer2 On bit
1 = Timer2 is on
0 = Timer2 is off
5. Configura el registro CCPx para operar como PWM.
Registro :
CCPxCON
Bits:
CCPxM3:CCPxM0: CCPx Module Mode Select bits
11xx = PWM mode
Frecuencia = 1/periodo
PWM Period = [(PR2) + 1] • 4 • TOSC • F
(TMR2 Prescale Value)
O si quieres Sacar el valor de PR2
PR2=[1/(frecuencia*4*Tosc*16)] -1
Vere si puedo conseguir un ejemplo luego, mientras intenta con esto.
Primero que nada hay que saber en que lenguaje lo necesitas? en ensamblador o en c
en C lo hago asi
setup_ccp1(CCP_PWM); ///esto al principio del programa
al modificar x modifico la frecuencia
al modificar time ajusto el tiempo de encendido
duty lo utilizo para modificar el ancho de pulso
void pulso(int x, long time,int duty)
{
setup_timer_2(T2_DIV_BY_16, x, 1);
set_pwm1_duty(duty);
delay_ms(time);
set_pwm1_duty(0);
}
la formula para obtener el valor que va en x es
x=[1/(frecuencia*4*Tosc*16)] -1 el numero 16 es el valor que se le da al timer 2 puede ser 16, 4 o 1.
Tosc es igual a 1/ (valor del oscilador)
#include <18F4550.h>
#device adc=8
#fuses hs,nowdt,noprotect,nolvp
#use delay(clock=20000000)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
byte velocidad;
void inicializar()
{
setup_ccp2(CCP_PWM);
setup_timer_2(T2_DIV_BY_4, 127, 1);
set_tris_b(0x00);
set_tris_a(0x01);
setup_adc(ADC_clock_internal);
setup_adc_ports(AN0);
set_adc_channel(0);
velocidad=0;
}
void main(){
inicializar();
while(1){
velocidad=read_adc();
set_pwm2_duty(velocidad);
}
}
#include <18F4550.h>
#device adc=8
#fuses hs,nowdt,noprotect,nolvp
#use delay(clock=20000000)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
unsigned int8 velocidad;
void inicializar()
{
setup_ccp2(CCP_PWM);
setup_timer_2(T2_DIV_BY_4, 127, 1);
set_tris_c(0xFD);
set_tris_a(0x01);
setup_adc(adc_clock_internal);
delay_us(12);
setup_adc_ports(AN0);
set_adc_channel(0);
velocidad=0;
}
void main(){
inicializar();
while(true){
velocidad=read_adc();
delay_us(12);
set_pwm2_duty(velocidad/2);
}
}
Hola, como puedo controlar la velocidad de un motor CD con el pwm. en lenguaje C.
void main()
{
setup_adc_ports(AN0_TO_AN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DIV_BY_1,99,1);
setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L);
setup_ccp2(CCP_PWM);
set_pwm1_duty(0);
set_pwm2_duty(0);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_4MHZ|OSC_TIMER1|OSC_31250|OSC_PLL_OFF);
{
long duty=0;
set_adc_channel(0); //selecciona el canal del adc
while (1)
{
duty=read_adc()/3; //leemos el valor el adc y lo dividimos en 2
delay_us(20); //esperamos 20us para el adc
set_pwm1_duty(duty); // ajustamos el pwm con el ciclo de trabajo q nos da el adc/2
}
}
-------------------proba con esto
Código:void main() { setup_adc_ports(AN0_TO_AN1|VSS_VDD); setup_adc(ADC_CLOCK_INTERNAL); setup_psp(PSP_DISABLED); setup_spi(SPI_SS_DISABLED); setup_wdt(WDT_OFF); setup_timer_0(RTCC_INTERNAL); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DIV_BY_1,99,1); setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L); setup_ccp2(CCP_PWM); set_pwm1_duty(0); set_pwm2_duty(0); setup_comparator(NC_NC_NC_NC); setup_vref(FALSE); setup_oscillator(OSC_4MHZ|OSC_TIMER1|OSC_31250|OSC_PLL_OFF); { long duty=0; set_adc_channel(0); //selecciona el canal del adc while (1) { duty=read_adc()/3; //leemos el valor el adc y lo dividimos en 2 delay_us(20); //esperamos 20us para el adc set_pwm1_duty(duty); // ajustamos el pwm con el ciclo de trabajo q nos da el adc/2 } }
también depende con que programa lo compiles...yo uso CCS
#include <18F4550.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES WDT128 //Watch Dog Timer uses 1:128 Postscale
#FUSES INTHS //Internal Oscillator, HS used by USB
#FUSES NOPROTECT //Code not protected from reading
#FUSES BROWNOUT //Reset when brownout detected
#FUSES BORV43 //Brownout reset at 4.3V
#FUSES PUT //Power Up Timer
#FUSES NOCPD //No EE protection
#FUSES STVREN //Stack full/underflow will cause reset
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT //Program memory not write protected
#FUSES NOWRTD //Data EEPROM not write protected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES NOPBADEN //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC //configuration not registers write protected
#FUSES NOWRTB //Boot block not write protected
#FUSES NOEBTR //Memory not protected from table reads
#FUSES NOEBTRB //Boot block not protected from table reads
#FUSES NOCPB //No Boot Block code protection
#FUSES MCLR //Master Clear pin enabled
#FUSES LPT1OSC //Timer1 configured for low-power operation
#FUSES NOXINST //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1 //No PLL PreScaler
#use delay(internal=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
void main(){
setup_adc_ports(AN0_TO_AN1|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_8);
setup_psp(PSP_DISABLED);
setup_spi(FALSE);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_1,99,1);
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
//setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L); aca era el problema que tenia;
setup_ccp1(ccp_pwm);
setup_ccp2(ccp_pwm);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_TIMER0);
enable_interrupts(INT_TIMER1);
enable_interrupts(INT_EXT);
enable_interrupts(INT_EXT1);
enable_interrupts(INT_EXT2);
enable_interrupts(GLOBAL);
setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_31250|OSC_PLL_OFF);
// TODO: USER CODE!!
{
long duty=0;
long duty1=0;
while (TRUE) {
set_adc_channel(0); //selecciona el canal 1 del adc
delay_us(10);
duty=read_adc()/3; //leemos el valor el adc y lo dividimos en 3
delay_us(20); //esperamos 20us para el adc
set_pwm1_duty(duty); // ajustamos el pwm con el ciclo de trabajo q nos da el adc/3
set_adc_channel(1);//selecciona el canal 2 del adc
delay_us(10); //esperamos
duty1=read_adc()/3;//leemos el valor el adc y lo dividimos en 3
delay_us(20); //esperamos
set_pwm2_duty(duty1);//salida del pwm2
}
}
}
Haber si alguien me puede ayudar. Tengo que generar una señal cuadrada de 7 Khz con el 18f4620, pero tengo que hacer 10 mediciones en 1 segundo cuando la señal este en la metad del ciclo positivo y desacupando lo maximo el micro. Lo intente solucionar simplemente con un timer, que divide cada ciclo en 4 partes y con un contador hago la conversión en un determinado instante. Pero la cresta de la señal tiene una pendiente y me acupa muchos ciclos maquina. ¿Hay alguna manera mas efectiva de hacerlo?