Remove PWM code

Pi's PWM pin has been replaced with PWM-generating hardware. Motor
location-finding algorithm has been left in, to ensure safe travel.
This commit is contained in:
Blizzard Finnegan 2023-03-13 10:14:11 -04:00
parent 9afbcfbf43
commit caed5f0d1e
No known key found for this signature in database
GPG key ID: DE547EDF547DDA49
5 changed files with 21 additions and 273 deletions

View file

@ -4,7 +4,7 @@
<groupId>org.baxter.disco</groupId> <groupId>org.baxter.disco</groupId>
<artifactId>ocr</artifactId> <artifactId>ocr</artifactId>
<name>Disco OCR Accuracy Over Life Testing</name> <name>Disco OCR Accuracy Over Life Testing</name>
<version>4.3.6</version> <version>4.3.7</version>
<description>Testing Discos for long-term accuracy, using automated optical character recognition.</description> <description>Testing Discos for long-term accuracy, using automated optical character recognition.</description>
<organization> <organization>
<name>Baxter International</name> <name>Baxter International</name>

View file

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.baxter.disco</groupId> <groupId>org.baxter.disco</groupId>
<artifactId>ocr</artifactId> <artifactId>ocr</artifactId>
<version>4.3.6</version> <version>4.3.7</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>Disco OCR Accuracy Over Life Testing</name> <name>Disco OCR Accuracy Over Life Testing</name>
<description>Testing Discos for long-term accuracy, using automated optical character recognition.</description> <description>Testing Discos for long-term accuracy, using automated optical character recognition.</description>

View file

@ -1,2 +1,2 @@
#! /usr/bin/env sh #! /usr/bin/env sh
sudo java -jar discoTesting-4.3.6.jar 2>/dev/null sudo java -jar discoTesting-4.3.7.jar 2>/dev/null

View file

