CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Sort Servomotor Application AN696 Microchip

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
RUFINOGG



Joined: 15 Jan 2010
Posts: 8

View user's profile Send private message Send e-mail

Sort Servomotor Application AN696 Microchip
PostPosted: Mon Dec 09, 2013 11:05 am     Reply with quote

I am using the Microchip AN696 application and it works perfectly, but I want to modify it to order a new motor shaft position (destination) is "real" and not the current position plus the value sent by RS232. For more changes I've made have been unable to get it. Has anyone used the application note or other which incorporates a PID that works well?
Thanks
temtronic



Joined: 01 Jul 2010
Posts: 9244
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Dec 09, 2013 2:05 pm     Reply with quote

As the AN was not written in CCS C , please post your translation of the AN, then we can show you what to do.
RUFINOGG



Joined: 15 Jan 2010
Posts: 8

View user's profile Send private message Send e-mail

PostPosted: Mon Dec 09, 2013 6:18 pm     Reply with quote

This is the complete program translated to CCS:
Code:

//
//                   
File: ZoomAN696.H
//
///////////////////////////////////////////////////////////////////////////////
//////// Program memory: 0x16  Data RAM: 3840  Stack: 31
//////// I/O: 40   Analog Pins: 12
//////// Data EEPROM: 1024
//////// C Scratch area: 00   ID Location: 2000
//////// Fuses: LP,XT,HS,RC,EC,EC_IO,H4,RC_IO,PROTECT,NOPROTECT,IESO,NOIESO
//////// Fuses: NOBROWNOUT,BROWNOUT,WDT1,WDT2,WDT4,WDT8,WDT16,WDT32,WDT64
//////// Fuses: WDT128,WDT,NOWDT,BORV25,BORV27,BORV42,BORV45,PUT,NOPUT,CPD
//////// Fuses: NOCPD,NOSTVREN,STVREN,NODEBUG,DEBUG,NOLVP,LVP,WRT,NOWRT,CPB
//////// Fuses: NOCPB,EBTRB,NOEBTRB,EBTR,NOEBTR,CCP2B3,CCP2C1,WRTD,NOWRTD
//////// Fuses: WRTC,NOWRTC,WRTB,NOWRTB,FCMEN,NOFCMEN,INTRC,INTRC_IO
//////// Fuses: BROWNOUT_SW,BROWNOUT_NOSL,WDT_256,WDT_512,WDT_1024,WDT_2048
//////// Fuses: WDT_4096,WDT_8192,WDT_16384,WDT_32768,LPT1OSC,NOLPT1OSC,MCLR
//////// Fuses: NOMCLR,XINST,NOXINST,BBSIZE1K,BBSIZE2K,BBSIZE4K
///////////////////////////////////////////////////////////////////////////////
#ifdef Debuger1
  #ifdef PLLMHz
   #fuses H4,noWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,DEBUG, WDT128,NOEBTR,BROWNOUT
  #else
   #fuses HS,noWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,DEBUG, WDT128,NOEBTR,BROWNOUT
  #endif
#else
  #ifdef PLLMHz
   #fuses H4,WDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,  noDEBUG, WDT128,NOEBTR,BROWNOUT
  #else
   #fuses HS,WDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,  noDEBUG, WDT128,NOEBTR,BROWNOUT
  #endif
#endif

#ifdef PLLMHz
   #use delay(clock=40000000,RESTART_WDT)   //10.000.000 * 4
#else
   #use delay(clock=20000000,RESTART_WDT)
#endif

#ifdef PIC18LF6722
  #use RS232(BAUD=115200, XMIT=PIN_G1,RCV=PIN_G2,BRGH1OK,RESTART_WDT,STREAM=UARTR1)
#else
  #use RS232(BAUD=115200, XMIT=PIN_C6,RCV=PIN_C7,BRGH1OK,RESTART_WDT,STREAM=UARTR1)
#endif
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//Constant Definitions
//---------------------------------------------------------------------

#define   DIST   0            // Array index for segment distance
#define   VEL      1            // Array index for segment vel. limit
#define   ACCEL   2            // Array index for segment accell.
#define   TIME   3            // Array index for segment delay time
#define   INDEX   RB0            // Input for encoder index pulse
#define   NLIM   RB1            // Input for negative limit switch
#define   PLIM   RB2            // Input for positive limit switch
#define   input(PIN_B3)         //GPI   RB3      // General purpose input
#define   MODE1   !input(PIN_B4)   //PORTBbits.RB4      // DIP switch #1
#define   MODE2   !input(PIN_B5)   //PORTBbits.RB5      // DIP switch #2
#define   MODE3   !input(PIN_B6)   //PORTBbits.RB6      // DIP switch #3
#define   MODE4   !input(PIN_B7)   //PORTBbits.RB7      // DIP switch #4
#define   SPULSE   PIN_C5         //#define   SPULSE RC5      // Software timing pulse output
#define   ADRES   ADRESH         // Redefine for 10-bit A/D converter
#define  KP       250
#define  KI       252
#define  KD       254
#define  ADRESHL   make16(ADRESH,ADRESL)
//---------------------------------------------------------------------
// Variable declarations
//---------------------------------------------------------------------
const char ready[] = "\r\nREADY>\r\n";
const char error[] = "\r\nERROR!\r\n";

signed int8 inpbuf[8];   //8bits

char
eeadrr,
firstseg,
lastseg,
segnum,
parameter,
i,                              // index to ASCII buffer
comcount,                        // index to input string
udata                           // received character from USART
;
//Un bit del byte stat
struct {                              // holds status bits for servo
    unsigned            phase:1;      // first half/ second half of profile
    unsigned         neg_move:1;      // backwards relative move
    unsigned          motion:1;      //
    unsigned        saturated:1;      // servo output is saturated
    unsigned             bit4:1;
    unsigned           bit5:1;
    unsigned              run:1;
    unsigned             loop:1;
} stat ;

union LNG{
signed int32 l;
unsigned int32 ul;
signed int16 i[2];
unsigned int16 ui[2];
unsigned int8 bb[4];
unsigned int8 ubb[4];
};

union LNG
accell,
temp,
u0,
ypid,
velact,
phase1dist
;

signed int16
dtime,                        // Segment delay time
integral,
kpp,
kii,
kdd,                     // PID gain constants
vlim, velcom,
mvelocity,
DnCount,
UpCount,
tempch;

signed int32
position,                     // Commanded position.
mposition,                  // Actual measured position.
fposition,                  // Originally commanded position.
flatcount;                    // Holds # of sample periods for which
                        // the velocity limit was reached in first
                        // half of the move.

float ValorADC;
signed int16 PosicionReal;
signed int16 Temporal1;
signed int16 OrdenPosOLD;
signed int16 OrdenPosNEW;
signed int16 OrdenPosADC;


signed int16 segment1[12][4];      // array in bank2 for 12 motion segments
signed int16 SegmentOrd[4];      // array in bank3 for 12 motion segments
unsigned char TramaRecUART[15];         //Trama recibida en UART de órdenes

unsigned int16 Timer0OLD,Timer1OLD;      //Control de patinado del servo cuando llega a topes

char FLAG;
#bit ENBMotor  =        FLAG.0      // Indicador de que el motor se acaba de arrancar
#define   ENBMotorASM      FLAG,0
#bit OrdenRec  =     FLAG.1
#define   OrdenRecASM   FLAG,1

#ifdef PIC18LF6722
   #define PINENBPW      PIN_A5   //DIR en la versión anterior
#else
   #define PINENBPW      PIN_E2
#endif
#define EnableDriverPW()   output_high(PINENBPW)
#define DisableDriverPW()   output_low(PINENBPW)



#define TIMER3ON()      bit_set(T3CON,TMR3ON);enable_interrupts(INT_TIMER3)
#define TIMER3OFF()      bit_clear(T3CON,TMR3ON); disable_interrupts(INT_TIMER3)

#define TIMER2ON()        bit_set(T2CON,TMR2ON)
#define TIMER2OFF()      bit_clear(T2CON,TMR2ON)




//
//                   File: ZoomSubPID.C
//
/********************************************************************
            Funciones del control PID
********************************************************************/
void UpdPos(void);
void UpdTraj(void);
void CalcError(void);
void CalcPID(void);
void SetupMove(void);

//---------------------------------------------------------------------
// UpdTraj()
//   Computes the next required value for the next commanded motor
// position based on the current motion profile variables.  Trapezoidal
// motion profiles are produced.
//---------------------------------------------------------------------
void UpdTraj(void){
 if(stat.motion && !stat.saturated){
   if(!stat.phase){               // If in the first half of the move.
      if(velact.ui[1] < vlim)         // If still below the velocity limit
         velact.ul += accell.ul;     // Accelerate
      else                         // If velocity limit has been reached,
         flatcount++;            // increment flatcount.
      temp.ul = velact.ul;         // Put velocity value into temp
                              // and round to 16 bits
      if(velact.ui[0] == 0x8000){
         if(!(velact.ubb[2] & 0x01))
            temp.ui[1]++;
         else;
      }
      else
        if(velact.ui[0] > 0x8000) temp.ui[1]++;
        else;
      phase1dist.ul -= (unsigned int32)temp.ui[1];
      if(stat.neg_move)
         position -= (unsigned int32)temp.ui[1];
      else
         position += (unsigned int32)temp.ui[1];
      if(phase1dist.l <= 0)         // If phase1dist is negative
                              // first half of the move has
         stat.phase = 1;            // completed.
   }
   else   {                     // If in the second half of the move,
                              // Decrement flatcount if not 0.
      if(flatcount) flatcount--;
     else
      if(velact.ul){            // If commanded velocity not 0,
         velact.ul -= accell.ul;   // Decelerate
         if(velact.i[1] < 0)
            velact.l = 0;
      }
      else{                  // else
         if(dtime) dtime--;      // Decrement delay time if not 0.
         else{
            stat.motion = 0;   // Move is done, clear motion flag
            position = fposition;
         }
      }
       temp.ul = velact.ul;         // Put velocity value into temp
                              // and round to 16 bits
      if(velact.ui[0] == 0x8000){
         if(!(velact.ubb[2] & 0x01))
            temp.ui[1]++;
         else;
      }
      else
        if(velact.ui[0] > 0x8000) temp.ui[1]++;
        else;
      if(stat.neg_move)            // Update commanded position
        position -= (unsigned int32)temp.ui[1];
      else
         position += (unsigned int32)temp.ui[1];
      }//end else if(!stat.phase){
  }   // END if (stat.motion)
 else{
   if(stat.run && !stat.motion){   // If motion stopped and profile
                           // running, get next segment number
      if(segnum < firstseg) segnum = firstseg;
      if(segnum > lastseg){
         segnum = firstseg;      // Clear run flag if loop flag not set.
         if(!stat.loop) stat.run = 0;
      }
      else{
         SetupMove();         // Get data for next motion segment.
         segnum++;            // Increment segment number.
      }
   }
   else;
   }
}

