6#include "..\include\myosyn.h"
7#define _USE_MATH_DEFINES
99 {1/0.020997, 0.138763},
100 {1/0.019916,-0.062009},
138 if (quickDAQgetStatus() <= STATUS_INIT) {
149 switch (quickDAQgetStatus())
153 setSampleClockTiming((samplingModes)HW_CLOCKED, (float64)
myosynSamplingRate(), DAQmxClockSource, (triggerModes)DAQmxTriggerEdge, DAQmxNumDataPointsPerSample, TRUE);
170 switch (quickDAQgetStatus())
222 this->channelID = muscleChannel;
226 if (quickDAQgetStatus() == (
int)STATUS_NASCENT) {
236 encoder_opt_config = NULL;
247 encoder_opt_config = NULL;
250 loadcell_gain = loadcell_config[channelID][0];
251 loadcell_offset = loadcell_config[channelID][1];
256 maxChannels_mtr = 12;
262 encoder_opt_config = NULL;
264 loadcell_config = NULL;
270 maxChannels_mtr = 12;
274 maxChannels_enc = 12;
278 loadcell_config = NULL;
284 fprintf(ERRSTREAM,
"ERROR: MyoSyn: Invalid DAQ arrangement selected. Program will terminate.");
296 if (channelID < maxChannels_mtr) {
300 pinMode(loadcell_config[channelID][0], ANALOG_IN, loadcell_config[channelID][1]);
304 pinMode(motor_value_config[channelID][0], ANALOG_OUT, motor_value_config[channelID][1]);
307 if (motor_enable_config[channelID][0] == 2) {
308 if (motor_enable_config[channelID][1] < 8) {
309 pinMode(motor_enable_config[channelID][0], DIGITAL_OUT, 0);
311 else if (motor_enable_config[channelID][1] > 15 && motor_enable_config[channelID][1] < 24) {
312 pinMode(motor_enable_config[channelID][0], ANALOG_OUT, motor_enable_config[channelID][1]);
320 pinMode(encoder_config[channelID][0], CTR_ANGLE_IN, encoder_config[channelID][1]);
324 pinMode(encoder_opt_config[channelID][0], CTR_ANGLE_IN, encoder_opt_config[channelID][1]);
329 fprintf(ERRSTREAM,
"ERROR: MyoSyn: Requested channel ID %d is greater than the number of available motor channels %d. Program will terminate.", channelID, maxChannels_mtr);
335 eprintf(
"myosyn: Muscle %d enabled.\n", channelID);
360 eprintf(
"myosyn: Muscle %d disabled.\n", channelID);
366 return this->channelID;
376 this->status = newStatus;
384 if (motor_enable_config[channelID][1] < 8) {
385 writeDigitalPin(motor_enable_config[channelID][0], 0, motor_enable_config[channelID][1], TRUE);
387 else if (motor_enable_config[channelID][1] > 15 && motor_enable_config[channelID][1] < 24) {
388 setAnalogOutPin(motor_enable_config[channelID][0], motor_enable_config[channelID][1], (float64)
DIGITAL_HIGH_VOLTS);
389 writeAnalog_intBuf(motor_enable_config[channelID][0]);
391 setAnalogOutPin(motor_value_config[channelID][0], motor_value_config[channelID][1], (float64)
WIND_UP_VOLTS);
392 writeAnalog_intBuf(motor_value_config[channelID][0]);
407 if (motor_enable_config[channelID][1] < 8) {
408 writeDigitalPin(motor_enable_config[channelID][0], 0, motor_enable_config[channelID][1], FALSE);
410 else if (motor_enable_config[channelID][1] > 15 && motor_enable_config[channelID][1] < 24) {
411 setAnalogOutPin(motor_enable_config[channelID][0], motor_enable_config[channelID][1], (float64)
DIGITAL_LOW_VOLTS);
413 setAnalogOutPin(motor_value_config [channelID][0], motor_value_config [channelID][1], (float64)
WIND_DOWN_VOLTS);
414 writeAnalog_intBuf(motor_enable_config[channelID][0]);
429 this->muscleToneTension = myMuscleTone_value;
434 return this->muscleToneTension;
439 this->maxMuscleTension = max_tension;
444 return this->maxMuscleTension;
449 this->refMuscleTension = refTension;
452 if (this->refMuscleTension < this->muscleToneTension) {
453 this->refMuscleTension = this->muscleToneTension;
456 else if (this->refMuscleTension > this->maxMuscleTension) {
457 this->refMuscleTension = this->maxMuscleTension;
464 return this->refMuscleTension;
471 this->loadcell_gain = (isnan(loadCellGain)) ?
loadcell_calib[channelID][0] : loadCellGain;
481 readAnalog_intBuf(loadcell_config[channelID][0]);
482 loadcell_offset += (double) getAnalogInPin(loadcell_config[channelID][0], loadcell_config[channelID][1]);
503 return ((LCvoltage - loadcell_offset) * loadcell_gain);
513 readCounterAngle_intBuf(encoder_opt_config[channelID][0], encoder_opt_config[channelID][1]);
528 return loadcellV2F( (
double)getAnalogInPin(loadcell_config[channelID][0], loadcell_config[channelID][1]) );
531 return encoderAngle2Excursion((
double)getCounterAngle(encoder_config[channelID][0], encoder_config[channelID][1]));
549 if (isnan(spoolDiameter))
551 this->encoder_angle_to_excursion_ratio = (M_PI/360.00) * spoolDiameter;
553 readCounterAngle_intBuf(encoder_config[channelID][0], encoder_config[channelID][1]);
554 encoder_offset_angle = (double)getCounterAngle(encoder_config[channelID][0], encoder_config[channelID][1]);
565 return ((encoderAngle - this->encoder_offset_angle) * 4.096 * this->encoder_angle_to_excursion_ratio);
570 if (quickDAQgetStatus() == STATUS_RUNNING) {
571 readCounterAngle_intBuf(encoder_config[channelID][0], encoder_config[channelID][1]);
585 return encoderAngle2Excursion((
double)getCounterAngle(encoder_config[channelID][0], encoder_config[channelID][1]));
607 return this->motorCommand;
618 this->motorCommand = newCommand;
619 setAnalogOutPin(motor_value_config[channelID][0], motor_value_config[channelID][1], (float64)this->motorCommand);
630 writeAnalog_intBuf(motor_value_config[channelID][0]);
void windUp()
Function starts/energizes the motor of the muscle channel to wind up the tendons to prevent slack.
void stopMuscleControl()
Stops the force controller and update the status of the muscle channel. This function only needs to b...
double getMaxMuscleTension()
Returns the upper limit of possible muscle tensions by the motor of the muscle channel.
double getMuscleToneTension()
Returns the current muscle tone of the muscle channel.
void setReferenceTension(double myTension)
The current reference/target muscle tension which the internal closed-loop controller will attempt to...
double loadcellV2F(double LCvoltage)
Returns the force on the loadcell when supplied with the voltage based on the gain and bias set by ca...
myosyn()
Default constructor of the myosyn class. Auto-selects muscle channel when setting up a muscle channel...
void readMuscleTension()
Uses the DAQ subsystem to read the muscle tension detected by the loadcell and puts it in the interna...
void calibrateTension(double loadCellGain=NAN)
Sets the gain to calibrate the transformation of the loadcell voltage to force in newtons....
void setMuscleToneTension(double myMuscleTone_value)
Sets the minimum tension held by the motor of a muscle channel. Corresponds to muscle tone and is the...
void startMuscleControl()
Starts the force controller and update the status of the muscle channel. This function only needs to ...
double encoderAngle2Excursion(double encoderAngle)
Returns the tendon excursion given an encoder angle.
void setMuscleStatus(muscleStatus newStatus)
Function sets the status of the muscle channel object.
void executeControl()
Executes the control law set by the controlRoutine function pointer.
muscleStatus getMuscleStatus()
Returns the status of the muscle channel. The possible statuses are listed in the enum muscleStatus.
double getReferenceTension()
Returns the current reference/target muscle tension that the motor controller is trying to achieve/ma...
void(* stopDAQ)()
Function pointer to the global myosynStop function to stop data acquisition. Only need to call this f...
double getTendonExcursion()
Returns the current tendon excursion value (in mm) in the internal memory.
double getMuscleTension()
Returns the current muscle tension value (in newtons) in the internal memory.
void(* startDAQ)()
Function pointer to the global myosynStart function to start data acquisition. Only need to call this...
void windDown()
Function stops/deenergizes the motor of the muscle channel to wind down the tendons before system shu...
void readTendonExcursion()
Uses the DAQ subsystem to read the tendon excursion detected by the shaft encoder and puts it in the ...
void setMaxMuscleTension(double max_tension)
Sets the upper limit to possible muscle tension of the motor of the muscle channel as a protection.
unsigned getChannelID()
Returns the channel ID number of the muscle channel.
void setMotorCommand(double newCommand)
Sets the current motor command to be sent to the DC motor.
void calibrateExcursion(double spoolDiameter=NAN)
Calibrates the rotary incremental shaft encoder to zero degrees and set the conversion from angle to ...
void(* controlRoutine)(unsigned numOutputs, double *outputs, unsigned numInputs, double *inputs)
[FOR FUTURE USE ONLY] Function pointer to any control law you might want the muscle channel to use.
double getMotorCommand()
Returns the current motor command that is being commanded to the motor.
unsigned myosynNumMuscles()
Returns the number of muscles configured by the library.
unsigned muscle_ld_cell[8][2]
double myosynSamplingRate(double newSamplingRate)
Sets the sampling rate of the data acquisition and controller of all the muscle channels....
unsigned muscle_mtr_en[16][2]
unsigned muscle_enc_kleo[8][2]
DAQarrangement myosynGetConfiguration()
int myosynGetLeaderChannel()
Returns the leader muscle channel which governs/triggers data acquisition on all other muscles.
void myosynStart()
This routine starts the data acquisition on all muscle channels that haven't already been started so ...
double loadcell_calib[8][2]
unsigned muscle_enc_ring[8][2]
void myosynWriteOutputs()
Global function to write all DAQ outputs in a synchronized manner. The results are put into the class...
void myosynWaitForClock()
This blocking function waits for the clock period to finish between two function calls....
unsigned numConfiguredMuscles
void myosynReadInputs()
Global function to read all DAQ inputs in a synchronized manner. The results are put into the class o...
void myosynStop()
This function sops the data acquisition of all muscle channels that were started (ie....
double myosyn_samplingRate_global
unsigned muscle_enc_spl[12][2]
DAQarrangement myosynConfiguration
void myosynSetConfiguration(DAQarrangement DAQconfiguration)
Set the muscle configuration/arrangement type of the library. List of possibilities in the DAQarrange...
unsigned muscle_mtr_val[16][2]
unsigned muscle_enc_mtr[12][2]
void myosynSetLeaderChannel(int newLeader)
Sets the leader/master muscle channel which governs/triggers data acquisition on all other muscles.
unsigned channel_limits[3][2]
unsigned myosynNumMuscles()
Returns the number of muscles configured by the library.
#define DIGITAL_LOW_VOLTS
unsigned muscle_ld_cell[8][2]
unsigned muscle_mtr_en[16][2]
#define eprintf(_STR,...)
unsigned muscle_enc_kleo[8][2]
enum _muscleStatus muscleStatus
This ENUM lists the possible statuses of each muscle channel.
DAQarrangement myosynGetConfiguration()
int myosynGetLeaderChannel()
Returns the leader muscle channel which governs/triggers data acquisition on all other muscles.
void myosynStart()
This routine starts the data acquisition on all muscle channels that haven't already been started so ...
double loadcell_calib[8][2]
unsigned muscle_enc_ring[8][2]
unsigned numConfiguredMuscles
void myosynStop()
This function sops the data acquisition of all muscle channels that were started (ie....
#define MAX_MUSCLE_TENSION
#define MOTOR_SHAFT_DIAMTR
enum _DAQarrangement DAQarrangement
Enumerates the different types of configurations supported by myosyn.
unsigned muscle_enc_spl[12][2]
DAQarrangement myosynConfiguration
#define LOADCELL_TARE_NSAMP
#define DEFAULT_MUSCLE_TONE
unsigned muscle_mtr_val[16][2]
unsigned muscle_enc_mtr[12][2]
void myosynSetLeaderChannel(int newLeader)
Sets the leader/master muscle channel which governs/triggers data acquisition on all other muscles.
#define DIGITAL_HIGH_VOLTS