@ -25,7 +25,7 @@ public class Cli
/** /**
* Complete build version number * Complete build version number
*/ */
private static final String version = "4.3.6"; private static final String version = "4.3.7";
/** /**
* Currently saved iteration count. * Currently saved iteration count.
@ -58,7 +58,7 @@ public class Cli
/** /**
* Number of options currently available in the camera configuration sub-menu. * Number of options currently available in the camera configuration sub-menu.
*/ */
private static final int cameraMenuOptionCount = 6; private static final int cameraMenuOptionCount = 7;
/** /**
* Lock object, used for temporary interruption of {@link #runTests()} * Lock object, used for temporary interruption of {@link #runTests()}
@ -85,7 +85,7 @@ public class Cli
int userInput = 0; int userInput = 0;
ErrorLogging.logError("Calibrating motor movement. This may take several minutes..."); ErrorLogging.logError("Calibrating motor movement. ");
ErrorLogging.logError("The piston will fire momentarily when the motor calibration is complete."); ErrorLogging.logError("The piston will fire momentarily when the motor calibration is complete.");
MovementFacade.pressButton(); MovementFacade.pressButton();
@ -191,6 +191,7 @@ public class Cli
*/ */
private static void printHelp() private static void printHelp()
{ {
println("\n\n");
println("========================================"); println("========================================");
println("Explanations:"); println("Explanations:");
println("----------------------------------------"); println("----------------------------------------");
@ -261,6 +262,7 @@ public class Cli
*/ */
private static void printCameraMenu(List<String> cameraList) private static void printCameraMenu(List<String> cameraList)
{ {
println("\n\n");
println("Available cameras to configure:"); println("Available cameras to configure:");
println("------------------------------------"); println("------------------------------------");
for(int index = 0; index < cameraList.size(); index++) for(int index = 0; index < cameraList.size(); index++)
@ -278,6 +280,7 @@ public class Cli
*/ */
private static void printSerialMenu(List<String> cameraList) private static void printSerialMenu(List<String> cameraList)
{ {
println("\n\n");
println("Available serial numbers to set:"); println("Available serial numbers to set:");
println("------------------------------------"); println("------------------------------------");
for(int index = 0; index < cameraList.size(); index++) for(int index = 0; index < cameraList.size(); index++)
@ -299,6 +302,7 @@ public class Cli
*/ */
private static void printActiveToggleMenu(List<String> cameraList) private static void printActiveToggleMenu(List<String> cameraList)
{ {
println("\n\n");
println("Available cameras to toggle:"); println("Available cameras to toggle:");
println("------------------------------------"); println("------------------------------------");
for(int index = 0; index < cameraList.size(); index++) for(int index = 0; index < cameraList.size(); index++)

View file

@ -9,9 +9,6 @@ import com.pi4j.io.gpio.digital.DigitalOutput;
import com.pi4j.io.gpio.digital.DigitalOutputConfigBuilder; import com.pi4j.io.gpio.digital.DigitalOutputConfigBuilder;
import com.pi4j.io.gpio.digital.DigitalState; import com.pi4j.io.gpio.digital.DigitalState;
import com.pi4j.io.gpio.digital.PullResistance; import com.pi4j.io.gpio.digital.PullResistance;
import com.pi4j.io.pwm.Pwm;
import com.pi4j.io.pwm.PwmConfigBuilder;
import com.pi4j.io.pwm.PwmType;
/** /**
* Facade for all movement of the fixture. * Facade for all movement of the fixture.
@ -36,30 +33,9 @@ public class MovementFacade
private static Thread runSwitchThread; private static Thread runSwitchThread;
/** /**
* Max allowed speed by current fixture design. * Fraction of the total travel time, so the arm won't push through the limit switch.
* Motor appears to start acting erratically over 192kHz.
*/ */
private static final int MAX_FREQUENCY = 192000; private static final double SLOW_POLL_FACTOR = 0.95;
/**
* Amount of buffer between the found absolute speed, and used speed.
*/
private static final int SPEED_BUFFER = 7500;
/**
* Minimum allowed speed of the fixture arm; also used for reset travels.
*/
private static final int MIN_FREQUENCY = 10000;
/**
* Fraction of the total travel time at speed to start slowing down.
*/
private static final double SLOW_POLL_FACTOR = 3.0 / 4.0;
/**
* Amount to slow down the speed by.
*/
private static final int SPEED_DOWN_FACTOR = 2;
/** /**
* Amount of distance to travel. * Amount of distance to travel.
@ -68,17 +44,6 @@ public class MovementFacade
*/ */
private static double TRAVEL_DIST; private static double TRAVEL_DIST;
/**
* Frequency fed to the PWM pin, which the motor controller converts into movement speed.
*/
private static int FREQUENCY = MIN_FREQUENCY;
/**
* PWM Duty Cycle.
* Does not affect motor speed; necessary for PWM setup.
*/
private static final int DUTY_CYCLE = 50;
//PWM Addresses //PWM Addresses
//All addresses are in BCM format. //All addresses are in BCM format.
@ -97,11 +62,6 @@ public class MovementFacade
*/ */
private static final int PISTON_ADDR = 25; private static final int PISTON_ADDR = 25;
/**
* PWM pin address.
*/
private static final int PWM_PIN_ADDR = 12;
/** /**
* Input pin address for the run switch. * Input pin address for the run switch.
*/ */
@ -122,11 +82,6 @@ public class MovementFacade
*/ */
private static final int POLL_WAIT = 10; private static final int POLL_WAIT = 10;
/**
* Multiply the time-out value by this value to get the number of polls to make.
*/
private static final int TIME_CONVERSION = 1000 / POLL_WAIT;
//Pi GPIO pin objects //Pi GPIO pin objects
/** /**
@ -177,12 +132,6 @@ public class MovementFacade
*/ */
private static DigitalOutput pistonActivate; private static DigitalOutput pistonActivate;
/**
* PWM pin object.
* Never used, but needs to be initialised to get GPIO to work properly.
*/
private static Pwm pwm;
/** /**
* {@link Pi4J} API interaction object. * {@link Pi4J} API interaction object.
*/ */
@ -224,60 +173,9 @@ public class MovementFacade
motorDirection = outputBuilder("motorDirection", "Motor Direction", MOTOR_DIRECTION_ADDR); motorDirection = outputBuilder("motorDirection", "Motor Direction", MOTOR_DIRECTION_ADDR);
pistonActivate = outputBuilder("piston" , "Piston Activate", PISTON_ADDR); pistonActivate = outputBuilder("piston" , "Piston Activate", PISTON_ADDR);
pwm = pwmBuilder("pwm","PWM Pin",PWM_PIN_ADDR); findDistance();
pwm.on(DUTY_CYCLE, FREQUENCY);
calibrate();
} }
/**
* Builder function for PWM pins.
*
* @param id ID of the new PWM pin.
* @param name Name of the new PWM pin.
* @param address BCM address of the PWM pin.
*
* @return newly created PWM pin object.
*/
private static Pwm pwmBuilder(String id, String name, int address)
{
PwmConfigBuilder configBuilder;
switch (address)
{
//The following pins allow for hardware PWM support.
case 12:
case 13:
case 18:
case 19:
case 40:
case 41:
case 45:
case 52:
case 53:
configBuilder = Pwm.newConfigBuilder(pi4j)
.id(id)
.name(name)
.address(address)
.pwmType(PwmType.HARDWARE)
.frequency(FREQUENCY)
.provider("pigpio-pwm")
.initial(1)
.shutdown(0);
break;
//Any pin not listed above must be software PWM controlled.
default:
configBuilder = Pwm.newConfigBuilder(pi4j)
.id(id)
.name(name)
.address(address)
.pwmType(PwmType.SOFTWARE)
.frequency(FREQUENCY)
.provider("pigpio-pwm")
.initial(1)
.shutdown(0);
}
return pi4j.create(configBuilder);
}
/** /**
* Builder function for DigitalInput pins. * Builder function for DigitalInput pins.
@ -328,7 +226,6 @@ public class MovementFacade
ErrorLogging.logError("DEBUG: --------------------------------------"); ErrorLogging.logError("DEBUG: --------------------------------------");
int counter; int counter;
ErrorLogging.logError("DEBUG: Setting minimum frequency of PWM..."); ErrorLogging.logError("DEBUG: Setting minimum frequency of PWM...");
pwm.on(DUTY_CYCLE, MIN_FREQUENCY);
if(upperLimit.isHigh()) if(upperLimit.isHigh())
{ {
ErrorLogging.logError("DEBUG: Motor at highest point! Lowering to reset."); ErrorLogging.logError("DEBUG: Motor at highest point! Lowering to reset.");
@ -362,22 +259,6 @@ public class MovementFacade
return counter; return counter;
} }
/**
* Used to programmatically determine the motor's max speed.
*/
private static void calibrate()
{
ErrorLogging.logError("Determining distance to limit switches...");
findDistance();
ErrorLogging.logError("Resetting arm to set speed.");
resetArm();
ErrorLogging.logError("Calibrating...");
FREQUENCY = calib(MIN_FREQUENCY, MAX_FREQUENCY, 10000);
ErrorLogging.logError("Calibration complete!");
ErrorLogging.logError("DEBUG: Speed set to " + (FREQUENCY - SPEED_BUFFER));
setFrequency(FREQUENCY - SPEED_BUFFER);
}
/** /**
* Used to programmatically find the distance between the upper and lower limit switches. * Used to programmatically find the distance between the upper and lower limit switches.
*/ */
@ -386,7 +267,7 @@ public class MovementFacade
resetArm(); resetArm();
int downTravelCounter = 0; int downTravelCounter = 0;
int upTravelCounter = 0; int upTravelCounter = 0;
pwm.on(DUTY_CYCLE, MIN_FREQUENCY); //pwm.on(DUTY_CYCLE, MIN_FREQUENCY);
motorDirection.low(); motorDirection.low();
motorEnable.on(); motorEnable.on();
for(downTravelCounter = 0; downTravelCounter < Integer.MAX_VALUE; downTravelCounter++) for(downTravelCounter = 0; downTravelCounter < Integer.MAX_VALUE; downTravelCounter++)
@ -401,8 +282,6 @@ public class MovementFacade
motorEnable.off(); motorEnable.off();
if(lowerLimit.isOff()) ErrorLogging.logError("DEBUG: False positive on findDistance down!"); if(lowerLimit.isOff()) ErrorLogging.logError("DEBUG: False positive on findDistance down!");
int downTravelDist = downTravelCounter * MIN_FREQUENCY;
ErrorLogging.logError("DEBUG: Down travel distance found to be: " + downTravelDist);
ErrorLogging.logError("DEBUG: Down travel count: " + downTravelCounter); ErrorLogging.logError("DEBUG: Down travel count: " + downTravelCounter);
motorDirection.high(); motorDirection.high();
@ -419,95 +298,10 @@ public class MovementFacade
motorEnable.off(); motorEnable.off();
if(upperLimit.isOff()) ErrorLogging.logError("DEBUG: False positive on findDistance up!"); if(upperLimit.isOff()) ErrorLogging.logError("DEBUG: False positive on findDistance up!");
int upTravelDist = upTravelCounter * MIN_FREQUENCY;
ErrorLogging.logError("DEBUG: Up travel distance found to be: " + upTravelDist);
ErrorLogging.logError("DEBUG: Up travel count: " + downTravelCounter); ErrorLogging.logError("DEBUG: Up travel count: " + downTravelCounter);
if(Math.abs(upTravelCounter - downTravelCounter) > 3)
{
ErrorLogging.logError("DEBUG: Values differ too far to be error. Setting to lower value.");
}
int travelCounter = Math.min(upTravelCounter, downTravelCounter); int travelCounter = Math.min(upTravelCounter, downTravelCounter);
TRAVEL_DIST = travelCounter * MIN_FREQUENCY; TRAVEL_DIST = travelCounter;
}
/**
* Find the max frequency to feed to the motor.
*
* @param start Lowest frequency to check
* @param max Highest frequency to check
* @param iterate How much to iterate by
*
* @return The largest safe value between start and max.
*/
private static int calib(int start, int max, int iterate)
{
for(int i = start; i < max; i+=iterate)
{
if(!setFrequency(i))
{
ErrorLogging.logError("DEBUG: Speed set unsuccessfully! returning " + MIN_FREQUENCY + "...");
return MIN_FREQUENCY;
}
ErrorLogging.logError("DEBUG: Motor travelling down.");
motorDirection.low();
ErrorLogging.logError("DEBUG: Motor Frequency: " + FREQUENCY);
ErrorLogging.logError("DEBUG: Motor calibrate on.");
motorEnable.on();
int TWO_SECONDS = 2 * TIME_CONVERSION;
for(int j = 0; j < TWO_SECONDS; j++)
{
try{ Thread.sleep(POLL_WAIT); } catch(Exception e){ ErrorLogging.logError(e); }
if(lowerLimit.isHigh())
{
ErrorLogging.logError("DEBUG: Breaking loop early!");
break;
}
}
motorEnable.off();
ErrorLogging.logError("DEBUG: Motor calibrate off.");
if(upperLimit.isHigh())
{
ErrorLogging.logError("DEBUG: Motor failed to move! Returning " + (i - iterate));
return i-iterate;
}
else
{
ErrorLogging.logError("DEBUG: Motor moved at speed " + i + ". Checking for errors.");
if(resetArm() < 10)
{
ErrorLogging.logError("DEBUG: Motor failed to move! Returning " + (i - iterate));
return i - iterate;
}
}
}
return max-iterate;
}
/**
* Safely set the speed of the motor and fixture.
*
* @return true if set successfully, else false
*/
private static boolean setFrequency(int newFrequency)
{
boolean output;
if(newFrequency < MIN_FREQUENCY || newFrequency > MAX_FREQUENCY)
{
ErrorLogging.logError("DEBUG: Invalid MovementFacade.setFrequency() value, setting to minfrequency!");
FREQUENCY = MIN_FREQUENCY;
output = false;
}
else
{
FREQUENCY = newFrequency;
output = true;
}
ErrorLogging.logError("DEBUG: Setting frequency to " + FREQUENCY);
pwm.on(DUTY_CYCLE, FREQUENCY);
return output;
} }
/** /**
@ -526,32 +320,22 @@ public class MovementFacade
{ {
motorDirection.high(); motorDirection.high();
limitSense = upperLimit; limitSense = upperLimit;
ErrorLogging.logError("Sending fixture up..."); ErrorLogging.logError("DEBUG: Sending fixture up...");
} }
else else
{ {
motorDirection.low(); motorDirection.low();
limitSense = lowerLimit; limitSense = lowerLimit;
ErrorLogging.logError("Sending fixture down..."); ErrorLogging.logError("DEBUG: Sending fixture down...");
} }
if(limitSense.isHigh()) return FinalState.SAFE; if(limitSense.isHigh()) return FinalState.SAFE;
pwm.on(DUTY_CYCLE, FREQUENCY); int totalPollCount = (int)(TRAVEL_DIST);
int totalPollCount = (int)(TRAVEL_DIST / FREQUENCY);
int highSpeedPolls = (int)(totalPollCount * SLOW_POLL_FACTOR); int highSpeedPolls = (int)(totalPollCount * SLOW_POLL_FACTOR);
int notHighSpeedPolls = totalPollCount - highSpeedPolls;
int medSpeedPolls = (int)(notHighSpeedPolls * SLOW_POLL_FACTOR);
int lowSpeedPolls = notHighSpeedPolls - medSpeedPolls;
medSpeedPolls *= SPEED_DOWN_FACTOR;
lowSpeedPolls *= 2 * SPEED_DOWN_FACTOR;
ErrorLogging.logError("DEBUG: ============================="); ErrorLogging.logError("DEBUG: =============================");
ErrorLogging.logError("DEBUG: Travel time: " + totalPollCount); ErrorLogging.logError("DEBUG: Travel time: " + totalPollCount);
ErrorLogging.logError("DEBUG: High speed poll count: " + highSpeedPolls); ErrorLogging.logError("DEBUG: High speed poll count: " + highSpeedPolls);
ErrorLogging.logError("DEBUG: Medium speed poll count: " + medSpeedPolls);
ErrorLogging.logError("DEBUG: Low speed poll count: " + lowSpeedPolls);
ErrorLogging.logError("DEBUG: ============================="); ErrorLogging.logError("DEBUG: =============================");
motorEnable.on(); motorEnable.on();
for(int i = 0; i < highSpeedPolls; i++) for(int i = 0; i < highSpeedPolls; i++)
@ -560,53 +344,13 @@ public class MovementFacade
if(limitSense.isOn()) if(limitSense.isOn())
{ {
motorEnable.off(); motorEnable.off();
ErrorLogging.logError("DEBUG: Motor moved too fast! Stopping motor early.");
ErrorLogging.logError("DEBUG: Breaking high-speed loop and turning off motor!");
ErrorLogging.logError("DEBUG: Iteration count: " + i);
output = FinalState.FAILED;
break; break;
} }
} }
if(motorEnable.isOn())
{
output = FinalState.UNSAFE;
pwm.on(DUTY_CYCLE, (FREQUENCY / SPEED_DOWN_FACTOR));
for(int i = 0; i < medSpeedPolls; i++)
{
try{ Thread.sleep(POLL_WAIT); } catch(Exception e){ ErrorLogging.logError(e); }
if(limitSense.isOn())
{
motorEnable.off();
ErrorLogging.logError("DEBUG: Motor only partially slowed down! Stopping motor early.");
ErrorLogging.logError("DEBUG: Breaking medium-speed loop and turning off motor!");
ErrorLogging.logError("DEBUG: Iteration count: " + i);
break;
}
}
}
if(motorEnable.isOn())
{
output = FinalState.SAFE;
pwm.on(DUTY_CYCLE, (FREQUENCY / (2 * SPEED_DOWN_FACTOR)));
for(int i = 0; i < lowSpeedPolls; i++)
{
try{ Thread.sleep(POLL_WAIT); } catch(Exception e){ ErrorLogging.logError(e); }
if(limitSense.isOn())
{
motorEnable.off();
ErrorLogging.logError("DEBUG: Motor slowed down completely, but hit limit switch early.");
ErrorLogging.logError("DEBUG: Breaking low-speed loop and turning off motor!");
ErrorLogging.logError("DEBUG: Iteration count: " + i);
break;
}
}
}
motorEnable.off(); motorEnable.off();
pwm.on(DUTY_CYCLE, FREQUENCY); output = (limitSense.isOn() ? FinalState.UNSAFE : FinalState.SAFE);
return output; return output;
} }