//---------------------------------------------------------------------
// SetupMove()
// Gets data for next motion segment to be executed
//---------------------------------------------------------------------
void SetupMove(void){
/* if(segnum < 12){                        // Get profile segment data from data memory.
   phase1dist.i[0] = segment1[segnum][DIST];
   vlim = segment1[segnum][VEL];
   accell.i[0] = segment1[segnum][ACCEL];
   dtime = segment1[segnum][TIME];
 }*/
// if(segnum < 24){         //Solo el 23

   phase1dist.i[0] = SegmentOrd[DIST];
   vlim = SegmentOrd[VEL];
   accell.i[0] = SegmentOrd[ACCEL];
   dtime = SegmentOrd[TIME];
// }
 phase1dist.bb[2] = phase1dist.bb[1];      // Rotate phase1dist one byte
 phase1dist.bb[1] = phase1dist.bb[0];      // to the left.
 phase1dist.bb[0] = 0;
 if(phase1dist.bb[2] & 0x80)             // Sign-extend value
   phase1dist.bb[3] = 0xff;
 else
   phase1dist.bb[3] = 0;

 accell.bb[3] = 0;                     // Rotate accell one byte to
 accell.bb[2] = accell.bb[1];            // the left
 accell.bb[1] = accell.bb[0];
 accell.bb[0] = 0;

 temp.l = position;

 if(temp.ubb[0] > 0x7f)                  // A fractional value is left
   temp.l += 0x100;                  // over in the 8 LSbits of
 temp.ubb[0] = 0;                     // position, so round position
                                 // variable to an integer value
 position = temp.l;                     // before computing final move
                                 // position.
 fposition = position + phase1dist.l;   // Compute final position for
                                 // the move
 if(phase1dist.bb[3] & 0x80){         // If the move is negative,
   stat.neg_move = 1;               // Set flag to indicate negative
   phase1dist.l = -phase1dist.l;      // move.
 }
 else stat.neg_move = 0;            // Clear flag for positive move

 phase1dist.l >>= 1;               // phase1dist holds total
                                     // move distance, so divide by 2
 velact.l = 0;                          // Clear commanded velocity
 flatcount = 0;                     // Clear flatcount
 stat.phase = 0;                  // Clear flag:first half of move
 if(accell.l && vlim)
 stat.motion = 1;                  // Enable motion
}
//---------------------------------------------------------------------
// UpdPos()
//---------------------------------------------------------------------
void UpdPos(void){
 // Old timer values are presently stored in UpCount and DnCount, so
 // add them into result now.
 mvelocity = DnCount;
 mvelocity -= UpCount;

 //  Write new timer values into UpCount and DnCount variables.
 UpCount = get_timer0();   //ReadTimer0();
 DnCount = get_timer1();   //ReadTimer1();



 // Add new count values into result.
 mvelocity += UpCount;
 mvelocity -= DnCount;
 // Add measured velocity to measured position to get new motor
 // measured position.
 mposition += (signed int32)mvelocity << 8;
}
//---------------------------------------------------------------------
// CalcError()
// Calculates position error and limits to 16 bit result
//---------------------------------------------------------------------
void CalcError(void){
 u0.l = mposition - position;            // Get error
 u0.bb[0] = u0.bb[1];
 u0.bb[1] = u0.bb[2];                  // shift to the right to discard
 u0.bb[2] = u0.bb[3];                  // lower 8 bits.
 if (u0.bb[2] & 0x80){                  // If error is negative.
   u0.bb[3] = 0xff;                  // Sign-extend to 32 bits.
   if((u0.i[1] != 0xffff) || !(u0.bb[1] & 0x80)){
      u0.ui[1] = 0xffff;               // Limit error to 16-bits.
      u0.ui[0] = 0x8000;
   }
   else;
   }
 else{                              // If error is positive.
   u0.bb[3] = 0x00;
   if((u0.i[1] != 0x0000) || (u0.bb[1] & 0x80)){
      u0.ui[1] = 0x0000;               // Limit error to 16-bits.
      u0.ui[0] = 0x7fff;
   }
   else;
   }
}
//---------------------------------------------------------------------
// CalcPID()
// Calculates PID compensator algorithm and determines new value for
// PWM duty cycle
//---------------------------------------------------------------------
void CalcPID(void){
  ypid.l = (signed int32)u0.i[0]*(signed int32)kpp;      // If proportional gain is not 0,
                                    // calculate proportional term.
  if(!stat.saturated)                        // If output is not saturated,
   integral += u0.i[0];                  // add present error to integral
                                    // value.
  if(kii)                                 // If integral value is not 0,
  ypid.l += (signed int32)integral*(signed int32)kii;   // calculate integral term.

  if(kdd)                              // If differential term is not 0,
  ypid.l += (signed int32)mvelocity*(signed int32)kdd;   // calculate differential term.
  if(ypid.bb[3] & 0x80){                  // If PID result is negative
   if((ypid.bb[3] < 0xff) || !(ypid.bb[2] & 0x80)){
      ypid.ui[1] = 0xff80;            // Limit result to 24-bit value
      ypid.ui[0] = 0x0000;
   }
   else;
  }
  else{                              // If PID result is positive
   if(ypid.bb[3] || (ypid.bb[2] > 0x7f)){
      ypid.ui[1] = 0x007f;            // Limit result to 24-bit value
      ypid.ui[0] = 0xffff;
   }
   else;
  }
  ypid.bb[0] = ypid.bb[1];               // Shift PID result right to
  ypid.bb[1] = ypid.bb[2];               // get upper 16 bits.

  stat.saturated = 0;                  // Clear saturation flag and see
  if(ypid.i[0] > 500){                  // if present duty cycle output
                                 // exceeds limits.
   ypid.i[0] = 500;
   stat.saturated = 1;
  }
  if(ypid.i[0] < -500){
   ypid.i[0] = -500;
   stat.saturated = 1;
  }
  ypid.i[0] += 512;                     // Add offset to get positive
  ypid.i[0] <<= 6;                     // duty cycle and shift left to
                                 // get 8 Msb's in upper byte.
  CCPR1L = ypid.bb[1];                  // Write upper byte to CCP register
                                 // to set duty cycle.
                                 // Set 2 LSb's of duty cycle in
                                 // CCP1CON register.
  if(ypid.bb[0] & 0x80) bit_set(CCP1CON,5);   // CCP1X = 1;
  else bit_clear(CCP1CON,5);   //CCP1X = 0;
  if(ypid.bb[0] & 0x40) bit_set(CCP1CON,4);   //CCP1Y = 1;
  else  bit_clear(CCP1CON,4);   //CCP1Y = 0;

}

//
//                   File: ZoomSUB.C
//
/********************************************************************

********************************************************************/
#define DisablePullups()  bit_set(INTCON2,RBPU);
#define EnablePullups()     bit_clear(INTCON2,RBPU);

// Function Prototypes-------------------------------------------------
void DoCommand(void);
void Setup(void);

void EEDatWrite(unsigned char address, int16 data);
signed int16 EEDatRead(unsigned char address);
void SetDCPWM1(unsigned int16 dutycycle);
void OpenPWM1( char period );
void EEDatWrite(unsigned char address, int16 data);
signed int16 EEDatRead(unsigned char address);
void DoCommand(void);
void CargaDistancia(signed int16 Distt);
void AnchoBanda(void);

//---------------------------------------------------------------------
//   Setup() initializes program variables and peripheral registers
//---------------------------------------------------------------------
void Setup(void){
  firstseg = 0;                     // 8 bits Initialize motion segment
  lastseg = 0;                     // 8 bits variables
  segnum = 0;
  parameter = 0;                  // 8 bits Motion segment parameter#
  i = 0;                        // Receive buffer index
  comcount = 0;                     // Input command index
  udata = 0;                        // Holds USART received data

  //Un bit del byte stat
  stat.phase = 0;                  // Initialize flags and variables
  stat.saturated = 0;               // used for servo calculations.
  stat.motion = 0;
  stat.run = 0;
  stat.loop = 0;
  stat.neg_move = 0;

  dtime = 0;
  integral = 0;
  vlim = 0;
  velcom = 0;
  mvelocity = 0;
  DnCount = 0;
  UpCount = 0;

  temp.l = 0;
  accell.l = 0;
  u0.l = 0;
  ypid.l = 0;
  velact.l = 0;
  phase1dist.l = 0;
  position = 0;
  mposition = position;
  fposition = position;
  flatcount = 0;

  memset(inpbuf,0,8);         // clear the input buffer
  udata = RCREG1;
  udata = RCREG1;
  RCREG1 = 0;
  udata = 0;

  #ifdef PLLMHz
   T2CON = 0b11111000;         //40MHz: INT cada 408us //Para el PWM solo actua el prescaler = 39,2 Khz
  #else
   T2CON = 0b11001000;         //   19.53 Khz PWM @ 20MHz 0b11001000
  #endif
  bit_clear(PIR1,TMR2IF);      //Borra INT
  bit_set(PIE1,TMR2IE);       //Habilita INT
  bit_set(T2CON,TMR2ON);      //Timer 2 ON
  SetDCPWM1(512);            // 50% initial duty cycle
  OpenPWM1(0xff);            // Setup Timer2, CCP1 to provide
  EnablePullups();              // Enable PORTB pullups

  T1CON = 0b10000010;         //Enable 16 bits
  bit_clear(PIE1,TMR1IE);      //No INT
  bit_clear(PIR1,TMR1IF);      //Borra INT

  set_timer1(0);
  bit_set(T1CON,TMR1ON);      //Timer1 ON

  T0CON = 0b00101000;         //16 bits
  bit_clear(INTCON,TMR0IE);      //No INT
  TMR0L = 0;               // Clear timers.
  TMR0H = 0;
  bit_set(T0CON,TMR0ON);      //Timer0 ON

  ADCON1 = 0b00001101;         //AN0,AN1
  ADCON0 = 0b00000001;         //Canal 0
  ADCON2 = 0b10111110;         //Right,20TAD,Fosc/64

  PORTC = 0;               // Clear PORTC
  PORTD = 0;               // Clear PORTD
  PORTE = 0x00;               // Clear PORTE
  TRISC = 0xdb;               //
  TRISD = 0;               // PORTD all outputs
  TRISE = 0;               // PORTE all outputs

  kpp = EEDatRead(KP);         // Get PID gain values from
  kii = 0;                  // data EEPROM
  kdd = EEDatRead(KD);         //
  if(Kdd == 0xFFFF)   Kdd= -1000;   //Para el servo MG946R
  if(Kpp == 0xFFFF)   Kpp=6000;   //Para el servo MG946R

  //Timer3 para llevar a tope el zoom y que no patine
  //set_timer3(53035);   //53035 = 10ms. con 40MHz
  set_timer3(400);   //400 = 40ms. con 40MHz
  setup_timer_3(T3_INTERNAL | T3_DIV_BY_8);
  TIMER3OFF();

  fprintf(UARTR1,"Configurado Servo...\r\n");
  fprintf(UARTR1,ready);
  enable_interrupts(GLOBAL);

  #ifdef PIC18LF6722
    enable_interrupts(INT_RDA2);
  #else
    enable_interrupts(INT_RDA);
  #endif
}
/****************************************************************/
/* Union used to hold the 10-bit duty cycle */
union PWMDC{
    unsigned int16 lpwm;
    signed int8 bpwm[2];      //char
};
/****************************************************************/
/////////////////////////////////////////////
void SetDCPWM1(unsigned int16 dutycycle){
  union PWMDC DCycle;
  // Save the dutycycle value in the union
  DCycle.lpwm = dutycycle << 6;
  // Write the high byte into CCPR1L
  CCPR1L = DCycle.bpwm[1];
  // Write the low byte into CCP1CON5:4
  CCP1CON = (CCP1CON & 0xCF) | ((DCycle.bpwm[0] >> 2) & 0x30);
}

