DAPL - Tension Control

Shown below is sample DAPL code for a hypothetical tension control experiment during which the muscle is

1) - held at its original length for 20 ms
2) - released to a target force -0.1 V below the prevailing level for 20 ms
3) - shortened rapidly to a fixed length for another 20 ms
4) - returned to its original length for the remaining 40 ms of the record.

Please note that the formatting of the DAPL code has been slightly altered for HTML display purposes. Several of the 'fill' commands and a few of the processing calculations wrap over several lines and would initiate a DAP error if passed to the interpreter in their present form.


RESET                                                           // Resets DAP

OPTION UNDERFLOWQ=OFF                                           // Disable underflow error messages
OPTION ERRORQ=OFF                                               // Disable all other warnings and error messages
                                                                // to prevent problems reading data back to the PC

OPTION SCHEDULING=FIXED                                         // Scheduling, buffering and quantum options
OPTION BUFFERING=OFF                                            // set for minimum latency
OPTION QUANTUM=100

;************************************************************

// Header

pipes pfl MAXSIZE=65500                                          // Define all the pipes used in the processing
pipes ptarget_force MAXSIZE=65500                                // functions and set their maximum size

pipes pservo MAXSIZE=65500

pipes poffset_marker MAXSIZE=65500
pipes poffset MAXSIZE=65500
pipes plastoffset MAXSIZE=65500

pipes pout MAXSIZE=65500
pipes plastout MAXSIZE=65500

pipes pfeedback MAXSIZE=65500

pipes ptrigger MAXSIZE=65500

pipes pdifference MAXSIZE=65500
pipes pamplified_diff MAXSIZE=65500
pipes pintegral MAXSIZE=65500

;************************************************************
                                                                 // The section of the code fills the processing pipes
                                                                 // with all of the required data

fill ptrigger 32439                                              // The first value (TTL high) for the DAC0 channel
                                                                 // This channel is intended as a trigger pulse

fill plastout 0                                                  // Initial values for plastout and plastoffset
fill plastoffset 0                                               // (required to initiate the control loop)

fill pdifference 0                                               // Initial values for pdifference (proportional error)
fill pintegral 0 0 0 0 0 0 0 0 0                                 // and pintegral (integral error)
                                                                 // required to initiate the control loop

fill pservo 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0              // pservo values (1 per data point)
fill pservo 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1              // 0 implies tension control is off
fill pservo 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0              // 1 implies tension control is on
fill pservo 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

fill poffset_marker 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1      // poffset_marker values (1 per data point)
fill poffset_marker 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0      // 1 implies update poffset with current force value
fill poffset_marker 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1      // 0 implies leave poffset unaltered
fill poffset_marker 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 

fill pfl 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0                 // pfl values (1 per data point)
fill pfl 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0                 // These are the desired DAC1 output values (the
fill pfl 64 64 64 64 64 64 64 64 64 64 64 64 64 64 ...           // motor command values) if tension control is off
         64 64 64 64 64 64 
fill pfl 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

fill ptarget_force 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0       // ptarget_force values (1 per data point)
fill ptarget_force -65 -65 -65 -65 -65 -65 -65 -65 -65 -65 ...   // These are the desired target_force points when the
                   -65 -65 -65 -65 -65 -65 -65 -65 -65 -65       // tension control is in operation
fill ptarget_force 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 
fill ptarget_force 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 

;************************************************************


pdef create_pipes                                                // Create_pipes procedure

  ptrigger=0                                                     // Set every ptrigger value (other than the first one)
                                                                 // to zero (i.e. trigger fires once, then stays low)

                                                                 // Simple Channel waveforms could be created on the fly
                                                                 // during this procedure if required
end

;************************************************************

pdef control                                                     // Main control procedure
                                                                 // (calculates output values and sends acquired data
                                                                 // back to the host PC)

  poffset=((1-poffset_marker)*plastoffset)+(poffset_marker*ip0)  // Update poffset with current force as required
  plastoffset=poffset                                            // Update plastoffset which is used above

  pdifference=pservo*(ip0-ptarget_force-poffset)                 // Calculate pdifference
                                                                 // (the proportional error if servo is on, 0 otherwise)

  pamplified_diff=5*pdifference                                  // Amplify difference to improve S/N for integral term
  raverage(pamplified_diff,10,pintegral)                         // Calculate the running average of the proportional
                                                                 // error and store as the integral error term

  pfeedback=plastout+ ...                                        // Calculate pfeedback, the desired motor command value
              (1*(2000*(ip0-ptarget_force-poffset)/10000))+ ...  // if tension control is operating. The 2000 and 200
              (1*(200*pintegral)/10000)                          // terms reflect the amount of (user-set) proportional
                                                                 // and integral gain respectively.  The 1 values
                                                                 // reflect the FL_POLARITY calibration factor

  pout=((1-pservo)*pfl)+(pservo*pfeedback)                       // Set pout to either pfeedback or pfl as required

  copy(pout,plastout,op1)                                        // Send pout to op1 (DAC1 channel) and plastout
                                                                 // (for the next cycle)

  copy(ptrigger,op0)                                             // Send ptrigger to op0 (DAC0 channel)

  merge(ip0,ip1,ip2,ip3,$binout)                                 // Send data back to the host PC through the binary
                                                                 // communication pipe
end

;************************************************************

odef outputproc 2                                                // Output procedure (2 channels of output)

  outputwait 2                                                   // Don't change the output values until there are 2
                                                                 // values waiting to be set.  This prevents underflow
                                                                 // at the beginning of the trial

  update burst                                                   // Prevents an underflow error message.  Output values
                                                                 // update only when 2 or more values are waiting

  set op0 a0                                                     // Send op0 to DAC0
  set op1 a1                                                     // Send op1 to DAC1

  time 500                                                       // Update data values for each channel every 500 µs
                                                                 // i.e. total update rate = 1 kHz
end

;************************************************************

idef inputproc 4                                                 // Input procedure (4 channels of input data)

  set ip0 s0                                                     // Set ip pipes to the appropriate ADC channels
  set ip1 s1
  set ip2 s2
  set ip3 s3

  count 320                                                      // Record a total of 320 points
                                                                 // i.e. 80 points/channel

  time 250                                                       // Read values for every channel every 250 µs
                                                                 // i.e. total update rate = 1 kHz
                                                                 // (This has to match the output rate or the input and
                                                                 // output procedures get out of synch.)
end

;************************************************************

start create_pipes,control,inputproc,outputproc


Last updated on 3rd June, 2003 by Ken.