Autor Tema: :: PWM :: CCS :: PIC18F2550 :: SERVOS::  (Leído 25739 veces)

0 Usuarios y 3 Visitantes están viendo este tema.

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #60 en: 18 de Agosto de 2012, 14:07:49 »
Hola AngelGris

La idea era obtener el algaritmos para obtener los grados en tick
pero de momento esta chungo...tengo el valor de los extremos
y el del centro, pero no logro obterner los puntos intermedios
por regla de tres tampoco sales..

la idea es pasarle los valores por i2c pero para ello debo de conocer
cuantos tick es un grado, sin que vibre o haga cosa raras.

estoy buscando el algaritmo que me relaciona los tick con los us en alto
pensaba que iba a ser mas facil,..

tambien me he dado cuenta que cuando vibran los servos, si reseteas el micro
ya no lo hace no se el porque ..!, hay alguna forma de hacer un reset por software?
y como hacerlo esto solo en el momento que los servos vibran, que no simpre lo hacen?.

a ver si doy con esa relacion.



« Última modificación: 18 de Agosto de 2012, 14:09:55 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #61 en: 18 de Agosto de 2012, 14:22:04 »
  Cuando hice las pruebas en el pasado, en ocasiones me vibraban los servos por falso contacto en el cable de señal del servo. También me pasó que en un par de oportunidades que se solucionó colocando un capacitor del orden de 10uF a la salida del regulador que alimenta al PIC y también 100nF bien cerquita del PIC y 100nF en la alimentación del servo.

  Yo lo hice con un pote y es relativamente sencillo... hay que usar la función de una recta que pasa por 2 puntos.... y = ax +b
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #62 en: 18 de Agosto de 2012, 15:01:57 »
Hola AngelGris
si lo de la ecuacion de la recta, le das valores a x para obtener y pero
como relacionas esto con ello.
y=ax+b


yo se que:

      0 grados es 120 us  
    90 grados es 375 us  
  180 grados es 630 us

 com 1us son 5 tick
sabemos :

120us  ----------     600 tick
375us  ----------   1875 tick
630us  ----------   3150 tick

la diferencia entre  630us  - 375us = 255us
y al de                  375us  - 120us = 255us

en tick                  3150  tick -  1875  tick  = 1275 tick
                            1875  tick -   600   tick = 1275 tick

cuantos tick o us para que se incremente un angulo de forma correcta

ambos numero 255 us y 1275 tick terminan en 5 por lo tanto son divisibles
entre 3 , 5 y su producto.

la reacion son esos dos numeros

entre los extremos y el centro hay 255us si dividimos entre 90 nos da 2.833333 perido
asi que para evitar errores tomare la operacion entera junto con lo decimales despues en la resta
lo hare con numeros enteros.

255us / 90º = 2.83us por grado

1 tick  --------  0.2 us
x tick  -------- 2.83333

x=14.1666667 tick   ---<>> 14 tick enteros  un grado.
           

Ya que solo se pueden sumar tick completos.

asi quedo el codigo del main:

Código: C++
  1. //variables i2c
  2. int8 state, comando;
  3. //int8 iic_dato, Direc_master;
  4. int8 direc_Mas_esc, recivo=0;
  5. int8 dato[4];
  6. //int8 dato_1[4];
  7. int8 cnt=0;
  8. int8 angulo;
  9. int8 inclina;
  10. int8 motor_on;
  11.  
  12. //servos pwm soft
  13. int8 servos[]={sv_0,sv_1,sv_2,sv_3,sv_4,0,0,0,0,0};
  14.  
  15.  
  16. //variables timer
  17. int8 cnt_t0=0;
  18. int8 cnt_t1=0;
  19. int1 t0=0;
  20. int1 t1=0;
  21.  
  22. //debug tick
  23. int16 valor;
  24.  
  25. #priority  ssp, timer0, timer1    
  26. /*
  27. #int_RTCC
  28. void  RTCC_isr(void)
  29. {
  30.  
  31. }
  32. */
  33. #int_TIMER0
  34. void  TIMER0_isr(void)
  35. {  
  36.    
  37.    output_high (servos[cnt_t0-1]);             //activo servo
  38.    //ventana de 1 ms cambio de svmotor
  39.      
  40.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);   //activo timer1
  41.    //valor = t_on(630); //convierte us en tick --<> no va bien
  42.    
  43.    //printf("\n\r tick: %ld "valor);
  44.    set_timer1(g_0);  //tiempo en alto
  45.    
  46.    set_timer0(ventana);             //ventana desborda cada Xms
  47.    //printf("\n\r cnt_t0: %d"cnt_t0);
  48.    if(cnt_t0==5){ //cambio de ventana
  49.       cnt_t0=0;
  50.       //printf("\n\r -->T0 1ms 20 ventanas  1 perido");
  51.    }
  52.  
  53.    //printf("\n\r cnt_t0: %d "cnt_t0);
  54.    //cnt_t0=cnt_t0+1; //incremta ventana => motor
  55. }
  56.  
  57. #int_TIMER1
  58. void  TIMER1_isr(void)
  59. {
  60. output_low (servos[cnt_t0-1]);     //apago motor
  61. //printf("\n\r OFF servo: %d "cnt_t0-1);
  62. cnt_t0=cnt_t0+1;                 // incremta ventana => motor
  63. setup_timer_1(0);                // desactivo timer 1
  64.  
  65. }
  66.  
  67.  
  68. #int_SSP
  69. void  SSP_isr(void){
  70. //disable_interrupts(INT_SSP);
  71. //disable_interrupts(INT_TIMER0);
  72. //disable_interrupts(INT_TIMER1);
  73. //int8 comando;
  74. //master escribe de esclavo  menor de <80
  75. //master lee de esclavo      mayor de >80
  76.  
  77. state = i2c_isr_state();
  78.    if(state==0)
  79.    {
  80.       direc_Mas_esc=i2c_read();
  81.       if(direc_Mas_esc==S1){
  82.       ////////////////////////////////
  83.       printf("\n\r --> Direccion: %X "direc_Mas_esc); //--- debug mas rapido
  84.       ////////////////////////////////
  85.          recivo=1;
  86.          output_high(PIN_B2);  //---debug rapido
  87.       }
  88.      
  89.       //printf("\n\r Direccion : %X "direc_Mas_esc); //para solo imprime s1
  90.       //if(SSPADD==S1){
  91.       //printf("\n\r state==0 soy S1: %X "SSPADD);
  92.       //}
  93.      
  94.    }
  95.    
  96.    if(state < 0x80)
  97.    {
  98.      
  99.       //iic_dato=i2c_read();
  100.       //comando=iic_dato;
  101.       if(recivo==1){
  102.          dato[cnt]=i2c_read();
  103.          
  104.          // coreccion para lo de error en dato=1
  105.          if(dato[cnt]==10){
  106.            dato[cnt]=1;
  107.          }
  108.          
  109.          if(dato[0]==1){ // control de motor
  110.             output_high(PIN_B6);
  111.             motor_on=1;
  112.          }
  113.          
  114.          if(dato[cnt]!=0){ //control de angulo
  115.             angulo=dato[1];
  116.             inclina=dato[2];
  117.          }
  118.          ///////////////////////
  119.          
  120.          /////////////////////////////
  121.          printf("\n\r dato[%u]:%u"cnt,dato[cnt]);  //-- debug +rapido
  122.          /////////////////////////////
  123.          recivo=0;
  124.          output_low(PIN_B2);  //--- debug rapido
  125.          
  126.          // para resetear almacen dato
  127.          if(dato[cnt]==99){  //cnt resetea en 3 si es 99
  128.            cnt=0;
  129.          }
  130.          else{
  131.            cnt=cnt+1;
  132.          }
  133.          
  134.       }
  135.      
  136.      
  137.      
  138.  
  139.      
  140.  
  141.      
  142.       //Aqui colocas lo que necesites hacer con el dato enviado por el maestro
  143.       //printf("\n\r comando recibo <80: %u"comando);
  144.      
  145.    }
  146.    if(state == 0x80)
  147.    {
  148.     /*
  149.     switch(comando)
  150.       {
  151.          Case Pide_Dato1:
  152.             i2c_write(Dato1);
  153.             output_high(PIN_B7);
  154.             delay_ms(300);
  155.             output_low(PIN_B7);
  156.            
  157.             printf("\n\r Llego dato.");
  158.             break;
  159.          Case Pide_Dato2:
  160.             i2c_write(Dato2);
  161.             output_high(PIN_B2);
  162.             break;
  163.       }
  164.       */
  165.    }
  166. enable_interrupts(INT_SSP);  //para imprimir completo priff del main
  167. //enable_interrupts(INT_TIMER0);
  168. //enable_interrupts(INT_TIMER1);
  169. }
  170.  
  171.  
  172. #int_BUSCOL
  173. void  BUSCOL_isr(void)
  174. {
  175.  
  176. }
  177.  
  178.  
  179.  
  180. void main()
  181. {
  182.  
  183.    setup_adc_ports(NO_ANALOGS|VSS_VDD);
  184.    setup_adc(ADC_CLOCK_DIV_2);
  185.    setup_wdt(WDT_OFF);
  186.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  187.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  188.    setup_timer_2(T2_DISABLED,0,1);
  189.    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
  190.    setup_comparator(NC_NC_NC_NC);
  191.    setup_vref(FALSE);
  192.    enable_interrupts(INT_RTCC);
  193.    enable_interrupts(INT_TIMER0);
  194.    enable_interrupts(INT_TIMER1);
  195.    enable_interrupts(INT_SSP);
  196.    enable_interrupts(INT_BUSCOL);
  197.    enable_interrupts(GLOBAL);
  198. //Setup_Oscillator parameter not selected from Intr Oscillator Config tab
  199.  
  200.    // TODO: USER CODE!!
  201. set_timer0(ventana);
  202. setup_timer_1(T1_DISABLED);  // timer 1 no activo
  203. //set_timer1(0);
  204.  
  205. printf("\n\r Prueba de timer: ");
  206.  
  207.    while(true){
  208.       if(t0==2){
  209.          printf("\n\r -->T0 20ms");
  210.       }
  211.       if(t1==4){
  212.          printf("\n\r -->T1 40ms");
  213.       }
  214.       enable_interrupts(INT_SSP);
  215.       enable_interrupts(INT_TIMER0);
  216.       enable_interrupts(INT_TIMER1);  
  217.    }
  218. }

y asi su cabecera:

Código: C++
  1. #include <18F2550.h>
  2. #device adc=8
  3.  
  4. #FUSES NOWDT                    //No Watch Dog Timer
  5. #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
  6. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
  7. #FUSES NOPROTECT                //Code not protected from reading
  8. #FUSES NOBROWNOUT               //No brownout reset
  9. #FUSES BORV20                   //Brownout reset at 2.0V
  10. #FUSES NOPUT                    //No Power Up Timer
  11. #FUSES NOCPD                    //No EE protection
  12. #FUSES STVREN                   //Stack full/underflow will cause reset
  13. #FUSES NODEBUG                  //No Debug mode for ICD
  14. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  15. #FUSES NOWRT                    //Program memory not write protected
  16. #FUSES NOWRTD                   //Data EEPROM not write protected
  17. #FUSES IESO                     //Internal External Switch Over mode enabled
  18. #FUSES FCMEN                    //Fail-safe clock monitor enabled
  19. #FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
  20. #FUSES NOWRTC                   //configuration not registers write protected
  21. #FUSES NOWRTB                   //Boot block not write protected
  22. #FUSES NOEBTR                   //Memory not protected from table reads
  23. #FUSES NOEBTRB                  //Boot block not protected from table reads
  24. #FUSES NOCPB                    //No Boot Block code protection
  25. #FUSES MCLR                     //Master Clear pin enabled
  26. #FUSES LPT1OSC                  //Timer1 configured for low-power operation
  27. #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
  28. #FUSES PLL12                    //Divide By 12(48MHz oscillator input)
  29. #FUSES CPUDIV4                  //System Clock by 4
  30. #FUSES USBDIV                   //USB clock source comes from PLL divide by 2
  31. #FUSES VREGEN                   //USB voltage regulator enabled
  32.  
  33. //timer 0
  34. /*
  35. #DEFINE T0CON 0xFD5     // timer0
  36. #DEFINE T1CON 0xFCD     // timert1
  37.  
  38. #BIT TMR0ON = T0CON.7   // valor enable del timer0 1=on, 0=Off
  39. #BIT RD16 = T1CON.7     // valor enable del timer0 1=on, 0=Off
  40.  
  41. #define TIMER1_ON RD16
  42. */
  43.  
  44. // --- esclavos  --------------------------------
  45. #define S1 0xB0
  46. #define S2 0xB2
  47. #define S4 0xB4
  48. #define S6 0xB6
  49. #define S8 0xB8
  50.  
  51. // ----- define los servos ----------------------
  52. #define sv_0 PIN_B7
  53. #define sv_1 PIN_B6
  54. #define sv_2 PIN_C1
  55. #define sv_3 PIN_C2
  56. #define sv_4 PIN_C0
  57. /*
  58. #define sv_5 PIN_B7
  59. #define sv_6 PIN_B6
  60. #define sv_7 PIN_B5
  61. #define sv_8 PIN_B4
  62. #define sv_9 PIN_B3
  63. */
  64.  
  65. // TIMER 2 exp 16 bit : 65536 tick 0.2us -->13107.2us 1 INT
  66.  
  67. // ---- perido de 20 ms 20000us -------------------------------
  68. //      1 tick ........ 0.2us
  69. //      5 tick ........ 1  us
  70.  
  71. // ----- ventana o cambio motor -------------------------------
  72. //                                      Tick para us en on
  73. //const int16 ventana = 60536;  // 65536 -  5000 = 1ms 1000us
  74. const int16 ventana = 55536;  // 65536 - 10000 = 2ms 2000us
  75. //const int16 ventana = 50536;  // 65536 - 15000 = 3ms 3000us
  76. //const int16 ventana = 45536;  // 65536 - 20000 = 4ms 4000us
  77. //const int16 ventana = 40536;  // 65536 - 25000 = 5ms 5000us
  78. //const int16 ventana = 15536;  // 65536 - 50000 = 10ms 10000us
  79.  
  80. #define max_v  10 /maxima ventana
  81.  
  82. //1 tick -------- 0.2us
  83. //x tick -------- y  us
  84.  
  85. // ----- tick para tiempo en ON -------------------------------
  86.  
  87. // --- generico ---------------------
  88. //const int16 g_0    = 63036;    //65536 -  2500  0.5ms  500us
  89. //const int16 g_90   = 58036;    //65536 -  7500  1.5ms 1500us
  90. //const int16 g_180  = 53036;    //65536 - 12500  2.5ms 2500us
  91. //-------------------------------------------------------------
  92.  
  93. // --- mis tick ---------------------
  94.  
  95. //conts inr16 g_1    = .....;    //65536 - .....  .....ms  ...us
  96. const int16 g_0    = 64936;    //65536 -   600  0.120ms  120us
  97. const int16 g_90   = 63661;    //65536 -  1875  0.375ms  375us
  98. const int16 g_180  = 62386;    //65536 -  3150  0.630ms  630us
  99.  
  100. //-----------------------------------------------------------------------
  101. // calculos con todos lo decimales y 65536 resta de tick solo parte entera
  102. // 375us -120us = 255us
  103. // 255us  ---<> 90 grados 255 /90 = 2.833333(periodo) cada grado
  104. // 2.8us grado --->> 14 tick por grado(con error de 0.3333)
  105. //------------------------------------------------------------------------
  106. // opero por angulos conocidos
  107. // 5tick = 1us ---<> Tus x5 = Ttick
  108. //------------------------------------------------------------------------
  109. // referencia de 120 us por ser superior a 0 grados
  110.  
  111. //const int16 g_0    = 64936;    //65536 -   600  0.120ms  120us
  112. const int16 g_15   = 64724;    //65536 -  812  255us/6 = 42us  +120us = 162us
  113. const int16 g_30   = 64511;    //65536 - 1025  255us/3 = 85us  +120us = 205us
  114.  
  115. const int16 g_45   = 64299;    //65536 - 1237  255us/2 = 127us +120us = 247us
  116. const int16 g_60   = 64086;    //65536 - 1450  255us/3 = 85us*2+120us = 290us
  117. const int16 g_75   = 63874;    //65536 - 1662  255us/6 = 42us*5+120us = 332us
  118.  
  119. // referecnia de 375us por ser superior a 90 grados
  120. //const int16 g_90   = 63661;    //65536 -  1875  0.375ms  375us
  121. const int16 g_105  = 63449;    //65536 - 2087  255us/6 = 42us  +375us = 417us
  122. const int16 g_120  = 63236;    //65536 - 2300  255us/3 = 85us  +375us = 460us
  123. const int16 g_135  = 63024;    //63536 - 2512  255us/6 = 42us*3+375us = 502us
  124.  
  125. const int16 g_150  = 62811;    //65536 - 2725  255us/3 = 85us*2+375us = 545us
  126. const int16 g_165  = 62599;    //65536 - 2937  255us/6 = 42us*5+375us = 587us
  127. //const int16 g_180  = 62386;    //65536 -  3150  0.630ms  630us
  128.  
  129.  
  130. // --- vector inicializacion y angulos servos ----------------------
  131.  
  132. static int16 valor_PWM[]={g_0, g_45, g_60, g_90, g_120, g_135, g_180};
  133. static int16 ini_PWM[]={g_90, g_90, g_90, g_90,0,0,0,0}; //8 servos
  134.  
  135. #define Pide_Dato1 2
  136. #define Pide_Dato2 3
  137. #define dato1 4
  138. #define dato2 5
  139.  
  140. #use delay(clock=20000000)
  141. //#define I2C_SCL   PIN_B7
  142. //#define I2C_SDA   PIN_C4
  143. #use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
  144. #use i2c(Slave,Slow,sda=PIN_B0,scl=PIN_B1,address=0xB0)
  145. //#include "milib.c"
  146.  
  147.  
  148. //--------- milib.c-------------
  149.  
  150. //convierte us en tick de reloj
  151. // 1us ---> 5tick
  152. // xus ---> y tick
  153. int16 t_on(int16 us_on){
  154.    int16 tick_on;
  155.  
  156.       tick_on= 65536 - (us_on * 5);
  157. return tick_on;
  158.  
  159. }