/****************************************************************/
////////////////////////////////////
void OpenPWM1( char period ){
      CCP1CON |= 0b00001100;    //ccpxm3:ccpxm0 11xx=pwm mode
   output_low(PIN_C2);
//---------------------------------------------------
    bit_clear(T2CON,TMR2ON);   // STOP TIMER2 registers to POR state
     PR2 = period;                // Set period
    bit_set(T2CON,TMR2ON);     // Turn on PWM1
}
/****************************************************************/
//---------------------------------------------------------------------
// ExtEEWrite()
// Writes an integer value to an EEPROM connected to the I2C bus at
// the specified location.
//---------------------------------------------------------------------
void EEDatWrite(unsigned char address, int16 data){
 unsigned int Tmp;
  Tmp = make8(data,0);
  write_eeprom(address,Tmp);   // Attempt to write low byte of data
  Tmp = make8(data,1);
  write_eeprom(address++,Tmp);   // Attempt to write high byte of data
}
//---------------------------------------------------------------------
// ExtEEWrite()
// Reads an integer value from an EEPROM connected to the I2C bus at
// the specified location.
//---------------------------------------------------------------------
signed int16 EEDatRead(unsigned char address){
 unsigned int8 TemH,TemL;
  TemL = read_eeprom(address),         // Attempt to read low byte of data
  TemH = read_eeprom(address++);      // Attempt to read high byte of data
 return make16(TemH,TemL);
}
//-------------------------------------------------------------------
// DoCommand()
// Processes incoming USART data.
//-------------------------------------------------------------------
void DoCommand(void){
 if(comcount == 0){      // If this is the first parameter of the input command...
   switch(inpbuf[0]){
      case 'X':   parameter = DIST;      // Segment distance change
                  break;

      case 'V':   parameter = VEL;      // Segment velocity change
                  break;

      case 'A':   parameter = ACCEL;      // Segment acceleration change
                  break;

      case 'T':   parameter = TIME;      // Segment delay time change
                  break;

      case 'P':   parameter = 'P';      // Change proportional gain
                  break;

      case 'I':   parameter = 'I';      // Change integral gain
                  break;

      case 'D':   parameter = 'D';      // Change differential gain
                  break;

      case 'L':   parameter = 'L';      // Loop a range of segments
                  break;

      case 'S':   stat.run = 0;         // Stop execution of segments
                  break;

      case 'G':   parameter = 'G';      // Execute a range of segments
                  break;

      case 'W':   if(ENBMotor){               // Enable or disable motor driver IC
                     DisableDriverPW();ENBMotor=False;   //RE2 = 0;
                     //output_low(PIN_E2);ENBMotor=False;   //RE2 = 0;
                     fprintf(UARTR1,"\r\nPWM Off\r\n");
               }
               else{
                     EnableDriverPW();ENBMotor=True;//RE2 = 1;
                     //output_high(PIN_E2);ENBMotor=True;//RE2 = 1;
                     fprintf(UARTR1,"\r\nPWM On\r\n");
               }
               break;
      default:   { if(inpbuf[0] != '\0'){
                 fprintf(UARTR1,"Error\r\n");
                   }
                 }
                 break;
      }
   }
 else if(comcount == 1){      // If this is the second parameter of the input command.
   if(parameter < 4) segnum = (char)(atol(inpbuf));
   else
   switch(parameter){
      case 'P':{  kpp = atol(inpbuf);         // proportional gain change
                  EEDatWrite(KP, kpp);      // Store value in EEPROM
             }
               break;

      case 'I':{   kii = atol(inpbuf);         // integral gain change
                  EEDatWrite(KI, kii);      // Store value in EEPROM
             }
               break;

      case 'D':{   kdd = atol(inpbuf);         // differential gain change
                  EEDatWrite(KD, kdd);      // Store value in EEPROM
             }
               break;

      case 'G':   firstseg = (char)(atoi(inpbuf));
               break;
                                    // Get the first segment in
                                       // the range to be executed.

      case 'L':   firstseg = (char)(atoi(inpbuf));
               break;

      default:    break;
        }
 }
 else if(comcount == 2){
      ////Al quitar if(!stat.run), cuando está en "loop" basta con enviar un nuevo "X"
      //// para que actue. Con el if, hay que llevar a "Stop", cambiar el "X" y enviar "L"
      //if(!stat.run){               // If no profile is executing
      if(parameter < 4){               // If this was a segment parameter change.
         /*   if(segnum < 12){
            // Write the segment paramater into data memory
            segment1[segnum][parameter] = atol(inpbuf);
            // Compute EEPROM address and write data to EEPROM
            eeadrr = (segnum << 3) + (parameter << 1);
            EEDatWrite(eeadrr, segment1[segnum][parameter]);
         }*/
         if(segnum < 24)
            // Write segment parameter data into data memory
            OrdenPosNEW  = atol(inpbuf);
            //SegmentOrd[parameter] = atol(inpbuf);


         /*Temporal1 = OrdenPosNEW;
            fprintf(UARTR1,"New: %ld\r\n",OrdenPosNEW);
         if(OrdenPosNEW != OrdenPosOLD){
            OrdenPosNEW  -= OrdenPosOLD;
            OrdenPosOLD = Temporal1;
            SegmentOrd[parameter] = OrdenPosNEW;   //atol(inpbuf);
          }else{
            SegmentOrd[parameter] = 0;   //atol(inpbuf);
         }
         fprintf(UARTR1,"Sum: %ld\r\n",SegmentOrd[parameter]);*/
      }
      else switch(parameter){
         case 'G':{   lastseg = (char)(atoi(inpbuf));   // Get value for
                     segnum = firstseg;            // last segment.
                  stat.loop = 0;
                  stat.run = 1;               // Start profile.
                }
               break;

         case 'L':{   lastseg = (char)(atoi(inpbuf));   // Get value for
                     segnum = firstseg;            // last segment.
                  stat.loop = 1;               // Enable looping
                  stat.run = 1;               // Start profile
                }
                break;

         default:    break;
       }//   else switch(parameter){
   //}//   if(!stat.run){
 }// else if(comcount == 2){
 else;
}
//-------------------------------------------------------------------
// ExtraeCommand()
// Processes incoming USART data.
//-------------------------------------------------------------------
void ExtraeCommand(char Caracter){
   //if(bit_test(PIR1,RC1IF)){            // Check for USART interrupt
      switch(Caracter){
         case ',':     DoCommand();            // process the string
                    memset(inpbuf,0,8);      // clear the input buffer
                     i = 0;               // clear the buffer index
                     comcount++;            // increment comma count
                     break;
         case 0x0d:  DoCommand();            // process the string
                     memset(inpbuf,0,8);      // clear the input buffer
                     i = 0;               // clear the buffer index
                     comcount = 0;            // clear comma count
                 segnum = 0;            // clear segment number
                 parameter = 0;         // clear paramater
                     break;
         default:    inpbuf[i] = Caracter,   //udata;      // get received char
                     i++;                  // increment buffer index
                     if(i > 7){         // If more than 8 chars received before getting
                        memset(inpbuf,0,8);   // buffer
                        i = 0;               // the buffer index
                     }
                     else;   // {TXREG1 = udata; }    //echo character
                     break;
      }//end switch(udata)
}

//////////////////////////////////////
/////////////////////////////////////
void CargaDistancia(signed int16 Distt){
  //segment2[segnum - 12][parameter] = atol(inpbuf);
  SegmentOrd[DIST] = Distt;   //Distancia
  SegmentOrd[VEL] = 4096;   //Velocidad
  SegmentOrd[ACCEL] = 32000;   //Aceleración
  SegmentOrd[TIME] = 0;      //Time
}
//////////////////////////////////////
/////////////////////////////////////
void AnchoBanda(void){
   PORTD = 0;               // Clear the LED bargraph display.
   PORTE   &= 0x04;         //                  "

   if(ADRES > 225){
      PORTE |= 0x03;         // Turn on 10 LEDS
      PORTD = 0xff;
   }
   if(ADRES > 200){
      PORTE |= 0x01;         // Turn on 9 LEDS
      PORTD = 0xff;
   }
   else if(ADRES > 175) PORTD = 0xff;   // Turn on 8 LEDS
   else if(ADRES > 150) PORTD = 0x7f;   // 7 LEDS
   else if(ADRES > 125) PORTD = 0x3f;   // 6 LEDS
   else if(ADRES > 100) PORTD = 0x1f;   // 5 LEDS
   else if(ADRES > 75) PORTD = 0x0f;   // 4 LEDS
   else if(ADRES > 50) PORTD = 0x07;   // 3 LEDS
   else if(ADRES > 25) PORTD = 0x03;   // 2 LEDS
   else if(ADRES > 0) PORTD = 0x01;   // 1 LED
   else;

}

