-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDriveTrain.ino
147 lines (126 loc) · 4.17 KB
/
DriveTrain.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* ESC */
#include <Adafruit_TiCoServo.h>
#include <known_16bit_timers.h>
#include <math.h>
const int ESC_MIN_MS = 600;
const int ESC_NEUTRAL_MS = 1500;
const int ESC_MAX_MS = 2400;
int throttleOffset = 220; // Dynamic offset based on weight?
float throttleModifyer = 1.0;
const float MAX_MS_CHANGE = 2.0; // Max change in ESC MS per update
boolean calibratingEsc = false;
Adafruit_TiCoServo esc;
int targetMs;
float currentMs = 1500.0; // Saving speed as float for increased sub-ms accuracy when smoothing
float SMOOTHNESS = 0.1;
/* RPM and KM/H */
volatile int currentHalfRevs = 0;
volatile unsigned long tripHalfRevs = 0;
volatile unsigned long totalHalfRevs = 0;
int rpm = 0;
const double DIAMETER = 0.085; // Wheel diameter in meters VARIABLE
void setMotorSpeed(float balance) {
targetMs = getServoMs(balance);
if (targetMs == ESC_NEUTRAL_MS) { // Neutral: Go to target instantly
currentMs = targetMs;
} else if (targetMs != round(currentMs)) { // Increment smoothly to target
currentMs += constrain((targetMs - currentMs) * SMOOTHNESS, -MAX_MS_CHANGE, MAX_MS_CHANGE);
}
Serial.println(currentMs);
esc.write(round(currentMs));
}
void setInstantMotorSpeed(float balance) {
currentMs = getServoMs(balance);
esc.write(currentMs);
}
int getServoMs(float balance) {
// Calculate exponential throttle curve
float exponential = pow(balance, 3);
//if (balance < 0.0) exponential = -exponential; // Use if power of 2
// Calculate min and max range limits, without offset
int minimum = ESC_NEUTRAL_MS - ((ESC_NEUTRAL_MS - ESC_MIN_MS) * throttleModifyer - throttleOffset); //1500-680=820
int maximum = ESC_NEUTRAL_MS + ((ESC_MAX_MS - ESC_NEUTRAL_MS) * throttleModifyer - throttleOffset); //1500+680=2180
int milliSeconds = range(exponential, -1, 1, minimum, maximum);
// Add offset (minimum speed) to limit cogging
if (milliSeconds > ESC_NEUTRAL_MS) milliSeconds += throttleOffset;
if (milliSeconds < ESC_NEUTRAL_MS) milliSeconds -= throttleOffset;
return milliSeconds;
}
void arm(){
esc.attach(9, ESC_MIN_MS, ESC_MAX_MS);
setInstantMotorSpeed(0);
}
/* RPM & TRIP INFO */
void resetTrip() {
noInterrupts();
tripHalfRevs = 0;
interrupts();
}
float getCurrentTripInKmh() {
noInterrupts();
float revolutions = (float) tripHalfRevs / 2;
interrupts();
return (revolutions * DIAMETER * PI) / 1000;
}
float getTotalTripInKmh() {
noInterrupts();
float revolutions = (float) totalHalfRevs / 2;
interrupts();
return (revolutions * DIAMETER * PI) / 1000;
}
float getSpeedInKmh() {
// Calculate RPM, reset counter
noInterrupts();
rpm = currentHalfRevs * 15;
currentHalfRevs = 0;
interrupts();
float metersPerSecond = DIAMETER * rpm * 0.10472;
return metersPerSecond * 3.6;
}
/*
void sendCurrentKmh() {
detachInterrupt(0); //Disable interrupt when calculating
rpm = currentHalfRevs * 15;
double metersPerSecond = DIAMETER * rpm * 0.10472;
double kmh = metersPerSecond * 3.6;
Serial.print("kmh=");
Serial.println(kmh);
currentHalfRevs = 0; // Restart the RPM counter
attachInterrupt(0, rpmCounter, CHANGE); // Enable interrupt
}*/
void saveTripInfoToLocalStorage() {
noInterrupts();
saveLong(EEPROM_CURRENT_TRIP, tripHalfRevs);
saveLong(EEPROM_TOTAL_TRIP, totalHalfRevs);
interrupts();
}
void startEscCalibration() {
calibratingEsc = true;
Serial.println("ESC Calibration");
Serial.println("1 = Reverse, 2 = Neutral, 3 = Foreward, q = Quit Calibration.");
while (calibratingEsc) {
if (Serial.available()) {
char inChar = (char)Serial.read();
if (inChar == '1') {
Serial.println("Setting motor speed: Reverse");
esc.write(ESC_MIN_MS);
} else if (inChar == '2') {
Serial.println("Setting motor speed: Neutral");
esc.write(ESC_NEUTRAL_MS);
} else if (inChar == '3') {
Serial.println("Setting motor speed: Foreward");
esc.write(ESC_MAX_MS);
} else if (inChar == 'q') {
Serial.println("Quit Calibration");
calibratingEsc = false;
}
}
}
}
// Called automatically whenever PIN 2 changes between HIGH and LOW
void rpmCounter(){
currentHalfRevs++;
tripHalfRevs++;
totalHalfRevs++;
Serial.println("RPM");
}