Das mit CH4-Position-rechts kann ansonsten auch erstmal weggelassen werden … Position Mitte und Position links ist eigentlich die Hauptsache
Ohne Ch3!! Das ist fest eingestellt
const byte bremsLichtPin = LED_BUILTIN;
const byte backFirePin = 12;
const byte bremsLichtPwmPin = 11;
const byte rueckLichtPwmPin = 10;
const byte griffPwmPin = 9;
const byte rechtsBlinkPin = 8;
const byte linksBlinkPin = 7;
const byte rechtsBlinkPwmPin = 6;
const byte linksBlinkPwmPin = 5;
const byte rearLightPin = 4;
const byte fogLightPwmPin = 3;
const byte fogLightPin = 2;
const byte frontLightPin = A1;
// warnblink, griff, licht, nebel
bool switchState[] = {false, false, false, false};
enum blinkCondition {links, rechts, warn, aus};
enum lightCondition {no, all, back};
byte light = lightCondition::no;
uint8_t rearLightPwm = 0; // Für Rücklicht...
const uint8_t numCh = 5;
const uint8_t chInputPin[numCh] = {A2, A3, A4, A5, A0};
const char myType[numCh][10] = {"gas", "taster", "3-pos", "poti-1", "poti-2"};
volatile uint16_t aktChTime[numCh] = {0};
volatile uint16_t altChTime[numCh] = {0};
volatile bool aktChStatus[numCh] = {0};
volatile bool altChStatus[numCh] = {0};
volatile uint16_t altChInput[numCh] = {0};
uint16_t chInput[numCh] = {0};
void setup()
{
Serial.begin(115200);
delay(500);
Serial.println("\nStart ...");
randomSeed(A1);
for (byte b = 0; b < numCh; b++)
{
pinMode(chInputPin[b], INPUT);
}
const byte outPins[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, A1};
for (byte b = 0; b < sizeof(outPins); b++) // Output setzen
{
digitalWrite(b, LOW);
pinMode(b, OUTPUT);
}
PCICR |= B00000010; // Enable PCIE1 Bit2 = 1 (Port C)
PCMSK1 |= B00111101; // Enable PCINT8 (Pin A0) & PCINT10(Pin A2) & PCINT11(Pin A3) & PCINT12(Pin A4) & PCINT13(Pin A5)
}
//
void loop()
{
readSwitch();
setLighting();
backFire();
bremsLicht();
blinkLicht();
frontLicht();
rueckLicht();
backLight();
nebelLicht();
//printSerialChInput();
}
void readSwitch()
{
// Hier wird später CH3 ausgelesen
// Simulation state[0]
const uint32_t switchTime = 15000;
uint32_t lastSwitch = 0;
if (millis() - lastSwitch > switchTime)
{
lastSwitch = millis();
switchState[0] = !switchState[0];
}
}
//
void setLighting()
{
switch (aktChTime[4])
{
case 0 ... 1200:
light = lightCondition::all;
break;
case 1300 ... 1600:
light = lightCondition::no;
break;
case 1800 ... 2000:
light = lightCondition::back;
break;
}
}
//
void backLight() // Rückfahrscheinwerfer
{
if (light == lightCondition::back) // geht nur an, wenn back aktiv
{ digitalWrite(rearLightPin, HIGH); }
else
{ digitalWrite(rearLightPin, LOW); }
}
//
void nebelLicht() // Nebelscheinwerfer
{
if (light == lightCondition::all) // geht nur an, wenn Nachtkondition
{
digitalWrite(fogLightPin, HIGH);
// Hier kommt noch eine Bedingung für Ch3
analogWrite(fogLightPwmPin, 200); // wird später gekoppelt
}
else
{
digitalWrite(fogLightPin, LOW);
digitalWrite(fogLightPwmPin, LOW);
}
}
//
void rueckLicht()
{
if (light == lightCondition::all) // nur in Nachtkondition
{ rearLightPwm = 90; }
else
{ rearLightPwm = 0; }
analogWrite(rearLightPin, rearLightPwm);
}
//
void frontLicht()
{
if (light == lightCondition::all) // nur in Nachtkondition
{ digitalWrite(frontLightPin, HIGH); }
else
{ digitalWrite(frontLightPin, LOW); }
}
//
void positionsLicht() // wird von blinkLicht aufgerufen
{
const uint8_t blinkLightPwm = 60;
if ((light == lightCondition::all) || // Nachts und
(light == lightCondition::back)) // Rückwärts
{
analogWrite(linksBlinkPwmPin, blinkLightPwm); // setzt Grundhelligkeit "Positionslicht"
analogWrite(rechtsBlinkPwmPin, blinkLightPwm);
}
else
{
digitalWrite(linksBlinkPwmPin, LOW);
digitalWrite(rechtsBlinkPwmPin, LOW);
}
}
//
void blinken(const byte blinkRichtung, uint32_t &lastBlinkTime)
{
const uint32_t blinkTime = 500;
if (millis() - lastBlinkTime > blinkTime)
{
lastBlinkTime = millis();
switch (blinkRichtung)
{
case blinkCondition::rechts: // wenn rechts
digitalWrite(rechtsBlinkPin, !digitalRead(linksBlinkPin));
digitalWrite(linksBlinkPin, LOW); // sicherstellen, das aus, wenn aus warn zurück
break;
case blinkCondition::warn: /*FALLTRU*/
case blinkCondition::links:
digitalWrite(linksBlinkPin, !digitalRead(linksBlinkPin));
digitalWrite(rechtsBlinkPin, LOW);
break;
}
}
if (blinkRichtung == blinkCondition::warn) // sicherstellen, das rechts == links wird
{ digitalWrite(rechtsBlinkPin, digitalRead(linksBlinkPin)); }
digitalRead(linksBlinkPin) ? // Front an Heck angleichen
digitalWrite(linksBlinkPwmPin, HIGH) :
digitalWrite(linksBlinkPwmPin, LOW);
digitalRead(rechtsBlinkPin) ?
digitalWrite(rechtsBlinkPwmPin, HIGH) :
digitalWrite(rechtsBlinkPwmPin, LOW);
}
//
void blinkLicht()
{
static byte zustand = blinkCondition::aus;
static uint32_t lastBlinkTime = 0;
if (switchState[0]) // Warnblink ein?
{ zustand = blinkCondition::warn; } // hat immer Vorfahrt
switch (zustand)
{
case blinkCondition::links:
blinken(blinkCondition::links, lastBlinkTime);
if (aktChTime[4] < 1600)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::rechts:
blinken (blinkCondition::rechts, lastBlinkTime);
if (aktChTime[4] > 1400)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::warn:
blinken(blinkCondition::warn, lastBlinkTime);
{zustand = blinkCondition::aus;}
break;
case blinkCondition::aus:
positionsLicht();
digitalWrite(linksBlinkPin, LOW);
digitalWrite(rechtsBlinkPin, LOW);
if (aktChTime[4] > 1700)
{
zustand = blinkCondition::links;
digitalWrite(linksBlinkPin, HIGH);
lastBlinkTime = millis();
}
else if (aktChTime[4] < 1300)
{
zustand = blinkCondition::rechts;
digitalWrite(rechtsBlinkPin, HIGH);
lastBlinkTime = millis();
}
break;
}
}
//
void backFire()
{
if (light == lightCondition::no) // kein Licht
{
digitalWrite(backFirePin, LOW); // verhindert, das das an bleibt
return; // Funktionsabbruch
}
const uint16_t minSpeed = 1880; // SpeedWert ab wann ausgelöst
static uint32_t blinkTime = 0; // Zeitmerker
static uint32_t lastFireTime = 0; // Letzter Umschaltvorgang LED
if (aktChTime[0] > minSpeed) // Schnell genug
{
if (millis() - lastFireTime > blinkTime) // Umschaltzeit erreicht
{
digitalWrite(backFirePin, !digitalRead(backFirePin)); // Toggel
blinkTime = random(30, 100); // neue Zufallszeit
if (!digitalRead(backFirePin)) // Pin ist aus?...
{ blinkTime *= 3; } // ... Auszeit verlängern
}
lastFireTime = millis(); // umschaltzeit merken
}
else // Geschwindkeit nicht erreicht
{ digitalWrite(backFirePin, LOW); }
}
//
void bremsLicht()
{
enum condition {forward, neutral, backward}; //
static byte myState = condition::neutral;
static uint32_t lastForwardTime = 0; // Zeitmerker
const uint32_t reaktionsZeit = 200; // Zeit in ms... Das muss getestet werden
const uint16_t neutralSpeed = 1490; // Hier ist nüscht
const uint8_t hysterese = 200; // Pendel der Neutralstellung +/-
switch (myState)
{
case condition::forward:
if (aktChTime[0] < neutralSpeed + hysterese) // Neutralbereich erreicht?
{
myState = condition::neutral; // Zustand setzen
lastForwardTime = millis(); // Zeit merken
}
if (aktChTime[0] < neutralSpeed - hysterese) // Neutralbereich unterschritten?
{ myState = condition::backward; } // direkt Zustand wechseln
break;
case condition::neutral:
if (aktChTime[0] < neutralSpeed - hysterese) // Neutralbereich rückwärts verlassen?
{ myState = condition::backward; }
else if (aktChTime[0] > neutralSpeed + hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::forward; }
digitalWrite(bremsLichtPin, LOW); // Bremse deaktivieren
if (lightCondition::all) // Ch4 - ALL
{ analogWrite(bremsLichtPwmPin, rearLightPwm); } // Grundhelligkeit setzen
else
{ digitalWrite(bremsLichtPwmPin, LOW); } // oder ganz aus
break;
case condition::backward:
if (millis() - lastForwardTime < reaktionsZeit) // Zeit nicht abgelaufen ...
{
digitalWrite(bremsLichtPin, HIGH); // ... Bremse aktiviert!
digitalWrite(bremsLichtPwmPin, HIGH);
}
if (aktChTime[0] > neutralSpeed - hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::neutral; } // Zustand setzen
break;
}
}
//
void printSerialChInput()
{
for (byte b = 0; b < numCh; b++)
{
if (abs(int(altChTime[b] - aktChTime[b])) > 10)
{
Serial.print(myType[b]);
Serial.print(": ");
Serial.print(aktChTime[b]);
Serial.println('\t');
altChTime[b] = aktChTime[b];
}
}
}
//
ISR (PCINT1_vect) // Port C Interrupt occured
{
for (byte b = 0; b < numCh; b++)
{
aktChStatus[b] = digitalRead(chInputPin[b]);
if (altChStatus[b] != aktChStatus[b])
{
altChStatus[b] = aktChStatus[b];
if (aktChStatus[b])
{ altChInput[b] = micros(); }
else
{ aktChTime[b] = micros() - altChInput[b]; }
}
}
}
Ist ein erster Versuch - ich hoffe nicht allzuviel übersehen zu haben.
Vielleicht kommt ja auch mein kleiner Gag zwischendurch zum tragen.
Bedenke, ich mache das blind.
Video nutzt mir nichts - schön wäre, wenn irgendwas nicht geht das kurz zu erklären.
Alles klar, mach ich gerne!
Teste gerade das neue Sketch. Kurze Frage hierzu:
void setLighting()
{
switch (aktChTime[4])
Ist damit CH4 gemeint? Wenn ja, müsste das dann nicht …
void setLighting()
{
switch (aktChTime[2])
… heißen?
Ja.
Das macht mich irre, wenn das nicht zueinander passt.
Ich werd das nochmal aufnehmen und die Channelangaben überarbeiten...
Ja, in der Tat, geht mir genau so
So, das habe ich über den Sketch von post #62 feststellen können:
CH4 Position Mitte (alle LEDs ausnahmslos aus):
- Wenn das CH6-Potentiometer neutral ist, flackern alle vier Blinker ganz schwach ungefähr im 1/2 Sekundentakt.
- Wenn CH6 nach rechts gedreht ist, leuchten alle 4 Blinker, blinken aber nicht.
- Wenn CH6 nach links gedreht ist, leuchtet nur der Blinker hinten rechts, blinkt aber nicht.
- Alle LEDs sind aus, so wie geplant. Außer die zwei Bremslichter: Pin 13 leuchtet sehr schwach beim bremsen, Pin 11 leuchtet stark beim bremsen.
CH4 Position links („Nachtkondition“):
- Backfire: Geht kurz vor Vollgas an, blinkt aber nicht mehr. Leuchtet nur ganz normal.
- Blinker und Standlicht:
- Standlicht ist an, flackert aber etwas. Die beiden hinteren Blinker flackern ganz schwach, ungefähr im 1/2 Sekundentakt.
- Wenn CH6 nach rechts gedreht ist, leuchten alle 4 Blinker auf voller Helligkeit, blinken aber nicht (zudem flackern die beiden vorderen leicht).
- Wenn CH6 nach links gedreht ist, leuchtet der Blinker hinten rechts auf voller Helligkeit, blinkt aber nicht. Die beiden vorderen Blinker bleiben beide gedimmt an und der linke blinkt nicht.
- Frontscheinwerfer leuchten nur sehr schwach, fast 0% Helligkeit. Sollte ja eigentlich auf 100% sein.
- Bremslichter: Pin 13 ist im Ruhezustand ausgeschaltet, so wie es sein soll. Allerdings leuchtet die LED auch hier nur sehr schwach (fast 0%), wenn gebremst wird. Pin 11 dagegen leuchtet gedimmt und wenn gebremst wird, leuchtet die LED auf voller Helligkeit. Top!
- Rücklicht (Pin 10): Sollte eigentlich dauerhaft gedimmt leuchten, ist aber dauerhaft ausgeschaltet.
- Rückfahrscheinwerfer (Pin 4): Leuchtet leider nicht beim Rückwärtsfahren.
- Nebelscheinwerfer: Pin 2 leuchtet hell, so wie es sein soll. Pin 3 leuchtet ebenfalls hell, aber die Helligkeit lässt sich leider nicht mit CH5 verändern.
CH4 Position rechts („Tagkondition“):
- Rückscheinwerfer leuchtet dauerhaft, egal ob ich vorwärts, rückwärts oder gar nicht Gas gebe.
- Pin 11 leuchtet nur hell, wenn gerade gebremst wird und ist ansonsten ausgeschaltet. Genau richtig! Pin 13 leuchtet leider auch hier nur ganz schwach während des Bremsvorgangs.
- Blinker und Standlicht: Gleich wie bei der Nachtkondition. Interessanterweise flackert das Standlicht besonders stark, wenn ich rückwärts Gas gebe. Wenn ich kein Gas oder vorwärts Gas gebe, flackern sie weniger.
- Backfire: Gleich wie bei der Nachtkondition.
- Front- und Nebelscheinwerfer sind ausgeschaltet, so wie es in der Tagkondition sein soll. Top
Na dann bis morgen...
Ich schau drauf, ob und wo ich evtl aktChStatus anstelle von aktChTime genommen habe
Das mit dem blinken bau ich einzeln nach.
Warum der Rfscheinwerfer nicht geht erschliesst sich nicht, schau ich drauf.
Die Frontscheinwerfer haben kein PWM. Das geht nur HIGH oder LOW.
Ist das Package evtl. schon an der Lastgrenze?
Na mal sehen. Liste ausgedruckt - Mal sehen, was ich als Simulation zusammenbekomme.
Man liest sich.
Korrekt. Komischerweise leuchten sie trotzdem nur gaaanz schwach. Irgendwie kommt nicht genug Strom bei der LED an.
Möglich, zumindest was den Strom betrifft. Insgesamt sind derzeit 13 LEDs angeschlossen. Allerdings sind natürlich nicht alle gleichzeitig eingeschaltet. Bspw. eine LED für einen Türgriff hab ich schonmal angeschlossen, die ist ja aber noch inaktiv. Und z. B. Pin 13, Rückfahrscheinwerfer und die hinteren Blinker sind ja auch die meiste Zeit aus. Also vielleicht doch noch alles im Rahmen …
Jedenfalls vielen Dank für deine Bemühen, ich weiß das wirklich sehr zu schätzen Bis morgen!
ich habs!
Pins vertauscht. rearLightPin != rueckLichtPwmPin
Damit ist dann auch klar, warum das nicht geht, wie gewollt.
Das Rückfahrscheinwerfer ist das Rücklicht
Naja.
Morgen. Schluß für heute.
Ohne CH3.
Ich hab Deiner Beschreibung entnommen:
Das Ding reagiert wie ein Schalter. Damit wird es schwerer, aber ist machbar.
Aber erstmal sehen, was geht.
Da Du mit der FrontLed gestern so gehadert hast, habe ich mal ein paar mehr Ausgaben für den Seriellen Monitor eingebaut.
Mit den CHs komm ich zurecht... Wie das gelöst ist, musst selbst rausfinden.
Und für CH3 bau ich mal was extra.
#define DEBUG
#ifdef DEBUG
#define DEBUG_P(...) Serial.print(__VA_ARGS__)
#define DEBUG_Pln(...) Serial.println(__VA_ARGS__)
#define BLINK_P(...) Serial.print(__VA_ARGS__)
#define BLINK_Pln(...) Serial.println(__VA_ARGS__)
#else
#define DEBUG_P(...)
#define DEBUG_Pln(...)
#define BLINK_P(...)
#define BLINK_Pln(...)
#endif
const byte bremsLichtPin = LED_BUILTIN;
const byte backFirePin = 12;
const byte bremsLichtPwmPin = 11;
const byte rueckLichtPwmPin = 10;
const byte griffPwmPin = 9;
const byte rechtsBlinkPin = 8;
const byte linksBlinkPin = 7;
const byte rechtsBlinkPwmPin = 6;
const byte linksBlinkPwmPin = 5;
const byte rearLightPin = 4;
const byte fogLightPwmPin = 3;
const byte fogLightPin = 2;
const byte frontLightPin = A1;
// warnblink, griff, licht, nebel
bool switchState[] = {false, false, false, false};
enum blinkCondition {links, rechts, warn, aus};
enum lightCondition {no, all, back};
byte light = lightCondition::no;
uint8_t rearLightPwm = 0; // Für Rücklicht...
const uint8_t numCh = 5;
const uint8_t chInputPin[numCh] = {A2, A3, A4, A5, A0};
const uint8_t CH2 = 0, CH3 = 1, CH4 = 2, CH5 = 3, CH6 = 4;
const char myType[numCh][12] = {"CH2 gas", "CH3 taster", "CH4 3-pos", "CH5 poti-1", "CH6 Blinker"};
volatile uint16_t aktChTime[numCh] = {0};
volatile uint16_t altChTime[numCh] = {0};
volatile bool aktChStatus[numCh] = {0};
volatile bool altChStatus[numCh] = {0};
volatile uint16_t altChInput[numCh] = {0};
uint16_t chInput[numCh] = {0};
void setup()
{
Serial.begin(115200);
delay(500);
Serial.println("\nStart ...");
randomSeed(A1);
for (byte b = 0; b < numCh; b++)
{
pinMode(chInputPin[b], INPUT);
}
const byte outPins[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, A1};
for (byte b = 0; b < sizeof(outPins); b++) // Output setzen
{
digitalWrite(b, LOW);
pinMode(b, OUTPUT);
}
PCICR |= B00000010; // Enable PCIE1 Bit2 = 1 (Port C)
PCMSK1 |= B00111101; // Enable PCINT8 (Pin A0) & PCINT10(Pin A2) & PCINT11(Pin A3) & PCINT12(Pin A4) & PCINT13(Pin A5)
}
//
void loop()
{
readSwitch();
setLighting();
backFire();
bremsLicht();
blinkLicht();
frontLicht();
rueckLicht();
backLight();
nebelLicht();
//printSerialChInput();
}
void readSwitch()
{
// Hier wird später CH3 ausgelesen
// Ist ein Schalter! 995 / 2000
// Simulation state[0]
const uint32_t switchTime = 15000;
static uint32_t lastSwitch = 0;
if (millis() - lastSwitch > switchTime)
{
lastSwitch = millis();
switchState[0] = !switchState[0];
}
}
//
void setLighting()
{
switch (aktChTime[CH4])
{
case 0 ... 1200:
light = lightCondition::all;
break;
case 1300 ... 1600:
light = lightCondition::no;
break;
case 1800 ... 2000:
light = lightCondition::back;
break;
}
#ifdef DEBUG
static byte lastState = 255;
if (lastState != light)
{
lastState = light;
Serial.print(F("Licht: "));
if (lastState == lightCondition::all)
{ Serial.println(F("Nacht")); }
else if (lastState == lightCondition::no)
{ Serial.println(F("aus")); }
else if (lastState == lightCondition::back)
{ Serial.println(F("Tag")); }
}
#endif
}
//
void backLight() // Rückfahrscheinwerfer
{
if (light == lightCondition::back) // geht nur an, wenn back aktiv
{ digitalWrite(rearLightPin, HIGH); }
else
{ digitalWrite(rearLightPin, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(rearLightPin))
{
lastState = !lastState;
Serial.print(F("Rückwärts: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
uint16_t blueLed() // verwendet von Nebelscheinwerfer
{
const uint16_t obereSchwelle = 1900;
const uint16_t untereSchwelle = 1100;
uint8_t blueLight = 0;
uint16_t temp = aktChTime[CH5];
if (temp > obereSchwelle)
{ blueLight = 255; }
else if (temp > untereSchwelle)
{ blueLight = map(temp, untereSchwelle, obereSchwelle, 0, 255); }
#ifdef DEBUG
static byte lastState = 255;
if (lastState != blueLight)
{
lastState = blueLight;
Serial.print(F("blueLed: "));
{ Serial.println(lastState);}
}
#endif
return blueLight;
}
void nebelLicht() // Nebelscheinwerfer
{
if (light == lightCondition::all) // geht nur an, wenn Nachtkondition
{
digitalWrite(fogLightPin, HIGH);
// Hier kommt noch eine Bedingung für Ch5
analogWrite(fogLightPwmPin, blueLed()); // gekoppelt an CH5
}
else
{
digitalWrite(fogLightPin, LOW);
digitalWrite(fogLightPwmPin, LOW);
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(fogLightPin))
{
lastState = !lastState;
Serial.print(F("Nebelleuchte: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void rueckLicht()
{
if (light == lightCondition::all) // nur in Nachtkondition
{ rearLightPwm = 90; }
else
{ rearLightPwm = 0; }
analogWrite(rueckLichtPwmPin, rearLightPwm);
#ifdef DEBUG
static byte lastState = 255;
if (lastState != rearLightPwm)
{
lastState = rearLightPwm;
Serial.print(F("Rücklicht: "));
Serial.println(lastState);
}
#endif
}
//
void frontLicht()
{
if (light == lightCondition::all) // nur in Nachtkondition
{ digitalWrite(frontLightPin, HIGH); }
else
{ digitalWrite(frontLightPin, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(frontLightPin))
{
lastState = !lastState;
Serial.print(F("Frontlicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void positionsLicht() // wird von blinkLicht aufgerufen
{
const uint8_t blinkLightPwm = 60;
if ((light == lightCondition::all) || // Nachts und
(light == lightCondition::back)) // Rückwärts
{
analogWrite(linksBlinkPwmPin, blinkLightPwm); // setzt Grundhelligkeit "Positionslicht"
analogWrite(rechtsBlinkPwmPin, blinkLightPwm);
}
else
{
digitalWrite(linksBlinkPwmPin, LOW);
digitalWrite(rechtsBlinkPwmPin, LOW);
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(linksBlinkPwmPin))
{
lastState = !lastState;
Serial.print(F("Positionslicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void blinken(const byte blinkRichtung, uint32_t &lastBlinkTime)
{
const uint32_t blinkTime = 500;
if (millis() - lastBlinkTime > blinkTime)
{
lastBlinkTime = millis();
switch (blinkRichtung)
{
case blinkCondition::rechts: // wenn rechts
digitalWrite(rechtsBlinkPin, !digitalRead(linksBlinkPin));
digitalWrite(linksBlinkPin, LOW); // sicherstellen, das aus, wenn aus warn zurück
BLINK_Pln(F("rechts"));
break;
case blinkCondition::warn:
BLINK_Pln(F("warn"));
[[fallthrough]];
case blinkCondition::links:/* fall trough */
digitalWrite(linksBlinkPin, !digitalRead(linksBlinkPin));
digitalWrite(rechtsBlinkPin, LOW);
BLINK_Pln(F("links"));
break;
}
}
if (blinkRichtung == blinkCondition::warn) // sicherstellen, das rechts == links wird
{ digitalWrite(rechtsBlinkPin, digitalRead(linksBlinkPin)); }
digitalRead(linksBlinkPin) ? // Front an Heck angleichen
digitalWrite(linksBlinkPwmPin, HIGH) :
digitalWrite(linksBlinkPwmPin, LOW);
digitalRead(rechtsBlinkPin) ?
digitalWrite(rechtsBlinkPwmPin, HIGH) :
digitalWrite(rechtsBlinkPwmPin, LOW);
}
//
void blinkLicht()
{
static byte zustand = blinkCondition::aus;
static uint32_t lastBlinkTime = 0;
// aktChTime[CH6] = 1500;
if (switchState[0]) // Warnblink ein?
{ zustand = blinkCondition::warn; } // hat immer Vorfahrt
switch (zustand)
{
case blinkCondition::links:
blinken(blinkCondition::links, lastBlinkTime);
if (aktChTime[CH6] < 1600)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::rechts:
blinken (blinkCondition::rechts, lastBlinkTime);
if (aktChTime[CH6] > 1400)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::warn:
blinken(blinkCondition::warn, lastBlinkTime);
{zustand = blinkCondition::aus;}
break;
case blinkCondition::aus:
positionsLicht();
digitalWrite(linksBlinkPin, LOW);
digitalWrite(rechtsBlinkPin, LOW);
if (aktChTime[CH6] > 1700)
{
zustand = blinkCondition::links;
digitalWrite(linksBlinkPin, HIGH);
lastBlinkTime = millis();
DEBUG_Pln(F("Blink aus"));
}
else if (aktChTime[CH6] < 1300)
{
zustand = blinkCondition::rechts;
digitalWrite(rechtsBlinkPin, HIGH);
lastBlinkTime = millis();
}
break;
}
}
//
void backFire()
{
if (light == lightCondition::no) // kein Licht
{
digitalWrite(backFirePin, LOW); // verhindert, das das an bleibt
return; // Funktionsabbruch
}
const uint16_t minSpeed = 1880; // SpeedWert ab wann ausgelöst
static uint32_t blinkTime = 0; // Zeitmerker
static uint32_t lastFireTime = 0; // Letzter Umschaltvorgang LED
if (aktChTime[CH2] > minSpeed) // Schnell genug
{
if (millis() - lastFireTime > blinkTime) // Umschaltzeit erreicht
{
digitalWrite(backFirePin, !digitalRead(backFirePin)); // Toggel
blinkTime = random(30, 100); // neue Zufallszeit
if (!digitalRead(backFirePin)) // Pin ist aus?...
{ blinkTime *= 3; } // ... Auszeit verlängern
DEBUG_Pln(F("BackFire"));
}
lastFireTime = millis(); // umschaltzeit merken
}
else // Geschwindkeit nicht erreicht
{ digitalWrite(backFirePin, LOW); }
}
//
void bremsLicht()
{
enum condition {forward, neutral, backward}; //
static byte myState = condition::neutral;
static uint32_t lastForwardTime = 0; // Zeitmerker
const uint32_t reaktionsZeit = 200; // Zeit in ms... Das muss getestet werden
const uint16_t neutralSpeed = 1490; // Hier ist nüscht
const uint8_t hysterese = 200; // Pendel der Neutralstellung +/-
switch (myState)
{
case condition::forward:
if (aktChTime[CH2] < neutralSpeed + hysterese) // Neutralbereich erreicht?
{
myState = condition::neutral; // Zustand setzen
lastForwardTime = millis(); // Zeit merken
}
if (aktChTime[CH2] < neutralSpeed - hysterese) // Neutralbereich unterschritten?
{ myState = condition::backward; } // direkt Zustand wechseln
break;
case condition::neutral:
if (aktChTime[CH2] < neutralSpeed - hysterese) // Neutralbereich rückwärts verlassen?
{ myState = condition::backward; }
else if (aktChTime[CH2] > neutralSpeed + hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::forward; }
digitalWrite(bremsLichtPin, LOW); // Bremse deaktivieren
if (lightCondition::all) // Ch4 - ALL
{ analogWrite(bremsLichtPwmPin, rearLightPwm); } // Grundhelligkeit setzen
else
{ digitalWrite(bremsLichtPwmPin, LOW); } // oder ganz aus
break;
case condition::backward:
if (millis() - lastForwardTime < reaktionsZeit) // Zeit nicht abgelaufen ...
{
digitalWrite(bremsLichtPin, HIGH); // ... Bremse aktiviert!
digitalWrite(bremsLichtPwmPin, HIGH);
}
if (aktChTime[CH2] > neutralSpeed - hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::neutral; } // Zustand setzen
break;
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(bremsLichtPin))
{
lastState = !lastState;
Serial.print(F("Bremslicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void printSerialChInput()
{
for (byte b = 0; b < numCh; b++)
{
if (abs(int(altChTime[b] - aktChTime[b])) > 10)
{
DEBUG_P(myType[b]);
DEBUG_P(": ");
DEBUG_P(aktChTime[b]);
DEBUG_Pln('\t');
altChTime[b] = aktChTime[b];
}
}
}
//
ISR (PCINT1_vect) // Port C Interrupt occured
{
for (byte b = 0; b < numCh; b++)
{
aktChStatus[b] = digitalRead(chInputPin[b]);
if (altChStatus[b] != aktChStatus[b])
{
altChStatus[b] = aktChStatus[b];
if (aktChStatus[b])
{ altChInput[b] = micros(); }
else
{ aktChTime[b] = micros() - altChInput[b]; }
}
}
}
Und wenn es Dir gelungen ist den Sketch oben einmal durchzuspeilen, will ich mal wissen, ob das zählen auf dem CH3 geht.
Die Zeit für den Zähler mal versuchsweise anpassen, je nachdem wie schnell Du am drücken sein kannst. Auf dem SerMon beobachten, ob das tut, was vorgestellt ist.
// Forensketch - austesten Controller CH3 als AuswahlSchalter
bool warnState, griffState, posLightState, backFireState, fogLightState = false;
const uint8_t numCh = 5;
const uint8_t chInputPin[numCh] = {A2, A3, A4, A5, A0};
const uint8_t CH2 = 0, CH3 = 1, CH4 = 2, CH5 = 3, CH6 = 4;
volatile uint16_t aktChTime[numCh] = {0};
volatile uint16_t altChTime[numCh] = {0};
volatile bool aktChStatus[numCh] = {0};
volatile bool altChStatus[numCh] = {0};
volatile uint16_t altChInput[numCh] = {0};
void setup()
{
Serial.begin(115200);
Serial.println(F("Start..."));
for (byte b = 0; b < numCh; b++)
{
pinMode(chInputPin[b], INPUT);
}
PCICR |= B00000010; // Enable PCIE1 Bit2 = 1 (Port C)
PCMSK1 |= B00111101; // Enable PCINT8 (Pin A0) & PCINT10(Pin A2) & PCINT11(Pin A3) & PCINT12(Pin A4) & PCINT13(Pin A5)
}
void loop()
{
const uint32_t timeOut = 200; // Die Zeit soweit wie möglich verringern.
static uint32_t startTime = 0;
static bool lastState = false;
static byte counter = 0;
bool state = LOW;
if (aktChTime[CH3] > 1600)
{ state = HIGH;}
if (state != lastState)
{
startTime = millis();
counter++;
}
if (millis() - startTime > timeOut)
{
switch (counter)
{
case 1:
warnState = !warnState;
Serial.print(F("Warnstate: "));
Serial.println(warnState ? "ein" : "aus");
break;
case 2:
griffState = !griffState;
Serial.print(F("Griffstate: "));
Serial.println(griffState ? "ein" : "aus");
break;
case 3:
posLightState = !posLightState;
Serial.print(F("Positionstate: "));
Serial.println(posLightState ? "ein" : "aus");
break;
case 4:
backFireState = ! backFireState;
Serial.print(F("Backfirestate: "));
Serial.println(backFireState ? "ein" : "aus");
break;
case 5:
fogLightState = !fogLightState;
Serial.print(F("Nebelstate: "));
Serial.println(fogLightState ? "ein" : "aus");
}
counter = 0;
}
}
//
ISR (PCINT1_vect) // Port C Interrupt occured
{
for (byte b = 0; b < numCh; b++)
{
aktChStatus[b] = digitalRead(chInputPin[b]);
if (altChStatus[b] != aktChStatus[b])
{
altChStatus[b] = aktChStatus[b];
if (aktChStatus[b])
{ altChInput[b] = micros(); }
else
{ aktChTime[b] = micros() - altChInput[b]; }
}
}
}
Post #70 Sketch habe ich ausprobiert.
Mir ist aufgefallen, dass die Blinker falsch herum waren: Wenn ich CH6 nach rechts gedreht habe, haben die linken Blinker geleuchtet und andersherum. Hier der korrigierte Code (habe einfach überfall bei void blinken() und void blinkLicht() links und rechts vertauscht):
#define DEBUG
#ifdef DEBUG
#define DEBUG_P(...) Serial.print(__VA_ARGS__)
#define DEBUG_Pln(...) Serial.println(__VA_ARGS__)
#define BLINK_P(...) Serial.print(__VA_ARGS__)
#define BLINK_Pln(...) Serial.println(__VA_ARGS__)
#else
#define DEBUG_P(...)
#define DEBUG_Pln(...)
#define BLINK_P(...)
#define BLINK_Pln(...)
#endif
const byte bremsLichtPin = LED_BUILTIN; // drittes Bremslicht
const byte backFirePin = 12; // Backfire
const byte bremsLichtPwmPin = 11; // Brems- und Rücklicht (PWM)
const byte rueckLichtPwmPin = 10; // Rücklicht (PWM)
const byte griffPwmPin = 9; // Türgriff-Beleuchtung (PWM)
const byte linksBlinkPin = 8; // Blinker hinten links
const byte rechtsBlinkPin = 7; // Blinker hinten rechts
const byte linksBlinkPwmPin = 6; // Blinker vorne links
const byte rechtsBlinkPwmPin = 5; // Blinker vorne rechts
const byte rearLightPin = 4; // Rückfahrscheinwerfer
const byte fogLightPwmPin = 3; // RGB Nebelscheinwerfer blau (PWM)
const byte fogLightPin = 2; // RGB Nebelscheinwerfer rot&grün
const byte frontLightPin = A1; // Frontscheinwerfer
// warnblink, griff, licht, nebel
bool switchState[] = {false, false, false, false};
enum blinkCondition {links, rechts, warn, aus};
enum lightCondition {no, all, back};
byte light = lightCondition::no;
uint8_t rearLightPwm = 0; // Für Rücklicht...
const uint8_t numCh = 5;
const uint8_t chInputPin[numCh] = {A2, A3, A4, A5, A0};
const uint8_t CH2 = 0, CH3 = 1, CH4 = 2, CH5 = 3, CH6 = 4;
const char myType[numCh][12] = {"CH2 gas", "CH3 taster", "CH4 3-pos", "CH5 poti-1", "CH6 Blinker"};
volatile uint16_t aktChTime[numCh] = {0};
volatile uint16_t altChTime[numCh] = {0};
volatile bool aktChStatus[numCh] = {0};
volatile bool altChStatus[numCh] = {0};
volatile uint16_t altChInput[numCh] = {0};
uint16_t chInput[numCh] = {0};
void setup()
{
Serial.begin(115200);
delay(500);
Serial.println("\nStart ...");
randomSeed(A1);
for (byte b = 0; b < numCh; b++)
{
pinMode(chInputPin[b], INPUT);
}
const byte outPins[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, A1};
for (byte b = 0; b < sizeof(outPins); b++) // Output setzen
{
digitalWrite(b, LOW);
pinMode(b, OUTPUT);
}
PCICR |= B00000010; // Enable PCIE1 Bit2 = 1 (Port C)
PCMSK1 |= B00111101; // Enable PCINT8 (Pin A0) & PCINT10(Pin A2) & PCINT11(Pin A3) & PCINT12(Pin A4) & PCINT13(Pin A5)
}
//
void loop()
{
readSwitch();
setLighting();
backFire();
bremsLicht();
blinkLicht();
frontLicht();
rueckLicht();
backLight();
nebelLicht();
//printSerialChInput();
}
void readSwitch()
{
// Hier wird später CH3 ausgelesen
// Ist ein Schalter! 995 / 2000
// Simulation state[0]
const uint32_t switchTime = 15000;
static uint32_t lastSwitch = 0;
if (millis() - lastSwitch > switchTime)
{
lastSwitch = millis();
switchState[0] = !switchState[0];
}
}
//
void setLighting()
{
switch (aktChTime[CH4])
{
case 0 ... 1200:
light = lightCondition::all;
break;
case 1300 ... 1600:
light = lightCondition::no;
break;
case 1800 ... 2000:
light = lightCondition::back;
break;
}
#ifdef DEBUG
static byte lastState = 255;
if (lastState != light)
{
lastState = light;
Serial.print(F("Licht: "));
if (lastState == lightCondition::all)
{ Serial.println(F("Nacht")); }
else if (lastState == lightCondition::no)
{ Serial.println(F("aus")); }
else if (lastState == lightCondition::back)
{ Serial.println(F("Tag")); }
}
#endif
}
//
void backLight() // Rückfahrscheinwerfer
{
if (light == lightCondition::back) // geht nur an, wenn back aktiv
{ digitalWrite(rearLightPin, HIGH); }
else
{ digitalWrite(rearLightPin, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(rearLightPin))
{
lastState = !lastState;
Serial.print(F("Rückwärts: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
uint16_t blueLed() // verwendet von Nebelscheinwerfer
{
const uint16_t obereSchwelle = 1900;
const uint16_t untereSchwelle = 1100;
uint8_t blueLight = 0;
uint16_t temp = aktChTime[CH5];
if (temp > obereSchwelle)
{ blueLight = 255; }
else if (temp > untereSchwelle)
{ blueLight = map(temp, untereSchwelle, obereSchwelle, 0, 255); }
#ifdef DEBUG
static byte lastState = 255;
if (lastState != blueLight)
{
lastState = blueLight;
Serial.print(F("blueLed: "));
{ Serial.println(lastState);}
}
#endif
return blueLight;
}
void nebelLicht() // Nebelscheinwerfer
{
if (light == lightCondition::all) // geht nur an, wenn Nachtkondition
{
digitalWrite(fogLightPin, HIGH);
// Hier kommt noch eine Bedingung für Ch5
analogWrite(fogLightPwmPin, blueLed()); // gekoppelt an CH5
}
else
{
digitalWrite(fogLightPin, LOW);
digitalWrite(fogLightPwmPin, LOW);
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(fogLightPin))
{
lastState = !lastState;
Serial.print(F("Nebelleuchte: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void rueckLicht()
{
if (light == lightCondition::all) // nur in Nachtkondition
{ rearLightPwm = 90; }
else
{ rearLightPwm = 0; }
analogWrite(rueckLichtPwmPin, rearLightPwm);
#ifdef DEBUG
static byte lastState = 255;
if (lastState != rearLightPwm)
{
lastState = rearLightPwm;
Serial.print(F("Rücklicht: "));
Serial.println(lastState);
}
#endif
}
//
void frontLicht()
{
if (light == lightCondition::all) // nur in Nachtkondition
{ digitalWrite(frontLightPin, HIGH); }
else
{ digitalWrite(frontLightPin, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(frontLightPin))
{
lastState = !lastState;
Serial.print(F("Frontlicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void positionsLicht() // wird von blinkLicht aufgerufen
{
const uint8_t blinkLightPwm = 60;
if ((light == lightCondition::all) || // Nachts und
(light == lightCondition::back)) // Rückwärts
{
analogWrite(linksBlinkPwmPin, blinkLightPwm); // setzt Grundhelligkeit "Positionslicht"
analogWrite(rechtsBlinkPwmPin, blinkLightPwm);
}
else
{
digitalWrite(linksBlinkPwmPin, LOW);
digitalWrite(rechtsBlinkPwmPin, LOW);
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(linksBlinkPwmPin))
{
lastState = !lastState;
Serial.print(F("Positionslicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void blinken(const byte blinkRichtung, uint32_t &lastBlinkTime)
{
const uint32_t blinkTime = 500;
if (millis() - lastBlinkTime > blinkTime)
{
lastBlinkTime = millis();
switch (blinkRichtung)
{
case blinkCondition::links:
digitalWrite(linksBlinkPin, !digitalRead(rechtsBlinkPin));
digitalWrite(rechtsBlinkPin, LOW); // sicherstellen, das aus, wenn aus warn zurück
BLINK_Pln(F("links"));
break;
case blinkCondition::warn:
BLINK_Pln(F("warn"));
[[fallthrough]];
case blinkCondition::rechts:/* fall trough */
digitalWrite(rechtsBlinkPin, !digitalRead(rechtsBlinkPin));
digitalWrite(linksBlinkPin, LOW);
BLINK_Pln(F("rechts"));
break;
}
}
if (blinkRichtung == blinkCondition::warn) // sicherstellen, das rechts == links wird
{ digitalWrite(linksBlinkPin, digitalRead(rechtsBlinkPin)); }
digitalRead(rechtsBlinkPin) ? // Front an Heck angleichen
digitalWrite(rechtsBlinkPwmPin, HIGH) :
digitalWrite(rechtsBlinkPwmPin, LOW);
digitalRead(linksBlinkPin) ?
digitalWrite(linksBlinkPwmPin, HIGH) :
digitalWrite(linksBlinkPwmPin, LOW);
}
//
void blinkLicht()
{
static byte zustand = blinkCondition::aus;
static uint32_t lastBlinkTime = 0;
// aktChTime[CH6] = 1500;
if (switchState[0]) // Warnblink ein?
{ zustand = blinkCondition::warn; } // hat immer Vorfahrt
switch (zustand)
{
case blinkCondition::rechts:
blinken(blinkCondition::rechts, lastBlinkTime);
if (aktChTime[CH6] < 1600)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::links:
blinken (blinkCondition::links, lastBlinkTime);
if (aktChTime[CH6] > 1400)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::warn:
blinken(blinkCondition::warn, lastBlinkTime);
{zustand = blinkCondition::aus;}
break;
case blinkCondition::aus:
positionsLicht();
digitalWrite(rechtsBlinkPin, LOW);
digitalWrite(linksBlinkPin, LOW);
if (aktChTime[CH6] > 1700)
{
zustand = blinkCondition::rechts;
digitalWrite(rechtsBlinkPin, HIGH);
lastBlinkTime = millis();
DEBUG_Pln(F("Blink aus"));
}
else if (aktChTime[CH6] < 1300)
{
zustand = blinkCondition::links;
digitalWrite(linksBlinkPin, HIGH);
lastBlinkTime = millis();
}
break;
}
}
//
void backFire()
{
if (light == lightCondition::no) // kein Licht
{
digitalWrite(backFirePin, LOW); // verhindert, das das an bleibt
return; // Funktionsabbruch
}
const uint16_t minSpeed = 1880; // SpeedWert ab wann ausgelöst
static uint32_t blinkTime = 0; // Zeitmerker
static uint32_t lastFireTime = 0; // Letzter Umschaltvorgang LED
if (aktChTime[CH2] > minSpeed) // Schnell genug
{
if (millis() - lastFireTime > blinkTime) // Umschaltzeit erreicht
{
digitalWrite(backFirePin, !digitalRead(backFirePin)); // Toggel
blinkTime = random(30, 100); // neue Zufallszeit
if (!digitalRead(backFirePin)) // Pin ist aus?...
{ blinkTime *= 3; } // ... Auszeit verlängern
DEBUG_Pln(F("BackFire"));
}
lastFireTime = millis(); // umschaltzeit merken
}
else // Geschwindkeit nicht erreicht
{ digitalWrite(backFirePin, LOW); }
}
//
void bremsLicht()
{
enum condition {forward, neutral, backward}; //
static byte myState = condition::neutral;
static uint32_t lastForwardTime = 0; // Zeitmerker
const uint32_t reaktionsZeit = 200; // Zeit in ms... Das muss getestet werden
const uint16_t neutralSpeed = 1490; // Hier ist nüscht
const uint8_t hysterese = 200; // Pendel der Neutralstellung +/-
switch (myState)
{
case condition::forward:
if (aktChTime[CH2] < neutralSpeed + hysterese) // Neutralbereich erreicht?
{
myState = condition::neutral; // Zustand setzen
lastForwardTime = millis(); // Zeit merken
}
if (aktChTime[CH2] < neutralSpeed - hysterese) // Neutralbereich unterschritten?
{ myState = condition::backward; } // direkt Zustand wechseln
break;
case condition::neutral:
if (aktChTime[CH2] < neutralSpeed - hysterese) // Neutralbereich rückwärts verlassen?
{ myState = condition::backward; }
else if (aktChTime[CH2] > neutralSpeed + hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::forward; }
digitalWrite(bremsLichtPin, LOW); // Bremse deaktivieren
if (lightCondition::all) // Ch4 - ALL
{ analogWrite(bremsLichtPwmPin, rearLightPwm); } // Grundhelligkeit setzen
else
{ digitalWrite(bremsLichtPwmPin, LOW); } // oder ganz aus
break;
case condition::backward:
if (millis() - lastForwardTime < reaktionsZeit) // Zeit nicht abgelaufen ...
{
digitalWrite(bremsLichtPin, HIGH); // ... Bremse aktiviert!
digitalWrite(bremsLichtPwmPin, HIGH);
}
if (aktChTime[CH2] > neutralSpeed - hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::neutral; } // Zustand setzen
break;
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(bremsLichtPin))
{
lastState = !lastState;
Serial.print(F("Bremslicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void printSerialChInput()
{
for (byte b = 0; b < numCh; b++)
{
if (abs(int(altChTime[b] - aktChTime[b])) > 10)
{
DEBUG_P(myType[b]);
DEBUG_P(": ");
DEBUG_P(aktChTime[b]);
DEBUG_Pln('\t');
altChTime[b] = aktChTime[b];
}
}
}
//
ISR (PCINT1_vect) // Port C Interrupt occured
{
for (byte b = 0; b < numCh; b++)
{
aktChStatus[b] = digitalRead(chInputPin[b]);
if (altChStatus[b] != aktChStatus[b])
{
altChStatus[b] = aktChStatus[b];
if (aktChStatus[b])
{ altChInput[b] = micros(); }
else
{ aktChTime[b] = micros() - altChInput[b]; }
}
}
}
Zudem habe ich die vier Blinker Pins vertauscht, mein neues Schematic sieht also so aus:
Meine Beobachtungen:
CH4 Position Mitte (alle LEDs ausnahmslos aus):
- Die Bremslichter gehen nach wie vor noch beim Bremsen an: Pin 13 sehr schwach, Pin 11 stark. Eigentlich sollten die ja auch komplett inaktiv sein.
- Die Blinker können über CH6 auch in diesem CH4-Modus eingeschaltet werden. Sollte eigentlich nicht möglich sein, da alle LEDs ausnahmslos aus sein sollten.
- GUT: Die Blinker flackern nicht mehr.
- Ansonsten alles bestens: Alle anderen LEDs sind ausgeschaltet.
CH4 Position links (Nachtkondition):
- Blinker und Standlicht:
- Das linke Standlicht flackert ziemlich stark, das rechte sieht aber super aus.
- GUT: CH6-Potentiometer nach rechts drehen = beide rechte Blinker gehen an und blinken.
- CH6-Potentiometer nach links drehen = beide linke Blinker gehen an, blinken aber nicht.
- Backfire: Hier hat sich nichts verändert: Es springt kurz vor Vollgas an, blinkt aber nicht.
- Frontscheinwerfer: Dauerhaft eingeschaltet, so wie es sein soll. Leider immer noch nahezu 0% Helligkeit.
- Rückfahrscheinwerfer leider dauerhaft ausgeschaltet. Wenn ich rückwärts fahre, tut sich nichts.
- Brems- und Rücklichter:
- Pin 13: Wenn nicht gebremst wird, ist die LED ausgeschaltet, das ist gut so. Beim bremsen leuchtet es aber fast gar nicht, Helligkeit immer noch nahezu 0%.
- Pin 11: Perfekt: Leuchtet gedimmt und beim Bremsen 100%.
- Pin 10: Ebenfalls perfekt: Leuchtet dauerhaft gedimmt.
- Nebelscheinwerfer: Einwandfrei: Pin 2 leuchtet ununterbrochen 100%, die Helligkeit von Pin 3 kann mit CH5 verändert werden.
CH4 Position rechts (Tagkondition):
- Rückfahrscheinwerfer: Leider dauerhaft eingeschaltet, egal ob ich kein Gas, vorwärts oder rückwärts Gas gebe.
- Bremslicht:
- Pin 13 hat auch hier beim Bremsen kaum Helligkeit.
- Pin 11 ist perfekt.
- Backfire: Gleiches Problem wie bei der Nachtkondition
- Blinker: Gleich wie bei der Nachtkondition.
- Front- und Nebelscheinwerfer sowie Rückleuchte alle ausgeschaltet. Top
Egal auf welcher Position CH4 war, die Warnblinkanlage ist immer wieder unerwartet angesprungen, ohne dass ich irgendetwas gemacht habe. Aber die ist ja auch noch nicht fertig, CH3 war in diesem Sketch ja noch nicht an Bord.
Alles klar, das probiere ich mal aus, danke
Du erinnerst Dich?
es hat funktioniert.
Ne, das ist Mist.
Damit ist die Logik kaputt.
Richtig wäre:
case blinkCondition::aus:
positionsLicht();
digitalWrite(linksBlinkPin, LOW);
digitalWrite(rechtsBlinkPin, LOW);
if (aktChTime[CH6] > 1700)
{
zustand = blinkCondition::links;
digitalWrite(linksBlinkPin, HIGH);
lastBlinkTime = millis();
DEBUG_Pln(F("Blink aus"));
}
else if (aktChTime[CH6] < 1300)
{
zustand = blinkCondition::rechts;
digitalWrite(rechtsBlinkPin, HIGH);
lastBlinkTime = millis();
}
break;
die beiden Richtungswerte zu tauschen.
Neu:
case blinkCondition::aus:
positionsLicht();
digitalWrite(linksBlinkPin, LOW);
digitalWrite(rechtsBlinkPin, LOW);
if (aktChTime[CH6] < 1300)
{
zustand = blinkCondition::links;
digitalWrite(linksBlinkPin, HIGH);
lastBlinkTime = millis();
DEBUG_Pln(F("Blink aus"));
}
else if (aktChTime[CH6] > 1700)
{
zustand = blinkCondition::rechts;
digitalWrite(rechtsBlinkPin, HIGH);
lastBlinkTime = millis();
}
break;
Und für den Rest schreib ich mir nachher was, um mir die Ausgaben anzusehen.
Na denne.
Beim CH3 Sketch hat sich jetzt bei mir nichts getan. Auf dem Serial Monitor zeigt nur einmal am Anfang „Start…“ an. Wenn ich CH3 drücke, passiert leider nichts.
Ahh okay, deswegen also

Wenn ich CH3 drücke, passiert leider nichts.
Ach:
änder mal:
if (state != lastState)
{
startTime = millis();
lastState = state; // <--- Das hier fehlte
counter++;
}
Wenn ich 1900 vorgebe, dann zählt er auf. Also die Logik ist richtig.

Ne, das ist Mist.
Damit ist die Logik kaputt.
Ups

Neu:
Habe das grad eingefügt und zusätzlich die Blinker Pins vertauscht. Jetzt ist …
- Pin 8 = Blinker hinten links
- Pin 7 = Blinker hinten rechts
- Pin 6 = Blinker vorne links
- Pin 5 = Blinker vorne rechts
CH4 Position Mitte:
Nun hat die Richtung gestimmt, allerdings blinken jetzt beide Seiten nicht mehr, sondern leuchten einfach nur. Der linke vordere Blinker leuchtet jetzt beim Blinken zudem schwächer als der hintere linke.
Bei CH4 Position links und CH4 Position rechts:
Auch hier blinken beide Seiten nicht mehr. Das linke Standlicht flackert, wenn CH6 neutral oder nach links ist. Ist CH6 nach rechts gedreht, flackert das linke Standlicht immer noch und der rechte Blinker flackert auch etwas, aber weniger stark als das linke Standlicht.
Das alles zu beobachten dauert übrigens ziemlich lange, weil mir immer wieder der Gag dazwischen grätscht und ich warten muss, bis die Warnblinkanlage wieder aus geht

änder mal:
Jetzt hat es funktioniert
Das hat der Serial Monitor angezeigt:
- Start...
- Warnstate: ein (1× drücken)
- Warnstate: aus (1× drücken)
- Griffstate: ein (2× drücken)
- Griffstate: aus (2× drücken)
- Positionstate: ein (3× drücken)
- Positionstate: aus (3× drücken)
- Backfirestate: ein (4× drücken)
- Backfirestate: aus (4× drücken)
- Nebelstate: ein (5× drücken)
- Nebelstate: aus (5× drücken)
const uint32_t timeOut = 300; // Die Zeit soweit wie möglich verringern.
Habe es auf 300 erhöht, 200 war eher zu wenig.

Jetzt hat es funktioniert
Na dann habe ich eine Grundlage

weil mir immer wieder der Gag dazwischen grätscht
Einfach auskommentieren:
void loop()
{
// readSwitch();
Rest schau ich drauf.

Habe es auf 300 erhöht, 200 war eher zu wenig.
Und ich habs mal mit übernommen.
Nur nochmal zum Verständnis... Das wäre meine Matrix für Ch4
Type | PIN | Tag | Nacht | aus |
---|---|---|---|---|
Frontlicht | A1 | inaktiv | aktiv | inaktiv |
Nebel | 2 | aktiv | aktiv | inaktiv |
Nebel PWM | 3 | inaktiv | aktiv | inaktiv |
Rückfahr | 4 | inaktiv | aktiv | inaktiv |
Blinker PWM | 5, 6 | aktiv | aktiv | inaktiv |
Blinker | 7, 8 | aktiv | aktiv | inaktiv |
Grifflicht | 9 | inaktiv | aktiv | inaktiv |
Rücklicht PWM | 10 | inaktiv | aktiv | inaktiv |
Bremse PWM | 11 | inaktiv | aktiv | inaktiv |
Backfire | 12 | aktiv | aktiv | inaktiv |
Bremslicht | 13 | aktiv | aktiv | inaktiv |
Und nur wenn CH4 aktiv, kommt CH3 zur Anwendung.
Erster Vorschlag. (Und es blinkt auch wieder)
[EDIT: Grifflicht vervollständigt]
#define DEBUG
#ifdef DEBUG
#define DEBUG_P(...) Serial.print(__VA_ARGS__)
#define DEBUG_Pln(...) Serial.println(__VA_ARGS__)
#define BLINK_P(...) Serial.print(__VA_ARGS__)
#define BLINK_Pln(...) Serial.println(__VA_ARGS__)
#else
#define DEBUG_P(...)
#define DEBUG_Pln(...)
#define BLINK_P(...)
#define BLINK_Pln(...)
#endif
const byte bremsLichtPin = LED_BUILTIN;
const byte backFirePin = 12;
const byte bremsLichtPwmPin = 11;
const byte rueckLichtPwmPin = 10;
const byte griffPwmPin = 9;
const byte rechtsBlinkPin = 7;
const byte linksBlinkPin = 8;
const byte rechtsBlinkPwmPin = 5;
const byte linksBlinkPwmPin = 6;
const byte rearLightPin = 4;
const byte fogLightPwmPin = 3;
const byte fogLightPin = 2;
const byte frontLightPin = A1;
bool warnState, griffState, posLightState, backFireState, fogLightState = false;
enum blinkCondition {links, rechts, warn, aus};
enum lightCondition {no, nacht, tag};
byte light = lightCondition::no;
uint8_t rearLightPwm = 0; // Für Rücklicht...
const uint8_t numCh = 5;
const uint8_t chInputPin[numCh] = {A2, A3, A4, A5, A0};
const uint8_t CH2 = 0, CH3 = 1, CH4 = 2, CH5 = 3, CH6 = 4;
const char myType[numCh][12] = {"CH2 gas", "CH3 taster", "CH4 3-pos", "CH5 poti-1", "CH6 Blinker"};
volatile uint16_t aktChTime[numCh] = {0};
volatile uint16_t altChTime[numCh] = {0};
volatile bool aktChStatus[numCh] = {0};
volatile bool altChStatus[numCh] = {0};
volatile uint16_t altChInput[numCh] = {0};
uint16_t chInput[numCh] = {0};
void setup()
{
Serial.begin(115200);
delay(500);
Serial.println("\nStart ...");
randomSeed(A1);
for (byte b = 0; b < numCh; b++)
{
pinMode(chInputPin[b], INPUT);
}
const byte outPins[] = {13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, A1};
for (byte b = 0; b < sizeof(outPins); b++) // Output setzen
{
digitalWrite(b, LOW);
pinMode(b, OUTPUT);
}
PCICR |= B00000010; // Enable PCIE1 Bit2 = 1 (Port C)
PCMSK1 |= B00111101; // Enable PCINT8 (Pin A0) & PCINT10(Pin A2) & PCINT11(Pin A3) & PCINT12(Pin A4) & PCINT13(Pin A5)
}
//
void loop()
{
readSwitch();
setLighting();
backFire();
bremsLicht();
blinkLicht();
frontLicht();
rueckLicht();
backLight();
nebelLicht();
griffLicht();
//printSerialChInput();
}
void readSwitch()
{
const uint32_t timeOut = 300; // Die Zeit soweit wie möglich verringern.
static uint32_t startTime = 0;
static bool lastState = false;
static byte counter = 0;
bool state = LOW;
if (aktChTime[CH3] > 1600)
{ state = HIGH;}
if (state != lastState)
{
startTime = millis();
lastState = state;
counter++;
}
if (millis() - startTime > timeOut)
{
switch (counter)
{
case 1:
warnState = !warnState;
DEBUG_P(F("Warnstate: "));
DEBUG_Pln(warnState ? "ein" : "aus");
break;
case 2:
griffState = !griffState;
DEBUG_P(F("Griffstate: "));
DEBUG_Pln(griffState ? "ein" : "aus");
break;
case 3:
posLightState = !posLightState;
DEBUG_P(F("Positionstate: "));
DEBUG_Pln(posLightState ? "ein" : "aus");
break;
case 4:
backFireState = ! backFireState;
DEBUG_P(F("Backfirestate: "));
DEBUG_Pln(backFireState ? "ein" : "aus");
break;
case 5:
fogLightState = !fogLightState;
DEBUG_P(F("Nebelstate: "));
DEBUG_Pln(fogLightState ? "ein" : "aus");
}
counter = 0;
}
}
//
void setLighting()
{
switch (aktChTime[CH4])
{
case 0 ... 1200:
light = lightCondition::nacht;
break;
case 1300 ... 1600:
light = lightCondition::no;
break;
case 1800 ... 2000:
light = lightCondition::tag;
break;
}
#ifdef DEBUG
static byte lastState = 255;
if (lastState != light)
{
lastState = light;
Serial.print(F("Licht: "));
if (lastState == lightCondition::nacht)
{ Serial.println(F("Nacht")); }
else if (lastState == lightCondition::no)
{ Serial.println(F("aus")); }
else if (lastState == lightCondition::tag)
{ Serial.println(F("Tag")); }
}
#endif
}
//
void griffLicht()
{
if (light == lightCondition::nacht && griffState)
{ digitalWrite(griffPwmPin, HIGH); }
else
{ digitalWrite(griffPwmPin, LOW); }
}
//
void backLight() // Rückfahrscheinwerfer
{
if (light == lightCondition::nacht) // geht nur an, wenn back aktiv
{ digitalWrite(rearLightPin, HIGH); }
else
{ digitalWrite(rearLightPin, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(rearLightPin))
{
lastState = !lastState;
Serial.print(F("Rückwärts: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
uint16_t blueLed() // verwendet von Nebelscheinwerfer
{
const uint16_t obereSchwelle = 1900;
const uint16_t untereSchwelle = 1100;
uint8_t blueLight = 0;
uint16_t temp = aktChTime[CH5];
if (temp > obereSchwelle)
{ blueLight = 255; }
else if (temp > untereSchwelle)
{ blueLight = map(temp, untereSchwelle, obereSchwelle, 0, 255); }
if (light != lightCondition::nacht) // Wenn nicht Nacht
{blueLight = 0;} // keine Farbänderung!
#ifdef DEBUG
static byte lastState = 255;
if (lastState != blueLight)
{
lastState = blueLight;
Serial.print(F("blueLed: "));
{ Serial.println(lastState);}
}
#endif
return blueLight;
}
void nebelLicht() // Nebelscheinwerfer
{
if (light != lightCondition::no && fogLightState) // geht am Tag und in der Nacht
{
digitalWrite(fogLightPin, HIGH);
analogWrite(fogLightPwmPin, blueLed()); // gekoppelt an CH5
}
else
{
digitalWrite(fogLightPin, LOW);
digitalWrite(fogLightPwmPin, LOW);
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(fogLightPin))
{
lastState = !lastState;
Serial.print(F("Nebelleuchte: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void rueckLicht()
{
if (light == lightCondition::nacht) // nur in Nachtkondition
{ rearLightPwm = 90; }
else
{ rearLightPwm = 0; }
analogWrite(rueckLichtPwmPin, rearLightPwm);
#ifdef DEBUG
static byte lastState = 255;
if (lastState != rearLightPwm)
{
lastState = rearLightPwm;
Serial.print(F("Rücklicht: "));
Serial.println(lastState);
}
#endif
}
//
void frontLicht()
{
if (light == lightCondition::nacht) // nur in Nachtkondition
{ digitalWrite(frontLightPin, HIGH); }
else
{ digitalWrite(frontLightPin, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(frontLightPin))
{
lastState = !lastState;
Serial.print(F("Frontlicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void positionsLicht() // wird von blinkLicht aufgerufen
{
const uint8_t blinkLightPwm = 60;
if (light != lightCondition::no && posLightState) // nicht abgeschaltet
{
analogWrite(linksBlinkPwmPin, blinkLightPwm); // setzt Grundhelligkeit "Positionslicht"
analogWrite(rechtsBlinkPwmPin, blinkLightPwm);
}
else
{
digitalWrite(linksBlinkPwmPin, LOW);
digitalWrite(rechtsBlinkPwmPin, LOW);
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(linksBlinkPwmPin))
{
lastState = !lastState;
Serial.print(F("Positionslicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void blinken(const byte blinkRichtung, uint32_t &lastBlinkTime)
{
const uint32_t blinkTime = 500;
if (millis() - lastBlinkTime > blinkTime)
{
lastBlinkTime = millis();
switch (blinkRichtung)
{
case blinkCondition::rechts: // wenn rechts
digitalWrite(rechtsBlinkPin, !digitalRead(linksBlinkPin));
digitalWrite(linksBlinkPin, LOW); // sicherstellen, das aus, wenn aus warn zurück
BLINK_Pln(F("rechts"));
break;
case blinkCondition::warn:
BLINK_Pln(F("warn"));
[[fallthrough]];
case blinkCondition::links:/* fall trough */
digitalWrite(linksBlinkPin, !digitalRead(linksBlinkPin));
digitalWrite(rechtsBlinkPin, LOW);
BLINK_Pln(F("links"));
break;
}
}
if (blinkRichtung == blinkCondition::warn) // sicherstellen, das rechts == links wird
{ digitalWrite(rechtsBlinkPin, digitalRead(linksBlinkPin)); }
digitalRead(linksBlinkPin) ? // Front an Heck angleichen
digitalWrite(linksBlinkPwmPin, HIGH) :
digitalWrite(linksBlinkPwmPin, LOW);
digitalRead(rechtsBlinkPin) ?
digitalWrite(rechtsBlinkPwmPin, HIGH) :
digitalWrite(rechtsBlinkPwmPin, LOW);
}
//
void blinkLicht()
{
static byte zustand = blinkCondition::aus;
static uint32_t lastBlinkTime = 0;
//aktChTime[CH6] = 1800;
if (warnState) // Warnblink ein?
{ zustand = blinkCondition::warn; } // hat immer Vorfahrt
if (light == lightCondition::no)
{
positionsLicht();
digitalWrite(linksBlinkPin, LOW);
digitalWrite(rechtsBlinkPin, LOW);
return;
}
switch (zustand)
{
case blinkCondition::links:
blinken(blinkCondition::links, lastBlinkTime);
if (aktChTime[CH6] > 1400)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::rechts:
blinken (blinkCondition::rechts, lastBlinkTime);
if (aktChTime[CH6] < 1600)
{zustand = blinkCondition::aus;}
break;
case blinkCondition::warn:
blinken(blinkCondition::warn, lastBlinkTime);
{zustand = blinkCondition::aus;}
break;
case blinkCondition::aus:
positionsLicht();
digitalWrite(linksBlinkPin, LOW);
digitalWrite(rechtsBlinkPin, LOW);
if (aktChTime[CH6] < 1300)
{
zustand = blinkCondition::links;
digitalWrite(linksBlinkPin, HIGH);
lastBlinkTime = millis();
DEBUG_Pln(F("Blink aus"));
}
else if (aktChTime[CH6] > 1700)
{
zustand = blinkCondition::rechts;
digitalWrite(rechtsBlinkPin, HIGH);
lastBlinkTime = millis();
}
break;
}
}
//
void backFire()
{
const uint16_t minSpeed = 1880; // SpeedWert ab wann ausgelöst
static uint32_t blinkTime = 0; // Zeitmerker
static uint32_t lastFireTime = 0; // Letzter Umschaltvorgang LED
bool ledStatus = LOW;
if (light != lightCondition::no && backFireState) // aktiv
{
if (aktChTime[CH2] > minSpeed) // Schnell genug
{
if (millis() - lastFireTime > blinkTime) // Umschaltzeit erreicht
{
ledStatus = !digitalRead(backFirePin); // Toggel
blinkTime = random(30, 100); // neue Zufallszeit
if (!digitalRead(backFirePin)) // Pin ist aus?...
{ blinkTime *= 3; } // ... Auszeit verlängern
DEBUG_Pln(F("BackFire"));
}
lastFireTime = millis(); // umschaltzeit merken
}
}
digitalWrite(backFirePin, ledStatus);
}
//
void bremsLicht()
{
enum condition {forward, neutral, backward}; //
static byte myState = condition::neutral;
static uint32_t lastForwardTime = 0; // Zeitmerker
const uint32_t reaktionsZeit = 200; // Zeit in ms... Das muss getestet werden
const uint16_t neutralSpeed = 1490; // Hier ist nüscht
const uint8_t hysterese = 200; // Pendel der Neutralstellung +/-
if (light == lightCondition::no) // kein Licht
{ myState = condition::neutral; }
switch (myState)
{
case condition::forward:
if (aktChTime[CH2] < neutralSpeed + hysterese) // Neutralbereich erreicht?
{
myState = condition::neutral; // Zustand setzen
lastForwardTime = millis(); // Zeit merken
}
if (aktChTime[CH2] < neutralSpeed - hysterese) // Neutralbereich unterschritten?
{ myState = condition::backward; } // direkt Zustand wechseln
break;
case condition::neutral:
if (aktChTime[CH2] < neutralSpeed - hysterese) // Neutralbereich rückwärts verlassen?
{ myState = condition::backward; }
else if (aktChTime[CH2] > neutralSpeed + hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::forward; }
digitalWrite(bremsLichtPin, LOW); // Bremse deaktivieren
if (light == lightCondition::nacht)
{ analogWrite(bremsLichtPwmPin, rearLightPwm); } // Grundhelligkeit setzen
else
{ digitalWrite(bremsLichtPwmPin, LOW); } // oder ganz aus
break;
case condition::backward:
if (millis() - lastForwardTime < reaktionsZeit) // Zeit nicht abgelaufen ...
{
digitalWrite(bremsLichtPin, HIGH); // ... Bremse aktiviert!
digitalWrite(bremsLichtPwmPin, HIGH);
}
if (aktChTime[CH2] > neutralSpeed - hysterese) // Neutralbereich vorwärts verlassen?
{ myState = condition::neutral; } // Zustand setzen
break;
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(bremsLichtPin))
{
lastState = !lastState;
Serial.print(F("Bremslicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void printSerialChInput()
{
for (byte b = 0; b < numCh; b++)
{
if (abs(int(altChTime[b] - aktChTime[b])) > 10)
{
DEBUG_P(myType[b]);
DEBUG_P(": ");
DEBUG_P(aktChTime[b]);
DEBUG_Pln('\t');
altChTime[b] = aktChTime[b];
}
}
}
//
ISR (PCINT1_vect) // Port C Interrupt occured
{
for (byte b = 0; b < numCh; b++)
{
aktChStatus[b] = digitalRead(chInputPin[b]);
if (altChStatus[b] != aktChStatus[b])
{
altChStatus[b] = aktChStatus[b];
if (aktChStatus[b])
{ altChInput[b] = micros(); }
else
{ aktChTime[b] = micros() - altChInput[b]; }
}
}
}

Verständnis
Fast alles richtig, das kursiv Geschriebene habe ich korrigiert/hinzugefügt:
Type | PIN | Tag | Nacht | aus |
---|---|---|---|---|
Frontlicht | A1 | inaktiv | aktiv | inaktiv |
Nebel | 2 | inaktiv | aktiv | inaktiv |
Nebel PWM | 3 | inaktiv | aktiv | inaktiv |
Rückfahr | 4 | aktiv (nur beim Rückwärtsfahren) | aktiv | inaktiv |
Blinker PWM | 5, 6 | aktiv | aktiv | inaktiv |
Blinker | 7, 8 | aktiv | aktiv | inaktiv |
Grifflicht | 9 | gleich wie bei Nacht | standardmäßig inaktiv. Erst nach CH3-Doppelclick eingeschaltet. | inaktiv |
Rücklicht PWM | 10 | inaktiv | aktiv | inaktiv |
Bremse PWM | 11 | Ausschließlich beim Bremsen auf volle Helligkeit. Wenn nicht gebremst wird: inaktiv. | aktiv | inaktiv |
Backfire | 12 | aktiv | aktiv | inaktiv |
Bremslicht | 13 | aktiv | aktiv | inaktiv |

Und nur wenn CH4 aktiv, kommt CH3 zur Anwendung.
Korrekt, das gleiche gilt für CH5 und CH6: Wenn CH4 auf Position Mitte ist, sind CH3, CH5 und CH6 inaktiv.

Erster Vorschlag.
Danke, mache mich gleich daran, ihn auszuprobieren und Rückmeldung zu geben