//
//                   File: ZoomSYS.C
//
//---------------------------------------------------------------------
// servo_isr()
// Performs the servo calculations
//---------------------------------------------------------------------
///---------------------------------------------------------------------
// Interrupt Timer 2
// Esta interrupción sirve para que se ejecuten los controles
//    cada xx ms.
// El temporizador se ajusta con el Prescaler y
//      Postescaler del registro T2CON
// El PWM se ajusta solo con el Prescaler
//---------------------------------------------------------------------
#INT_TIMER2
void Timer2(){
  output_high(SPULSE);   // = 1;      // Toggle output pin for ISR code timing
    UpdTraj();                  // Get new commanded position
    UpdPos();                     // Get new measured position
    CalcError();                  // Calculate new position errorr
    CalcPID();
    bit_clear(PIR1,TMR2IF);         //PIR1bits.TMR2IF = 0;   // Clear Timer2 Interrupt Flag.
  output_low(SPULSE);// = 0;      // Toggle output pin for ISR code timing
}

/////////////////////////////////////////////////////////////
//                INT TIMER3
//   La INT3 se emplea para llevar a tope el zoom y que no patine
//   Con el servo MG946R en aceleración la distancia entre pulsos
//      es de 12 ms máx y en frenado 22ms.
/////////////////////////////////////////////////////////////
#INT_TIMER3
void Timer3() {

  set_timer3(400);   //400 = 40ms. con 40MHz

  if((get_timer0() == Timer0OLD) && (get_timer1() == Timer1OLD)){
   TIMER3OFF();
  }
  else{
   Timer0OLD=get_timer0();Timer1OLD = get_timer1();
  }
}
/////////////////////////////////////////////////////////////
//                INT RDA, RS232
//         Recibe una orden através del la UART
/////////////////////////////////////////////////////////////
#ifdef PIC18LF6722
   #INT_RDA2
#else
   #INT_RDA
#endif
void  UARTRx() {
unsigned char ByteRx,buffer;
unsigned int8 timeout;
  ByteRx=fgetc(UARTR1);
  #ifdef PIC18LF6722
     bit_clear(PIR1,RC1IF);               //Borra bandera de INT
  #else
    bit_clear(PIR1,RCIF);
  #endif
      TramaRecUART[buffer]=ByteRx;
      buffer++;               // Incrementa string pointer, el primero es ">"
      comcount = 0;
      do{
         timeout =0;            //Espera a recibir, y si no, solo espera 1ms después de recibir el último
         while (!kbhit(UARTR1) && (++timeout<100))delay_us(10);
         if(kbhit(UARTR1)) {
            ByteRx = fgetc(UARTR1);   }   // Get un caracter de la USART
          else{OrdenRec = False;break;}
           TramaRecUART[buffer] = ByteRx;
           buffer++;                             // Incrementa string pointer
           //if(ByteRx == ',') comcount++;         //N parametros
          if(buffer >80){buffer = 0; break;}
       }while(ByteRx > 9);//9                     //Incluye CR y LF
      OrdenRec = True;
      if((ByteRx == 13)) {   //|| (ByteRx == 10)){      //Incluye CR y LF
         TramaRecUART[buffer] = 0;
         OrdenRec = True;
      }
}


//
//                   File: ZoomAN696.C
//
/////////////////////////////////////////////////////////////////////////////
//                 CONTROL DE MOTORRES PARA PLATAFORMA                    ///
//                     GIROESTABILIZADA                          ///
//                      PIC "C" Compiler PCM                                ///
//      Esta versión es la que procede de la original del PIC18C452           ///
//      Se ha añadido la comprobación, después de leer la EEPROM,           ///
//      si Kp y Kd son 0xFFFF. Esto indica que la EEPROM estaba              ///
//      borrada. Un valor 0xFFFF hace que no funcione nada                 ///
//      Se inicializa Kp con 6000 y Kd con -1000 (0 a 6000 y -32000 a 32000)///
///            para el servo MG946R                              ///
///////////////////////////////////////////////////////////////////////////////

//#define PIC18LF6722
#define PLLMHz
#define Debuger1
#ifdef PIC18LF6722
   #include <18F6722.h>
   #include <p18f6722m.inc>
#else
   #include <18F8722.h>
   #include <p18f8722m.inc>
#endif
#device *=16
#include "STRING.H"
#include "STDLIB.H"


#include <ZoomAN696.h>
#include <ZoomSubPID.c>
#include <ZoomSUB.c>
#include <ZoomSYS.c>

#ZERO_RAM
//#priority ext, timer1,timer3
//---------------------------------------------------------------------
// main()
//---------------------------------------------------------------------
void main(){
unsigned int8 CaracterRec,NCaracterRec;
  fprintf(UARTR1,"Configurando PIC18xx...\r\n");
  Setup();
  fprintf(UARTR1,"PWM On\r\n");
  EnableDriverPW();ENBMotor=True;   //RE2 = 1;

  SegmentOrd[DIST] = 450;
  //CargaDistancia(450);
  SegmentOrd[VEL] = 20;   //10 4096Velocidad
  //SegmentOrd[ACCEL] = 32000;   //Aceleración
  SegmentOrd[ACCEL] = 50;         //6000 Acelera
  SegmentOrd[TIME] = 0;      //Time

  firstseg =23;lastseg=23;
  stat.loop = 0;
  stat.run = 1;




  delay_ms(100);      //Espera que arranque
  TIMER3ON();
  do{
     delay_us(100);
  }while(bit_test(T3CON,TMR3ON));
  //stat.run = 0;
  // set_timer0(450);
   SegmentOrd[DIST] = 0;
   mposition = position =fposition;
    stat.motion = flatcount = velact = dtime = 0; stat.motion = 0;

  fprintf(UARTR1,"mpos: %Ld fpos: %Ld posi: %Ld\r\n",mposition,fposition,position);

  fprintf(UARTR1,"T0: %Ld T1: %Ld\r\n",get_timer0(),get_timer1());
  delay_ms(100);      //Espera que arranque
  set_timer1(0);
  set_timer0(0);

  UpCount =  DnCount = 0;

  SegmentOrd[DIST] = -450;
  //CargaDistancia(-450);
  firstseg =23;lastseg=23;
  stat.loop = 0;
  stat.run = 1;
  delay_ms(100);      //Espera que arranque
  TIMER3ON();
  do{
    delay_us(100);
  }while(bit_test(T3CON,TMR3ON));
 PosicionReal = get_timer0() - get_timer1();
 // set_timer1(450);
   SegmentOrd[DIST] = 0;
  mposition = position =fposition;
  stat.motion = flatcount = velact = dtime = 0; stat.motion = 0;

  delay_ms(50);   //250
  set_timer1(0);  set_timer0(0); PosicionReal = 0;
  DnCount = UpCount =   flatcount = velact = dtime = 0; stat.motion = 0;
OrdenPosOLD = OrdenPosNEW = SegmentOrd[DIST] = 0;

////////////////////////////////////////////////////
///////////////////////////////////////////////////


  while(1){
   restart_wdt();
   bit_clear(PIR1,ADIF);      //Borra INT
   bit_set(ADCON0,GO);         // Start an A/D conversion
   while(!bit_test(PIR1,ADIF));   //while(ADGO);               // Wait for the conversion to complete

     ValorADC = (float)ADRESHL;
     ValorADC = (ValorADC*100)/1024;

    OrdenPosADC  = (unsigned int16)ValorADC;

    if(ValorADC >60) PORTD = 0b10000000;
   else if(ValorADC >55) PORTD = 0b01000000;
   else if(ValorADC >50) PORTD = 0b00100000;
   else if(ValorADC >47) PORTD = 0b00010000;
   else if(ValorADC >45) PORTD = 0b00001000;
   else if(ValorADC >40) PORTD = 0b00000100;
   else if(ValorADC >35) PORTD = 0b00000010;
   else if(ValorADC >30) PORTD = 0b00000001;
   else;


//   fprintf(UARTR1,"New: %ld, %ld\r\n",OrdenPosNEW,PosicionReal);





   if(OrdenRec){
      NCaracterRec = strlen(TramaRecUART);
      for(CaracterRec=0;CaracterRec<NCaracterRec;CaracterRec++){
      ExtraeCommand(TramaRecUART[CaracterRec]);
      }
      OrdenRec = False;
   }

 }//end while(1)
}
Jerry I



Joined: 14 Sep 2003
Posts: 96
Location: Toronto, Ontario, Canada

View user's profile Send private message

PostPosted: Tue Dec 10, 2013 10:58 pm     Reply with quote

Hi

I did a conversion of this AN 2 years ago, but did get to work but never actually used it.

The function your looking for to go directly to an encoder position, I did implement. Your code is different than mine, but I did try to add the functionality to your code.

I add new variable travel_to.
and new command R
changed T for Time -> H Hold Time
made T for Travel to position.

Look though the changes I added to your code should find.
/***** ADDED NEW xxxxxxxxxxx

I did not compile your code, so I am not sure if something is missing. I just compared my code to yours and added the changes I had made.

Not sure it will work. It took me a good month to get my code working.

Let me know.

Code:



//
//                   
File: ZoomAN696.H
//
///////////////////////////////////////////////////////////////////////////////
//////// Program memory: 0x16  Data RAM: 3840  Stack: 31
//////// I/O: 40   Analog Pins: 12
//////// Data EEPROM: 1024
//////// C Scratch area: 00   ID Location: 2000
//////// Fuses: LP,XT,HS,RC,EC,EC_IO,H4,RC_IO,PROTECT,NOPROTECT,IESO,NOIESO
//////// Fuses: NOBROWNOUT,BROWNOUT,WDT1,WDT2,WDT4,WDT8,WDT16,WDT32,WDT64
//////// Fuses: WDT128,WDT,NOWDT,BORV25,BORV27,BORV42,BORV45,PUT,NOPUT,CPD
//////// Fuses: NOCPD,NOSTVREN,STVREN,NODEBUG,DEBUG,NOLVP,LVP,WRT,NOWRT,CPB
//////// Fuses: NOCPB,EBTRB,NOEBTRB,EBTR,NOEBTR,CCP2B3,CCP2C1,WRTD,NOWRTD
//////// Fuses: WRTC,NOWRTC,WRTB,NOWRTB,FCMEN,NOFCMEN,INTRC,INTRC_IO
//////// Fuses: BROWNOUT_SW,BROWNOUT_NOSL,WDT_256,WDT_512,WDT_1024,WDT_2048
//////// Fuses: WDT_4096,WDT_8192,WDT_16384,WDT_32768,LPT1OSC,NOLPT1OSC,MCLR
//////// Fuses: NOMCLR,XINST,NOXINST,BBSIZE1K,BBSIZE2K,BBSIZE4K
///////////////////////////////////////////////////////////////////////////////
#ifdef Debuger1
  #ifdef PLLMHz
   #fuses H4,noWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,DEBUG, WDT128,NOEBTR,BROWNOUT
  #else
   #fuses HS,noWDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,DEBUG, WDT128,NOEBTR,BROWNOUT
  #endif
#else
  #ifdef PLLMHz
   #fuses H4,WDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,  noDEBUG, WDT128,NOEBTR,BROWNOUT
  #else
   #fuses HS,WDT,NOPROTECT,NOPUT,NOBROWNOUT,NOLVP,  noDEBUG, WDT128,NOEBTR,BROWNOUT
  #endif
#endif

#ifdef PLLMHz
   #use delay(clock=40000000,RESTART_WDT)   //10.000.000 * 4
#else
   #use delay(clock=20000000,RESTART_WDT)
#endif

#ifdef PIC18LF6722
  #use RS232(BAUD=115200, XMIT=PIN_G1,RCV=PIN_G2,BRGH1OK,RESTART_WDT,STREAM=UARTR1)
#else
  #use RS232(BAUD=115200, XMIT=PIN_C6,RCV=PIN_C7,BRGH1OK,RESTART_WDT,STREAM=UARTR1)
#endif
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//Constant Definitions
//---------------------------------------------------------------------

#define   DIST   0            // Array index for segment distance
#define   VEL      1            // Array index for segment vel. limit
#define   ACCEL   2            // Array index for segment accell.
#define   TIME   3            // Array index for segment delay time

   /***********ADDED NEW DEFINE **************/
