Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] 16F887 > 2 axis joystick drive 2 servomotors

Status
Not open for further replies.
it was not working, (no interrupt) until i changed the name of interrupt
i used in the MikroC tools
interrupt assistant
It_assistant.jpg


i will test your *.hex tommorow
and then, try again to compile the source .. without changing interrup function definition
 

Hello Hexreader,

i try to use directly your file forum.hex with Pickit3 gives checksum=9213
Yes, it works !

i tried after to load your "forum.c" , compile it , and load resulting Forum.hex
on Pickit3
the 2 config words are the same = normal
but i get a different checksum ! 2C85 !
and
IT DON'T WORKS !

i compared also the 2 log files :
with yours : used RAM 13, used ROM 267
with mine : used RAM 8 used ROM : 143

are you using the Debugger ?

if i change the definition of interrupt by using the mikroC tools
Code:
void Interrupt() iv 0x0004 ics ICS_AUTO {
//void Interrupt(){
  unsigned int TMR1_value;
... etc ..

IT WORKS !
and into the log file
i get
Used RAM (bytes): 13 (4%)
Used ROM (program words): 267
same as yours! running version

it seems that with void Interrupt(){
the compiler doesn't see the code inside the interrupt
 

Attachments

  • log_comparaison.txt
    4.8 KB · Views: 94

Not using debugger

Not using PicKIT3 (but I do own one) - using easyPIC7

Drunk right now - will think harder when sober :rolleyes:
 

Hello,

I found the problem !

My compiler config :
Tools
....Output
......compiler
........Case sensitive coché <- to respect 100% original syntax

in fact, the original problem is on your side
because the correct syntaxe for interrupt is
First letter i in lowercase
Code:
void interrupt()                                   <-- Works OK
{
... etc ...

compiler doesn't gives any error msg about that !
just ignore the code
 

Nice catch!

Seem to remember being caught with something similar in the past, in the days when I turned on case sensitivity.

Thanks

Seems the problem lies with MikroE's own "timer calculator" utility. Will investigate further and raise problem report on ME forum if necessary.
 
Last edited:

For paulfjujo...

I am very bored right now, so I made same project, but using your project settings (internal 4MHz osc) - attached

Tested with scope traces and with hobby servo - works well.

Gives accurate 0.5ms to 2.5ms high from 0-5V ADC input - for full range servo operation - 20ms repetition rate. Two channels.

High pulse is a fraction less than 7-bits (128 count) resolution on RD0, a fraction less than 8-bits resolution on RD1.

Do not understand why it does not work for you.

Dear all guys, Paul, HexReader, Klaus !

Thanks for all your answers ! Very interesting and helpful ! 👍 Some exchanges between your three are little too complicate for me. Will harass you of questions probably soon. 😱

@Paul :
I needed time to read again your codes and comments, lines after lines. But it’s clear.
Thanks for your remark concerning ADC_read routine (while { ... }, return(k) ...) I passed many times over this routine while troubleshooting and didn’t see this beginner error ! Even with one instruction after, I still need { ... } with my while ...

@hexreader :
Thanks for your code V2 ... with your honest, funny and more complete comments. I m studying now. Interesting code ...

@all3 :
But your last exchanges concerning
compilers version, interrupt subroutine ... it’s chineese for me ! Will probably ask you some questions after tests of your codes on development board with both servos. Can not now. On duty trip ... Will test maybe this weekend.
In 2 words, concerning this topic what do you recommend me to do with compiler, interrupt() ? Will read your last posts again.

Merci beaucoup !

Bon week-end !
 

Ignore the side-discussion between paulfjujo and I about the 'timer-calculator' bug Interrupt vs interrupt. We learnt from it, but it is unlikely to matter to you. Ideally we would have discussed on a separate thread.

Ask away - helping is fun, and I already learnt more by helping you, than you learnt from being helped.

EDIT: "Interupt vs interrupt" corrected to "Interrupt vs interrupt" - don't want to add a second bug :(
 
Last edited:

Hello,

I found the problem !

My compiler config :
Tools
....Output
......compiler
........Case sensitive coché <- to respect 100% original syntax

in fact, the original problem is on your side
because the correct syntaxe for interrupt is
First letter i in lowercase
Code:
void interrupt()                                   <-- Works OK
{
... etc ...

compiler doesn't gives any error msg about that !
just ignore the code
Telling differently
Ignore the side-discussion between paulfjujo and I about the 'timer-calculator' bug Interupt vs interrupt. We learnt from it, but it is unlikely to matter to you. Ideally we would have discussed on a separate thread.

Ask away - helping is fun, and I already learnt more by helping you, than you learnt from being helped.
OK ! I see.
Wanted to miss nothing. I did just check in my Mikroe compiler v7.6.0 :
Options > Output > Compiler > Case sensitive 🔲 empty.
That means, void interrupt() or void Interrupt() are considerate as similar in the code, and will be read by compiler ? And faults detected In case of ?
Merci beaucoup HexReader.
 

Case sensitive 🔲 empty.
That means, void interrupt() or void Interrupt() are considerate as similar in the code
You understand perfectly.

And faults detected In case of ?
The compiler will not report a problem with Interrupt or interrupt case sensitivity turned on.
In C, myfunction, Myfunction and myfUNction are three completely different items when case sensitivity is on.

interrupt is recognised as an interrupt function - Interrupt is recognised as a valid function, but not as the special interrupt function.

I guess this may be why case sensitivity is turned off by default in mikroC, and why most mikroC users leave it turned off most of the time.
 

another way using Timer2 to drive a state machine
whis a step time of 1mS
so one step is used to build the first mS,
second step to add the Timer1 value
(corresponding time = analog value 0 to 1023 (µS))
to obtain a range of 1 to 2mS
repeat time after step 19
Step 0 ...to Step 19 => every 20mS

Step 3 and 4 used for the other servo

Code:
#define Version "2020_0918"
#define Directory  "C:\\_MikroC\\_MesProjets_MikroC\\_16F877_2servomoteurs"
#define Source     "Test_2_servo_16F887_using_State_Machine_TMR2_TMR1_2xEA_"
#define Project    "Test_2servo_16F887_State_Machine_TMR2_TMR1_2xEA_2020_09.mcppi"
#define MCU "P16F887 Dip40"
#define FOSC_INTERNE      // not needed if FOSC= 4MHZ , because is the default value
#define FOSC "4Mhz"

// voir SQA_test_cde_2servo_16F887_2020_0916.scana
//CONFIG1 : $2007 : 0x2CF4
//CONFIG2 : $2008 : 0x0700

#define Bavard

 //ac:pinout
 
  //ac:SQA_analyze


// https://www.edaboard.com/threads/16f887-2-axis-joystick-drive-2-servomotors.394685/

// 2 axes joysticks drives 2 servos :
// Servo motor control signals on RB0 and RB1
// Analogue inputs on RA0 and RA1
// MCU : PIC 16F887, internal fosc 4 MHz
// Driving of 2 servomotors :   
// Timer2 drive State machine
// one step to built the start pulse beginning at a minima of 1mS
// the Timer1 elapsed time value comes from EA0 or EA1  to complete the total time SERVO ON     
// maxima is 2mS !
//                  - servomotor LOWER (360 ° turn) on PORTD.B0 (pin 19),
//                  > Servomotor TOWER PRO MG995 (360 °),
//                  - servomotor UPPER (180 °/270 ° turn) on PORTD.B1 (pin 20),
//                  > Servomotor TOWER PRO MG996R (180 °/270 °),


// global variables
volatile unsigned int Consigne1=0;
volatile unsigned int Consigne2=0;
volatile unsigned int Value_Timer1 ;
int Step=0;

sbit Servo_Lower  at PORTD.B0   ;
sbit Servo_Upper  at PORTD.B1   ;
sbit Servo_Lower_dir  at TRISD.B0   ;
sbit Servo_Upper_dir  at PORTD.B1   ;
sbit SQA at PORTC.B3   ;
sbit SQA_dir  at TRISC.B3 ;
int i,j,k;
char CRam1[80];
char c1,cx;


// void Toto_le_Rigolo() iv 0x0004 ics ICS_AUTO {
//}
void Interrupts() iv 0x0004 ics ICS_AUTO {
//or
//void interrupt ()   // OK
//void Interrupt()    // <- BAD if "Case sensitive" option  is checkek for compiler !
//{
  unsigned int TMR1_value;                        // temporary calculation value
  //TXREG='@';  // to test if interrupt fire

  if ((TMR2IE_bit) && (TMR2IF_bit))
   {
    switch (Step)
    {
       case 0:              // 1rst ms ON on Servo Lower
           SQA=1;
           Servo_Lower=1;
           Servo_Upper=0;
           TMR1ON_bit=0;
           TMR1IF_bit=0;
           TMR1IE_bit=0;
           Step++;
           break;
       case 1:
           Servo_Lower=1;
           Servo_Upper=0;    // TON= 1ms + TMR1 time
           Value_Timer1= 65535-Consigne1;
           TMR1H= Value_Timer1>>8;
           TMR1L=  Value_Timer1 & 0x00FF;
           TMR1IF_bit=0;
           TMR1IE_bit=1;
           TMR1ON_bit=1;
           Step++;
           break;
       case 2 :
           Servo_Lower=0;    // 1rst ms ON on Servo UPPER
           Servo_Upper=1;
           TMR1IE_bit=0;
           TMR1ON_bit=0;
           TMR1IF_bit=0;
           Step++;
           break;
       case 3:
           Servo_Upper=1;    // TON= 1ms + TMR1 time
           Servo_Lower=0;
           Value_Timer1= 65535-Consigne2;
           TMR1H= Value_Timer1>>8;
           TMR1L=  Value_Timer1 & 0x00FF;
           TMR1IF_bit=0;
           TMR1IE_bit=1;
           TMR1ON_bit=1;
           Step++;
           break;
       case 4 :
           Servo_Lower=0;    // 1rst ms ON on Servo UPPER
           Servo_Upper=0;
           TMR1IE_bit=0;
           TMR1ON_bit=0;
           TMR1IF_bit=0;
           SQA=0;
           Step++;
           break;
       case 19 :
           Step=0;
           break;
       default:
           Step++;
           break;
       }
        PR2     = 249;
        TMR2IF_bit = 0;
   }
   // ----------  TMR1 --------------------
    if ( (TMR1IE_bit) && (TMR1IF_bit) )
    {                              // handle timer 1 interrupt

        if (Step==2)   Servo_Lower=0;
        if (Step==4)   Servo_Upper=0;
       TMR1ON_bit=0;
       TMR1IE_bit=0;
       TMR1IF_bit = 0;
    }
}


 void Init_Timer2()
 {
 // at Fosc=4MHz  Actual Interrupt Time : 1 ms
 //Prescaler 1:1; Postscaler 1:4; TMR2 Preload = 249;
  T2CON         = 0x1C;
  PR2           = 250;
  TMR2IE_bit    = 1;
  INTCON        = 0xC0;

}

//Timer1   at  Fosc=4MHz
//Prescaler 1:1; TMR1 Preload = 65036; Actual Interrupt Time : 500 us
//Place/Copy this part in declaration section
void Init_Timer1(){
  T1CON     = 0x01;
  TMR1IF_bit = 0;
  TMR1H     = 0xFE;
  TMR1L     = 0x0C;
  TMR1IE_bit     = 0;
  INTCON= 0x00;
}


void CRLF1(void)
{
    UART1_Write(13);
      UART1_Write(10);
}

void Print( char *T)
{
  while(*(T)>0)
  {
   UART1_Write(*(T++));
   }
 }

void CPrint(const char *T1)
{
  while(*(T1)>0)
  {
   UART1_Write(*(T1++));
   }
 }
 

void main()
{
#ifdef FOSC_INTERNE
    OSCCON=0;
    OSCCON.IRCF2=1;   // 4MHz
    OSCCON.IRCF1=1;
    OSCCON.IRCF0=0;
    OSCCON.SCS=1;
  //OSCCON=0b01110001 ; // 8MHz (111) & SCS=1  (sinon 4 MHz par defaut)
  //OSCCON=0b01100001 ; // 4 MHz par defaut
  #endif
    ANSEL=0x03;
    TRISC = 0x00;      
    TRISD = 0x00;t
    PORTC = 0x00;
    PORTD = 0x00;
    SQA_dir=0;
    SQA=0;
    
    ADC_Init();
    UART1_Init(19200);
   // vider le registre de transmission
    if (UART1_Tx_Idle() == 1)   UART1_Write(' ');
    CRLF1();
    CPrint(" Compiler: MikroC 7.60 \r\n");
    CPrint(" Directory : "Directory"\r\n");
    CPrint(" Source : "Source"Version"Version"\r\n");
    CPrint(" Test 2 servo , MCU" MCU" FOSC="FOSC"\r\n");
    CPrint(" Servomotor LOWER 270° : TOWER PRO M996R (270°) \r\n");
    CPrint(" Servomotor UPPER x360° : TOWER PRO MG995 (360°)\r\n");
    CPrint(" Usage de Timer2 pour gerer une machine d'etat \r\n");
    CRLF1();

    Init_Timer1();  // sans  interrupt
    PEIE_bit=1;
    GIE_bit=1;
    Init_Timer2(); // avec interrupt armée
    Step=0;


     // -------------- main loop   ---------------------------
     while(1)
    {
    // consigne  0 à 1000µS  + offset constant de 1ms généré par Timer2
    // soit  gamme de 1 à 2mS
    Consigne1 = ADC_Read(0);
    Consigne2 = ADC_Read(1);
    #ifdef Bavard
     CPrint(" Consigne1 Lower Servo :");
     WordToStr(Consigne1 ,CRam1);
     Print(CRam1);
     CPrint(" Consigne2 Upper Servo :");
     WordToStr(Consigne2 ,CRam1);
     Print(CRam1);
     CRLF1();
    Delay_1sec();      // à modifier si besoin
    #else
    Delay_ms(20);
    #endif
    }
}

/*
on terminal display

 Compiler: MikroC 7.60
 Directory<NUL><SOH>
 Compiler: MikroC 7.60
 Directory : C:\_MikroC\_MesProjets_MikroC\_16F877_2servomoteurs
 Source : Test_2_servo_16F887_using_State_Machine_TMR2_TMR1_2xEA_Version2020_0918
 Test 2 servo , MCUP16F887 Dip40 FOSC=4Mhz
 Servomotor LOWER 270° : TOWER PRO M996R (270°)
 Servomotor UPPER x360° : TOWER PRO MG995 (360°)
 Usage de Timer2 pour gerer une machine d'etat

 Consigne1 Lower Servo :  164 Consigne2 Upper Servo :  167
 Consigne1 Lower Servo :  167 Consigne2 Upper Servo :  167
 Consigne1 Lower Servo :  183 Consigne2 Upper Servo :  182
 Consigne1 Lower Servo :  170 Consigne2 Upper Servo :  172
 Consigne1 Lower Servo :  163 Consigne2 Upper Servo :  165
 Consigne1 Lower Servo :  172 Consigne2 Upper Servo :  168
 Consigne1 Lower Servo :  183 Consigne2 Upper Servo :  183

*/
 

    Eric_O

    Points: 2
    Helpful Answer Positive Rating
another way using Timer2 to drive a state machine
whis a step time of 1mS
so one step is used to build the first mS,
second step to add the Timer1 value
(corresponding time = analog value 0 to 1023 (µS))
to obtain a range of 1 to 2mS
repeat time after step 19
Step 0 ...to Step 19 => every 20mS

Step 3 and 4 used for the other servo

Code:
#define Version "2020_0918"
#define Directory  "C:\\_MikroC\\_MesProjets_MikroC\\_16F877_2servomoteurs"
#define Source     "Test_2_servo_16F887_using_State_Machine_TMR2_TMR1_2xEA_"
#define Project    "Test_2servo_16F887_State_Machine_TMR2_TMR1_2xEA_2020_09.mcppi"
#define MCU "P16F887 Dip40"
#define FOSC_INTERNE      // not needed if FOSC= 4MHZ , because is the default value
#define FOSC "4Mhz"

// voir SQA_test_cde_2servo_16F887_2020_0916.scana
//CONFIG1 : $2007 : 0x2CF4
//CONFIG2 : $2008 : 0x0700

#define Bavard

//ac:pinout

  //ac:SQA_analyze


// https://www.edaboard.com/threads/16f887-2-axis-joystick-drive-2-servomotors.394685/

// 2 axes joysticks drives 2 servos :
// Servo motor control signals on RB0 and RB1
// Analogue inputs on RA0 and RA1
// MCU : PIC 16F887, internal fosc 4 MHz
// Driving of 2 servomotors :  
// Timer2 drive State machine
// one step to built the start pulse beginning at a minima of 1mS
// the Timer1 elapsed time value comes from EA0 or EA1  to complete the total time SERVO ON    
// maxima is 2mS !
//                  - servomotor LOWER (360 ° turn) on PORTD.B0 (pin 19),
//                  > Servomotor TOWER PRO MG995 (360 °),
//                  - servomotor UPPER (180 °/270 ° turn) on PORTD.B1 (pin 20),
//                  > Servomotor TOWER PRO MG996R (180 °/270 °),


// global variables
volatile unsigned int Consigne1=0;
volatile unsigned int Consigne2=0;
volatile unsigned int Value_Timer1 ;
int Step=0;

sbit Servo_Lower  at PORTD.B0   ;
sbit Servo_Upper  at PORTD.B1   ;
sbit Servo_Lower_dir  at TRISD.B0   ;
sbit Servo_Upper_dir  at PORTD.B1   ;
sbit SQA at PORTC.B3   ;
sbit SQA_dir  at TRISC.B3 ;
int i,j,k;
char CRam1[80];
char c1,cx;


// void Toto_le_Rigolo() iv 0x0004 ics ICS_AUTO {
//}
void Interrupts() iv 0x0004 ics ICS_AUTO {
//or
//void interrupt ()   // OK
//void Interrupt()    // <- BAD if "Case sensitive" option  is checkek for compiler !
//{
  unsigned int TMR1_value;                        // temporary calculation value
  //TXREG='@';  // to test if interrupt fire

  if ((TMR2IE_bit) && (TMR2IF_bit))
   {
    switch (Step)
    {
       case 0:              // 1rst ms ON on Servo Lower
           SQA=1;
           Servo_Lower=1;
           Servo_Upper=0;
           TMR1ON_bit=0;
           TMR1IF_bit=0;
           TMR1IE_bit=0;
           Step++;
           break;
       case 1:
           Servo_Lower=1;
           Servo_Upper=0;    // TON= 1ms + TMR1 time
           Value_Timer1= 65535-Consigne1;
           TMR1H= Value_Timer1>>8;
           TMR1L=  Value_Timer1 & 0x00FF;
           TMR1IF_bit=0;
           TMR1IE_bit=1;
           TMR1ON_bit=1;
           Step++;
           break;
       case 2 :
           Servo_Lower=0;    // 1rst ms ON on Servo UPPER
           Servo_Upper=1;
           TMR1IE_bit=0;
           TMR1ON_bit=0;
           TMR1IF_bit=0;
           Step++;
           break;
       case 3:
           Servo_Upper=1;    // TON= 1ms + TMR1 time
           Servo_Lower=0;
           Value_Timer1= 65535-Consigne2;
           TMR1H= Value_Timer1>>8;
           TMR1L=  Value_Timer1 & 0x00FF;
           TMR1IF_bit=0;
           TMR1IE_bit=1;
           TMR1ON_bit=1;
           Step++;
           break;
       case 4 :
           Servo_Lower=0;    // 1rst ms ON on Servo UPPER
           Servo_Upper=0;
           TMR1IE_bit=0;
           TMR1ON_bit=0;
           TMR1IF_bit=0;
           SQA=0;
           Step++;
           break;
       case 19 :
           Step=0;
           break;
       default:
           Step++;
           break;
       }
        PR2     = 249;
        TMR2IF_bit = 0;
   }
   // ----------  TMR1 --------------------
    if ( (TMR1IE_bit) && (TMR1IF_bit) )
    {                              // handle timer 1 interrupt

        if (Step==2)   Servo_Lower=0;
        if (Step==4)   Servo_Upper=0;
       TMR1ON_bit=0;
       TMR1IE_bit=0;
       TMR1IF_bit = 0;
    }
}


void Init_Timer2()
{
// at Fosc=4MHz  Actual Interrupt Time : 1 ms
//Prescaler 1:1; Postscaler 1:4; TMR2 Preload = 249;
  T2CON         = 0x1C;
  PR2           = 250;
  TMR2IE_bit    = 1;
  INTCON        = 0xC0;

}

//Timer1   at  Fosc=4MHz
//Prescaler 1:1; TMR1 Preload = 65036; Actual Interrupt Time : 500 us
//Place/Copy this part in declaration section
void Init_Timer1(){
  T1CON     = 0x01;
  TMR1IF_bit = 0;
  TMR1H     = 0xFE;
  TMR1L     = 0x0C;
  TMR1IE_bit     = 0;
  INTCON= 0x00;
}


void CRLF1(void)
{
    UART1_Write(13);
      UART1_Write(10);
}

void Print( char *T)
{
  while(*(T)>0)
  {
   UART1_Write(*(T++));
   }
}

void CPrint(const char *T1)
{
  while(*(T1)>0)
  {
   UART1_Write(*(T1++));
   }
}


void main()
{
#ifdef FOSC_INTERNE
    OSCCON=0;
    OSCCON.IRCF2=1;   // 4MHz
    OSCCON.IRCF1=1;
    OSCCON.IRCF0=0;
    OSCCON.SCS=1;
  //OSCCON=0b01110001 ; // 8MHz (111) & SCS=1  (sinon 4 MHz par defaut)
  //OSCCON=0b01100001 ; // 4 MHz par defaut
  #endif
    ANSEL=0x03;
    TRISC = 0x00;     
    TRISD = 0x00;t
    PORTC = 0x00;
    PORTD = 0x00;
    SQA_dir=0;
    SQA=0;
   
    ADC_Init();
    UART1_Init(19200);
   // vider le registre de transmission
    if (UART1_Tx_Idle() == 1)   UART1_Write(' ');
    CRLF1();
    CPrint(" Compiler: MikroC 7.60 \r\n");
    CPrint(" Directory : "Directory"\r\n");
    CPrint(" Source : "Source"Version"Version"\r\n");
    CPrint(" Test 2 servo , MCU" MCU" FOSC="FOSC"\r\n");
    CPrint(" Servomotor LOWER 270° : TOWER PRO M996R (270°) \r\n");
    CPrint(" Servomotor UPPER x360° : TOWER PRO MG995 (360°)\r\n");
    CPrint(" Usage de Timer2 pour gerer une machine d'etat \r\n");
    CRLF1();

    Init_Timer1();  // sans  interrupt
    PEIE_bit=1;
    GIE_bit=1;
    Init_Timer2(); // avec interrupt armée
    Step=0;


     // -------------- main loop   ---------------------------
     while(1)
    {
    // consigne  0 à 1000µS  + offset constant de 1ms généré par Timer2
    // soit  gamme de 1 à 2mS
    Consigne1 = ADC_Read(0);
    Consigne2 = ADC_Read(1);
    #ifdef Bavard
     CPrint(" Consigne1 Lower Servo :");
     WordToStr(Consigne1 ,CRam1);
     Print(CRam1);
     CPrint(" Consigne2 Upper Servo :");
     WordToStr(Consigne2 ,CRam1);
     Print(CRam1);
     CRLF1();
    Delay_1sec();      // à modifier si besoin
    #else
    Delay_ms(20);
    #endif
    }
}

/*
on terminal display

Compiler: MikroC 7.60
Directory<NUL><SOH>
Compiler: MikroC 7.60
Directory : C:\_MikroC\_MesProjets_MikroC\_16F877_2servomoteurs
Source : Test_2_servo_16F887_using_State_Machine_TMR2_TMR1_2xEA_Version2020_0918
Test 2 servo , MCUP16F887 Dip40 FOSC=4Mhz
Servomotor LOWER 270° : TOWER PRO M996R (270°)
Servomotor UPPER x360° : TOWER PRO MG995 (360°)
Usage de Timer2 pour gerer une machine d'etat

Consigne1 Lower Servo :  164 Consigne2 Upper Servo :  167
Consigne1 Lower Servo :  167 Consigne2 Upper Servo :  167
Consigne1 Lower Servo :  183 Consigne2 Upper Servo :  182
Consigne1 Lower Servo :  170 Consigne2 Upper Servo :  172
Consigne1 Lower Servo :  163 Consigne2 Upper Servo :  165
Consigne1 Lower Servo :  172 Consigne2 Upper Servo :  168
Consigne1 Lower Servo :  183 Consigne2 Upper Servo :  183

*/
Merci Paul !
I just discovered your code.
i will test it tonight.
Will send you a feedback.
👍
--- Updated ---

You understand perfectly.

The compiler will not report a problem with Interrupt or interrupt case sensitivity turned on.
In C, myfunction, Myfunction and myfUNction are three completely different items when case sensitivity is on.

interrupt is recognised as an interrupt function - Interrupt is recognised as a valid function, but not as the special interrupt function.

I guess this may be why case sensitivity is turned off by default in mikroC, and why most mikroC users leave it turned off most of the time.
Bonjour HexReader,
I just made an error ... I probably erase my last post for you ... 😕
Have to write again ...

In your code I guessed that you do not need my subroutines Init_Timer0, 1, 2.
You use only timer 0 for Ton combines with timer 1 (5 times) for toff in order to obtain 20 mS period ?

Lower servo :
Joystick move from neutral to left > Servo turns from 0 to 270 left to right and comes back to 0 when joystick to neutral position again.
Same rotation when joystick move from neutral to right.
I was expecting joystick from neutral to left > servo turns from 0 to - 90° and joystick from neutral to right > servo turns from 0 to + 90° ...
Upper servo :
Turns from -90º to +90° while moving joystick from central to left and central to right, but not properly and smoothly when approaching - 90 and + 90.
I guess I should change your formula in both if before loading calculate value in TMR1_value ?

🤔

Merci beaucoup pour ton aide.
 
Last edited:

Interrupt code would take a lot of explaining, sadly I do not have the patience, nor the teaching skills

If you just accept that the interrupt code works, then any adjustments that you might want to make are in these two lines:
Code:
        PWM1_high_time = ADC_Read(0)/4;                                         // 0 = 0.5mS, 252 = 2.5mS
        PWM2_high_time = ADC_Read(1)/4;                                         // 0 = 0.5mS, 252 = 2.5mS

Each line reads a number 0 to 1023 from ADC, then converts that number to 0 to 255 to control PWM pulse width.

If you do not want the full range 0.5ms to 2.5ms then manipulate the numbers to give - say...
.. set PWM1_high_time to values of 63 to 189 for 1ms to 2ms pulse width.

Not sure what it is that you want that is different to standard hobby servo.

maybe paulfjujo's code might suit you better? He is much better at understanding, explaining and teaching.
 
Last edited:

Interrupt code would take a lot of explaining, sadly I do not have the patience, nor the teaching skills

If you just accept that the interrupt code works, then any adjustments that you might want to make are in these two lines:
Code:
        PWM1_high_time = ADC_Read(0)/4;                                         // 0 = 0.5mS, 252 = 2.5mS
        PWM2_high_time = ADC_Read(1)/4;                                         // 0 = 0.5mS, 252 = 2.5mS

Each line reads a number 0 to 1023 from ADC, then converts that number to 0 to 255 to control PWM pulse width.

If you do not want the full range 0.5ms to 2.5ms then manipulate the numbers to give - say...
.. set PWM1_high_time to values of 63 to 189 for 1ms to 2ms pulse width.

Not sure what it is that you want that is different to standard hobby servo.

maybe paulfjujo's code might suit you better? He is much better at understanding, explaining and teaching.
Thanks !
I understood interrupt process with values to load in timer register.
Will try your advise.
Wait for Paul explanation about your code ... maybe. 🤔
Eric
 

Hello Eric,

Does the program run OK ?
if not , what is the problem ?
What part of code needs more explanations ?
use personal MP to explain that, ( in French could be, better for us..)
or you can put here all your project in a zip
( *.cfg , *.mcpi, *.c, *.h ...) with your questions ..
 

Hello Eric,

Does the program run OK ?
if not , what is the problem ?
What part of code needs more explanations ?
use personal MP to explain that, ( in French could be, better for us..)
or you can put here all your project in a zip
( *.cfg , *.mcpi, *.c, *.h ...) with your questions ..
Thank you Paul for your availability !
I will reply soon.
Maybe before, il will run your code first. Looks interesting too and same structure like your first codes you sent me last may when entered in contact with you.
OK, i will use MP.
À plus tard.
Eric
 

Hello Eric,

Does the program run OK ?
if not , what is the problem ?
What part of code needs more explanations ?
use personal MP to explain that, ( in French could be, better for us..)
or you can put here all your project in a zip
( *.cfg , *.mcpi, *.c, *.h ...) with your questions ..
Bonsoir Paul,
Finally, I just run your code without understanding it. Great ! Turns left/center/right of each servo are completely in accordance with movements left/center/right of the joystick. 👍
Range of turns are a little bit short ... something like -45°/0°/+45. I will study your code which is becoming more familiar now and probably will have to adjust values min/max in the timers registers ...
I will also ask you some explanations of HexReader code too.
Merci beaucoup !
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top