ya solo falta daptar el codido para que se modifique
con un vector y este a su vez lo cambiaremos por i2c.



« Última modificación: 19 de Agosto de 2012, 10:44:26 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #63 en: 18 de Agosto de 2012, 15:29:19 »
  Para uso de Potenciómetro la cosa es bien sencilla...

  Tomemos como ejemplo tus datos, el mínimo 120uS y el máximo 630uS.
  Si se utiliza cristal de 20MHz, el tiempo de instrucción (el que contaran los timers) es de 200nS

   Para lograr 120uS, el timer tiene que contar 120uS/200nS = 600. El valor a precargar 65536 - 600 --> 64936
   Para lograr 630uS la cuenta será 630uS/200nS = 3150. El valor a precargar 65536 - 3150 --> 62386

Esos valores son estimados, ya que seguramente habrá que hacer ligeros ajustes.

  Volvamos a la ecuación de la recta.

Y = aX +b

donde "Y" será el valor que tiene que contar el timer (600 para el mínimo y 3150 para el máximo)
"a" sería el valor leído por el ADC. (para el mínimo es 0 y para el máximo es 1023)

usando esa fórmula para el mínimo nos da

600 = 0X + b --> 600 = b, con lo cual ya tenemos el valor de b

volvemos a la fórmula pero para calcular el máximo

3150 = 1023X + 600 --> 3150-600 = 1023X --> X = 2550/1023 --> X = 2.49

por lo tanto la fórmula final nos queda

Y = ((valor ADC) * 2.49 + 600)

precargar del timer = 65536 - Y

-----------

  Para el tema de grados por ticks creo que sería así...

  3150-600 --> 180º --> 2550 = 180º luego

  2550/180 --> 14.16 = 1º
 
Esto implicaría que a partir de 600 (que es el mínimo), si quieres moverte de a 1 º deberás incrementar los ticks en 14.16,

Ejemplo: si tu centro es 375, (90º) si pones 375 + 14.16 = 91º --> 389 = 91º.

Eso, obviamente, será aproximado porque se pierden decimales.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #64 en: 19 de Agosto de 2012, 10:40:02 »
Hola AngelGris

modifique algunos pos anteriores y lo que hago es practicamante lo que dices
pero yo cogi todos lo decimales ya que la diferencia puedes ser varios tick

Buena explicacion lo del potenciometro, si señor. ((:-))
muy bien explicado.

Entre linea veo que la resolución del conversor la tienes en 10 bit -->1023
imagino que a mayor resolucion mayor sensibilidad.

El potenciometro que le pones es de 1k o es de otro valor?
¿cual recomendarias?
esto del potenciometro tengo ganas de probarlo....!


« Última modificación: 19 de Agosto de 2012, 10:50:18 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #65 en: 19 de Agosto de 2012, 11:44:44 »
Hola AngelGris

modifique algunos pos anteriores y lo que hago es practicamante lo que dices
pero yo cogi todos lo decimales ya que la diferencia puedes ser varios tick


  Sí, es cierto que los decimales pueden generar una variación importante de ticks. Pero de todas maneras recuerda que cuando trabajas con la precarga lo haces con una variable entera por lo tanto no toma en cuenta los decimales.

  A no ser que te manejes con variables float y sólo hagas un cast al momento de cargar el timer. De esa manera el error será un poco menor.

  Si suponemos que el valor por grado es 14.5, al pasarlo a integer es 14. Si lo manejas directamente como integer, dos incrementos darán 28. Pero si lo manejas como float dos incrementos darán 29.



Buena explicacion lo del potenciometro, si señor. ((:-))
muy bien explicado.

Entre linea veo que la resolución del conversor la tienes en 10 bit -->1023
imagino que a mayor resolucion mayor sensibilidad.

El potenciometro que le pones es de 1k o es de otro valor?
¿cual recomendarias?
esto del potenciometro tengo ganas de probarlo....!


  El ADC está en 10 bits porque es la resolución que tiene el PIC. Estoy utilizando un pote de 5K lineal
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #66 en: 19 de Agosto de 2012, 16:06:01 »
Hola
ya monte el potenciometro y parece que funciona, :-/
pero encontre algunos problemas, :? en mi caso tenia a mano un potenciometro de 1k
y descubri que con el 600us no se queda en la posicion 0º perpendicular como pasa
si lo hago por variable y tambien he descubierto que en el extremo opuesto no llega a los 180º
le faltan unos 45 grados, lo bueno seria que no se forzase el potenciometro a los extremos y que tampoco
se forzase al servo motor en sus extremo.

En el modo variable lo tengo de tal forma que en sus extremo sobra camino y asi no se fuerza el servo.

He intentado en hacer coincidir el centro del potenciomnetro con el del servo, pero fue imposible.

Intente comparar el problema, con el de algunas emisora, en ellas tienen otros 2 potenciometros para
aumentar la sensibilidad y pense que eso podria ser una solucion.

Seguro que hay otras posibilidades, si ustedes quisieran compartirlas yo las podria conocer...!

Alguna idea de como hacer esto?


« Última modificación: 19 de Agosto de 2012, 19:45:28 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #67 en: 20 de Agosto de 2012, 11:54:10 »
  Es muy raro ello.

  Te muestro un video con un 18F2550, un pote de 10K lineal y un MicroServo E-Sky.
feature=youtu.be

  Fijate que hacia la derecha el servo hace un pequeño salto. En la señal del osciloscopio también se aprecia que cuando el pulso está casi llegando a la mayor duración hace una pequeña falla.
Si ajusto muy finamente el pote, desaparece el pulso. Este mismo defecto lo note en Proteus, por lo tanto es algún inconveniente en el código.

  Aclaro que el servo no está centrado porque estaba colocado en un alerón de un avión de depron, y justamente necesitaba un movimiento diferencial.

  La base de tiempo del osciloscopio está ajustada a 1mV/Div

  La filmación no es muy buena porque está realizada con una cámara fotográfica un tanto viejita.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #68 en: 20 de Agosto de 2012, 13:12:19 »
Hola AngelGris

El potenciometro que uso es un piher,
de testos para meterle un palito y fijarlo a un valor

