/*
* This file is part of CBCJVM.
* CBCJVM is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CBCJVM is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with CBCJVM. If not, see <http://www.gnu.org/licenses/>.
*/
package cbccore.sensors.analog;
/**
* Calculates a distance in centimeters based of the value given by a floating
* analog sensor port. The ETSensor's values are approximately inversely
* proportional to the actual distance, and with some calibration, this class
* can use that relationship to solve for the actual distance. See the
* ETCalibrator test, which will give you k, power, and b required by the
* constructor. The class also contains calibration information collected by the
* programmer for his own sensor. This should only be used for prototyping, and
* you should do the calibration process yourself, as values could vary greatly
* from sensor to sensor.
* <p>
* The formula used is: <code>distance=k/Math.pow(analog10Value, power)+b</code>
*
* @author Benjamin Woodruff
*
*/
//Version 0.1: First stable version, had to add floating sensor support to
// CBCJVM
//Version 0.2: Added second getCm method that averages readings
//Version 0.3: New calibration values
//Version 1.0: Public CBCJVM release, added documentation.
//Sorry for excessive commenting, I think I'm going to use this for my
//documented code example
public class ETSensor extends Analog {
//calibration data
private double k; //multiplication factor
private double b; //fudge factor
private double power; //negitive power of analog value
//port number is handled by superclass
/**
* Basic constructor for fast tesing/prototyping, uses preset calibration
* values, which probably would differ slightly from your sensor. You should
* run the calibration utility yourself.
*
* @param port The port that the ETSensor is plugged into.
*/
public ETSensor(int port) {
this(port, 29470, 1.23, -.00448);
}
/**
* A constructor that you can plug your calibration data into. This is what
* you should use if you really want accuracy.
*
* @param port The port that the ETSensor is plugged into.
* @param k The calibration k value. A multiplication factor.
* @param power The calibration pow value. The negitive power of the
* analog value
* @param b The calibration b value. An offset, "fudge factor".
*/
public ETSensor(int port, double k, double power, double b) {
super(port);
setFloating(true);
this.k = k;
this.power = power;
this.b = b;
}
/**
* Conducts muliple readings and averages them together. Much more accurate,
* but takes much more time. It is recommended that you stop before calling
* this function so that it is not averaging positions from muliple
* positions.
*
* @param readings The number of readings to take that will be averaged
* @param millisWait The milliseconds to wait before each reading. 0
* should work in most cases. Don't make this too
* big, as the time it takes the function to return
* equals (millisWait+timeForSensorProbe)*readings
* with timeForSensorProbe being about 5-8 millis on
* a stock CBCv2. The main point of this is to allow
* a lower CPU usage, although with Matt's CBCv2 mod
* this shouldn't be too much of a problem, as
* in the mod, sensor probes are sleeping.
* @return The average distance in cm
*/
public double getCm(int readings, int millisWait) {
int sum = 0;
for(int i = 0; i < readings; ++i) {
sum += getValueHigh();
if(millisWait != 0) {
try { Thread.sleep(millisWait); } catch(Exception e) { return -1.; }
}
}
double avg = ((double)(sum))/((double)(readings));
return k/Math.pow(avg, power);
}
/**
* Calls getCm(1, 0), essentially giving you one quick reading. Accuracy is
* iffy, and it is recommended that you only use this function if you have
* your own averaging method, because CBC sensor readings have been known to
* fluctate from reading to reading. Otherwise, you should at least call
* getCm(3, 0) or something like that.
*
* @return a quick-and-dirty approximation for the distance.
*/
public double getCm() {
return getCm(1, 0);
}
}