#define   TRAVEL  4            // Array indev for segment motor travel via encoder
   /***********END NEW CODE*********/


#define   INDEX   RB0            // Input for encoder index pulse
#define   NLIM   RB1            // Input for negative limit switch
#define   PLIM   RB2            // Input for positive limit switch
#define   input(PIN_B3)         //GPI   RB3      // General purpose input
#define   MODE1   !input(PIN_B4)   //PORTBbits.RB4      // DIP switch #1
#define   MODE2   !input(PIN_B5)   //PORTBbits.RB5      // DIP switch #2
#define   MODE3   !input(PIN_B6)   //PORTBbits.RB6      // DIP switch #3
#define   MODE4   !input(PIN_B7)   //PORTBbits.RB7      // DIP switch #4
#define   SPULSE   PIN_C5         //#define   SPULSE RC5      // Software timing pulse output
#define   ADRES   ADRESH         // Redefine for 10-bit A/D converter
#define  KP       250
#define  KI       252
#define  KD       254
#define  ADRESHL   make16(ADRESH,ADRESL)
//---------------------------------------------------------------------
// Variable declarations
//---------------------------------------------------------------------
const char ready[] = "\r\nREADY>\r\n";
const char error[] = "\r\nERROR!\r\n";

signed int8 inpbuf[8];   //8bits

char
eeadrr,
firstseg,
lastseg,
segnum,
parameter,
i,                              // index to ASCII buffer
comcount,                        // index to input string
udata                           // received character from USART
;
//Un bit del byte stat
struct {                              // holds status bits for servo
    unsigned            phase:1;      // first half/ second half of profile
    unsigned         neg_move:1;      // backwards relative move
    unsigned          motion:1;      //
    unsigned        saturated:1;      // servo output is saturated
    unsigned             bit4:1;
    unsigned           bit5:1;
    unsigned              run:1;
    unsigned             loop:1;
} stat ;

union LNG{
signed int32 l;
unsigned int32 ul;
signed int16 i[2];
unsigned int16 ui[2];
unsigned int8 bb[4];
unsigned int8 ubb[4];
};

union LNG
accell,
temp,
u0,
ypid,
velact,
phase1dist
;

signed int16
dtime,                        // Segment delay time
integral,
kpp,
kii,
kdd,                     // PID gain constants
vlim, velcom,
mvelocity,
DnCount,
UpCount,
tempch;

signed int32
   /***********ADDED NEW VARIABLE **************/
travel_to,                    // Travel_to Position
   /***********END NEW VARIABLE **************/

position,                     // Commanded position.
mposition,                  // Actual measured position.
fposition,                  // Originally commanded position.
flatcount;                    // Holds # of sample periods for which
                        // the velocity limit was reached in first
                        // half of the move.

float ValorADC;
signed int16 PosicionReal;
signed int16 Temporal1;
signed int16 OrdenPosOLD;
signed int16 OrdenPosNEW;
signed int16 OrdenPosADC;


signed int16 segment1[12][4];      // array in bank2 for 12 motion segments
signed int16 SegmentOrd[4];      // array in bank3 for 12 motion segments
unsigned char TramaRecUART[15];         //Trama recibida en UART de órdenes

unsigned int16 Timer0OLD,Timer1OLD;      //Control de patinado del servo cuando llega a topes

char FLAG;
#bit ENBMotor  =        FLAG.0      // Indicador de que el motor se acaba de arrancar
#define   ENBMotorASM      FLAG,0
#bit OrdenRec  =     FLAG.1
#define   OrdenRecASM   FLAG,1

#ifdef PIC18LF6722
   #define PINENBPW      PIN_A5   //DIR en la versión anterior
#else
   #define PINENBPW      PIN_E2
#endif
#define EnableDriverPW()   output_high(PINENBPW)
#define DisableDriverPW()   output_low(PINENBPW)



#define TIMER3ON()      bit_set(T3CON,TMR3ON);enable_interrupts(INT_TIMER3)
#define TIMER3OFF()      bit_clear(T3CON,TMR3ON); disable_interrupts(INT_TIMER3)

#define TIMER2ON()        bit_set(T2CON,TMR2ON)
#define TIMER2OFF()      bit_clear(T2CON,TMR2ON)




//
//                   File: ZoomSubPID.C
//
/********************************************************************
            Funciones del control PID
********************************************************************/
void UpdPos(void);
void UpdTraj(void);
void CalcError(void);
void CalcPID(void);
void SetupMove(void);

//---------------------------------------------------------------------
// UpdTraj()
//   Computes the next required value for the next commanded motor
// position based on the current motion profile variables.  Trapezoidal
// motion profiles are produced.
//---------------------------------------------------------------------
void UpdTraj(void){
 if(stat.motion && !stat.saturated){
   if(!stat.phase){               // If in the first half of the move.
      if(velact.ui[1] < vlim)         // If still below the velocity limit
         velact.ul += accell.ul;     // Accelerate
      else                         // If velocity limit has been reached,
         flatcount++;            // increment flatcount.
      temp.ul = velact.ul;         // Put velocity value into temp
                              // and round to 16 bits
      if(velact.ui[0] == 0x8000){
         if(!(velact.ubb[2] & 0x01))
            temp.ui[1]++;
         else;
      }
      else
        if(velact.ui[0] > 0x8000) temp.ui[1]++;
        else;
      phase1dist.ul -= (unsigned int32)temp.ui[1];
      if(stat.neg_move)
         position -= (unsigned int32)temp.ui[1];
      else
         position += (unsigned int32)temp.ui[1];
      if(phase1dist.l <= 0)         // If phase1dist is negative
                              // first half of the move has
         stat.phase = 1;            // completed.
   }
   else   {                     // If in the second half of the move,
                              // Decrement flatcount if not 0.
      if(flatcount) flatcount--;
     else
      if(velact.ul){            // If commanded velocity not 0,
         velact.ul -= accell.ul;   // Decelerate
         if(velact.i[1] < 0)
            velact.l = 0;
      }
      else{                  // else
         if(dtime) dtime--;      // Decrement delay time if not 0.
         else{
            stat.motion = 0;   // Move is done, clear motion flag
            position = fposition;
         }
      }
       temp.ul = velact.ul;         // Put velocity value into temp
                              // and round to 16 bits
      if(velact.ui[0] == 0x8000){
         if(!(velact.ubb[2] & 0x01))
            temp.ui[1]++;
         else;
      }
      else
        if(velact.ui[0] > 0x8000) temp.ui[1]++;
        else;
      if(stat.neg_move)            // Update commanded position
        position -= (unsigned int32)temp.ui[1];
      else
         position += (unsigned int32)temp.ui[1];
      }//end else if(!stat.phase){
  }   // END if (stat.motion)
 else{
   if(stat.run && !stat.motion){   // If motion stopped and profile
                           // running, get next segment number
      if(segnum < firstseg) segnum = firstseg;
      if(segnum > lastseg){
         segnum = firstseg;      // Clear run flag if loop flag not set.
         if(!stat.loop) stat.run = 0;
      }
      else{
         SetupMove();         // Get data for next motion segment.
         segnum++;            // Increment segment number.
      }
   }
   else;
   }
}