esta es la foto:

modelo PT10LV.

http://www.tme.eu/html/gfx/ramka_294.jpg
http://www.retroamplis.com/WebRoot/StoreES2/Shops/62070367/4BA8/A509/E673/EC99/A4B6/C0A8/28BC/1310/PT10_PIHER.jpg
http://www.tiendaelectronica.com.ve/788-989-home/trimmer-20k.jpg

recuerdo que tambien tengo 1 de eso que giran 300º y de mango muy lardo a lo mejor lo pruebo con el.

http://www.pinchaycompra.com/24383-55-large/potenciometro.jpg

Puede que lo ponga a ver,
de todas formas coloco la funcion que uso para el potenciometro
puede qur yo no le vea el error..

no se que pensar ... me pasan unas cosas mas raras..

cabaecera con la  funcion :

Código: C++
  1. #include <18F2550.h>
  2. #device adc=10
  3.  
  4. #FUSES NOWDT                    //No Watch Dog Timer
  5. #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
  6. #FUSES HS                       //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
  7. #FUSES NOPROTECT                //Code not protected from reading
  8. #FUSES NOBROWNOUT               //No brownout reset
  9. #FUSES BORV20                   //Brownout reset at 2.0V
  10. #FUSES NOPUT                    //No Power Up Timer
  11. #FUSES NOCPD                    //No EE protection
  12. #FUSES STVREN                   //Stack full/underflow will cause reset
  13. #FUSES NODEBUG                  //No Debug mode for ICD
  14. #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
  15. #FUSES NOWRT                    //Program memory not write protected
  16. #FUSES NOWRTD                   //Data EEPROM not write protected
  17. #FUSES IESO                     //Internal External Switch Over mode enabled
  18. #FUSES FCMEN                    //Fail-safe clock monitor enabled
  19. #FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
  20. #FUSES NOWRTC                   //configuration not registers write protected
  21. #FUSES NOWRTB                   //Boot block not write protected
  22. #FUSES NOEBTR                   //Memory not protected from table reads
  23. #FUSES NOEBTRB                  //Boot block not protected from table reads
  24. #FUSES NOCPB                    //No Boot Block code protection
  25. #FUSES MCLR                     //Master Clear pin enabled
  26. #FUSES LPT1OSC                  //Timer1 configured for low-power operation
  27. #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
  28. #FUSES PLL12                    //Divide By 12(48MHz oscillator input)
  29. #FUSES CPUDIV4                  //System Clock by 4
  30. #FUSES USBDIV                   //USB clock source comes from PLL divide by 2
  31. #FUSES VREGEN                   //USB voltage regulator enabled
  32.  
  33. ...
  34. ...
  35. //---------- para potenciomentro -----
  36. // y = Xa + b
  37. //
  38. // y=tick  a contar
  39. // x= valor del ADC 0-1023
  40. // b=tick del minimo,   (off-set)
  41. //
  42. // valor minio     0º ---> 120us ---> 600 tick
  43. // valor maximo  180º ---> 630us --->3150 tick
  44.  
  45. // ----valor minimo
  46. //  y   =  ( X   * a ) + b
  47. // 600  =  ( 0   * a ) + b  --> b=600
  48.  
  49. // --- valor maximo
  50. //  y   =  X   * a  +  b
  51. // 3150 = 1023 * a  + 600  --> a = (3150 - 600) / 1023
  52. //
  53. // a = 2550 /1023 --> 2.49
  54.  
  55. // Y = ( ((valor ADC) * 2.49) + 600)
  56.  
  57. //precargar del timer = 65536 - Y
  58.  
  59. int16 potenciometro
  60. (int16 min_tick,int16 max_tick,int16 min_res,int16 max_res,int16 valor_adc ){
  61.  
  62. int16 p_tick;
  63.  
  64. p_tick = 65536 - ( (valor_adc * ((max_tick - min_tick)/max_res)) + min_res);
  65.  
  66. return p_tick;
  67. }


y como la implemento en el codigo principal:

