unbestritten.
Ich habs mal umgebaut.
Zumindest kompilieren tuts...
@etoilevolante das wäre jetzt der Umbau und wir verbrauchen kein zusätzliches Array.
//#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 PINZAHL = 13;
union
{
byte alle[PINZAHL];
struct
{
const byte fogLight = 2;
const byte fogLightPwm = 3;
const byte rearLight = 4;
const byte rechtsBlinkPwm = 5;
const byte linksBlinkPwm = 6;
const byte rechtsBlink = 7;
const byte linksBlink = 8;
const byte griffPwm = 9;
const byte rueckLichtPwm = 10;
const byte bremsLichtPwm = 11;
const byte backFire = 12;
const byte bremsLicht = 13;
const byte frontLight = 15;
};
} pin;
bool warnState, griffState, posLightState, backFireState, fogLightState, backwardState = false;
enum class blinkCondition : byte {links, rechts, warn, aus};
enum class lightCondition : byte {tag, nacht, aus};
lightCondition light = lightCondition::aus;
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][20] = {"CH2 Gas", "CH3 Taster", "CH4 Tag/Nacht", "CH5 BlueLEd", "CH6 Blinker"};
volatile uint16_t aktChTime[numCh] = {1500};
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()
{
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)
Serial.begin(115200);
Serial.println("\nStart ...");
delay(1000);
randomSeed(A1);
for (byte b = 0; b < numCh; b++)
{
pinMode(chInputPin[b], INPUT);
}
for (byte b = 0; b < PINZAHL; b++)
{
digitalWrite(pin.alle[b], LOW);
pinMode(pin.alle[b], OUTPUT);
}
}
//
void loop()
{
readSwitch();
setLighting();
kickBack();
brakeLight();
blinkLicht();
frontLicht();
rueckLicht();
backLight();
nebelLicht();
griffLicht();
}
//
void readSwitch()
{
const uint32_t timeOut = 400; // [war ursprünglich auf 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();
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()
{
static lightCondition lastCondition = lightCondition::aus;
switch (aktChTime[CH4])
{
case 0 ... 1200:
light = lightCondition::nacht;
if (lastCondition != lightCondition::nacht)
{
posLightState = true;
fogLightState = true;
lastCondition = lightCondition::nacht; // [war ursprünglich ==]
}
break;
case 1300 ... 1600:
light = lightCondition::aus;
lastCondition = lightCondition::aus;
break;
case 1800 ... 2000:
light = lightCondition::tag;
if (lastCondition != lightCondition::tag)
{
posLightState = false;
fogLightState = false;
lastCondition = lightCondition::tag;
}
break;
}
#ifdef DEBUG
static lightCondition lastState = lightCondition::aus;
if (lastState != light)
{
lastState = light;
Serial.print(F("Licht: "));
if (lastState == lightCondition::nacht)
{ Serial.println(F("Nacht")); }
else if (lastState == lightCondition::aus)
{ Serial.println(F("aus")); }
else if (lastState == lightCondition::tag)
{ Serial.println(F("Tag")); }
}
#endif
}
//
void griffLicht()
{
const uint8_t griffPwm = 30; // [war ursprünglich auf 100]
uint8_t tempPwm = 0;
if ((light != lightCondition::aus) && griffState) // funktioniert bei Tag und Nacht!
{ tempPwm = griffPwm; }
tempPwm ? analogWrite(pin.griffPwm, griffPwm) : digitalWrite(pin.griffPwm, LOW);
#ifdef DEBUG
static uint8_t lastState = LOW;
if (lastState != tempPwm)
{
lastState = tempPwm;
Serial.print(F("Grifflicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void backLight() // Rückfahrscheinwerfer
{
if ((light != lightCondition::aus) && backwardState) // Tag und Nacht
{ digitalWrite(pin.rearLight, HIGH); }
else
{ digitalWrite(pin.rearLight, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(pin.rearLight))
{
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 (light != lightCondition::aus) // Wenn nicht Tag oder Nacht
{
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::aus) && fogLightState) // Pin 3 funktioniert Tags und Nachts
{
digitalWrite(pin.fogLight, HIGH);
analogWrite(pin.fogLightPwm, blueLed()); // gekoppelt an CH5
}
else
{
digitalWrite(pin.fogLight, LOW);
digitalWrite(pin.fogLightPwm, LOW);
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(pin.fogLight))
{
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(pin.rueckLichtPwm, 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(pin.frontLight, HIGH); }
else
{ digitalWrite(pin.frontLight, LOW); }
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(pin.frontLight))
{
lastState = !lastState;
Serial.print(F("Frontlicht: "));
Serial.println(lastState ? "ein" : "aus");
}
#endif
}
//
void linksBlinken(const byte myBlink)
{
const uint8_t posLightPwm = 30;
switch (myBlink)
{
case 0:
digitalWrite(pin.linksBlink, LOW);
if (light == lightCondition::aus || !posLightState)
{ digitalWrite(pin.linksBlinkPwm, LOW);}
else
{ analogWrite(pin.linksBlinkPwm, posLightPwm);}
break;
case 1: digitalWrite(pin.linksBlink, HIGH); break;
case 2: digitalWrite(pin.linksBlink, !digitalRead(pin.linksBlink)); break;
}
if (myBlink)
{ digitalWrite(pin.linksBlinkPwm, digitalRead(pin.linksBlink)); }
}
//
void rechtsBlinken(const byte myBlink)
{
const uint8_t posLightPwm = 30;
switch (myBlink)
{
case 0:
digitalWrite(pin.rechtsBlink, LOW);
if (light == lightCondition::aus || !posLightState)
{ digitalWrite(pin.rechtsBlinkPwm, LOW); }
else
{ analogWrite(pin.rechtsBlinkPwm, posLightPwm); }
break;
case 1: digitalWrite(pin.rechtsBlink, HIGH); break;
case 2: digitalWrite(pin.rechtsBlink, !digitalRead(pin.rechtsBlink)); break;
}
if (myBlink)
{ digitalWrite(pin.rechtsBlinkPwm, digitalRead(pin.rechtsBlink)); }
}
//
void blinkLicht()
{
blinkCondition zustand = blinkCondition::aus; // Vorbelegung
static blinkCondition lastBlinkCondition = blinkCondition::warn;
byte blinkByte = 0; // 0=aus, 1=an, 2=toggle
const uint32_t blinkTime = 500;
static uint32_t lastBlinkTime = 0;
if (light != lightCondition::aus)
{
if (warnState) // Warnblinker?
{ zustand = blinkCondition::warn; }
else if (aktChTime[CH6] < 1300) // links?
{ zustand = blinkCondition::links; }
else if (aktChTime[CH6] > 1700) // rechts?
{ zustand = blinkCondition::rechts; }
}
//
if (zustand != lastBlinkCondition) // Neue Auswahl?
{
blinkByte = 1; // Startbyte setzen
lastBlinkCondition = zustand; // merken
lastBlinkTime = millis();
}
else
{ blinkByte = 2; } // oder wenn nicht, dann blinkt es
//
if (zustand == blinkCondition::aus)
{
linksBlinken(0);
rechtsBlinken(0);
}
else if ((blinkByte == 2 && millis() - lastBlinkTime > blinkTime) || blinkByte == 1)
{
lastBlinkTime = millis();
switch (zustand)
{
case blinkCondition::links: { linksBlinken(blinkByte); rechtsBlinken(0); } break;
case blinkCondition::rechts: { rechtsBlinken(blinkByte); linksBlinken(0);} break;
case blinkCondition::warn:
{
rechtsBlinken(blinkByte);
linksBlinken(blinkByte);
}
break;
default: break;
}
}
}
//
void kickBack()
{
const uint16_t minSpeed = 1880; // SpeedWert ab wann ausgelöst
static uint32_t blinkTime = 0; // Zeitmerker
static uint32_t lastFireTime = 0; // Letzter Umschaltvorgang LED
static bool ledStatus = LOW;
if ((light != lightCondition::aus) && backFireState) // aktiv
{
if (aktChTime[CH2] > minSpeed) // Schnell genug
{
if (millis() - lastFireTime > blinkTime) // Umschaltzeit erreicht
{
ledStatus = !digitalRead(pin.backFire); // Toggel
blinkTime = random(30, 100); // neue Zufallszeit
if (!digitalRead(pin.backFire)) // Pin ist aus?...
{ blinkTime *= 3; } // ... Auszeit verlängern
lastFireTime = millis(); // umschaltzeit merken
DEBUG_Pln(F("BackFire"));
}
}
else
{ ledStatus = LOW; }
}
digitalWrite(pin.backFire, ledStatus);
}
//
void brakeLight()
{
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 +/-
static bool ledStatus = LOW;
if (light == lightCondition::aus) // 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; }
backwardState = false; // merken das nicht mehr zurück gefahren
ledStatus = LOW; // merken das nicht gebremst wird
break;
case condition::backward:
if (millis() - lastForwardTime < reaktionsZeit) // Zeit nicht abgelaufen ...
{ ledStatus = HIGH; } // ... Bremse aktivieren
if (!ledStatus) // Bremse nicht aktiv ...
{ backwardState = true; } // ... dann Rückwärts
if (aktChTime[CH2] > neutralSpeed - hysterese) // Neutralbereich vorwärts verlassen? ...
{ myState = condition::neutral; } // ... Zustand setzen
break;
}
// Ab hier Ausgabe
if (ledStatus) // Bremse aktiviert?
{
digitalWrite(pin.bremsLicht, HIGH);
digitalWrite(pin.bremsLichtPwm, HIGH);
}
else // keine Bremse
{
analogWrite(pin.bremsLichtPwm, rearLightPwm); // Grundhelligkeit setzen...
digitalWrite(pin.bremsLicht, LOW); // ... anderen ganz aus
}
#ifdef DEBUG
static bool lastState = false;
if (lastState != digitalRead(pin.bremsLicht))
{
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]; }
}
}
}