/*
This script is designed to upload thrust data
by following a user-specified test sequence.
You should design the test sequence to cover as much as
possible in terms of the motor and propeller rotations
speeds.
*/
////////// Script parameters /////////
var throttlePoints = [
[1100, 1150, 1200, 1250, 1300, 1350, 1400, 1450, 1500, 1550, 1600, 1650, 1700, 1750],
]; // List of test points
var escStart = 1000; // ESC idle value
var escInitTime = 4; // Hold time at ESC idle
var settlingTime_s = 5; // Settling time before measurement
var cooldownTime_s = 0; // If the motor needs to cool down between steps
var cooldownThrottle_us = 1000; // Cool down faster when slowly spinning
var max_slew_rate_us_per_s = 40; // Limits torque from throttle changes, but adds extra test time
var samplesAvg = 25; // Number of samples to average
var save_CSV_file = false; // Save data to CSV file
//////// Beginning of the script /////////
var output = "esc";
var firstRowAdded = false;
var stepState = 0;
var lastThrottle = escStart;
// Begin the sequence
initESC(function(){
tare(function(){
takeSample(step);
});
});
// validate the throttle points
throttlePoints[0].forEach(function(el){
if(isNaN(el) || !Number.isInteger(el)){
rcb.console.error("Error: throttle points should be integers. Given: " + el);
}
if(el < 700 || el > 2300){
rcb.console.error("Error: throttle points should be between 700 and 2300 µs.");
}
});
//Starting a new CSV log file
if(save_CSV_file){
rcb.files.newLogFile({prefix: 'U15XXL with 62- prop'});
}
//Tare the load cells and the current sensor
function tare(callback){
rcb.sensors.tareLoadCells(function(){
//taring current has an effect only in the Series 1780
rcb.sensors.tareCurrent(callback);
});
}
//Arms the ESC
function initESC(callback){
//ESC initialization
rcb.console.print("Initializing ESC...");
rcb.database.log("ESC init value (µs): " + escStart);
rcb.output.set(output, escStart);
rcb.wait(callback, escInitTime);
}
//Performs steps, until no more.
function step(){
switch(stepState) {
// ramp up to next data point
case 0:
if(throttlePoints[0].length > 0){
var nextPoint = throttlePoints[0].shift();
rcb.console.print("Testing at : " + nextPoint);
var rampUpTime_s = calcRampTime(lastThrottle, nextPoint);
rcb.output.ramp(output, lastThrottle, nextPoint, rampUpTime_s, step);
lastThrottle = nextPoint;
stepState++;
}else{
endFct(); // no more points to test, finish the script
}
break;
// stabilization time then take a measurement.
case 1:
rcb.wait(function(){
takeSample(step);
}, settlingTime_s);
// next step will depend on if there is cooldown time specified
if(cooldownTime_s > 0){
stepState++;
}else{
stepState = 0;
}
break;
// ramp down to specified cooling throttle
case 2:
var coolDownThrottle = cooldownThrottle_us;
var rampDownTime_s = calcRampTime(lastThrottle, coolDownThrottle);
rcb.output.ramp(output, lastThrottle, coolDownThrottle, rampDownTime_s, step);
lastThrottle = coolDownThrottle;
stepState++;
break;
// wait for cooldown time, then go to the next step
case 3:
rcb.console.print("Cooling down...");
rcb.wait(step, cooldownTime_s);
stepState = 0;
break;
}
}
// calculates the time needed to perform a ramp from and to
// without exceeding the max slew rate parameter.
function calcRampTime(from, to){
if(max_slew_rate_us_per_s > 0){
rcb.console.print("Ramping...");
return math.abs(from-to) / max_slew_rate_us_per_s;
}
return 0;
}
//Calculates the rpm value depending on if using the optical or electrical probe
function getRPM(result){
var rpm = result.motorOpticalSpeed.workingValue;
if(result.motorElectricalSpeed){
rpm = math.max(result.motorElectricalSpeed.workingValue, rpm);
}
return rpm;
}
// Records a sample to database
function takeSample(callback){
rcb.sensors.read(function (result){
var rpm = getRPM(result);
if(result.thrust.workingValue < -0.05){
rcb.console.error("At this time we only support positive thrust values. Please reverse the thrust sign from the utilities tab.");
}
if(result.torque && result.torque.workingValue < -0.01){
rcb.console.error("At this time we only support positive torque values. Please reverse the torque sign from the utilities tab.");
}
if(result.current.workingValue < -0.1){
rcb.console.error("At this time we only support positive current values.");
}
if(!firstRowAdded && rpm > 0){
rcb.console.error("The first row of the data should be at zero rpm.");
}
// do not add more than one rpm=0 rows
if(!firstRowAdded || rpm > 0){
rcb.database.addData(result);
firstRowAdded = true;
}
if(save_CSV_file){
rcb.files.newLogEntry(result, callback);
}else{
callback();
}
}, samplesAvg);
}
// Called at the end of the steps
function endFct(){
// ramp down the motor back to initial throttle
var finishThrottle = escStart;
var rampTime_s = calcRampTime(lastThrottle, finishThrottle);
rcb.output.ramp(output, lastThrottle, finishThrottle, rampTime_s, function(){
// give time for the motor to reach a full stop
rcb.wait(function(){
rcb.database.submit(rcb.endScript);
}, 1);
});
}