Código: C++
  1. //variables i2c
  2. int8 state, comando;
  3. //int8 iic_dato, Direc_master;
  4. int8 direc_Mas_esc, recivo=0;
  5. int8 dato[4];
  6. //int8 dato_1[4];
  7. int8 cnt=0;
  8. int8 angulo;
  9. int8 inclina;
  10. int8 motor_on;
  11.  
  12. //servos pwm soft
  13. int8 servos[]={sv_0,sv_1,sv_2,sv_3,sv_4,0,0,0,0,0};
  14.  
  15.  
  16. //variables timer
  17. int8 cnt_t0=0;
  18. int8 cnt_t1=0;
  19. int1 t0=0;
  20. int1 t1=0;
  21.  
  22. //debug tick
  23. int16 valor, valor1;
  24.  
  25. #priority  ssp, timer0, timer1    
  26. /*
  27. #int_RTCC
  28. void  RTCC_isr(void)
  29. {
  30.  
  31. }
  32. */
  33. #int_TIMER0
  34. void  TIMER0_isr(void)
  35. {  
  36.    
  37.    output_high (servos[cnt_t0-1]);             //activo servo
  38.    //ventana de 1 ms cambio de svmotor
  39.      
  40.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);   //activo timer1
  41.    //valor = t_on(630); //convierte us en tick --<> no va bien
  42.    
  43.    valor=read_adc();
  44.    //printf("\n\r ADC: %ld" valor);
  45.    valor1=potenciometro(600,3150,0,1023,valor);
  46.    
  47.    //printf("\n\r tick: %ld "valor);
  48.    //set_timer1(g_0);  //tiempo en alto
  49.    set_timer1(valor1);
  50.    
  51.    set_timer0(ventana);             //ventana desborda cada Xms
  52.    
  53.    
  54.    
  55.    //printf("\n\r cnt_t0: %d"cnt_t0);
  56.    if(cnt_t0==5){ //cambio de ventana
  57.       cnt_t0=0;
  58.       //printf("\n\r -->T0 1ms 20 ventanas  1 perido");
  59.    }
  60.  
  61.    //printf("\n\r cnt_t0: %d "cnt_t0);
  62.    //cnt_t0=cnt_t0+1; //incremta ventana => motor
  63. }
  64.  
  65. #int_TIMER1
  66. void  TIMER1_isr(void)
  67. {
  68. output_low (servos[cnt_t0-1]);     //apago motor
  69. //printf("\n\r OFF servo: %d "cnt_t0-1);
  70. cnt_t0=cnt_t0+1;                 // incremta ventana => motor
  71. setup_timer_1(0);                // desactivo timer 1
  72.  
  73. }
  74.  
  75.  
  76. #int_SSP
  77. void  SSP_isr(void){
  78. //disable_interrupts(INT_SSP);
  79. //disable_interrupts(INT_TIMER0);
  80. //disable_interrupts(INT_TIMER1);
  81. //int8 comando;
  82. //master escribe de esclavo  menor de <80
  83. //master lee de esclavo      mayor de >80
  84.  
  85. state = i2c_isr_state();
  86.    if(state==0)
  87.    {
  88.       direc_Mas_esc=i2c_read();
  89.       if(direc_Mas_esc==S1){
  90.       ////////////////////////////////
  91.       printf("\n\r --> Direccion: %X "direc_Mas_esc); //--- debug mas rapido
  92.       ////////////////////////////////
  93.          recivo=1;
  94.          output_high(PIN_B2);  //---debug rapido
  95.       }
  96.      
  97.       //printf("\n\r Direccion : %X "direc_Mas_esc); //para solo imprime s1
  98.       //if(SSPADD==S1){
  99.       //printf("\n\r state==0 soy S1: %X "SSPADD);
  100.       //}
  101.      
  102.    }
  103.    
  104.    if(state < 0x80)
  105.    {
  106.      
  107.       //iic_dato=i2c_read();
  108.       //comando=iic_dato;
  109.       if(recivo==1){
  110.          dato[cnt]=i2c_read();
  111.          
  112.          // coreccion para lo de error en dato=1
  113.          if(dato[cnt]==10){
  114.            dato[cnt]=1;
  115.          }
  116.          
  117.          if(dato[0]==1){ // control de motor
  118.             output_high(PIN_B6);
  119.             motor_on=1;
  120.          }
  121.          
  122.          if(dato[cnt]!=0){ //control de angulo
  123.             angulo=dato[1];
  124.             inclina=dato[2];
  125.          }
  126.          ///////////////////////
  127.          
  128.          /////////////////////////////
  129.          printf("\n\r dato[%u]:%u"cnt,dato[cnt]);  //-- debug +rapido
  130.          /////////////////////////////
  131.          recivo=0;
  132.          output_low(PIN_B2);  //--- debug rapido
  133.          
  134.          // para resetear almacen dato
  135.          if(dato[cnt]==99){  //cnt resetea en 3 si es 99
  136.            cnt=0;
  137.          }
  138.          else{
  139.            cnt=cnt+1;
  140.          }
  141.          
  142.       }
  143.      
  144.      
  145.      
  146.  
  147.      
  148.  
  149.      
  150.       //Aqui colocas lo que necesites hacer con el dato enviado por el maestro
  151.       //printf("\n\r comando recibo <80: %u"comando);
  152.      
  153.    }
  154.    if(state == 0x80)
  155.    {
  156.     /*
  157.     switch(comando)
  158.       {
  159.          Case Pide_Dato1:
  160.             i2c_write(Dato1);
  161.             output_high(PIN_B7);
  162.             delay_ms(300);
  163.             output_low(PIN_B7);
  164.            
  165.             printf("\n\r Llego dato.");
  166.             break;
  167.          Case Pide_Dato2:
  168.             i2c_write(Dato2);
  169.             output_high(PIN_B2);
  170.             break;
  171.       }
  172.       */
  173.    }
  174. enable_interrupts(INT_SSP);  //para imprimir completo priff del main
  175. //enable_interrupts(INT_TIMER0);
  176. //enable_interrupts(INT_TIMER1);
  177. }
  178.  
  179.  
  180. #int_BUSCOL
  181. void  BUSCOL_isr(void)
  182. {
  183.  
  184. }
  185.  
  186.  
  187.  
  188. void main()
  189. {
  190.  
  191.    setup_adc_ports(AN0|VSS_VDD);
  192.    setup_adc(ADC_CLOCK_DIV_2);
  193.    set_adc_channel(0);
  194.    setup_wdt(WDT_OFF);
  195.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  196.    setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
  197.    setup_timer_2(T2_DISABLED,0,1);
  198.    
  199.    setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
  200.    setup_comparator(NC_NC_NC_NC);
  201.    setup_vref(FALSE);
  202.    enable_interrupts(INT_RTCC);
  203.    enable_interrupts(INT_TIMER0);
  204.    enable_interrupts(INT_TIMER1);
  205.    enable_interrupts(INT_SSP);
  206.    enable_interrupts(INT_BUSCOL);
  207.    enable_interrupts(GLOBAL);
  208. //Setup_Oscillator parameter not selected from Intr Oscillator Config tab
  209.  
  210.    // TODO: USER CODE!!
  211. set_timer0(ventana);
  212. setup_timer_1(T1_DISABLED);  // timer 1 no activo
  213. //set_timer1(0);
  214.  
  215. printf("\n\r Prueba de timer: ");
  216.  
  217.    while(true){
  218.       if(t0==2){
  219.          printf("\n\r -->T0 20ms");
  220.       }
  221.       if(t1==4){
  222.          printf("\n\r -->T1 40ms");
  223.       }
  224.       enable_interrupts(INT_SSP);
  225.       enable_interrupts(INT_TIMER0);
  226.       enable_interrupts(INT_TIMER1);  
  227.    }
  228. }

en proteus al simularlo se atasca un poco
con el potenciometro al 8% ya llega al 0.98
tiene mas rango en la parte del cero que en la de por encima del 0

voy a printer por terminal virtual lo que me lea el conversor ...

me lee 0 y al principio en 0 con letras,
como es posible ....

para printerar int16 es  %lu

en el cabecera le puse #device adc=10
leo por el canal 0 AN0

