Hallo zusammen,
ich wollte hier mal kurz mein Projekt vorstellen, an dem ich gerade arbeite.
Entstehen soll eine automatische Temperatursteuerung für die Heizgriffe meines Motorrads sowie eine Steuerung für den Kettenöler.
Der Kettenöler ansich ist simpel. Das Tachosignal wird mit einem Pulldown über Interrupt gezählt und in gefahrene Strecke umgerechnet. Ist die voreingestellte Sollstrecke erreicht, wird geölt und die gefahrene Strecke wird zurückgesetzt.
Die Sollstrecke kann verändert und gespeichert werden (so kann man die Ölmenge einstellen). Zusätzlich will ich eine Geschwindigkeitsabhängige anpassung umsetzen. Wenn die Sollstrecke erstmal erreicht ist, werden die millis gespeichert. Beim nächsten erreichen der Sollstrecke wird aus den Millis die gefahrene Geschwindigkeit ermittelt. Ab einer bestimmten Mindestgeschwindigkeit wird die Sollstrecke dann über einen quadratischen Koeffizienten, der sich aus der Geschwindigkeit ergibt, verringert (je höher die Geschwindigkeit, desto öfter wird geölt).
Quadratisch deshalb, weil die Fliehkraft quadratisch mit der Geschwindigkeit steigt und somit auch die Menge des abgeschleuderten Öls quadratisch ansteigt.
Zum Kettenöler existiert bisher nur das Konzept in meinem Kopf. Umgesetzt ist da noch nichts, weil eigentlich schon alles klar ist.
Die Temperatursteuerung soll bei Unterschreitung eines StartTemperaturwerts mit einer definierten Leistung einschalten. Danach steigt die Leistung mit fallender Temperatur weiter an, bis ein EndTemperaturwert erreicht ist. Ab hier bleibt die Leistung gleich (eingestelltes Dauermaximum). Um den Leistungsanstieg noch beeinflussen zu können, kann optional ein Referenzpunkt gespeichert werden. So stellt man bei einer definierten Temperatur die Wohlfühleistung ein und die Steuerung regelt dann zwischen Start - Referenzpunkt und zwischen Referenzpunkt und Ende jeweils linear.
UserInterface wird ein 2 Tasten Menu mit LCD. Das LCD fehlt mir noch, daher geht aktuell einfach alles über Serial auf die Console.
Außerhalb des Setups soll auf der Anzeige dann einfach die aktuelle Temperatur, die Leistung der Griffe und die aktuell ermittelte Sollstrecke für die Ölung angezeigt werden.
Natürlich will ich meinen Code auch sharen. Hier ein paar Auszüge aus dem aktuellen Sketch:
Funktion zur Erkennung eines Tastendrucks (hier der HOCH Taster). Bei kurzzeitigem Druck wird die Funktion buttonUpShort ausgelöst. Bei längerem Druck von 2sec wird buttonUpLong ausgelöst. Eine explizite Entprellung hab ich nicht eingebaut, bisher wars aber auch nicht nötig.
void checkButtonUp() {
static int buttonState = HIGH;
static unsigned long buttonMillis = 0;
int button = digitalRead(buttonUp);
if (button != buttonState) {
if (button == HIGH && buttonMillis != 0) {
buttonUpShort();
buttonMillis = 0;
} else {
buttonMillis = millis();
}
buttonState = button;
} else {
if (button == LOW) {
if (buttonMillis != 0 && millis() > buttonMillis + 2000) {
buttonUpLong();
buttonMillis = 0;
}
}
}
}
Geglättetes auslesen der Temperatur. Ich verwende aktuell einen einfachen Widerstandssensor und begnüge mich mit der gemessenen Spannung. Wird noch durch einen digitalen Sensor ausgetauscht mit tatsächlichem Temperaturwert. Wahrscheinlich kann dann die Glättung entfallen.
int getActualTemp() {
static int temps[] = { 0, 0, 0, 0, 0 };
static int tempIdx = 0;
static int temp = 0;
int val = analogRead(A0);
temp -= temps[tempIdx];
temp += temp;
temps[tempIdx] = val;
tempIdx++;
if (tempIdx == 5) {
tempIdx = 0;
}
}
Errechnen der aktuell nötigen Heizleistung: startTemp, startHeater, mTemp, mHeater, endTemp und endHeater sind die zuvor erwähnten Temperaturpunkte mit zugeordneter Leistung. actualHeater ist der resultierende Wert für die Heizung, der dann später auf den PWM Pin geschrieben werden muss.
void processHeat(){
static long lastMillis = 0;
if (millis() > lastMillis + 5000) {
lastMillis = millis();
if (!setupModeActive){
int lowTemp = startTemp;
int lowHeat = startHeat;
int highTemp = endTemp;
int highHeat = endHeat;
if (actualTemp < startTemp) {
if (mTemp != 0){
if (mTemp > actualTemp){
highTemp = mTemp;
highHeat = mHeat;
} else {
lowTemp = mTemp;
lowHeat = mHeat;
}
}
actualHeater = map(actualTemp, lowTemp, highTemp, lowHeat, highHeat);
} else {
actualHeater = 0;
}
}
}
}
Die Funktionsweise des Menus (das noch nicht fertig ist) kann ich leider nicht so einfach veröffentlichen, weil da im sketch alles drunter und drüber geht. Ich habe einfach ein Flag, das mir sagt ob ich mich im SetupModus befinde. Dazu nochmal ein Flag, das mir sagt, ob sich das Setup im Editmodus befindet. Dazu noch einen int, der den entsprechenden Menupunkt repräsentiert. Drückt man den UP-Taster lang, dann wechselt man in den SetupModus. Durch kurzes UP und DOWN kann man nun durch die Menupunkte navigieren (selector++ , selector–). Ist man im SetupModus und drück DOWN lang, gelangt man in den Editmodus. Jetzt kann man mit UP und DOWN die Werte verändern. Mit einem langen DOWN speichert man die Änderungen ab. Mit einem langen UP könnte man innerhalb des Menus im Editmodus nochmal zwischen 2 Werten wechseln (z.B. Temperatur und Leistung). Das habe ich aber akutell nicht umgesetzt, da ich die Temperatur einfach über die aktuelle Temperatur setze. In der Praxis wird es ja so sein, dass man fährt und während der Fahrt merkt, dass man bei der aktuellen Temperatur mehr bzw. weniger Power braucht. Also stellt man die Power ein und speichert mit der aktuellen Temperatur ab.
Soweit dieses. Jetzt muss ich erstmal noch an der Menuführung feilen und ein Display finden (mein Problem ist, dass mir die üblichen Displays aus dem Handel zu groß sind). Davon abgesehn muss ich das dann auch noch irgendwie Wasserdicht bekommen. Die Steuerung für den Kettenöler mache ich mal nebenbei.