Sign in

username:

password:



Not a member?

Search rabbit-semi



Search tips

Subscribe to rabbit-semi



Ads

Discussion Groups

Discussion Groups | Rabbit-Semi | Best way to timer a pid

This is a group for folks designing and programming embedded systems using the Rabbit Semiconductor C-programmable microcontroller. Rabbit Semi is a spin-off from Z-World who makes a variety of embedded modules and tools. This group is not affiliated with either Rabbit or Z-World, but is a user forum for sharing ideas, asking questions, flaunting knowledge, and other typical user group stuff. The Rabbit is a powerful uC, supported by a full-featured C-compiler.

Best way to timer a pid - Marco Trapanese - Sep 3 6:11:14 2008

Hello,

I'm working on a project based on an RCM4100 running at 60 MHz. It has
three PIDs: each one has a setpoint, an analog input as feedback and
all of them output to an array. This one will update an external
8-channel DAC.

I have no problem to implement such a PID but I'm wondering what is
the best way to call the input, process and output functions in the
Rabbit world.

My goal is to update the three PID every 50 ms (or less, if possible).
In detail I have to do:

1) acquire all analog signals with the on-board ADC (8 ch)
2) process the PIDs calculations
3) update the SPI DAC

You know, a digital algorithm like a PID needs an accurate clock to
work well. So I bet I need a timer interrupt to do all the staff.
Better, in the ISR I'll acquire the signals and update the DAC while
the PID update is not time critical.

What timer should I use? Is there any example to see how to generate
an interrupt at this low frequency?

Thanks in advance
Marco / iw2nzm

------------------------------------



(You need to be a member of rabbit-semi -- send a blank email to rabbit-semi-subscribe@yahoogroups.com )


Re: Best way to timer a pid - jmsardon01 - Sep 4 10:20:02 2008

In my experience, I think that you don't need to be so acuarate in a
PID algoritm. Obtain 50 ms can be done with a costate inside a loop
with low time in complete a cycle (say 1 or 2 ms, in function of your
requested precision).
--- In r...@yahoogroups.com, "Marco Trapanese"
wrote:
>
> Hello,
>
> I'm working on a project based on an RCM4100 running at 60 MHz. It has
> three PIDs: each one has a setpoint, an analog input as feedback and
> all of them output to an array. This one will update an external
> 8-channel DAC.
>
> I have no problem to implement such a PID but I'm wondering what is
> the best way to call the input, process and output functions in the
> Rabbit world.
>
> My goal is to update the three PID every 50 ms (or less, if possible).
> In detail I have to do:
>
> 1) acquire all analog signals with the on-board ADC (8 ch)
> 2) process the PIDs calculations
> 3) update the SPI DAC
>
> You know, a digital algorithm like a PID needs an accurate clock to
> work well. So I bet I need a timer interrupt to do all the staff.
> Better, in the ISR I'll acquire the signals and update the DAC while
> the PID update is not time critical.
>
> What timer should I use? Is there any example to see how to generate
> an interrupt at this low frequency?
>
> Thanks in advance
> Marco / iw2nzm
>

------------------------------------



(You need to be a member of rabbit-semi -- send a blank email to rabbit-semi-subscribe@yahoogroups.com )

Re: Best way to timer a pid - Marco Trapanese - Sep 4 12:32:34 2008

--- In r...@yahoogroups.com, "jmsardon01" wrote:
>
> In my experience, I think that you don't need to be so acuarate in a
> PID algoritm. Obtain 50 ms can be done with a costate inside a loop
> with low time in complete a cycle (say 1 or 2 ms, in function of your
> requested precision).
I'm not so sure. A PID is an algorithm in the digital domain (aka
z-domain) so the accuracy of the clock source should be quite important.

Anyway, I want to try to use the timerC to generate a 50 ms interrupt.
Using the example provided into the sample folder all works fine. When
I copy & paste that code in my program it will reset the RCM4100
continuously.

In detail the instruction which will hang the CPU is:

WrPortI(TCCR, &TCCRShadow, 0x01);

in other words I can't enable the interrupt.
The only difference between the sample code and mine is I use a custom
BoardInit() function to setup I/O ports and serials.

Of course, I need to do that in order to configure my hardware and of
course again there is something that is wrong.

I copied the BoardInit() code after the signature.

Can you find out what could hang the CPU?

Thanks again!
Marco / iw2nzm

--

/*** BeginHeader */
#ifndef __SFC_CORE_BOARD_LIB
#define __SFC_CORE_BOARD_LIB
/*** EndHeader */

