home *** CD-ROM | disk | FTP | other *** search
- /***********************************************************************
-
- FILE
- rtsim3.c - simulation module for cntrl3.c
-
- ENTRY ROUTINES
- tstep - advance one time step
- SetTimer - set count-down timer
- TimeUp - has count down completed?
-
- ad_init - simulates A/D initialization
- ad_start - simulates starting an A/D read
- ad_read - simulates reading A/D value
- ad_wread - simulates read from A/D
-
- da_init - simulates D/A initialization
- da_limits - returns simulation D/A output limits
- da_write - simulates write to D/A
-
- sim_reset - reset simulation parameters
-
- PRIVATE ROUTINE
- simul - motor plant simulation
-
- INITIALIZATION ROUTINE
- sim_init - initialize this module
-
- REMARKS
- Implements multiple motor simulation for main3.c and cntrl3.c.
-
- We adopt the convention that the ADC and DAC channel number refers
- to the motor number, i.e., its index in the array of motor simulation
- descriptors. For example, (pmsim0 + 0) points to the simulated
- motor "connected" to ADC and DAC channel 0; (pmsim0 + 2) points to
- the motor "connected" to ADC and DAC channel 2. Of course, the
- ADC and DAC channels must be the same.
-
- LAST UPDATE
- 22 March 1985
- recast in module format.
- 20 March 1988
- use ANSI features
- 10 April 1988
- copy timer simulation from rtsim2.c
-
- Copyright (C) 1984-1988 D.M. Auslander and C.H. Tham
-
- ***********************************************************************/
-
- /***********************************************************************
- I M P O R T S
- ***********************************************************************/
-
- #include <stdio.h>
- #include <stdlib.h>
-
- #include "envir.h" /* environment specifications */
- #include "dash8.h" /* declarations for dash8.c */
- #include "dac2.h" /* declarations for dac2.c */
- #include "time0.h" /* declarations for time0.c */
-
- /***********************************************************************
- F O R W A R D D E C L A R A T I O N S
- ***********************************************************************/
-
- #ifdef ANSI
-
- extern void tstep(void); /* these are referened outside of */
- extern void sim_init(int); /* this simulation module. */
- extern void sim_reset(char *);
-
- void simul(void); /* these are not referenced outside */
- void runtimer(void); /* of this simulation module. */
-
- #else
-
- extern void tstep();
- extern void sim_init();
- extern void sim_reset();
-
- void simul();
- void runtimer();
-
- #endif
-
- /**********************************************************************
- P R I V A T E D A T A
- **********************************************************************/
-
- #define VEL_SCALE 512.0 /* scale speed to A/D units */
-
- #define ADMAX 2047 /* max A/D input value */
- #define ADMIN -2048 /* min A/D input value */
-
- #define DASCALE 2047.0 /* scale D/A value to torque */
- #define DAMIN -2048 /* min. output value accepted */
- #define DAMAX 2047 /* max. output value accepted */
-
- static double t; /* time */
- static double dt; /* simulation step size in seconds */
-
- static long freq = 1000L; /* timer frequency (ticks/sec) */
- static long ticks; /* how many ticks to timeout */
- static int tflag; /* set to 1 if timer runs out */
-
- static int initflag = 0; /* indicates if module initialized */
-
- typedef struct motsim { /* motor simulation control structure */
- double inertia; /* motor inertia */
- double speed; /* motor speed */
- double torque; /* applied torque */
- } MOTSIM;
-
- static MOTSIM *pmsim0; /* pointer to first motor simulation block */
-
- static int nmotor; /* number of motors */
-
- /***********************************************************************
- T I M E S I M U L A T I O N
- ***********************************************************************/
-
- #ifndef RTIME
-
- /*---------------------------------------------------------------------
- PROCEDURE
- TSTEP - advance time forward one step
-
- SYNOPSIS
- void tstep(void)
-
- LAST UPDATE
- 10 March 1988
- check if simulation is initialized
- ---------------------------------------------------------------------*/
-
- void tstep()
- {
-
- if (initflag)
- {
- simul(); /* compute one time step in the differential */
- /* equation for the motor system. */
-
- t += dt; /* increment time by dt */
-
- runtimer(); /* simulate timer run */
- }
- else
- {
- printf("simulation module not initialized\n");
-
- tflag = 1;
- }
-
- }
-
-
-
- /*----------------------------------------------------------------------
- PROCEDURE
- SETTIMER - set countdown timer
-
- SYNOPSIS
- void SetTimer(ms)
- long ms;
-
- PARAMETER
- period - count down period in milliseconds
-
- LAST UPDATE
- 15 January 1988
- ----------------------------------------------------------------------*/
-
- void SetTimer(ms)
- long ms;
- {
-
- tflag = 0; /* timeout flag to false */
-
- ticks = ((ms * freq) + 500L) / 1000L; /* 500 is for rounding */
-
- if (ticks <= 0L)
- printf("simulation time step too coarse\n");
-
- }
-
-
-
- /*---------------------------------------------------------------------
- FUNCTION
- TIMEUP - has timer timed out?
-
- SYNOPSIS
- int TimeUp()
-
- RETURNS
- 1 if timer runs out, 0 otherwise
-
- LAST UPDATE
- 1 March 1985
- ----------------------------------------------------------------------*/
-
- int TimeUp()
- {
-
- return(tflag);
- }
-
-
-
- /*----------------------------------------------------------------------
- PROCEDURE
- RUNTIMER - simulates timer run
-
- SYNOPSIS
- static void runtimer()
-
- LAST UPDATE
- 20 March 1988
- one tick per simulation time step
- ----------------------------------------------------------------------*/
-
- static void runtimer()
- {
-
- if (!tflag) /* if timeout, just return, otherwise... */
- {
- --ticks;
-
- if (ticks <= 0L) /* time has run out */
- tflag = 1;
- }
-
- }
-
- #endif /* ifndef RTIME */
-
- /***********************************************************************
- A / D S I M U L A T I O N
-
- These routines dummies the routines in dash8.c which drives the
- Metrabyte DASH8 A/D board.
-
- ***********************************************************************/
-
- void ad_init()
- {
- int m; /* motor number (also serves as loop index) */
-
-
- for (m = 0; m < nmotor; m++)
- (pmsim0 + m)->speed = 0.0; /* motor is at rest */
-
- }
-
-
- void ad_start(channel)
- int channel;
- {
- /* nothing */
- }
-
-
- int ad_read(channel)
- int channel;
- {
- int rval; /* return value */
-
-
- if ((channel >= 0) && (channel < nmotor))
- {
- rval = (int)((pmsim0 + channel)->speed * VEL_SCALE);
- }
- else
- {
- rval = 0;
- }
-
- if (rval > ADMAX) /* apply converter limits */
- rval = ADMAX;
- else if (rval < ADMIN)
- rval = ADMIN;
-
- return(rval);
- }
-
-
-
- int ad_wread(channel)
- int channel;
- {
-
- return(ad_read(channel));
- }
-
-
- /***********************************************************************
- D / A S I M U L A T I O N
-
- These routines dummies the routines in dac2.c which drives the
- Metrabyte DAC02 D/A board. See rtsim2.c also.
-
- ***********************************************************************/
-
- void da_init()
- {
- int m;
-
-
- for (m = 0; m < nmotor; m++)
- (pmsim0 + m)->torque = 0.0;
-
- }
-
-
- void da_limits(lo, hi)
- int *lo, *hi;
- {
-
- *lo = DAMIN;
- *hi = DAMAX;
-
- }
-
-
- int da_write(channel, value)
- int channel, value;
- {
-
- if ((channel >= 0) && (channel < nmotor))
- {
- if (value < 0) /* OR with a binary number having 0's for */
- value |= ~0xfff; /* the lower 12 bits and 1's elsewhere */
- else
- value &= 0xfff; /* for positive values, just save the */
- /* lower 12 bits. */
-
- (pmsim0 + channel)->torque = value / DASCALE;
- }
-
- return(0);
- }
-
-
- /**********************************************************************
- P L A N T S I M U L A T I O N
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- PROCEDURE
- SIM_RESET - reset simulation module
-
- SYNOPSIS
- void sim_reset(cline)
- char *cline;
-
- PARAMETER
- cline - user's input command line
-
- REMARKS
-
- LAST UPDATE
- 20 March 1988
- adapt timer resolution to simulation time step
- ----------------------------------------------------------------------*/
-
- void sim_reset(cline)
- char *cline;
- {
-
- sscanf(cline, "%lf", &dt); /* get the step size */
-
- #ifdef DEBUG
- printf("<init> dt = %f\n", dt);
- #endif
-
- t = 0.0; /* reset time */
- freq = (long)(1.0 / dt + 0.5); /* adapt timer frequency */
-
- ad_init(); /* reset ADC (speed) */
- da_init(); /* reset DAC (torque) */
-
- }
-
-
-
- /*----------------------------------------------------------------------
- PROCEDURE
- DO_SIMUL - special hook into simul() for demo purposes
-
- SYNOPSIS
- void do_simul(void);
-
- LAST UPDATE
- 10 April 1988
- creation
- ----------------------------------------------------------------------*/
-
- void do_simul()
- {
- simul();
- }
-
-
- /*----------------------------------------------------------------------
- PROCEDURE
- simul - simulates motor plant
-
- SYNOPSIS
- static void simul(void)
-
- REMARKS
- Solve the motor system differential equation. This version uses
- the Euler method for integration; it isn't very efficient, but its
- easy to program!
-
- Simulates a motor with pure inertial load only.
-
- LAST UPDATE
- 1 April 1988
- add friction
- ----------------------------------------------------------------------*/
-
- static void simul()
- {
- MOTSIM *pms; /* pointer to motor simulation descriptor */
- int m; /* loop index (motor number) */
- double friction; /* friction proportional to speed */
-
-
- for (m = 0, pms = pmsim0; m < nmotor; m++, pms++)
- {
- friction = pms->speed * 0.1; /* 0.1 factor is arbitrary */
-
- pms->speed += (pms->torque - friction) * dt / pms->inertia;
- }
-
- }
-
-
- /***********************************************************************
- I N I T I A L I Z A T I O N R O U T I N E
- ***********************************************************************/
-
- /*----------------------------------------------------------------------
- PROCEDURE
- SIM_INIT - initialize simulation module
-
- SYNOPSIS
- void sim_init(nm)
- int nm;
-
- PARAMETER
- nm - number of motors
-
- REMARKS
- In a "real" real-time program, this function would be used to set
- up interrupts, set clock modes, etc. In this simulation version,
- it sets time to zero and sets the motor simulation initial conditions.
-
- LAST UPDATE
- 20 March 1988
- rearrange sequence
- ----------------------------------------------------------------------*/
-
- void sim_init(nm)
- int nm;
- {
- int m; /* motor number (loop index also) */
- MOTSIM *pms; /* pointer to motor simulation block */
-
-
- /* allocate memory for the motor simulation data structures */
-
- if ((pmsim0 = (MOTSIM *)calloc(nm, sizeof(MOTSIM))) != (MOTSIM *)NULL)
- {
- pms = pmsim0; /* starting with first structure... */
-
- for (m = 0; m < nm; m++)
- {
- pms->inertia = 1.0; /* initialize with defaults */
- pms->speed = 0.0;
- pms->torque = 0.0;
-
- pms++; /* next motor */
- }
-
- nmotor = nm; /* record number of motors */
-
- initflag = 1;
- }
- else
- {
- printf("INSUFFICIENT MEMORY: ");
- printf("cannot allocate %d simulation structures\n", nm);
-
- exit(1);
- }
-
- }
-
-