![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Code for the COVR project DROPSAW project test rig (previously used for the Heros testing).
Dependencies: SPTE_10Bar_5V mbed AS5048 SDFileSystem MODSERIAL LCM101_DROPSAW LinearActuator
Revision 15:a84d54e25775, committed 2020-10-26
- Comitter:
- cnckiwi31
- Date:
- Mon Oct 26 11:55:27 2020 +0000
- Parent:
- 14:dd4193213be9
- Commit message:
- Code ready for inclusion in documentation (compiles, but no last check on runBenchmarkExperiment1() code done)
Changed in this revision
diff -r dd4193213be9 -r a84d54e25775 AS5048.lib --- a/AS5048.lib Mon Oct 26 08:33:02 2020 +0000 +++ b/AS5048.lib Mon Oct 26 11:55:27 2020 +0000 @@ -1,1 +1,1 @@ -https://developer.mbed.org/users/megrootens/code/AS5048/#1b84babf3042 +https://os.mbed.com/users/cnckiwi31/code/AS5048/#1b84babf3042
diff -r dd4193213be9 -r a84d54e25775 LCM101.lib --- a/LCM101.lib Mon Oct 26 08:33:02 2020 +0000 +++ b/LCM101.lib Mon Oct 26 11:55:27 2020 +0000 @@ -1,1 +1,1 @@ -https://os.mbed.com/users/cnckiwi31/code/LCM101/#f7af875abe50 +https://os.mbed.com/users/cnckiwi31/code/LCM101_DROPSAW/#f7af875abe50
diff -r dd4193213be9 -r a84d54e25775 bench.cpp --- a/bench.cpp Mon Oct 26 08:33:02 2020 +0000 +++ b/bench.cpp Mon Oct 26 11:55:27 2020 +0000 @@ -1,6 +1,21 @@ +/* Copyright 2020 Allan Joshua Veale + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + #include "bench.h" -/** +/** constructor * Create an object representing the test rig * @param mosi: mosi pin for sensor chain (SPI angle sensors) * @param miso: miso pin for sensor chain (SPI angle sensors) @@ -38,16 +53,16 @@ //init serial things pc.baud(timing::kSerialBaudrate);//set the serial rate - sd_card_present = false; - fname_prepend = 0; - is_logging = false; - is_printing = false; - was_printing = false; + sd_card_present = false;//have not checked for an sd card + fname_prepend = 0;//have not checked what is on the sd card + is_logging = false;//not datalogging + is_printing = false;//not printing anything + was_printing = false;//was not printing - usedExtraCols = 0; + usedExtraCols = 0;//default firstReadMS = 0; //first timer value read - startedLogging = false; //in the middle of a logging cycle + startedLogging = false; //not in the middle of a logging cycle keyIntOffset = timing::minKeyInt;//any right keypress is ok at the start k = '\0'; //keyboard value starts off as a null value @@ -56,6 +71,7 @@ loggingUS = timing::kTimeLogDataUs; loggingHz = (int)(1000000/timing::kTimeLogDataUs); + //set all angle sensor calibration data for (int i=0; i<sensors::kNumJoints; ++i) { as5048_.setOffsetDegrees(i,sensors::kOffsetsDegrees[i]); as5048_.setDirection(i,sensors::kDirections[i]); @@ -69,7 +85,7 @@ */ void Bench::initialise() { - //setup the timing + //setup the timing for the control loop (which only reads the angle sensors) tick_update.attach_us(this,&Bench::update,timing::kTimeControlUs); // set rate at which data is printed @@ -80,7 +96,7 @@ //display welcome message pc.printf("\r\n**Hello!**\r\n"); - pc.printf("Version: 3/12/2019 - 00:00\r\n\n"); + pc.printf("Version: V4\r\n\n"); Bench::pc.printf("5kN load cell? %s\r\n\n",sensors::use5kN?"Yes":"No"); @@ -95,7 +111,7 @@ } /** - * Sets the rate at which data is logged in an experiment + * Sets the rate at which data is logged in an experiment - when automatic datalogging is used * @param hertz: logging frequency in Hz */ void Bench::setLoggingFrequency(float hertz) @@ -104,26 +120,25 @@ if (hertz > 0) { loggingUS = 1000000/hertz; loggingHz = hertz; - } else { + } else { //default if bad value supplied loggingUS = timing::kTimeLogDataUs; loggingHz = (int)(1000000/timing::kTimeLogDataUs); } } /** - * Sets names of extra columns of data to be recorded + * Sets names of extra columns of data to be recorded (those more than maxCols are + * ignored) * @param extraColumnNames: string array of the column names * @param numCols: number of elements in the string array */ void Bench::setExtraColumns(string extraColumnNames[], int numCols) { usedExtraCols = numCols; - //pc.printf("Length: %i\r\n",usedExtraCols); // save the names for(int i=0; i<maxCols; i++) { if (i<numCols) { extraColNames[i] = extraColumnNames[i]; - //pc.printf("\r\nS%d: %s\r\n",i,extraColNames[i]); } else { extraColNames[i] = ""; //less columns than the max possible are filled with a null space } @@ -139,9 +154,7 @@ { for (int i=0; i<usedExtraCols; i++) { extraColValues[i] = data[i]; - //pc.printf("\r\nD%d: %f\r\n",i,extraColValues[i]); - } - + } } // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = @@ -151,7 +164,6 @@ /** * Update routine for the test rig * - Updates the angle buffer of the sensor array - * - ... that's it for now (add filtering?) * Note that angles lag one update() behind, due to the way the SPI * protocol works. */ @@ -163,18 +175,6 @@ /** * Obtain the joint angle in degrees * These are the angles at the time of two Update() calls back - * @param joint: the joint for which the angle is requested (as enumerated in - * class header - TOES, KNEE, ANKLE, HIP - * @return: joint angle - */ -float Bench::getDegrees(Joint joint) -{ - return getDegrees(joint); -} - -/** - * Obtain the joint angle in degrees - * These are the angles at the time of two Update() calls back * @param joint: the joint for which the angle is requested (a number starting * from 0 indicating the position in the sensor daisy chain) * @return: joint angle @@ -189,44 +189,18 @@ } /** - * Obtain the joint angle in radians - * These are the angles at the time of two Update() calls back - * @param joint: the joint for which the angle is requested (as enumerated in - * class header - TOES, KNEE, ANKLE, HIP - * @return: joint angle - */ -float Bench::getRadians(Joint joint) -{ - return getRadians(joint); -} - -/** - * Obtain the joint angle in radians - * These are the angles at the time of two Update() calls back * @param joint: the joint for which the angle is requested (a number starting * from 0 indicating the position in the sensor daisy chain) - * @return: joint angle + * @return the name of the joint number */ -float Bench::getRadians(int i_joint) -{ - float ang = as5048_.getAngleRadians(i_joint); - if (ang>kCutOffRadians) { - return ang-As5048::kRadPerRev; - } - return ang; -} - - const char* Bench::getJointName(int i_joint) { return sensors::kJointNames[i_joint]; } -const char* Bench::getJointName(Joint joint) -{ - return getJointName(joint); -} - +/** + * @return the encoder object reference + */ As5048* Bench::get_as5048() { return &as5048_; @@ -246,6 +220,9 @@ } +/** + * zero the force reading (like a tare function) + */ void Bench::nullForce() { if (use5kN) { @@ -264,16 +241,26 @@ return spte0.getPressure(); } +/** + * zero the pressure reading (like a tare function) + */ void Bench::nullPressure0() { return spte0.nullPressure(); } +/** + * The pressure measured by pressure sensor 0 in bar + * @return: pressure + */ float Bench::getPressure1() { return spte1.getPressure(); } +/** + * zero the pressure reading (like a tare function) + */ void Bench::nullPressure1() { return spte1.nullPressure(); @@ -323,6 +310,7 @@ { LinAct.setPWM(pwm); } + // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = // IMPLEMENTATION DATA LOGGING // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = @@ -342,9 +330,10 @@ struct dirent *p; d = opendir("/sd"); - if (d != NULL) { + if (d != NULL) {//if there is an SD card sd_card_present = true; - + + //print existing files pc.printf("\t> Contents of SD Card:\r\n"); while ((p = readdir(d)) != NULL) { if (p->d_name[0] != '.') { @@ -367,7 +356,9 @@ } /** - * Start logging data + * Start logging data (now manual, meaning user has to call a method to record a datapoint + * but if tick_logging.attach...(...) is uncommmented + * then recording becomes automatic) * param fname_append: a string describing the name appended to each logged file * (along with its unique loggging number). */ @@ -375,7 +366,6 @@ { pc.printf("\r\nDATA LOGGING"); if (sd_card_present) { - // create unique file name ++fname_prepend; char fname[50]; @@ -386,24 +376,19 @@ // open file for writing and start logging after success fp_data = fopen(fname,"w"); if (fp_data==NULL) { - pc.printf("\t> ERROR: failed to open log file (t=%d ms)\r\n", - timer.read_ms()); + pc.printf("\t> ERROR: failed to open log file (t=%d ms)\r\n",timer.read_ms()); } else { - string fHeader = "time (s),theta_knee (deg),force (N),pressure (kPa)"; + string fHeader = "time (s),theta_knee (deg),force (N),pressure (kPa)";//default data points recorded for (int i=0; i<usedExtraCols; i++) { if (extraColNames[i] != "") { fHeader = fHeader + "," + extraColNames[i]; } } - //pc.printf("%s", fHeader.c_str()); fprintf(fp_data, "%s", fHeader.c_str()); - //tick_logging.attach_us(this,&Bench::LogData,loggingUS); - timer.start(); - startedLogging = true; - - //pc.printf("\t> Logging started.\r\n"); - + //tick_logging.attach_us(this,&Bench::LogData,loggingUS); - uncomment to automatically log data + timer.start();//enable a time stamp for the logging file + startedLogging = true; is_logging = true; } } else { @@ -430,8 +415,7 @@ // open file for writing and start logging after success fp_data = fopen(fname,"w"); if (fp_data==NULL) { - pc.printf("\t> ERROR: failed to open log file (t=%d ms)\r\n", - timer.read_ms()); + pc.printf("\t> ERROR: failed to open log file (t=%d ms)\r\n",timer.read_ms()); } else { timer.start(); startedLogging = true; @@ -447,13 +431,13 @@ } /** - * Stop logging data. + * Stop automatically logging data. */ void Bench::StopLogging() { Bench::pc.printf("\r\nDATA LOGGING:"); if (sd_card_present) { - // close data file, stop logging + // close data file, stop logging, reset time stamp fclose(fp_data); tick_logging.detach(); timer.stop(); @@ -461,8 +445,7 @@ Bench::pc.printf("\r> Stopped."); } else { Bench::pc.printf("\t> No data was logged."); - } - + } is_logging = false; } @@ -479,26 +462,27 @@ } /** - * Log data + * Log data (record all the data points, default and custom with a timestamp) */ void Bench::LogData() { int currTime = timer.read_ms(); - if(startedLogging) { + if(startedLogging) {//the first time this is called, save the timer offset firstReadMS = currTime; startedLogging = false; } - double currTimeS = ((double)currTime - firstReadMS)/1000; + double currTimeS = ((double)currTime - firstReadMS)/1000;//time stamp // time fprintf(fp_data,"\n%f",currTimeS); - // bench: joint angles and force sensor and pressure sensor values + // bench default datapoints: joint angles and force sensor and pressure sensor values fprintf(fp_data,",%f,%f,%f", getDegrees(0), getForce(), getPressure0()*100 ); + //custom datapoints for (int i=0; i<usedExtraCols; i++) { fprintf(fp_data,",%f",extraColValues[i]); } @@ -515,19 +499,20 @@ if (is_printing) { if(sd_card_present) { + //file name and whether logging is happening Bench::pc.printf("\tFile number %15i\r\n", fname_prepend); Bench::pc.printf("\tLogging? %18s\r\n",is_logging?"Yes":"No"); } + //angles printed for (int i=0; i<sensors::kNumJoints; ++i) { string jointName = sensors::kJointNames[i]; jointName = jointName + " (deg)"; Bench::pc.printf("\t%15s %7.2f\r\n",jointName, getDegrees(i)); } - Bench::pc.printf("\t%15s %7.2f\r\n","Force (N)", getForce()); - - Bench::pc.printf("\t%15s %7.2f\r\n","Pressure0 (kPa)", getPressure0()*100); + Bench::pc.printf("\t%15s %7.2f\r\n","Force (N)", getForce()); //force reading + Bench::pc.printf("\t%15s %7.2f\r\n","Pressure0 (kPa)", getPressure0()*100); //pressure reading } } @@ -570,25 +555,24 @@ // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = /** - * d toggles printing state of sensors and l toggles logging of data + * s toggles printing state of sensors and l toggles logging of data * use the keyboard on the pc - * do not press longer than a second or it will toggle back + * do not press longer than a minKeyInt or it will toggle back */ void Bench::ToggleState(MODSERIAL_IRQ_INFO *q) { //if we have data and it was not too soon since the last data if(Bench::pc.readable() && (((Bench::keyIntT.read() + keyIntOffset) >= timing::minKeyInt))) { - k = Bench::pc.getc();//read the keystroke - Bench::pc.rxBufferFlush(); - //toggle status of logging + k = Bench::pc.getc();//read the keystroke + Bench::pc.rxBufferFlush();//delete all recorded keystrokes + if(k == 's') {//toggle printing of data Bench::pc.printf("\tInput: %c\r\n",k); TogglePrinting(); keyIntT.reset(); keyIntT.start(); keyIntOffset = 0; - - } else if (k == 'l') { + } else if (k == 'l') {//toggle status of logging Bench::pc.printf("\tInput: %c\r\n",k); ToggleLogging(); keyIntT.reset(); @@ -608,7 +592,7 @@ is_printing = true; } else { is_printing = false; - PrintMenu(); + PrintMenu();//data no longer printed, print home menu } was_printing = is_printing; } @@ -623,7 +607,6 @@ } else { is_logging = false; } - //PrintMenu(); } /**
diff -r dd4193213be9 -r a84d54e25775 bench.h --- a/bench.h Mon Oct 26 08:33:02 2020 +0000 +++ b/bench.h Mon Oct 26 11:55:27 2020 +0000 @@ -1,3 +1,18 @@ +/* Copyright 2020 Allan Joshua Veale + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + #ifndef _BENCH02_H_ #define _BENCH02_H_ #include "MODSERIAL.h" @@ -15,30 +30,21 @@ #include "LinearActuator.h" /** - * Class to read out sensory information from the second test bench: + * Class to read out sensory information from the test rig: * the knee joint angle as measured by an AMS AS5048 absolute rotary sensor * the vertical force applied externally at the hip joint * the pressure (for example of an actuator used in the device under test). - * Additionally, an on /off valve can pressurise the actuator on the leg + * Additionally, an on /off valve can pressurise the actuator on the leg and a linear + * actuator can be used to raise and lower the test leg */ class Bench { public: - static const float kCutOffDegrees = 180.0f; + //angle is only allowed to be< this value + static const float kCutOffDegrees = 180.0f; static const float kCutOffRadians = 3.14159265359f; - - enum Joint { - TOES, - ANKLE, - KNEE, - HIP - }; - - enum DACChannel { - A, - B - }; - + + // constructor Bench(PinName mosi = AS5048_MOSI, PinName miso = AS5048_MISO, PinName sck = AS5048_SCLK, PinName cs = AS5048_CS, bool use5kN = sensors::use5kN,PinName p_lcm101 = LCM101, @@ -50,59 +56,50 @@ //setup void initialise(); - void setLoggingFrequency(float logHertz); - void setExtraColumns(string extraColumnNames[], int numCols); - void setExtraData(float data[]); - void update(); + void setLoggingFrequency(float logHertz); //set datalogging frequency (for when automatic data logging is used - not in this code) + void setExtraColumns(string extraColumnNames[], int numCols);//manually add extra columns of data so user can have custom data recorded + void setExtraData(float data[]);//manually add extra datapoints + void update(); //read angle data afresh bool isLogging();//indicates if we are now datalogging - void stopLogging();//halts the data logging if we are now datalogging - void StopLogging(); //halts the data logging if we are now datalogging - void StartLogging(const char * fname_append = "data"); //starts datalogging + void stopLogging();//halts the manual data logging if we are now datalogging + void StopLogging(); //halts the automatic data logging if we are now datalogging + void StartLogging(const char * fname_append = "data"); //starts datalogging (now manual) void RestartLogging(const char * fname_append = "data");//restart datalogging - void LogData(); + void LogData(); //records the predetermined datapoints (and those in extracolumns) - //reading angle sensors + //for reading angle sensors As5048* get_as5048(); - float getDegrees(int i_joint); - float getDegrees(Joint joint); - - float getRadians(int i_joint); - float getRadians(Joint joint); + float getDegrees(int i_joint); //read angle + const char* getJointName(int i_joint);//return joint name - const char* getJointName(int i_joint); - const char* getJointName(Joint joint); - - //reading and calibrating force and pressure sensors - float getForce(); - void nullForce(); + //for reading and calibrating force and pressure sensors + float getForce();//read force + void nullForce();//tare reading - float getPressure0(); - void nullPressure0(); - float getPressure1(); - void nullPressure1(); + float getPressure0();//read pressure + void nullPressure0();//tare reading + float getPressure1();//read pressure + void nullPressure1();//tare reading - //MAX5322 DACs (two channels per DAC) - void setDACA(DACChannel ch, unsigned int bitValue); - void setDACB(DACChannel ch, unsigned int bitValue); - //controlling valve - bool getValve(); - void setValve(bool pressurise); + //for controlling valve + bool getValve();//return valve state + void setValve(bool pressurise); //turn valve on/off // controlling linear actuator - void setDir(bool dir); - bool getDir(); - void setPWM(int pwm); + void setDir(bool dir);//set actuator direction + bool getDir();//return actuator direction + void setPWM(int pwm); //actuator speed /** Object for printing/receiving data to the PC the test rig is connected * to. Note that it uses the MODSERIAL.h class. */ MODSERIAL pc; - void pausePrint(); - void resumePrint(); + void pausePrint();//stops automatic printing of data + void resumePrint();//resumes automatic printing of data private: //timing @@ -118,8 +115,8 @@ bool is_logging; bool is_printing; - bool was_printing; //if printing is paused true if is_printing was true - char k; //value from keyboard + bool was_printing; //if printing is paused true, or if is_printing was true + char k; //value from keyboard press //joint angle As5048 as5048_; @@ -144,22 +141,23 @@ FILE * fp_data; int fname_prepend;//file number bool sd_card_present;//card detected - + void InitSdCard(); //setup the SD card + + // recording extra data static const int maxCols = 5; int usedExtraCols; //number of extra columns useds string extraColNames[maxCols];//names of extra columns (up to maxCols allowed with 15 characters) float extraColValues[maxCols];//value held in extra columns for current time step - - void InitSdCard(); + //for toggling logging or printing - void ToggleState(MODSERIAL_IRQ_INFO *q); + void ToggleState(MODSERIAL_IRQ_INFO *q);//method for parsing keyboard presses - void ToggleLogging(); + void ToggleLogging();//change state of logging (between on and off) // serial printing - void TogglePrinting(); - void PrintStatus(); - void PrintMenu(); + void TogglePrinting(); //change state of printing (between on and off) + void PrintStatus();//print the read out from the test rig sensors + void PrintMenu(); //print the standard menu showing which keys control what in the test rig }; #endif \ No newline at end of file
diff -r dd4193213be9 -r a84d54e25775 constants.cpp --- a/constants.cpp Mon Oct 26 08:33:02 2020 +0000 +++ b/constants.cpp Mon Oct 26 11:55:27 2020 +0000 @@ -1,9 +1,30 @@ +/* Copyright 2020 Allan Joshua Veale + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + #include "constants.h" +/** Default values for constants + */ + namespace sensors { const bool use5kN = false; // LCM101-100kgf force sensor + const float kLcm101Offset = -1.5; + const float kLcm101Factor = 970.55; + // Equation from 7/6/2018 calibration used: // kLcm101Offset = 1.99 // kLcm101Factor = 969.2 @@ -11,57 +32,51 @@ // kLcm101Offset = 4.31 // kLcm101Factor = 1001.1 - const float kLcm101Offset = -1.5;//-1.52; - //This is currently the offset for the S610 sensor -5.41; - //Offset for LCM101 sensor = -1.52 - const float kLcm101Factor = 970.55;//970.55; - //This is currently the factor for the S610 sensor 977.35; - //Factor for LCM101 sensor is 970.55 // Gen5kN force sensor + const float kGen5kNOffset = 0; + const float kGen5kNFactor = 5530; + // Equation from 21/2/2019 calibration used: // kLcm101Offset = 21.2 // kLcm101Factor = 5530 - - const float kGen5kNOffset = 0; - const float kGen5kNFactor = 5530; + // Pressure sensor slope and offset values for a gauge pressure reading in bar // Equation from 25/6/2018 calibration used: - // kSPTE0Offset = -2.47 - // kSPTE0Factor = 12.5 + const float kSPTE0Offset = -2.33; + const float kSPTE0Factor = 12.0; + + const float kSPTE1Offset = -2.47; + const float kSPTE1Factor = 12.5; // Equation from 21/2/2019 calibration used // kSPTE0Offset = -2.33 // kSPTE0Factor = 12.0 - - const float kSPTE0Offset = -2.33; - - const float kSPTE0Factor = 12.0; - const float kSPTE1Offset = -2.47; - - const float kSPTE1Factor = 12.5; // // AS5048 abs angle sensor chain - const int kNumJoints = 1; + const int kNumJoints = 1;// if hard leg used again - use 4 - const char *kJointNames[] = {"Knee"};//{"1","Knee","3","4"}; - const float kOffsetsDegrees[] = {250};//{180,180,180,180}; - const bool kDirections[] = {true};//{true,true,true,true}; + const char *kJointNames[] = {"Knee"};// if hard leg used again - use {"Toes","Ankle","Knee","Hip"} + const float kOffsetsDegrees[] = {250};// if hard leg used again - use {83.2f,6.3f,170.7f,6.5f} + const bool kDirections[] = {true};// if hard leg used again - use {false,true,false,true} } namespace timing { const int TimeControlHertz = 1000;// control loop sample rate const int LogDataHertz = 249; //data log sample rate - const int SerialPrintHertz = 2; //print rate of serial + const int SerialPrintHertz = 2; //print rate of serial + + //corresponding values as a period const int kTimeControlUs = 1000000/TimeControlHertz; // 1000 Hz control loop const int kTimeLogDataUs = 1000000/LogDataHertz; // 200 Hz data logging const int kTimeSerialPrintUs = 1000000/SerialPrintHertz; // 2 Hz serial print - const int minKeyInt = 1; //minimum key press interval in s - const int kSerialBaudrate = 115200; - const int PWMHertz = 10000; + const int minKeyInt = 1; //minimum key press interval in s. if key is pressed more than once in this time interval it will just register as one press + const int kSerialBaudrate = 115200; //serial data rate + + const int PWMHertz = 10000;//linear actuator PWM frequency } namespace rigStructure {
diff -r dd4193213be9 -r a84d54e25775 constants.h --- a/constants.h Mon Oct 26 08:33:02 2020 +0000 +++ b/constants.h Mon Oct 26 11:55:27 2020 +0000 @@ -1,3 +1,18 @@ +/* Copyright 2020 Allan Joshua Veale + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + #ifndef _CONSTANTS_HARDWARE_H_ #define _CONSTANTS_HARDWARE_H_ @@ -7,6 +22,10 @@ #define M_PI 3.14159265359f #endif +/** + * Hardware connections to the mbed + */ + // SPI Communication AS5048 joint encoders #define AS5048_MOSI PTD6 // D11 #define AS5048_MISO PTD7 // D12 @@ -30,8 +49,8 @@ #define LCM101 A1 // SPTE analog output pressure sensors (0-10bar for 0-5V output) -#define SPTE_0 A0 -#define SPTE_1 A5 +#define SPTE_0 A0 //this is the one currently in use +#define SPTE_1 A5 //this one is not used, and its use on this pin needs to be tested - hence not in schematics //Festo digital valve (one for inflate) #define VALVE_PIN D0 @@ -75,9 +94,9 @@ extern const int kTimeLogDataUs; // data logging extern const int TimeControlHertz; // control loop sample rate extern const int kTimeSerialPrintUs; // serial printing - extern const int minKeyInt; //key interval time out value + extern const int minKeyInt; //key interval time out value - extern const int kSerialBaudrate; + extern const int kSerialBaudrate; //frequency of serial port extern const int PWMHertz; //Linear actuator frequency for pwm }
diff -r dd4193213be9 -r a84d54e25775 main.cpp --- a/main.cpp Mon Oct 26 08:33:02 2020 +0000 +++ b/main.cpp Mon Oct 26 11:55:27 2020 +0000 @@ -28,9 +28,9 @@ #include "bench.h" //Methods describing the tests -void runFatigueExperiment0(int cycles, float targetkPa, float inflateTimeOut,float deflateTimeOut); -void runFailureExperiment0(float targetkPa); -void runBenchmarkExperiment0(); +void runFatigueExperiment0(int cycles, float targetkPa, float inflateTimeOut,float deflateTimeOut,int logHz); +void runFailureExperiment0(float targetkPa,int logHz); +void runBenchmarkExperiment0(int logHz); void runBenchmarkExperiment1(int minForce, float maxAngle, float inflationT, int pwm, int cycles, int logHz); // Create bench object - this is used to control the test rig @@ -40,17 +40,27 @@ * Main loop */ int main() -{ - leg.setLoggingFrequency(10); //Set datalogging frequency (Hz) - +{ /* Two extra columns of data will be recorded in this experiment. One for the target pressure, and the other for the number of inflation-deflation cycles currently completed in the experiment */ - string colNames[] = {"Target pressure (kPa)","Cycle",}; //add data headings + string colNames[] = {"Target pressure (kPa)","Cycle"}; //add data headings leg.setExtraColumns(colNames,2); - float targetP = 300; //Pressure at which inflation is stopped and deflation begins (kPa) - int expCycles = 40; //Number of inflation cycles + int logHz = 10; //(Hz) datalogging frequency + float targetP = 300; //Pressure at which inflation is stopped and deflation begins (kPa) + + int fatCycles = 40; //Number of inflation cycles for the fatigue test + float infTimeAllow = 10;// (s) time allowed for inflation in a fatigue cycle + float defTimeAllow = 10;// (s) time allowed for deflation in a fatigue cycle + + //for benchmark experiment + float minForce = 5;//(N) force threshold at which leg extension changes to flexion + float maxAngle = 70;//(deg) angle threshold at which leg flexion changes to extension + float inflationTime = 3;//(s) time actuator given to inflate before starting experiment + int pwm = 75; //(%) linear actuator motor pwm + int benchCycles = 1;//(-) number of flexion/extension cycles + float vals[] = {targetP,0}; //set of initial values of data that will be logged leg.setExtraData(vals); @@ -62,14 +72,16 @@ stop it if the button is pressed again to stop datalogging (or when experiment stops - then datalogging stops by itself) */ while (true) { - if (leg.isLogging()) { - leg.pc.printf("Logging started"); - runFatigueExperiment0(expCycles,targetP,10,10); - //runBenchmarkExperiment0(); - runBenchmarkExperiment1(5, 70, 3, 75, 1, 10); - //runFailureExperiment0(targetP); + if (leg.isLogging()) {//check if logging has started, if so, run an experiment procedure + leg.pc.printf("Logging started");//user feedback + + //uncomment the type of experiment you want to try + runFatigueExperiment0(fatCycles,targetP,infTimeAllow,defTimeAllow,logHz); + //runBenchmarkExperiment0(logHz); + //runBenchmarkExperiment1(minForce, maxAngle, inflationTime, pwm, benchCycles, logHz); + //runFailureExperiment0(targetP,logHz); } - wait(0.5); + wait(0.5);//wait a bit before checking again } } @@ -81,13 +93,19 @@ * @param targetkPa: the pressure at which the valve is opened to let the leg go down (kPa) * @param inflateTimeOut: (s) if inflation takes longer than this, experiment is assumed to fail and stops, saving data * @param deflateTimeOut: (s) if deflation takes longer than this, experiment is assumed to fail and stops, saving data + * @param logHz: datalogging frequency */ -void runFatigueExperiment0(int cycles, float targetkPa, float inflateTimeOut, float deflateTimeOut) +void runFatigueExperiment0(int cycles, float targetkPa, float inflateTimeOut, float deflateTimeOut,int logHz) { //method constants Timer flowT;//timer used to time flow into and out of actuator - float loopTime = 0.1; //(s) time between checking pressure - int num_file = 1; //number of data files to save + + float loopTime = 1/logHz; //(s) time between checking pressure + + //number of data files to save (so we can create a safety barrier + //when lots of cycles are done e.g. you may want 100 cycles in each file + //so if something goes wrong, you will have most of the data, to within a 100 cycles) + int num_file = 1; for (int i=0; i<num_file; i++) { //record data @@ -165,6 +183,7 @@ /* Logging stopped as experiment is fully completed (desired number of cycles reached)*/ + leg.pc.printf("\r\nExit Fatigue Test"); leg.setValve(false); //Depressurise leg.StopLogging(); //Stop logging data leg.resumePrint(); //Let the Bench class print @@ -177,11 +196,13 @@ * increasing the actuator pressure by manually opening up the pressure regulator * connected to the actuator. It is also assumed that the user will stop inflation * if they deem the actuator to have failed. - * Data is recorded at ~10Hz. * @param targetkPa: the pressure at which the valve is opened to deflate the actuator (kPa) + * @param logHz: datalogging frequency */ -void runFailureExperiment0(float targetkPa) +void runFailureExperiment0(float targetkPa,int logHz) { + double logTime = 1/logHz;//s interval between logging data + //Pressurise the actuator under test leg.StartLogging(); leg.setValve(true); @@ -191,12 +212,12 @@ while(leg.isLogging() && (leg.getPressure0()*100 < targetkPa)) { leg.pc.printf("\r\nPressure (kPa): \t%7.2f",leg.getPressure0()*100);//print the pressure leg.LogData();//record a datapoint - wait(0.1);//wait + wait(logTime);//wait } //Depressurise when the user is done with benchmarking or the target pressure is //reached - leg.pc.printf("\r\nExit Benchmarking Test"); + leg.pc.printf("\r\nExit Failure Test"); leg.setValve(false); leg.StopLogging(); //Stop logging data leg.resumePrint(); //Let the Bench class print @@ -205,17 +226,19 @@ /** * A method used to benchmark the actuator under test before the linear actuator * was fitted to the test rig. It simply pressurises the actuator and records data - * at ~10 Hz + * @param logHz: datalogging frequency */ -void runBenchmarkExperiment0() +void runBenchmarkExperiment0(int logHz) { + double logTime = 1/logHz;//s interval between logging data + //Pressurise the actuator under test leg.StartLogging(); leg.setValve(true);//inflation while(leg.isLogging()) {//until the user presses the key to stop datalogging leg.pc.printf("\r\nPressure (kPa): \t%7.2f",leg.getPressure0()*100); //print the pressure leg.LogData();//record a datapoint - wait(0.1);//wait + wait(logTime);//wait } //Depressurise when the user is done with benchmarking @@ -226,8 +249,8 @@ } /** - * A benchmark test with the linear actuator. The actuator is cycled from its flexed position - * to the point at which it no longer produces force. This is considered its range of motion. + * A benchmark test with the linear actuator. The actuator is cycled from its flexed position, + * to the point at which it no longer produces force, and back again. This is considered its range of motion. * NOTE - not extensively tested * @param minForce: (N) force at which cycle goes from extension to flexion * @param maxAngle: (deg) angle at which cycle goes from flexion to extension @@ -270,7 +293,8 @@ wait(logTime);//wait } - if (!leg.isLogging()) {//If the user stopped + //If the user stopped + if (!leg.isLogging()) { leg.pc.printf("\r\nUser stopped during extension Exit"); leg.setPWM(0); //turn off linear actuator leg.setValve(false);//Depressurise @@ -292,7 +316,8 @@ wait(logTime);//wait } - if (!leg.isLogging()) {//If the user stopped + //If the user stopped + if (!leg.isLogging()) { leg.pc.printf("\r\nUser stopped during flexion Exit"); leg.setPWM(0); leg.setValve(false);//Depressurise