//---------------------------------------------------------------------
// SetupMove()
// Gets data for next motion segment to be executed
//---------------------------------------------------------------------
void SetupMove(void){
/* if(segnum < 12){                        // Get profile segment data from data memory.
   phase1dist.i[0] = segment1[segnum][DIST];
   vlim = segment1[segnum][VEL];
   accell.i[0] = segment1[segnum][ACCEL];
   dtime = segment1[segnum][TIME];
 }*/
// if(segnum < 24){         //Solo el 23

   phase1dist.i[0] = SegmentOrd[DIST];
   vlim = SegmentOrd[VEL];
   accell.i[0] = SegmentOrd[ACCEL];
   dtime = SegmentOrd[TIME];

   /***********ADDED NEW CODE**************/
   travel_to = SegmentOrd[TRAVEL]
   /***********END NEW CODE*********/

// }
 phase1dist.bb[2] = phase1dist.bb[1];      // Rotate phase1dist one byte
 phase1dist.bb[1] = phase1dist.bb[0];      // to the left.
 phase1dist.bb[0] = 0;
 if(phase1dist.bb[2] & 0x80)             // Sign-extend value
   phase1dist.bb[3] = 0xff;
 else
   phase1dist.bb[3] = 0;

 accell.bb[3] = 0;                     // Rotate accell one byte to
 accell.bb[2] = accell.bb[1];            // the left
 accell.bb[1] = accell.bb[0];
 accell.bb[0] = 0;

 temp.l = position;

 if(temp.ubb[0] > 0x7f)                  // A fractional value is left
   temp.l += 0x100;                  // over in the 8 LSbits of
 temp.ubb[0] = 0;                     // position, so round position
                                 // variable to an integer value
 position = temp.l;                     // before computing final move
                                 // position.
 fposition = position + phase1dist.l;   // Compute final position for
                                 // the move
 if(phase1dist.bb[3] & 0x80){         // If the move is negative,
   stat.neg_move = 1;               // Set flag to indicate negative
   phase1dist.l = -phase1dist.l;      // move.
 }
 else stat.neg_move = 0;            // Clear flag for positive move

 phase1dist.l >>= 1;               // phase1dist holds total
                                     // move distance, so divide by 2
 velact.l = 0;                          // Clear commanded velocity
 flatcount = 0;                     // Clear flatcount
 stat.phase = 0;                  // Clear flag:first half of move
 if(accell.l && vlim)
 stat.motion = 1;                  // Enable motion
}
//---------------------------------------------------------------------
// UpdPos()
//---------------------------------------------------------------------
void UpdPos(void){
 // Old timer values are presently stored in UpCount and DnCount, so
 // add them into result now.
 mvelocity = DnCount;
 mvelocity -= UpCount;

 //  Write new timer values into UpCount and DnCount variables.
 UpCount = get_timer0();   //ReadTimer0();
 DnCount = get_timer1();   //ReadTimer1();



 // Add new count values into result.
 mvelocity += UpCount;
 mvelocity -= DnCount;
 // Add measured velocity to measured position to get new motor
 // measured position.
 mposition += (signed int32)mvelocity << 8;
}
//---------------------------------------------------------------------
// CalcError()
// Calculates position error and limits to 16 bit result
//---------------------------------------------------------------------
void CalcError(void){
 u0.l = mposition - position;            // Get error
 u0.bb[0] = u0.bb[1];
 u0.bb[1] = u0.bb[2];                  // shift to the right to discard
 u0.bb[2] = u0.bb[3];                  // lower 8 bits.
 if (u0.bb[2] & 0x80){                  // If error is negative.
   u0.bb[3] = 0xff;                  // Sign-extend to 32 bits.
   if((u0.i[1] != 0xffff) || !(u0.bb[1] & 0x80)){
      u0.ui[1] = 0xffff;               // Limit error to 16-bits.
      u0.ui[0] = 0x8000;
   }
   else;
   }
 else{                              // If error is positive.
   u0.bb[3] = 0x00;
   if((u0.i[1] != 0x0000) || (u0.bb[1] & 0x80)){
      u0.ui[1] = 0x0000;               // Limit error to 16-bits.
      u0.ui[0] = 0x7fff;
   }
   else;
   }
}
//---------------------------------------------------------------------
// CalcPID()
// Calculates PID compensator algorithm and determines new value for
// PWM duty cycle
//---------------------------------------------------------------------
void CalcPID(void){
  ypid.l = (signed int32)u0.i[0]*(signed int32)kpp;      // If proportional gain is not 0,
                                    // calculate proportional term.
  if(!stat.saturated)                        // If output is not saturated,
   integral += u0.i[0];                  // add present error to integral
                                    // value.
  if(kii)                                 // If integral value is not 0,
  ypid.l += (signed int32)integral*(signed int32)kii;   // calculate integral term.

  if(kdd)                              // If differential term is not 0,
  ypid.l += (signed int32)mvelocity*(signed int32)kdd;   // calculate differential term.
  if(ypid.bb[3] & 0x80){                  // If PID result is negative
   if((ypid.bb[3] < 0xff) || !(ypid.bb[2] & 0x80)){
      ypid.ui[1] = 0xff80;            // Limit result to 24-bit value
      ypid.ui[0] = 0x0000;
   }
   else;
  }
  else{                              // If PID result is positive
   if(ypid.bb[3] || (ypid.bb[2] > 0x7f)){
      ypid.ui[1] = 0x007f;            // Limit result to 24-bit value
      ypid.ui[0] = 0xffff;
   }
   else;
  }
  ypid.bb[0] = ypid.bb[1];               // Shift PID result right to
  ypid.bb[1] = ypid.bb[2];               // get upper 16 bits.

  stat.saturated = 0;                  // Clear saturation flag and see
  if(ypid.i[0] > 500){                  // if present duty cycle output
                                 // exceeds limits.
   ypid.i[0] = 500;
   stat.saturated = 1;
  }
  if(ypid.i[0] < -500){
   ypid.i[0] = -500;
   stat.saturated = 1;
  }
  ypid.i[0] += 512;                     // Add offset to get positive
  ypid.i[0] <<= 6;                     // duty cycle and shift left to
                                 // get 8 Msb's in upper byte.
  CCPR1L = ypid.bb[1];                  // Write upper byte to CCP register
                                 // to set duty cycle.
                                 // Set 2 LSb's of duty cycle in
                                 // CCP1CON register.
  if(ypid.bb[0] & 0x80) bit_set(CCP1CON,5);   // CCP1X = 1;
  else bit_clear(CCP1CON,5);   //CCP1X = 0;
  if(ypid.bb[0] & 0x40) bit_set(CCP1CON,4);   //CCP1Y = 1;
  else  bit_clear(CCP1CON,4);   //CCP1Y = 0;

}

//
//                   File: ZoomSUB.C
//
/********************************************************************

********************************************************************/
#define DisablePullups()  bit_set(INTCON2,RBPU);
#define EnablePullups()     bit_clear(INTCON2,RBPU);

// Function Prototypes-------------------------------------------------
void DoCommand(void);
void Setup(void);

void EEDatWrite(unsigned char address, int16 data);
signed int16 EEDatRead(unsigned char address);
void SetDCPWM1(unsigned int16 dutycycle);
void OpenPWM1( char period );
void EEDatWrite(unsigned char address, int16 data);
signed int16 EEDatRead(unsigned char address);
void DoCommand(void);
void CargaDistancia(signed int16 Distt);
void AnchoBanda(void);

//---------------------------------------------------------------------
//   Setup() initializes program variables and peripheral registers
//---------------------------------------------------------------------
void Setup(void){
  firstseg = 0;                     // 8 bits Initialize motion segment
  lastseg = 0;                     // 8 bits variables
  segnum = 0;
  parameter = 0;                  // 8 bits Motion segment parameter#
  i = 0;                        // Receive buffer index
  comcount = 0;                     // Input command index
  udata = 0;                        // Holds USART received data

  //Un bit del byte stat
  stat.phase = 0;                  // Initialize flags and variables
  stat.saturated = 0;               // used for servo calculations.
  stat.motion = 0;
  stat.run = 0;
  stat.loop = 0;
  stat.neg_move = 0;

  dtime = 0;
  integral = 0;
  vlim = 0;
  velcom = 0;
  mvelocity = 0;
  DnCount = 0;
  UpCount = 0;

  temp.l = 0;
  accell.l = 0;
  u0.l = 0;
  ypid.l = 0;
  velact.l = 0;
  phase1dist.l = 0;
  position = 0;
  mposition = position;
  fposition = position;
  flatcount = 0;

   /***********ADDED NEW CODE VARIABLE**************/
  travel_to = 0;
   /***********END NEW CODE*********/




  memset(inpbuf,0,8);         // clear the input buffer
  udata = RCREG1;
  udata = RCREG1;
  RCREG1 = 0;
  udata = 0;

  #ifdef PLLMHz
   T2CON = 0b11111000;         //40MHz: INT cada 408us //Para el PWM solo actua el prescaler = 39,2 Khz
  #else
   T2CON = 0b11001000;         //   19.53 Khz PWM @ 20MHz 0b11001000
  #endif
  bit_clear(PIR1,TMR2IF);      //Borra INT
  bit_set(PIE1,TMR2IE);       //Habilita INT
  bit_set(T2CON,TMR2ON);      //Timer 2 ON
  SetDCPWM1(512);            // 50% initial duty cycle
  OpenPWM1(0xff);            // Setup Timer2, CCP1 to provide
  EnablePullups();              // Enable PORTB pullups

  T1CON = 0b10000010;         //Enable 16 bits
  bit_clear(PIE1,TMR1IE);      //No INT
  bit_clear(PIR1,TMR1IF);      //Borra INT

  set_timer1(0);
  bit_set(T1CON,TMR1ON);      //Timer1 ON

  T0CON = 0b00101000;         //16 bits
  bit_clear(INTCON,TMR0IE);      //No INT
  TMR0L = 0;               // Clear timers.
  TMR0H = 0;
  bit_set(T0CON,TMR0ON);      //Timer0 ON

  ADCON1 = 0b00001101;         //AN0,AN1
  ADCON0 = 0b00000001;         //Canal 0
  ADCON2 = 0b10111110;         //Right,20TAD,Fosc/64

  PORTC = 0;               // Clear PORTC
  PORTD = 0;               // Clear PORTD
  PORTE = 0x00;               // Clear PORTE
  TRISC = 0xdb;               //
  TRISD = 0;               // PORTD all outputs
  TRISE = 0;               // PORTE all outputs

  kpp = EEDatRead(KP);         // Get PID gain values from
  kii = 0;                  // data EEPROM
  kdd = EEDatRead(KD);         //
  if(Kdd == 0xFFFF)   Kdd= -1000;   //Para el servo MG946R
  if(Kpp == 0xFFFF)   Kpp=6000;   //Para el servo MG946R

  //Timer3 para llevar a tope el zoom y que no patine
  //set_timer3(53035);   //53035 = 10ms. con 40MHz
  set_timer3(400);   //400 = 40ms. con 40MHz
  setup_timer_3(T3_INTERNAL | T3_DIV_BY_8);
  TIMER3OFF();

  fprintf(UARTR1,"Configurado Servo...\r\n");
  fprintf(UARTR1,ready);
  enable_interrupts(GLOBAL);

  #ifdef PIC18LF6722
    enable_interrupts(INT_RDA2);
  #else
    enable_interrupts(INT_RDA);
  #endif
}
/****************************************************************/
/* Union used to hold the 10-bit duty cycle */
union PWMDC{
    unsigned int16 lpwm;
    signed int8 bpwm[2];      //char
};
/****************************************************************/
/////////////////////////////////////////////
void SetDCPWM1(unsigned int16 dutycycle){
  union PWMDC DCycle;
  // Save the dutycycle value in the union
  DCycle.lpwm = dutycycle << 6;
  // Write the high byte into CCPR1L
  CCPR1L = DCycle.bpwm[1];
  // Write the low byte into CCP1CON5:4
  CCP1CON = (CCP1CON & 0xCF) | ((DCycle.bpwm[0] >> 2) & 0x30);
}