/* START LIBRARY DESCRIPTION
************************************************
SFC_CORE_BOARD.LIB
DESCRIPTION:
This library was generated by the Rabbit 4000 I/O LIB Utility.
If it is modified in any incorrect way it might not load properly.
Usage:
#use "SFC_CORE_BOARD.LIB"
main()
{
SFC_BoardInit();
...
}

SUPPORT LIBRARIES: none
END DESCRIPTION
*************************************************************/

/*** BeginHeader SFC_BoardInit */
void SFC_BoardInit();
void ClockCheck();
void SetupSerial();
#define DINBUFSIZE 511
#define DOUTBUFSIZE 511
#define SERD_TXPORT PCDR
#define DDRIVE_TXD 0
#define SERD_RXPORT PCDR
#define DDRIVE_RXD 1
#define EINBUFSIZE 63
#define EOUTBUFSIZE 63
#define SERE_TXPORT PEDR
#define EDRIVE_TXD 6
#define SERE_RXPORT PEDR
#define EDRIVE_RXD 7
#define FINBUFSIZE 31
#define FOUTBUFSIZE 31
#define SERF_TXPORT PEDR
#define FDRIVE_TXD 2
#define SERF_RXPORT PEDR
#define FDRIVE_RXD 3
/*** EndHeader */

/* START FUNCTION DESCRIPTION
***********************************************
SFC_BoardInit
END DESCRIPTION
*************************************************************/

void ClockCheck()
{
if (freq_divider != 96) // 29.49 MHz, doubled
{
exception(-ERR_LIBCLOCKSPEED);
}
}

void SetupSerial()
{
serDopen(115200L);
serEopen(460800L);
WrPortI(SECR,&SECRShadow, 0x21);
serFopen(19200L);
WrPortI(SFCR,&SFCRShadow, 0x21);
}

void SFC_BoardInit()
{
ClockCheck();
// The following differ from BIOS settings
SetupSerial();
WrPortI(I0CR,&I0CRShadow,0x03); // Port E Input and output Pins
WrPortI(ICS1R,&ICS1RShadow,0x33); // IC Channel 1
WrPortI(ICT1R,&ICT1RShadow,0x42); // Port C Input and output Pins
WrPortI(PBDDR,&PBDDRShadow,0xFF); // Port B Input and output Pins
WrPortI(PCAHR,&PCAHRShadow,0xC0); // Port C Input and output Pins
WrPortI(PCFR,&PCFRShadow,0x15); // Port C Input and output Pins
WrPortI(PEAHR,&PEAHRShadow,0x30); // Port E Input and output Pins
WrPortI(PEALR,&PEALRShadow,0x30); // Port E Input and output Pins
WrPortI(PEDDR,&PEDDRShadow,0x44); // Port E Input and output Pins
WrPortI(PEFR,&PEFRShadow,0x44); // Port E Input and output Pins
WrPortI(QDCR,&QDCRShadow,0x08); // Port E Input and output Pins
WrPortI(SBDHR,NULL, 0x81); // Serial Port B
WrPortI(SBDLR,NULL, 0xFF); // Serial Port B
WrPortI(SCDLR,NULL, 0x7F); // Serial Port C
WrPortI(TCCR,&TCCRShadow,0x08); // Timer C
WrPortI(TCCSR,&TCCSRShadow,0x01); // Timer C
WrPortI(TCDHR,NULL, 0x16); // Timer C
WrPortI(TCDLR,NULL, 0x7F); // Timer C
}

// The following are used by the configuration utility
// Restore(SBCR, 0x0D) // Serial Port B
// Restore(SCCR, 0x0D) // Serial Port C
// Restore(SDCR, 0x01) // Serial Port D
// Restore(SDDLR, 0x1F) // Serial Port D
// Restore(SECR, 0x21) // Serial Port E
// Restore(SEDLR, 0x07) // Serial Port E
// Restore(SFCR, 0x21) // Serial Port F
// Restore(SFDLR, 0xBF) // Serial Port F
// Restore(APIC, 0x01) // Serial Port C
// Restore(APID, 0x01) // Serial Port D
// Restore(APIE, 0x01) // Serial Port E
// Restore(APIF, 0x01) // Serial Port F
// Restore(DBL, 0x01) // Processor Options
// Restore(DINBF, 0x1FF) // Serial Port D
// Restore(DOUTBF, 0x1FF) // Serial Port D
// Restore(EINBF, 0x3F) // Serial Port E
// Restore(EOUTBF, 0x3F) // Serial Port E
// Restore(USEPC, 0x01) // Serial Port C
// Restore(USEPD, 0x01) // Serial Port D
// Restore(USEPE, 0x01) // Serial Port E
// Restore(USEPF, 0x01) // Serial Port F

/*** BeginHeader */
#endif
/*** EndHeader */
//checksum:E118

------------------------------------



(You need to be a member of rabbit-semi -- send a blank email to rabbit-semi-subscribe@yahoogroups.com )