Skip to content

Commit

Permalink
Version 2.1.8
Browse files Browse the repository at this point in the history
- Updated Hall calibration: Hall counter offset calculated for every Hall state
  • Loading branch information
mspider65 committed Feb 28, 2021
1 parent cc39cf7 commit 06e94c0
Show file tree
Hide file tree
Showing 9 changed files with 295 additions and 277 deletions.
4 changes: 2 additions & 2 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ android {
applicationId "spider65.ebike.tsdz2_esp32"
minSdkVersion 23
targetSdkVersion 28
versionCode 14
versionName "2.1.7"
versionCode 15
versionName "2.1.8"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

Expand Down
6 changes: 3 additions & 3 deletions app/src/main/java/spider65/ebike/tsdz2_esp32/TSDZConst.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,10 @@ public interface TSDZConst {
int STATUS_ADV_SIZE = 20;

// Default Hall Counter Offset values
int DEFAULT_HALL_DOWN_OFFSET = 23; // Hall counter Offset for counter starting from Hall falling edge
int DEFAULT_HALL_UP_OFFSET = 43; // Hall counter Offset for counter starting from Hall rising edge
int[] DEFAULT_HALL_OFFSET = {44,23,44,23,44,23};
double DEFAULT_AVG_OFFSET = (double)Math.round(((44*3) + (23*3))/6D * 2) / 2.0; // average rounded to 0.5

// Default motor Phase
int DEFAULT_PHASE_OFFSET = 4; // Phase angle adjust regarding the rotor reference Hall angle
int DEFAULT_ROTOR_OFFSET = 4; // Rotor angle adjust regarding the Hall angle reference
int DEFAULT_PHASE_ANGLE = 64; // Phase has 90 deg difference from rotor position
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import spider65.ebike.tsdz2_esp32.TSDZBTService;
import spider65.ebike.tsdz2_esp32.TSDZConst;
import spider65.ebike.tsdz2_esp32.data.TSDZ_Config;
import spider65.ebike.tsdz2_esp32.utils.Cramer;
import spider65.ebike.tsdz2_esp32.utils.LinearRegression;
import spider65.ebike.tsdz2_esp32.utils.RollingAverage;

Expand All @@ -35,8 +36,8 @@
public class HallCalibrationActivity extends AppCompatActivity {
private static final String TAG = "HallCalibration";

private static final int SETUP_STEPS = 15;
private static final int AVG_SIZE = 150;
private static final int SETUP_STEPS = 30;
private static final int AVG_SIZE = 100;

private final TSDZ_Config cfg = new TSDZ_Config();
private final IntentFilter mIntentFilter = new IntentFilter();
Expand Down Expand Up @@ -67,7 +68,7 @@ public class HallCalibrationActivity extends AppCompatActivity {
private final LinearRegression[] linearRegression = new LinearRegression[6];

private final int[] phaseAngles = new int[6];
private int hallUpDnDiff;
private final int[] hallTOffset = new int[6];


@Override
Expand Down Expand Up @@ -100,7 +101,7 @@ protected void onCreate(Bundle savedInstanceState) {
errorTV[5] = findViewById(R.id.err6TV);
hallValuesTV = findViewById(R.id.hallValuesTV);
hallUpDnDiffTV = findViewById(R.id.hallUpDnDiffTV);
resetBT = findViewById(R.id.defaultBT);
resetBT = findViewById(R.id.resetBT);
cancelBT = findViewById(R.id.exitButton);
saveBT = findViewById(R.id.saveButton);
progressBar = findViewById(R.id.progressBar);
Expand Down Expand Up @@ -180,24 +181,24 @@ public void onButtonClick(View view) {
} else if (view.getId() == R.id.saveButton) {
if (TSDZBTService.getBluetoothService() != null) {
System.arraycopy(phaseAngles, 0, cfg.ui8_hall_ref_angles, 0, 6);
cfg.ui8_hall_counter_offset_up = cfg.ui8_hall_counter_offset_down + hallUpDnDiff;
System.arraycopy(hallTOffset, 0, cfg.ui8_hall_counter_offset, 0, 6);
TSDZBTService.getBluetoothService().writeCfg(cfg);
} else
showDialog(getString(R.string.error), getString(R.string.connection_error), false);
} else if (view.getId() == R.id.defaultBT) {
} else if (view.getId() == R.id.resetBT) {
for (int i=0; i<6; i++) {
angleTV[i].setText(R.string.dash);
offsetTV[i].setText(R.string.dash);
errorTV[i].setText(R.string.dash);
}
for (int i=0; i<6; i++) {
double v = Math.round(((30D + 60D * (double) i) * (256D / 360D)
+ TSDZConst.DEFAULT_PHASE_OFFSET
+ TSDZConst.DEFAULT_ROTOR_OFFSET
- TSDZConst.DEFAULT_PHASE_ANGLE));
if (v < 0) v += 256;
phaseAngles[i] = (int)v;
}
hallUpDnDiff = TSDZConst.DEFAULT_HALL_UP_OFFSET - TSDZConst.DEFAULT_HALL_DOWN_OFFSET;
System.arraycopy(TSDZConst.DEFAULT_HALL_OFFSET,0,hallTOffset,0,hallTOffset.length);
refresValues();
saveBT.setEnabled(true);
showDialog("", getString(R.string.defaultLoaded), false);
Expand All @@ -213,7 +214,14 @@ private void refresValues() {
s.append(String.format(Locale.getDefault(), "%d", phaseAngles[i]));
}
hallValuesTV.setText(s.toString());
hallUpDnDiffTV.setText(String.format(Locale.getDefault(), "%d", hallUpDnDiff));

s = new StringBuilder();
for (int i=0; i<6; i++) {
if (i > 0)
s.append(" ");
s.append(String.format(Locale.getDefault(), "%d", hallTOffset[i]));
}
hallUpDnDiffTV.setText(s.toString());
}

private void updateUI() {
Expand Down Expand Up @@ -269,42 +277,113 @@ private void showDialog (String title, String message, boolean exit) {
builder.show();
}

private void updateResult() {
for (int i=0; i<6; i++) {
linearRegression[i] = new LinearRegression(px[i], py[i]);
angleTV[i].setText(String.format(Locale.getDefault(),"%.1f", linearRegression[i].slope()*360));
offsetTV[i].setText(String.format(Locale.getDefault(),"%.1f", linearRegression[i].intercept()));
errorTV[i].setText(String.format(Locale.getDefault(),"%.2f", linearRegression[i].R2()));

/*
* F1=Hall1 Tfall, R1=Hall1 TRise, F2=Hall2 TFall etc..
* The 6 linear equations calculated with the linear regression are dependant and have
* infinite solutions.
* Lets set F1=0 and then calculate all the other values 6 times for each equation
* combination and then calculate the average for each value.
* At the end add an offset to all values so that the total average value is TSDZConst.DEFAULT_AVG_OFFSET.
*/
private void calculateOffsets() {
final double[][] A1 = {
{ 0, 0,-1, 0, 1, 0}, // -F3 + R2 = linearRegression[0].intercept();
{ 1, 0, 0, 0,-1, 0}, // F1 - R2 = linearRegression[1].intercept();
{-1, 0, 0, 0, 0, 1}, // -F1 + R3 = linearRegression[2].intercept();
{ 0, 1, 0, 0, 0,-1}, // F2 - R3 = linearRegression[3].intercept();
{ 0,-1, 0, 1, 0, 0}, // -F2 + R1 = linearRegression[4].intercept();
{ 0, 0, 1,-1, 0, 0} // F3 - R1 = linearRegression[5].intercept();
};
final double[] Ak = {1,0,0,0,0,0}; // F1 = 0

double[][] A = new double[6][];
double[] b = new double[6];

double[] result = {0,0,0,0,0,0};

for (int i = 0; i < 6; i++) {
for (int j = 0; j < 6; j++) {
if (j == i) {
A[j] = Ak;
b[j] = 0;
} else {
A[j] = A1[j];
b[j] = linearRegression[j].intercept();
}
}
Cramer cramer = new Cramer(A, b);
double[] solution = cramer.solve();
for (int k = 0; k < solution.length; k++) {
result[k] += solution[k];
}
}

if (valuesOK()) {
showDialog("", getString(R.string.calibrationDataValid), false);
saveBT.setEnabled(true);
} else {
showDialog(getString(R.string.error), getString(R.string.calibrationDataNotValid), false);
saveBT.setEnabled(false);
for (int i=0; i<6; i++)
result[i] = result[i] / 6;

double avgOffset = 0;
for (int i=0; i<6; i++)
avgOffset += result[i];
avgOffset /= 6;
double diffOffset = TSDZConst.DEFAULT_AVG_OFFSET - avgOffset;
for (int i=0; i<6; i++) {
result[i] += diffOffset;
}

hallTOffset[0] = (int)Math.round(result[4]); // R2 - delay for Hall state 6
hallTOffset[1] = (int)Math.round(result[0]); // F1 - delay for Hall state 2
hallTOffset[2] = (int)Math.round(result[5]); // R3 - delay for Hall state 3
hallTOffset[3] = (int)Math.round(result[1]); // F2 - delay for Hall state 1
hallTOffset[4] = (int)Math.round(result[3]); // R1 - delay for Hall state 5
hallTOffset[5] = (int)Math.round(result[2]); // F3 - delay for Hall state 4
}

private void calculateAngles() {
double[] calcRefAngles = {0d,0d,0d,0d,0d,0d};
double value = 0;
double error = 0;
// Calculate the Hall incremental angles setting Hall state 6 = 0 degrees.
// Calculate the average offset error in regard to the reference positions.
for (int i=1; i<6; i++) {
value += linearRegression[i].slope()*256D;
error += value - ((double)i*256D/6D);
calcRefAngles[i] = value;
}
error /= 6D;
double offset = 0;

// Calculate the Phase reference angles applying the error correction and the absolute
// reference position correction.
for (int i=0; i<6; i++) {
// add 30 degree and subtract the calculated error
calcRefAngles[i] = calcRefAngles[i] - error + 256D/12D;
// Add rotor offset and subtract phase angle (90 degree)
int v = (int)Math.round(calcRefAngles[i])
+ TSDZConst.DEFAULT_PHASE_OFFSET
+ TSDZConst.DEFAULT_ROTOR_OFFSET
- TSDZConst.DEFAULT_PHASE_ANGLE;
if (v<0) v += 256;
phaseAngles[i] = v;
offset += Math.abs(linearRegression[i].intercept());
}
hallUpDnDiff = (byte)Math.round(offset/6D);
}

private void updateResult() {
for (int i=0; i<6; i++) {
linearRegression[i] = new LinearRegression(px[i], py[i]);
angleTV[i].setText(String.format(Locale.getDefault(),"%.1f", linearRegression[i].slope()*360));
offsetTV[i].setText(String.format(Locale.getDefault(),"%.1f", linearRegression[i].intercept()));
errorTV[i].setText(String.format(Locale.getDefault(),"%.2f", linearRegression[i].R2()));
}

if (valuesOK()) {
showDialog("", getString(R.string.calibrationDataValid), false);
saveBT.setEnabled(true);
} else {
showDialog(getString(R.string.error), getString(R.string.calibrationDataNotValid), false);
saveBT.setEnabled(false);
}

calculateAngles();
calculateOffsets();

Log.d(TAG,"ui8_hall_ref_angles:" + (phaseAngles[0] & 0xff)
+ "," + (phaseAngles[1] & 0xff)
Expand All @@ -313,7 +392,13 @@ private void updateResult() {
+ "," + (phaseAngles[4] & 0xff)
+ "," + (phaseAngles[5] & 0xff)
);
Log.d(TAG, "Hall Up-Down diff:" + hallUpDnDiff);
Log.d(TAG, "hallTOffset:" + (hallTOffset[0] & 0xff)
+ "," + (hallTOffset[1] & 0xff)
+ "," + (hallTOffset[2] & 0xff)
+ "," + (hallTOffset[3] & 0xff)
+ "," + (hallTOffset[4] & 0xff)
+ "," + (hallTOffset[5] & 0xff)
);
refresValues();
}

Expand Down Expand Up @@ -357,9 +442,8 @@ public void onReceive(Context context, Intent intent) {
}

System.arraycopy(cfg.ui8_hall_ref_angles, 0, phaseAngles, 0, 6);
hallUpDnDiff = cfg.ui8_hall_counter_offset_up - cfg.ui8_hall_counter_offset_down;
System.arraycopy(cfg.ui8_hall_counter_offset, 0, hallTOffset, 0, 6);
refresValues();

break;
case TSDZBTService.TSDZ_CFG_WRITE_BROADCAST:
if (intent.getBooleanExtra(TSDZBTService.VALUE_EXTRA,false))
Expand Down Expand Up @@ -389,7 +473,13 @@ public void onReceive(Context context, Intent intent) {
break;
}
} else if (data[0] == CMD_HALL_DATA) {
if (!calibrationRunning || (msgCounter++ < SETUP_STEPS)) {
if (!calibrationRunning) {
return;
}
msgCounter++;
long progress = (100 * (step * (AVG_SIZE + SETUP_STEPS) + msgCounter)) / (4 * (AVG_SIZE + SETUP_STEPS));
progressTV.setText(String.format(Locale.getDefault(), "%d%%", progress));
if (msgCounter <= SETUP_STEPS) {
return;
}
long sum = 0;
Expand All @@ -400,10 +490,6 @@ public void onReceive(Context context, Intent intent) {
erpsTV.setText(String.format(Locale.getDefault(), "%.2f", 250000D/sum));
if (avg[0].getIndex() == 0)
nextStep(sum);
else {
long progress = (100 * (step * AVG_SIZE + avg[0].getIndex())) / (4 * AVG_SIZE);
progressTV.setText(String.format(Locale.getDefault(), "%d%%", progress));
}
}
break;
}
Expand Down
Loading

0 comments on commit 06e94c0

Please sign in to comment.