su configuracion es esta:

 
setup_adc_ports(AN0|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
set_adc_channel(0);


que se me escapa..?

ya empiezan los poltergeist..!.

« Última modificación: 20 de Agosto de 2012, 13:28:17 por pajaro »

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #69 en: 20 de Agosto de 2012, 14:04:43 »
  A mi entender estás complicando demasiado el código... no tiene sentido llamar a una función para que te devuelva el valor a precargar.

  Tampoco es bueno hacer todo eso dentro de la rutina de interrupción. También debes procurar buscar una buena configuración del ADC. Fijate en el datasheet cuál es la velocidad máxima del ADC para un cristal de 20MHz.

  Creo que si haces ADC_CLOCK_DIV_2, la frecuencia del ADC será 20MHz/2 --> 10MHz --> tiempo TAD = 100nS, siendo que el TAD mínimo -según datasheet- es de 700nS..

  Esta es la muestra de mi código en SDCC.

Código: C
  1. #include <pic18fregs.h>
  2. #include <adc.h>
  3.  
  4. static __code char __at (__CONFIG1L) CONFIG1L = _USBPLL_CLOCK_SRC_FROM_OSC1_OSC2_1L &
  5.                    _CPUDIV__OSC1_OSC2_SRC___1__96MHZ_PLL_SRC___2__1L;
  6. static __code char __at (__CONFIG1H) CONFIG1H = _OSC_HS__USB_HS_1H & _FCMEN_OFF_1H &
  7.                    _IESO_OFF_1H;
  8. static __code char __at (__CONFIG2L) CONFIG2L = _VREGEN_OFF_2L & _PUT_OFF_2L & _BODEN_OFF_2L;
  9. static __code char __at (__CONFIG2H) CONFIG2H = _WDT_DISABLED_CONTROLLED_2H;
  10. static __code char __at (__CONFIG3H) CONFIG3H = _MCLRE_MCLR_OFF_RE3_ON_3H &
  11.                    _PBADEN_PORTB_4_0__CONFIGURED_AS_DIGITAL_I_O_ON_RESET_3H;
  12. static __code char __at (__CONFIG4L) CONFIG4L = _LVP_OFF_4L;
  13.  
  14. unsigned char parte_baja;
  15. unsigned char parte_alta;
  16.  
  17. void timers(void) __shadowregs __interrupt 1       // interrupcion alta prioridad
  18. {
  19.   static unsigned int salida = 1;
  20.   static unsigned char indice = 0;
  21.  
  22.   if ((INTCONbits.TMR0IE) && (INTCONbits.TMR0IF))  //interrupcion por timer0, cada 2mS
  23.   {
  24.     LATB = salida;         // salida correspondiente en 1
  25.     T1CONbits.TMR1ON = 1;  // enciendo el timer1
  26.     TMR0L = 0x4E;          
  27.     TMR0H = 0xCF;          // precargo nuevamente el timer0 (para que desborde cada 2mS)
  28.     salida = salida << 1;  
  29.     indice++;              // incremento el indice para el tiempo en alto
  30.     if (salida == 256)
  31.     {
  32.       salida = 1;
  33.       indice = 0;
  34.     }  
  35.    // precargo el timer1 con el valor correspondiente
  36.     TMR1L = parte_baja;
  37.     TMR1H = parte_alta;
  38.     INTCONbits.T0IF = 0;           // borro el flag interrupcion del timer0
  39.   }
  40.   if ((PIE1bits.TMR1IE) && (PIR1bits.TMR1IF))  // interrupcion timer1, el tiempo en alto
  41.   {
  42.     LATBbits.LATB0 = 0;           // pongo en 0 la salida actual
  43.     T1CONbits.TMR1ON = 0;         // apago el timer1
  44.     PIR1bits.TMR1IF = 0;          // borro el flag de interrupcion del timer1
  45.   }
  46. }
  47.  
  48.  
  49. void main(void)
  50. {
  51.   unsigned int valor_adc;
  52.   unsigned int valor_adc_anterior;
  53.   unsigned int pwm;
  54.  
  55.   TRISB = 0;
  56.  
  57.   // configuro los timers y les precargo un valor
  58.  
  59.   T0CON = 0x08;
  60.   T1CON = 0x80;
  61.   TMR1L = 0x77;
  62.   TMR1H = 0xEC;
  63.   TMR0L = 0x4E;
  64.   TMR0H = 0xCF;
  65.  
  66.   // habilito prioridades de interrupcion
  67.  
  68.   RCONbits.IPEN = 1;
  69.  
  70.   // el timer0 y timer1 alta prioridad
  71.  
  72.   INTCON2bits.TMR0IP = 1;
  73.   IPR1bits.TMR1IP = 1;
  74.   PIE1bits.TMR1IE = 1;
  75.   INTCONbits.TMR0IE = 1;
  76.   INTCONbits.GIEH = 1;
  77.  
  78.   T0CONbits.TMR0ON = 1;   // enciendo el timer0
  79.   adc_open(ADC_CHN_0, ADC_FOSC_16 | ADC_ACQT_4, ADC_CFG_1A, ADC_FRM_RJUST | ADC_INT_OFF | ADC_VCFG_VDD_VSS);
  80.  
  81.   while(1)
  82.   {
  83.     adc_conv();
  84.     while (adc_busy() == 1);
  85.     valor_adc = adc_read();
  86.     if (valor_adc != valor_adc_anterior)
  87.     {
  88.       valor_adc_anterior = valor_adc;
  89.  
  90.      // el calculo es 65536 - ((float)(valor_adc) * 4.887 + 5000)
  91.  
  92.       pwm = 65536- ((float)(valor_adc) * 4.887 + 4948); // uso 4948 para compenzar
  93.       parte_baja = pwm & 0x0FF;
  94.       parte_alta = pwm >> 8;
  95.     }
  96.   }
  97. }

  Fijate que hago la lectura del ADC dentro del main del programa en un ciclo while y no en la interrupción.
En mi caso leo un solo canal del ADC, pero se podría recurrir a un ciclo for para hacer la lectura de los distintos canales.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #70 en: 20 de Agosto de 2012, 15:40:25 »
Hola AngelGris
lo delas divisiones lo puse asi
porque en el asistente de proyectos es el minimo no te deja
la opcion de 1:1 ese es el minimo la resolucion 255, 1023, 65536
lo que se corresponde con 8 bit, 10 bit y 16 bits, y lo otro que deja
es el votaje y el tipo de entrada, no hay mas.

En el data del pic18F2550 busque eso de las frecuencias:




     TAD vs. DEVICE OPERATING FREQUENCIES

               AD Clock Source (TAD)                 Maximum Device Frequency

           Operation      ADCS2:ADCS0         PIC18FXXXX     PIC18LFXXXX(4)

1.           2 TOSC           000                         2.86 MHz       1.43 MHz
2.           4 TOSC           100                         5.71 MHz       2.86 MHz
3.           8 TOSC           001                       11.43 MHz       5.72 MHz
4.         16 TOSC           101                       22.86 MHz      11.43 MHz
5.         32 TOSC           010                       45.71 MHz      22.86 MHz
6.         64 TOSC           110                       48.0 MHz        45.71 MHz

RC(3) x11 1.00 MHz(1) 1.00 MHz(2)

Note 1: The RC source has a typical TAD time of 4 ms.
2: The RC source has a typical TAD time of 6 ms.
3: For device frequencies above 1 MHz,
    the device must be in Sleep for the entire conversion or the A/D
    accuracy may be out of specification.
4: Low-power devices only.


si lo quisiera poner lo mas rapido posiblesin que atropelle a nadie
deberia de poner el punto 4. o el tunto 1.,
y el divisor en vez de por dos lo tendria que poner a 16

no estoy muy seguro, mi cristal es de 20mhz no de 22
o esto es otra cosa..


Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #71 en: 20 de Agosto de 2012, 15:53:12 »
No te pide que lo coloques mas rápido, sino es que esta muy rápido  :? O sea, si en máximo periodo permitido es 700ns, como lo vas a colocar 100ns  :shock: Tiene que ser minimo 7 veces más lento, o fácil coloca el oscilador RC interno  :mrgreen:
No contesto mensajes privados, las consultas en el foro

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #72 en: 20 de Agosto de 2012, 15:55:10 »
Hola AngelGris
lo delas divisiones lo puse asi
porque en el asistente de proyectos es el minimo no te deja
la opcion de 1:1 ese es el minimo la resolucion 255, 1023, 65536
lo que se corresponde con 8 bit, 10 bit y 16 bits, y lo otro que deja
es el votaje y el tipo de entrada, no hay mas.


  A lo que me refiero es que no es necesario hacer una función a la cual pasarle tantos parámetros. Concretamente tu función potenciometro.

  debería dejarte poner simplemente...

Código: C
  1. variable = (float)(ADC) * 2.49 + 600;
  2. precarga = 65536 - variable;

  sin necesidad que pases como variable, el máximo y el mínimo.


En el data del pic18F2550 busque eso de las frecuencias:




     TAD vs. DEVICE OPERATING FREQUENCIES

               AD Clock Source (TAD)                 Maximum Device Frequency

           Operation      ADCS2:ADCS0         PIC18FXXXX     PIC18LFXXXX(4)

1.           2 TOSC           000                         2.86 MHz       1.43 MHz
2.           4 TOSC           100                         5.71 MHz       2.86 MHz
3.           8 TOSC           001                       11.43 MHz       5.72 MHz
4.         16 TOSC           101                       22.86 MHz      11.43 MHz
5.         32 TOSC           010                       45.71 MHz      22.86 MHz
6.         64 TOSC           110                       48.0 MHz        45.71 MHz

RC(3) x11 1.00 MHz(1) 1.00 MHz(2)

Note 1: The RC source has a typical TAD time of 4 ms.
2: The RC source has a typical TAD time of 6 ms.
3: For device frequencies above 1 MHz,
    the device must be in Sleep for the entire conversion or the A/D
    accuracy may be out of specification.
4: Low-power devices only.


si lo quisiera poner lo mas rapido posiblesin que atropelle a nadie
deberia de poner el punto 4. o el tunto 1.,
y el divisor en vez de por dos lo tendria que poner a 16

no estoy muy seguro, mi cristal es de 20mhz no de 22
o esto es otra cosa..



  Esos 22MHz significan que si usas esa configuración, la máxima frecuencia que puedes usar de cristal es justamente 22MHz.

  En tu caso con cristal de 20MHz / 16 --> 1.25MHz --> tiempo 800nS que cumple con la premisa que TAD >= 700nS
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas

Desconectado pajaro

  • PIC24H
  • ******
  • Mensajes: 1121
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #73 en: 20 de Agosto de 2012, 20:11:37 »
Hola

modifique la adquisicion de adc, de la interrupcion al while,
al final la conversion la puse div_16 printeo desde el while
con el potenciometro de 1k en su posicion de %50 en el adc da 40
cuando esta casi al final me pasa de 667 a 1018 y ese es el maximo

si operamos con (1018  *2.49) + 600
sale 3134.82-->redondeando 3135

si el maximo por encima es 3150 eso explicaria que con el potencimentro le faltara un cachito
en uno de sus extremos y sile añadimos que el centro esta desplazado
eso esplica casi los 45 grados hasta 180.

repasare las opreaciones por si me cole en algo, pero se comporta de la misma forma
haciendo sin funcion ...

miestras si se ocurre alguna idea del comportamiento del potenciometro
toda ayuda o idea es bienvenida.

no se si es efecto del refresco ..

por cierto, la señal de pwm en el osciloscopio no se cantea nada no se
si es un efecto del osciloscopio porque la cpu del proteus la tengo saltando de
entre 70% a 95% y de normal por encima del 80%

voy a revisar las cosas...

Desconectado AngelGris

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2480
Re: :: PWM :: CCS :: PIC18F2550 :: SERVOS::
« Respuesta #74 en: 20 de Agosto de 2012, 21:27:10 »
Hola

modifique la adquisicion de adc, de la interrupcion al while,
al final la conversion la puse div_16 printeo desde el while
con el potenciometro de 1k en su posicion de %50 en el adc da 40
cuando esta casi al final me pasa de 667 a 1018 y ese es el maximo


  Definitivamente hay algo que NO está bien. Con un pote lineal, a la mitad de su recorrido, el ADC debería leer como muy variable entre 510 y 512, pero nunca tener una lectura de 40.
De vez en cuando la vida
nos besa en la boca
y a colores se despliega
como un atlas


 

anything