/****************************************************************/
////////////////////////////////////
void OpenPWM1( char period ){
      CCP1CON |= 0b00001100;    //ccpxm3:ccpxm0 11xx=pwm mode
   output_low(PIN_C2);
//---------------------------------------------------
    bit_clear(T2CON,TMR2ON);   // STOP TIMER2 registers to POR state
     PR2 = period;                // Set period
    bit_set(T2CON,TMR2ON);     // Turn on PWM1
}
/****************************************************************/
//---------------------------------------------------------------------
// ExtEEWrite()
// Writes an integer value to an EEPROM connected to the I2C bus at
// the specified location.
//---------------------------------------------------------------------
void EEDatWrite(unsigned char address, int16 data){
 unsigned int Tmp;
  Tmp = make8(data,0);
  write_eeprom(address,Tmp);   // Attempt to write low byte of data
  Tmp = make8(data,1);
  write_eeprom(address++,Tmp);   // Attempt to write high byte of data
}
//---------------------------------------------------------------------
// ExtEEWrite()
// Reads an integer value from an EEPROM connected to the I2C bus at
// the specified location.
//---------------------------------------------------------------------
signed int16 EEDatRead(unsigned char address){
 unsigned int8 TemH,TemL;
  TemL = read_eeprom(address),         // Attempt to read low byte of data
  TemH = read_eeprom(address++);      // Attempt to read high byte of data
 return make16(TemH,TemL);
}
//-------------------------------------------------------------------
// DoCommand()
// Processes incoming USART data.
//-------------------------------------------------------------------
void DoCommand(void){
 if(comcount == 0){      // If this is the first parameter of the input command...
   switch(inpbuf[0]){
      case 'X':   parameter = DIST;      // Segment distance change
                  break;

      case 'V':   parameter = VEL;      // Segment velocity change
                  break;

      case 'A':   parameter = ACCEL;      // Segment acceleration change
                  break;

   /***********ADDED NEW CODE CHANGED COMMAND T TIME to H for HOLD TIME **************/
      case 'H':   parameter = TIME;      // Segment HOLD delay time change
                  break;
//       case 'T':   parameter = TIME;      // Segment delay time change
//                   break;
   /***********END NEW CODE CHANGED **************/

   /***********ADDED NEW CODE MADE COMMAND T -> TRAVEL **************/
      case 'T':   parameter = TRAVEL;      // Segment encoder travel to point change
                  break;
   /***********END NEW CODE CHANGED **************/

      case 'P':   parameter = 'P';      // Change proportional gain
                  break;

      case 'I':   parameter = 'I';      // Change integral gain
                  break;

      case 'D':   parameter = 'D';      // Change differential gain
                  break;

      case 'L':   parameter = 'L';      // Loop a range of segments
                  break;

      case 'S':   stat.run = 0;         // Stop execution of segments
                  break;

      case 'G':   parameter = 'G';      // Execute a range of segments
                  break;

   /***********ADDED NEW CODE MADE COMMAND R -> RUN to **************/
      case 'R':   parameter = 'R';      // Run segments
                  break;
   /*********** END NEW CODE COMMAND R Run **************/

      case 'W':   if(ENBMotor){               // Enable or disable motor driver IC
                     DisableDriverPW();ENBMotor=False;   //RE2 = 0;
                     //output_low(PIN_E2);ENBMotor=False;   //RE2 = 0;
                     fprintf(UARTR1,"\r\nPWM Off\r\n");
               }
               else{
                     EnableDriverPW();ENBMotor=True;//RE2 = 1;
                     //output_high(PIN_E2);ENBMotor=True;//RE2 = 1;
                     fprintf(UARTR1,"\r\nPWM On\r\n");
               }
               break;
      default:   { if(inpbuf[0] != '\0'){
                 fprintf(UARTR1,"Error\r\n");
                   }
                 }
                 break;
      }
   }
 else if(comcount == 1){      // If this is the second parameter of the input command.
   if(parameter < 4) segnum = (char)(atol(inpbuf));
   else
   switch(parameter){
      case 'P':{  kpp = atol(inpbuf);         // proportional gain change
                  EEDatWrite(KP, kpp);      // Store value in EEPROM
             }
               break;

      case 'I':{   kii = atol(inpbuf);         // integral gain change
                  EEDatWrite(KI, kii);      // Store value in EEPROM
             }
               break;

      case 'D':{   kdd = atol(inpbuf);         // differential gain change
                  EEDatWrite(KD, kdd);      // Store value in EEPROM
             }
               break;

      case 'G':   firstseg = (char)(atoi(inpbuf));
               break;
                                    // Get the first segment in
                                       // the range to be executed.

   /***********ADDED NEW CODE COMMAND R Run **************/
      case 'R':
            firstseg = (char) (atoi(inpbuf));
         break;
   /*********** END NEW CODE COMMAND R Run **************/


      case 'L':   firstseg = (char)(atoi(inpbuf));
               break;

      default:    break;
        }
 }
 else if(comcount == 2){
      ////Al quitar if(!stat.run), cuando está en "loop" basta con enviar un nuevo "X"
      //// para que actue. Con el if, hay que llevar a "Stop", cambiar el "X" y enviar "L"
      //if(!stat.run){               // If no profile is executing
      if(parameter < 4){               // If this was a segment parameter change.
         /*   if(segnum < 12){
            // Write the segment paramater into data memory
            segment1[segnum][parameter] = atol(inpbuf);
            // Compute EEPROM address and write data to EEPROM
            eeadrr = (segnum << 3) + (parameter << 1);
            EEDatWrite(eeadrr, segment1[segnum][parameter]);
         }*/
         if(segnum < 24)
            // Write segment parameter data into data memory
            OrdenPosNEW  = atol(inpbuf);
            //SegmentOrd[parameter] = atol(inpbuf);


         /*Temporal1 = OrdenPosNEW;
            fprintf(UARTR1,"New: %ld\r\n",OrdenPosNEW);
         if(OrdenPosNEW != OrdenPosOLD){
            OrdenPosNEW  -= OrdenPosOLD;
            OrdenPosOLD = Temporal1;
            SegmentOrd[parameter] = OrdenPosNEW;   //atol(inpbuf);
          }else{
            SegmentOrd[parameter] = 0;   //atol(inpbuf);
         }
         fprintf(UARTR1,"Sum: %ld\r\n",SegmentOrd[parameter]);*/
      }
      else switch(parameter){
         case 'G':{   lastseg = (char)(atoi(inpbuf));   // Get value for
                     segnum = firstseg;            // last segment.
                  stat.loop = 0;
                  stat.run = 1;               // Start profile.
                }
               break;

   /***********ADDED NEW CODE COMMAND R Run **************/
      case 'R':
            lastseg = firstseg;                             // Get value for
          segnum = firstseg;                            // last segment.

            phase1dist.i[0] = SegmentOrd[DIST];
            vlim = SegmentOrd[VEL];
            accell.i[0] = SegmentOrd[ACCEL];
            dtime = SegmentOrd[TIME];
           travel_to = SegmentOrd[TRAVEL];

            SegmentOrd[DIST] = travel_to - (mposition >> 8);

         stat.loop = 0;
         stat.run = 1;                     // Start profile.
         break;
   /***********END NEW CODE*********/

         case 'L':{   lastseg = (char)(atoi(inpbuf));   // Get value for
                     segnum = firstseg;            // last segment.
                  stat.loop = 1;               // Enable looping
                  stat.run = 1;               // Start profile
                }
                break;

         default:    break;
       }//   else switch(parameter){
   //}//   if(!stat.run){
 }// else if(comcount == 2){
 else;
}
//-------------------------------------------------------------------
// ExtraeCommand()
// Processes incoming USART data.
//-------------------------------------------------------------------
void ExtraeCommand(char Caracter){
   //if(bit_test(PIR1,RC1IF)){            // Check for USART interrupt
      switch(Caracter){
         case ',':     DoCommand();            // process the string
                    memset(inpbuf,0,8);      // clear the input buffer
                     i = 0;               // clear the buffer index
                     comcount++;            // increment comma count
                     break;
         case 0x0d:  DoCommand();            // process the string
                     memset(inpbuf,0,8);      // clear the input buffer
                     i = 0;               // clear the buffer index
                     comcount = 0;            // clear comma count
                 segnum = 0;            // clear segment number
                 parameter = 0;         // clear paramater
                     break;
         default:    inpbuf[i] = Caracter,   //udata;      // get received char
                     i++;                  // increment buffer index
                     if(i > 7){         // If more than 8 chars received before getting
                        memset(inpbuf,0,8);   // buffer
                        i = 0;               // the buffer index
                     }
                     else;   // {TXREG1 = udata; }    //echo character
                     break;
      }//end switch(udata)
}

//////////////////////////////////////
/////////////////////////////////////
void CargaDistancia(signed int16 Distt){
  //segment2[segnum - 12][parameter] = atol(inpbuf);
  SegmentOrd[DIST] = Distt;   //Distancia
  SegmentOrd[VEL] = 4096;   //Velocidad
  SegmentOrd[ACCEL] = 32000;   //Aceleración
  SegmentOrd[TIME] = 0;      //Time
}
//////////////////////////////////////
/////////////////////////////////////
void AnchoBanda(void){
   PORTD = 0;               // Clear the LED bargraph display.
   PORTE   &= 0x04;         //                  "

   if(ADRES > 225){
      PORTE |= 0x03;         // Turn on 10 LEDS
      PORTD = 0xff;
   }
   if(ADRES > 200){
      PORTE |= 0x01;         // Turn on 9 LEDS
      PORTD = 0xff;
   }
   else if(ADRES > 175) PORTD = 0xff;   // Turn on 8 LEDS
   else if(ADRES > 150) PORTD = 0x7f;   // 7 LEDS
   else if(ADRES > 125) PORTD = 0x3f;   // 6 LEDS
   else if(ADRES > 100) PORTD = 0x1f;   // 5 LEDS
   else if(ADRES > 75) PORTD = 0x0f;   // 4 LEDS
   else if(ADRES > 50) PORTD = 0x07;   // 3 LEDS
   else if(ADRES > 25) PORTD = 0x03;   // 2 LEDS
   else if(ADRES > 0) PORTD = 0x01;   // 1 LED
   else;

}

//
//                   File: ZoomSYS.C
//
//---------------------------------------------------------------------
// servo_isr()
// Performs the servo calculations
//---------------------------------------------------------------------
///---------------------------------------------------------------------
// Interrupt Timer 2
// Esta interrupción sirve para que se ejecuten los controles
//    cada xx ms.
// El temporizador se ajusta con el Prescaler y
//      Postescaler del registro T2CON
// El PWM se ajusta solo con el Prescaler
//---------------------------------------------------------------------
#INT_TIMER2
void Timer2(){
  output_high(SPULSE);   // = 1;      // Toggle output pin for ISR code timing
    UpdTraj();                  // Get new commanded position
    UpdPos();                     // Get new measured position
    CalcError();                  // Calculate new position errorr
    CalcPID();
    bit_clear(PIR1,TMR2IF);         //PIR1bits.TMR2IF = 0;   // Clear Timer2 Interrupt Flag.
  output_low(SPULSE);// = 0;      // Toggle output pin for ISR code timing
}

