SERVO control with TIM module of HC908JK1

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

SERVO control with TIM module of HC908JK1

3,441件の閲覧回数
mauricio2346
Contributor II
HI.   i need to control a servo with the pwm module of JK1.   this is the code i wrote but it doesn't work!!!

maybe i have a big mistake in the way i analized the program, or maybe im using a wrong method to control the servo...

this is the code:
#include <hidef.h>
#include < MC68HC908JK1.h>
#include "TIMERAPI.h"

double Frecuencia=0.05;   
double Dureza;
double Modulo;
double Duty;   

double Periodos[5]={ 3.25,4.875,6.5,8.125,9.75};
unsigned char i;

void Init_uC(void);
void Init_PWM(void);

void main(void) {
    Init_uC();
    for(i=1;i<=5;i++) {
    Dureza=Periodos[i];
    Delayms(1000);
    }
}


void Init_uC (void){
    EnableInterrupts;
    CONFIG1_COPD=1;
    DDRB=0x18;
    DDRD=0x3C;
    PTB=0;
    PTD=0;
}


void Init_PWM(void){
    Modulo  = 2500/Frecuencia;            // 2.5Mhz / Frecuencia en Khz
    Duty       = Dureza*Modulo/100;
    TSC_TSTOP  = 1;                     // PARA EL TIMER
    TSC_TRST   = 1;                        // RESET AL TIMER
    TMOD       = Modulo;                 // Periodo de la señal de PWM                   
    TCH0       = Duty;                    // Ancho de pulso requerido
    TSC0_MS0A  = 1;                        // Unbufered PWM
    TSC0_ELS0B = 1;                        // Clear output on compare
    TSC0_TOV0  = 1;                        // Toggle on overflow
    TSC_TRST   = 0;                     // RESET AL TIMER
    TSC_TSTOP  = 0;                     // PARA EL TIMER       
}


TIMERAPI is a library that makes delays..... Delayms() is used with this library (milliseconds)
the servo i want to control : ROBBE RS200:

Min:0.65 ms
Neutral: 1.3 ms
Max: 1.95 ms
Frequency: 50 Hz (means 20 milliseconds period)


THANKS!!!!

ラベル(1)
0 件の賞賛
返信
7 返答(返信)

1,395件の閲覧回数
bigmac
Specialist III
Hello Mauricio,
 
I presume your code does not work because it will not compile.  The problem is that you are attempting to used floating point variables.  The HC908JK1 simply does not have sufficient memory resources to accommodate floating point calculations.
 
You will need to utilize integer arithmetic for your calculations.  Since the variables Modulo and Duty ultimately need to become integer values for writing to TIM module registers, this is not a drawback.
 
Assuming the TIM clock freqency remains at 2.5 MHz, as is likely to be the case, the modulo value can be pre-calculated at compile time for an overflow period of 20 ms, and this constant value (49999) written directly to the TMOD register.
 
The value written to TCH0 would then vary between the following limits -
0.65ms -> 1625
1.30ms -> 3250
1.95ms -> 4875
 
For example, if Dureza were to be expressed as an integer value 0 -> 100, the following integer calculation would be required -
 
unsigned int Dureza = 50;  /* Initialize to servo mid-point */
 
TCH0 = Dureza * 325 / 10 + 1625;
 
Regards,
Mac
 


Message Edited by bigmac on 2007-08-20 02:19 PM
0 件の賞賛
返信

1,395件の閲覧回数
mauricio2346
Contributor II
Hi Mac.
Thanks, you opinion is great, but i have a problem.   this is the program i wrote:

#include <hidef.h>
#include <MC68HC908JK1.h>
#include "TIMERAPI.h"

unsigned int Dureza;
unsigned int Modulo;
char i;
void Init_uC(void);
void Init_Servo(void);
void main(void) {
    Init_uC();
    Init_Servo();
       
for( ; ; )  {
            
    }
}


void Init_uC (void){
    EnableInterrupts;
    CONFIG1_COPD=1;
    DDRB=0x18;
    DDRD=0x3C;
    PTB=0;
    PTD=0;
}


void Init_Servo(void){
    TSC_TSTOP  = 1;                     
    TSC_TRST   = 1;                        
    TMOD       = 49999;                                     
    TCH0       = Dureza*(325/10)+1625;
    TSC0 = 0x1A;                        
    TSC = 0x00;                           
}

when a put some Dureza values (between 0 to 100), the servo only moves counterclockwise, and the motor doesn't stop (when it should).  

the exteral oscillator value is 4.9152 Mhz.   what is wrong with it?

THANKS!!!!







Message Edited by mauricio2346 on 2007-08-21 02:43 AM
0 件の賞賛
返信

1,395件の閲覧回数
bigmac
Specialist III
Hello Mauricio,
 