/////////////////////////////////////////////////////////////
//                INT TIMER3
//   La INT3 se emplea para llevar a tope el zoom y que no patine
//   Con el servo MG946R en aceleración la distancia entre pulsos
//      es de 12 ms máx y en frenado 22ms.
/////////////////////////////////////////////////////////////
#INT_TIMER3
void Timer3() {

  set_timer3(400);   //400 = 40ms. con 40MHz

  if((get_timer0() == Timer0OLD) && (get_timer1() == Timer1OLD)){
   TIMER3OFF();
  }
  else{
   Timer0OLD=get_timer0();Timer1OLD = get_timer1();
  }
}
/////////////////////////////////////////////////////////////
//                INT RDA, RS232
//         Recibe una orden através del la UART
/////////////////////////////////////////////////////////////
#ifdef PIC18LF6722
   #INT_RDA2
#else
   #INT_RDA
#endif
void  UARTRx() {
unsigned char ByteRx,buffer;
unsigned int8 timeout;
  ByteRx=fgetc(UARTR1);
  #ifdef PIC18LF6722
     bit_clear(PIR1,RC1IF);               //Borra bandera de INT
  #else
    bit_clear(PIR1,RCIF);
  #endif
      TramaRecUART[buffer]=ByteRx;
      buffer++;               // Incrementa string pointer, el primero es ">"
      comcount = 0;
      do{
         timeout =0;            //Espera a recibir, y si no, solo espera 1ms después de recibir el último
         while (!kbhit(UARTR1) && (++timeout<100))delay_us(10);
         if(kbhit(UARTR1)) {
            ByteRx = fgetc(UARTR1);   }   // Get un caracter de la USART
          else{OrdenRec = False;break;}
           TramaRecUART[buffer] = ByteRx;
           buffer++;                             // Incrementa string pointer
           //if(ByteRx == ',') comcount++;         //N parametros
          if(buffer >80){buffer = 0; break;}
       }while(ByteRx > 9);//9                     //Incluye CR y LF
      OrdenRec = True;
      if((ByteRx == 13)) {   //|| (ByteRx == 10)){      //Incluye CR y LF
         TramaRecUART[buffer] = 0;
         OrdenRec = True;
      }
}


//
//                   File: ZoomAN696.C
//
/////////////////////////////////////////////////////////////////////////////
//                 CONTROL DE MOTORRES PARA PLATAFORMA                    ///
//                     GIROESTABILIZADA                          ///
//                      PIC "C" Compiler PCM                                ///
//      Esta versión es la que procede de la original del PIC18C452           ///
//      Se ha añadido la comprobación, después de leer la EEPROM,           ///
//      si Kp y Kd son 0xFFFF. Esto indica que la EEPROM estaba              ///
//      borrada. Un valor 0xFFFF hace que no funcione nada                 ///
//      Se inicializa Kp con 6000 y Kd con -1000 (0 a 6000 y -32000 a 32000)///
///            para el servo MG946R                              ///
///////////////////////////////////////////////////////////////////////////////

//#define PIC18LF6722
#define PLLMHz
#define Debuger1
#ifdef PIC18LF6722
   #include <18F6722.h>
   #include <p18f6722m.inc>
#else
   #include <18F8722.h>
   #include <p18f8722m.inc>
#endif
#device *=16
#include "STRING.H"
#include "STDLIB.H"


#include <ZoomAN696.h>
#include <ZoomSubPID.c>
#include <ZoomSUB.c>
#include <ZoomSYS.c>

#ZERO_RAM
//#priority ext, timer1,timer3
//---------------------------------------------------------------------
// main()
//---------------------------------------------------------------------
void main(){
unsigned int8 CaracterRec,NCaracterRec;
  fprintf(UARTR1,"Configurando PIC18xx...\r\n");
  Setup();
  fprintf(UARTR1,"PWM On\r\n");
  EnableDriverPW();ENBMotor=True;   //RE2 = 1;

  SegmentOrd[DIST] = 450;
  //CargaDistancia(450);
  SegmentOrd[VEL] = 20;   //10 4096Velocidad
  //SegmentOrd[ACCEL] = 32000;   //Aceleración
  SegmentOrd[ACCEL] = 50;         //6000 Acelera
  SegmentOrd[TIME] = 0;      //Time

  firstseg =23;lastseg=23;
  stat.loop = 0;
  stat.run = 1;




  delay_ms(100);      //Espera que arranque
  TIMER3ON();
  do{
     delay_us(100);
  }while(bit_test(T3CON,TMR3ON));
  //stat.run = 0;
  // set_timer0(450);
   SegmentOrd[DIST] = 0;
   mposition = position =fposition;
    stat.motion = flatcount = velact = dtime = 0; stat.motion = 0;

  fprintf(UARTR1,"mpos: %Ld fpos: %Ld posi: %Ld\r\n",mposition,fposition,position);

  fprintf(UARTR1,"T0: %Ld T1: %Ld\r\n",get_timer0(),get_timer1());
  delay_ms(100);      //Espera que arranque
  set_timer1(0);
  set_timer0(0);

  UpCount =  DnCount = 0;

  SegmentOrd[DIST] = -450;
  //CargaDistancia(-450);
  firstseg =23;lastseg=23;
  stat.loop = 0;
  stat.run = 1;
  delay_ms(100);      //Espera que arranque
  TIMER3ON();
  do{
    delay_us(100);
  }while(bit_test(T3CON,TMR3ON));
 PosicionReal = get_timer0() - get_timer1();
 // set_timer1(450);
   SegmentOrd[DIST] = 0;
  mposition = position =fposition;
  stat.motion = flatcount = velact = dtime = 0; stat.motion = 0;

  delay_ms(50);   //250
  set_timer1(0);  set_timer0(0); PosicionReal = 0;
  DnCount = UpCount =   flatcount = velact = dtime = 0; stat.motion = 0;
OrdenPosOLD = OrdenPosNEW = SegmentOrd[DIST] = 0;

////////////////////////////////////////////////////
///////////////////////////////////////////////////


  while(1){
   restart_wdt();
   bit_clear(PIR1,ADIF);      //Borra INT
   bit_set(ADCON0,GO);         // Start an A/D conversion
   while(!bit_test(PIR1,ADIF));   //while(ADGO);               // Wait for the conversion to complete

     ValorADC = (float)ADRESHL;
     ValorADC = (ValorADC*100)/1024;

    OrdenPosADC  = (unsigned int16)ValorADC;

    if(ValorADC >60) PORTD = 0b10000000;
   else if(ValorADC >55) PORTD = 0b01000000;
   else if(ValorADC >50) PORTD = 0b00100000;
   else if(ValorADC >47) PORTD = 0b00010000;
   else if(ValorADC >45) PORTD = 0b00001000;
   else if(ValorADC >40) PORTD = 0b00000100;
   else if(ValorADC >35) PORTD = 0b00000010;
   else if(ValorADC >30) PORTD = 0b00000001;
   else;


//   fprintf(UARTR1,"New: %ld, %ld\r\n",OrdenPosNEW,PosicionReal);





   if(OrdenRec){
      NCaracterRec = strlen(TramaRecUART);
      for(CaracterRec=0;CaracterRec<NCaracterRec;CaracterRec++){
      ExtraeCommand(TramaRecUART[CaracterRec]);
      }
      OrdenRec = False;
   }

 }//end while(1)
}

Smile Smile Smile Smile Smile Smile Smile Smile Smile Very Happy Smile
RUFINOGG



Joined: 15 Jan 2010
Posts: 8

View user's profile Send private message Send e-mail

PostPosted: Wed Dec 11, 2013 3:44 am     Reply with quote

Thanks for the information. I can not prove until the end of January, all I can do is study it, when you try it will tell you what happens.
Thanks
RUFINOGG



Joined: 15 Jan 2010
Posts: 8

View user's profile Send private message Send e-mail

PostPosted: Wed Dec 11, 2013 4:48 am     Reply with quote

Hi Jerry I,
I am studying the changes you've made and see that SetupMove(){ has added:

/ *********** ADDED NEW CODE ************** /
travel_to = SegmentOrd [TRAVEL]
/ *********** END NEW CODE ********* /
but is useless because "travel_to" is not used. Only use in:

case 'R':
...
travel_to = SegmentOrd [TRAVEL];
SegmentOrd [DIST] = travel_to - (mposition >> 8);
....

must be missing something
Jerry I



Joined: 14 Sep 2003
Posts: 96
Location: Toronto, Ontario, Canada

View user's profile Send private message

PostPosted: Thu Dec 12, 2013 8:05 am     Reply with quote

Hi

Its been 2 years I last looked at code.

But from what I remember I would use the T command to enter the travel_to value. Then I would use the R (run) command to execute. R command has the same syntax as the G command.

I would only use the R command for the new code added.

Let me know if it works.
Jerry I



Joined: 14 Sep 2003
Posts: 96
Location: Toronto, Ontario, Canada

View user's profile Send private message

PostPosted: Thu Dec 12, 2013 2:40 pm     Reply with quote

Hi

Found other code where segment data is defined, and also assign a value


Code:

  //******** NEW ADDED Code Changed **************/

// signed int16 SegmentOrd[4];      // array in bank3 for 12 motion segments
signed int16 SegmentOrd[5];      // array in bank3 for 12 motion segments

  //******** NEW ADDED **************/


void main(){
unsigned int8 CaracterRec,NCaracterRec;
  fprintf(UARTR1,"Configurando PIC18xx...\r\n");
  Setup();
  fprintf(UARTR1,"PWM On\r\n");
  EnableDriverPW();ENBMotor=True;   //RE2 = 1;

  SegmentOrd[DIST] = 450;
  //CargaDistancia(450);
  SegmentOrd[VEL] = 20;   //10 4096Velocidad
  //SegmentOrd[ACCEL] = 32000;   //Aceleración
  SegmentOrd[ACCEL] = 50;         //6000 Acelera
  SegmentOrd[TIME] = 0;      //Time

    //******** NEW ADDED **************/
  SegmentOrd[TRAVEL] = ??????;      //Encoder value to Travel to
  //******** NEW ADDED **************/




  void CargaDistancia(signed int16 Distt){
  //segment2[segnum - 12][parameter] = atol(inpbuf);
  SegmentOrd[DIST] = Distt;   //Distancia
  SegmentOrd[VEL] = 4096;   //Velocidad
  SegmentOrd[ACCEL] = 32000;   //Aceleración
  SegmentOrd[TIME] = 0;      //Time

  //******** NEW ADDED **************/
  SegmentOrd[TRAVEL] = ??????;      //Encoder value to Travel to
  //******** NEW ADDED **************/

}


Let me know what you find.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group