For some reason, I though you were using a bus/TIM clock freqency of 2.5 MHz (10 MHz crystal), and the previous information was based on this incorrect assumption.
 
Using a 4.9152 MHz crystal, the TIM clock frequency will be 1.2288 MHz.  For a 20 ms overflow period, the TMOD value should be 24575.  The calculation for TCH0 value will approximate to the following -
 
TCH0 = Dureza * 16 + 799;

A small rounding error does occur because of the "odd" crystal frequency.  The multiplier should actually be 15.97, or 1597/100 as an integer calculation.  However, this would require that the intermediate result of the multiplication and division process be cast to an unsigned long (32-bit) value, to prevent overflow.  This additional complication is probably not warranted for the present project.
 
Regards,
Mac
 
0 件の賞賛
返信

1,395件の閲覧回数
mauricio2346
Contributor II
Ok Mac.  i'll think about it.  i don't know if the servo will work with the "rounding error".  please tell me if i understand this:
TMOD value is the number of oscillations needed to complete the 20 ms:
(20 ms/(1/12288 Mhz))= 24576
then the TCH0 depends of the duty period that the servo needs to move (with a simple numerical relation)

THANKS, Please forgive me if i'm boring you, but my teachers only gave to me the programs without a deep explanation.  now i'm making my own programs and it's a little difficult...


0 件の賞賛
返信

1,395件の閲覧回数
bigmac
Specialist III
Hello Mauricio,
 
I don't think the rounding error will have any impact on servo operation - it amounts to about 0.2 percent, probably much lower than the non-linearity and scaling accuracy of the servo.
 
Your understanding is basically correct.  The value (TMOD+1) represents the number of TIM clock cycles for a 20 ms period.  The TIM clock will equal the bus clock if the prescale value is1.
 
The TCH0 value represents the number of TIM clock cycles to provide a pulse width between 0.65 ms and 1.95 ms.  For the formula previously given, the TCH0 value will range between 799 and 2399 cycles.  Without the rounding error, the maximum value would be 2397 cycles.
 
Regards,
Mac
 
0 件の賞賛
返信

1,395件の閲覧回数
mauricio2346
Contributor II
Hi, i have made some changes in the program, and i want to control servo's angle with ADC module (with a pot).  when i try to write the ADR in the expression that creates the PWM signal to the servo, it doesn't move properly.
what i should do to change the TCH0 value (Dureza) during the execution of the program???
Dureza's value goes between 0 and 255;
this is the code:
 
#include<hidef.h>
#include<MC68HC908JK1.h>
#include "TIMERAPI.h"
 
unisgned int Ciclos_Altos, Dureza;
 
void Init_uC(void);
void Init_Servo(void);
void Init_Potenciometro();
 
 
void main(void){
Init_uC();
Init_Servo();
Init_Potenciometro();
for( ; ; ){
Dureza=ADR;
}
 
 
void Init_uC(void){
EnableInterrupts;
CONFIG1_COPD=1;
DDRB=0x80;
DDRD=0x10;
PTB=0;
PTD=0;
}
 
 
void Init_Servo(void);
Ciclos_Altos(Dureza*6)+1106;
TSC_TSTOP=1;
TSC_TRST=1;
TMOD=24576;
TCH0=Ciclos_Altos;
TSC0=0x1A;
TSC=0x00;
}
 
void Potenciometro(void){
ADICLK=0X40;
ADSCR=0X07;
ADSCR_AIEN=1;
}
 
void interrupt 16 Potenciometro_Isr(void){
ADSCR_AIEN=1;
}
 
0 件の賞賛
返信

1,395件の閲覧回数
bigmac
Specialist III
Hello Mauricio,
 
You should not attempt to update the PWM value any more than once per PWM period (20 ms).  To prevent the frequent updates from disrupting the ouput waveform, the update should occur after the output has gone low within each cycle.  This can be achieved by enabling the channel (output compare) interrupt, and updating the TCH0 value from within the ISR.
 
Specifically for the servo case, where there is always a substantial delay until the start of the new cycle, I might suggest the following approach within the timer channel ISR -
  1. When the ISR is first entered, initiate a single ATD conversion. 
  2. Continuously monitor the conversion complete flag, and wait until it is set.  The ATD interrupt must remain disabled.
  3. Read the ATD value, and update the TCH0 value.
  4. Clear the timer channel flag, and exit the ISR.
For compatibility with the 8-bit ATD range, the new value for TCH0 should use the following formula -
 
TMOD = ADR*25/4 + 799;
 
This will give a maximum range for TMOD of 799 to 2392.  Compare this with the maximum allowable range of the servo of 799 to 2396.
 
Regards,
Mac
 
0 件の賞賛
返信