Wie bekomme ich bei einer RGB-LED einen kurzen Farbwechsel von Rot auf Orange hin?

Hallo @agmue,
das geht aber so rein logisch nicht.
Der Smoker ist abhängig von der Glut.
Du musst also mindestens entweder einen globalen Merker benutzen oder das smoken nicht aus dem loop() heraus, sondern aus der glut() aufrufen :wink:

Sorry, dann mache ich oder der Simulator was falsch. Wenn ich den Sketch aus #3 ohne Modifikationen in den Simulator lade, ist bis 30 sec rot gedimmt, dann wird hoch gefadet bis 35 sec und es wechselt zu orange, das bleibt bis 51 sec, dann wir es wieder rot und das fadet runter bis 58 sec.

Muss ich's wohl zu Hause an einem richtigen Arduino testen...

Wie würde ich denn einbinden, dass eine Sekunde nach dem Runterfaden für zwei Sekunden der Smoke angeht?

Eine Sekunde nach dem das runterfaden begonnen hat, also 1 Sekunde nach hier:

|14:46:40.724 -> R: 254|G: 50| <= hab hier wirds dunkler

oder nachdem runterfaden beendet wurde:

14:46:41.419 -> R: 30

SmokerPin ist welcher?
PS: Dein Simulator benötigt ein Login "Willkommen zurück - wie meldest Du Dich an" - nein ich will Deine Zugangsdaten nicht :slight_smile:

PPS: Wenn Ich Deine Zeiten nehme, ist das ein Faktor von 10.

Wenn Ereignisse nichts miteinander zu tun haben, solltest du für jedes "einen eigenen Part" schreiben. Das macht es auch einfacher/übersichtlicher. Man schreibt dann auch gern eine eigene Funktion, Die man in der Arduino IDE sogar in einem eigenen Tab verstecken könnte.

Wenn sie allerdings zusammenhängen, ist es sinnvoll, das auch zusammenzuhalten. Wenn -als einfaches Beispiel- deine LED jeweils 1 sec an und 2 sec aus sein soll, hast du einen Zyklus von 3 Sekunden und beispielsweise eine Funktion

void Blinken13 () {
  const byte pin=13;
  const unsigned int zyklus=3000;
  const unsigned int z_ein=1000;

  static unsigned long lastStart;
  unsigned int dt = millis() -lastStart;
  if (dt >= zyklus)  lastStart = millis();
  digitalWrite(pin, dt < z_ein); // ein im ersten Teil des Zyklus, aus im zweiten
}

Diese Funktion braucht keine Zeit, und passt daher gut in ein loop(), das auch keine Zeit braucht, und neben

void loop()  {
   Blinken13();
   // beliebige andere Sachen
}

parallel nach dem gleichen Schema ausführt.

Wichtiger als delay() durch millis() ersetzen ist, den aktuellen Zustand (hier: lastStart) zu kennen, und in einfachen if Abfragen zu erkennen, dass gerade gar nichts zu tun ist.
Bei größeren Sachen und vielen Zustandsvariablen ist es oft sinnvoll, diese nicht global und mit Namen wie previousEvent02 zu benennen, sondern sie lokal in der jeweiligen Funktion zu "verstecken". static Variable behalten den Wert genauso wie eine globale Variable, aber der Name ist nur im definierenden Block bekannt und könnte mit selbem Namen woanders für etwas anderes verwendet werden.

Als geborener Nichtraucher habe ich den Ablauf vermutlich nicht verstanden :rofl:

Ja, die beiden Funktionen laufen gänzlich unabhängig, das war meine Absicht. Mir ging es nur um die Schrittkette in Ergänzung von millis().

Ich kann aber auch einen Merker einführen, der die Abhängigkeit herbeiführt:

const byte LED   = 5;
const byte SMOKEPIN = 13;

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(SMOKEPIN, OUTPUT);
}

void loop()
{
  bool merkerRauch = false;
  glut(merkerRauch);
  rauch(merkerRauch);
}

void glut(bool & rauch) {
  uint32_t jetzt = millis();
  static uint32_t vorhin = 0;
  static uint32_t intervall = 0;
  static byte schritt = 0;

  if (jetzt - vorhin >= intervall)
  {
    vorhin = jetzt;
    switch (schritt)
    {
      case 0:
        digitalWrite(LED, HIGH);
        intervall = 1000;
        schritt = 1;
        break;
      case 1:
        digitalWrite(LED, LOW);
        rauch = true;
        intervall = 3000;
        schritt = 0;
        break;
    }
  }
}

void rauch(bool & rauch)
{
  uint32_t jetzt = millis();
  static uint32_t vorhin = 0;
  const uint32_t intervall = 100;

  if (rauch)
  {
    digitalWrite(SMOKEPIN, HIGH);
    vorhin = jetzt;
    rauch = false;
  } else {
    if (jetzt - vorhin >= intervall)
    {
      digitalWrite(SMOKEPIN, LOW);
    }
  }
}

@cptblaubaer: Das "&" ist das Zeichen für eine Referenz, falls Du nachschlagen möchtest.

1 Like

13

Woher hat er den denn? Wenn ich sehe, dass Du
const unsigned long dunkelPause = 3000;
drin hast, da aber 30.000 Millisekunden draus werden, ist das doch auch Faktor 10??

Danke - ich versuche, das zu verstehen.

Das bin ich auch, aber er kann ja erst Rauch ausstoßen, nachdem er gezogen hat :yum:

Wenn's Dir hilft, den Fehler zu finden, schicke ich sie Dir gerne. Sind ja keine intimen Daten, worauf man Zugang bekommt...

Eventuell hilft Dir diese frei zugängliche Simulation:

  1. Programm aus #16: smoker.ino - Wokwi ESP32, STM32, Arduino Simulator

  2. Programm aus #25: sketch.ino - Wokwi ESP32, STM32, Arduino Simulator

Ich kommentiere meine Programme kaum, Du kannst aber gerne fragen. Manche Mitglieder dieses Forums können meine Programme sogar besser kommentieren, als ich selbst :slightly_smiling_face:

Na dann:
(Ich hab mal noch die HellPause kleiner gemacht und den Orangepegel verändert)

const byte rotPin = 5;
const byte gruenPin = 3;
const byte smokePin = 13;
bool smoker = false;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  pinMode(rotPin, OUTPUT);
  pinMode(gruenPin, OUTPUT);
  pinMode(smokePin, OUTPUT);
}

void loop()
{
  static unsigned long lastmillis = 0;
  if (millis() - lastmillis > 2)                         // Wenn Zeit abgelaufen ist...
  {
    glut();                                              // ... rufe Funktion auf ...
    lastmillis = millis();                               // ... merke Zeit
  }
  rauch();
}

void rauch()                                             // Es soll Rauch aufgehen
{
  static bool smokeStart = false;                        // Merker für den Start der Sequenz
  static unsigned long startZeit = 0;                    // StartZeit
  if (smoker == true)                                    // Wenn die Glut ausgelöst hat ...
  {
    if (smokeStart == false)                             // ... und bisher nicht ausgelöst war ...
    {
      startZeit = millis();                              // ... Zeit merken ...
      smokeStart = true;                                 // ... vermeidet, das die Zeit wieder gestellt wird ...
    }
    if (millis() - startZeit > 1000)                     // ... Zeit abgelaufen ...
    {
      digitalWrite(smokePin, HIGH);                      // ... dann las Rauch aufsteigen ...
    }
    if (millis() - startZeit > 1100)                     // ... noch mehr Zeit abgelaufen ...
    {
      digitalWrite(smokePin, LOW);                       // ... kein Rauch mehr
      smoker = false;                                    // setze Variablen zurück
      smokeStart = false;
    }
  }
}

void glut()                                              // Diese Funktion wird nur aufgerufen, wenn oben die Zeit abgelaufen
{
  const unsigned long dunkelPause = 3000;                // Zeit in ms die der PIN LOW ist
  const unsigned long hellPause = 500;                   // Zeit in ms die der PIN Dauerhaft HIGH ist
  static unsigned long lastmillis = 0;                   // Die Variable gilt nur lokal
  const byte minRot = 30;                                // kleinster Rot-Wert
  const byte minGruen = 0;                               // kleinster Gruen-Wert
  static bool heller = true;                             // diese Variable bestimmt die Richtung: ob heller(true) oder dunkler(false) werden soll
  static byte rotWert = minRot;                          // Startwert
  if ((millis() - lastmillis > dunkelPause) && heller)   // Wenn Dunkelpause abgelaufen UND die Richtung heller ist...
  {
    rotWert++;                                           // ... Increment ...
    if (rotWert > 254)                                   // ... Am oberen Ende? ...
    {
      heller = false;                                    // ... dann soll es dunkler werden ...
      lastmillis = millis();                             // ... merke die Zeit, wann es am hellsten war
    }
  }
  if ((millis() - lastmillis > hellPause) && !heller)    // Wenn Hellpause abgelaufen ist UND die Richtung dunkler ist...
  {
    rotWert--;                                           // ... decrement ...
    if (rotWert < minRot)                                // ... am unteren Ende? ...
    {
      rotWert = minRot;                                  // ... setze kleinsten Rotwert ...
      heller = true;                                     // ... wechsle Richtung ...
      smoker = true;                                     // ... Jetzt darf der Rauch aufsteigen
      lastmillis = millis();                             // ... merke Umschaltzeit
      //     Serial.print("STOP:"); Serial.println(millis());// Diese beiden Zeilen nur
      //     while (1);                                      // zum Durchlauftest
    }
  }
  Serial.print("R: "); Serial.print(rotWert);
  analogWrite(rotPin, rotWert);                          // schreibe auf Pin
  if (rotWert > 180)                                     // Hier ist der Einsatz, ab wann der Farbraum verändert wird ...
  {
    analogWrite(gruenPin, (rotWert - 180) * 3);          // ... der Gruenwert errechnet sich aus dem rotWert ...
    Serial.print("\tG: "); Serial.print(rotWert / 5);
  }
  else analogWrite(gruenPin, minGruen);                  // ... Wenn der rotWert nicht erreicht, schreibe kleinsten GruenWert
  Serial.println();                                      // Und hier ist die Funkltion einmal durchlaufen
}                                                        // der nächste Durchlauf ist erst wieder, wenn im loop die Zeit abgelaufen ist

Das ist eine gute Frage.
Keine Ahnung...

Simulation für #28: smoker.ino - Wokwi Arduino and ESP32 Simulator

Danke für die Simulationen, das ist ziemlich genau, was ich mir vorgestellt hatte. Wie ich die Zeiten des Ablaufs ändere, habe ich auch inzwischen (hoffe ich) kapiert.

Was ich aber überhaupt nicht verstehe:
In Deiner letzten Simulation von @my_xy_projekt #28 beginnt das Faden wie im Sketch beschrieben, bei 3000 angezeigten Millisekunden. In Echtzeit sind das aber 28 Sekunden - also ziemlich genau der Faktor 10 aus der tinkercad Simulation. In Deiner Simulation zum Sketch aus #25 läuft die Simulatoruhr syncron zur Echtzeit. Könnt Ihr mir das erklären?

1 Like

?
Was heisst das?
Wenn ich das hier in meinem Aufbau laufen lasse, geht der in Echtzeit nach 3000ms in den Fadebetrieb.

Könnte das möglicherweise an der Simulation und der langsamen Übertragung zu Dir liegen? Die Idee einer Simulation ist nicht die Echtzeitanzeige bei Dir.

Sieht die Ausgabe bei Dir auch so aus? Anfang gekürzt:

Start...
3	R: 30
6	R: 30
9	R: 30
12	R: 30
15	R: 30
...
2990	R: 30
2993	R: 30
2996	R: 30
2999	R: 30
3002	R: 31
3005	R: 32
3008	R: 33
3011	R: 34
3014	R: 35
3017	R: 36
3020	R: 37
3023	R: 38
3026	R: 39
3030	R: 40
3033	R: 41
3036	R: 42
3039	R: 43
3042	R: 44
3045	R: 45
3048	R: 46
3051	R: 47
3054	R: 48
3057	R: 49
3060	R: 50
3063	R: 51
3066	R: 52
3069	R: 53
3072	R: 54
3075	R: 55
3078	R: 56
3081	R: 57
3084	R: 58
3087	R: 59
3090	R: 60
3093	R: 61
3096	R: 62
3099	R: 63
3102	R: 64
3105	R: 65
3108	R: 66
3111	R: 67
3115	R: 68
3118	R: 69
3121	R: 70
3124	R: 71
3127	R: 72
3130	R: 73
3133	R: 74
3136	R: 75
3139	R: 76
3142	R: 77
3145	R: 78
3148	R: 79
3151	R: 80
3154	R: 81
3158	R: 82
3161	R: 83
3164	R: 84
3167	R: 85
3170	R: 86
3173	R: 87
3176	R: 88
3179	R: 89
3182	R: 90
3185	R: 91
3188	R: 92
3191	R: 93
3194	R: 94
3197	R: 95
3200	R: 96
3203	R: 97
3206	R: 98
3209	R: 99
3212	R: 100
3215	R: 101
3218	R: 102
3221	R: 103
3224	R: 104
3227	R: 105
3230	R: 106
3233	R: 107
3236	R: 108
3239	R: 109
3243	R: 110
3246	R: 111
3249	R: 112
3252	R: 113
3255	R: 114
3258	R: 115
3261	R: 116
3264	R: 117
3267	R: 118
3270	R: 119
3273	R: 120
3276	R: 121
3279	R: 122
3282	R: 123
3286	R: 124
3289	R: 125
3292	R: 126
3295	R: 127
3298	R: 128
3301	R: 129
3304	R: 130
3307	R: 131
3310	R: 132
3313	R: 133
3316	R: 134
3319	R: 135
3322	R: 136
3325	R: 137
3328	R: 138
3331	R: 139
3334	R: 140
3337	R: 141
3340	R: 142
3343	R: 143
3346	R: 144
3349	R: 145
3352	R: 146
3355	R: 147
3358	R: 148
3361	R: 149
3364	R: 150
3367	R: 151
3371	R: 152
3374	R: 153
3377	R: 154
3380	R: 155
3383	R: 156
3386	R: 157
3389	R: 158
3392	R: 159
3395	R: 160
3398	R: 161
3401	R: 162
3404	R: 163
3407	R: 164
3410	R: 165
3414	R: 166
3417	R: 167
3420	R: 168
3423	R: 169
3426	R: 170
3429	R: 171
3432	R: 172
3435	R: 173
3438	R: 174
3441	R: 175
3444	R: 176
3447	R: 177
3450	R: 178
3453	R: 179
3456	R: 180
3459	R: 181	G: 36
3462	R: 182	G: 36
3465	R: 183	G: 36
3468	R: 184	G: 36
3471	R: 185	G: 37
3474	R: 186	G: 37
3477	R: 187	G: 37
3480	R: 188	G: 37
3483	R: 189	G: 37
3486	R: 190	G: 38
3489	R: 191	G: 38
3492	R: 192	G: 38
3495	R: 193	G: 38
3499	R: 194	G: 38
3502	R: 195	G: 39
3505	R: 196	G: 39
3508	R: 197	G: 39
3511	R: 198	G: 39
3514	R: 199	G: 39
3517	R: 200	G: 40
3520	R: 201	G: 40
3523	R: 202	G: 40
3526	R: 203	G: 40
3529	R: 204	G: 40
3532	R: 205	G: 41
3535	R: 206	G: 41
3538	R: 207	G: 41
3542	R: 208	G: 41
3545	R: 209	G: 41
3548	R: 210	G: 42
3551	R: 211	G: 42
3554	R: 212	G: 42
3557	R: 213	G: 42
3560	R: 214	G: 42
3563	R: 215	G: 43
3566	R: 216	G: 43
3569	R: 217	G: 43
3572	R: 218	G: 43
3575	R: 219	G: 43
3578	R: 220	G: 44
3581	R: 221	G: 44
3584	R: 222	G: 44
3587	R: 223	G: 44
3590	R: 224	G: 44
3593	R: 225	G: 45
3596	R: 226	G: 45
3599	R: 227	G: 45
3602	R: 228	G: 45
3605	R: 229	G: 45
3608	R: 230	G: 46
3611	R: 231	G: 46
3614	R: 232	G: 46
3617	R: 233	G: 46
3620	R: 234	G: 46
3623	R: 235	G: 47
3627	R: 236	G: 47
3630	R: 237	G: 47
3633	R: 238	G: 47
3636	R: 239	G: 47
3639	R: 240	G: 48
3642	R: 241	G: 48
3645	R: 242	G: 48
3648	R: 243	G: 48
3651	R: 244	G: 48
3654	R: 245	G: 49
3657	R: 246	G: 49
3660	R: 247	G: 49
3663	R: 248	G: 49
3666	R: 249	G: 49
3670	R: 250	G: 50
3673	R: 251	G: 50
3676	R: 252	G: 50
3679	R: 253	G: 50
3682	R: 254	G: 50
3685	R: 255	G: 51
3688	R: 255	G: 51
3691	R: 255	G: 51
3694	R: 255	G: 51
3697	R: 255	G: 51
3700	R: 255	G: 51
3703	R: 255	G: 51
3706	R: 255	G: 51
3709	R: 255	G: 51
3712	R: 255	G: 51
3715	R: 255	G: 51
3718	R: 255	G: 51
3721	R: 255	G: 51
3724	R: 255	G: 51
3727	R: 255	G: 51
3730	R: 255	G: 51
3733	R: 255	G: 51
3736	R: 255	G: 51
3739	R: 255	G: 51
3742	R: 255	G: 51
3745	R: 255	G: 51
3748	R: 255	G: 51
3751	R: 255	G: 51
3755	R: 255	G: 51
3758	R: 255	G: 51
3761	R: 255	G: 51
3764	R: 255	G: 51
3767	R: 255	G: 51
3770	R: 255	G: 51
3773	R: 255	G: 51
3776	R: 255	G: 51
3779	R: 255	G: 51
3782	R: 255	G: 51
3785	R: 255	G: 51
3788	R: 255	G: 51
3791	R: 255	G: 51
3794	R: 255	G: 51
3798	R: 255	G: 51
3801	R: 255	G: 51
3804	R: 255	G: 51
3807	R: 255	G: 51
3810	R: 255	G: 51
3813	R: 255	G: 51
3816	R: 255	G: 51
3819	R: 255	G: 51
3822	R: 255	G: 51
3825	R: 255	G: 51
3828	R: 255	G: 51
3831	R: 255	G: 51
3834	R: 255	G: 51
3837	R: 255	G: 51
3840	R: 255	G: 51
3843	R: 255	G: 51
3846	R: 255	G: 51
3849	R: 255	G: 51
3852	R: 255	G: 51
3855	R: 255	G: 51
3858	R: 255	G: 51
3861	R: 255	G: 51
3864	R: 255	G: 51
3867	R: 255	G: 51
3870	R: 255	G: 51
3873	R: 255	G: 51
3876	R: 255	G: 51
3879	R: 255	G: 51
3883	R: 255	G: 51
3886	R: 255	G: 51
3889	R: 255	G: 51
3892	R: 255	G: 51
3895	R: 255	G: 51
3898	R: 255	G: 51
3901	R: 255	G: 51
3904	R: 255	G: 51
3907	R: 255	G: 51
3910	R: 255	G: 51
3913	R: 255	G: 51
3916	R: 255	G: 51
3919	R: 255	G: 51
3922	R: 255	G: 51
3926	R: 255	G: 51
3929	R: 255	G: 51
3932	R: 255	G: 51
3935	R: 255	G: 51
3938	R: 255	G: 51
3941	R: 255	G: 51
3944	R: 255	G: 51
3947	R: 255	G: 51
3950	R: 255	G: 51
3953	R: 255	G: 51
3956	R: 255	G: 51
3959	R: 255	G: 51
3962	R: 255	G: 51
3965	R: 255	G: 51
3968	R: 255	G: 51
3971	R: 255	G: 51
3974	R: 255	G: 51
3977	R: 255	G: 51
3980	R: 255	G: 51
3983	R: 255	G: 51
3986	R: 255	G: 51
3989	R: 255	G: 51
3992	R: 255	G: 51
3995	R: 255	G: 51
3998	R: 255	G: 51
4001	R: 255	G: 51
4004	R: 255	G: 51
4007	R: 255	G: 51
4011	R: 255	G: 51
4014	R: 255	G: 51
4017	R: 255	G: 51
4020	R: 255	G: 51
4023	R: 255	G: 51
4026	R: 255	G: 51
4029	R: 255	G: 51
4032	R: 255	G: 51
4035	R: 255	G: 51
4038	R: 255	G: 51
4041	R: 255	G: 51
4044	R: 255	G: 51
4047	R: 255	G: 51
4050	R: 255	G: 51
4054	R: 255	G: 51
4057	R: 255	G: 51
4060	R: 255	G: 51
4063	R: 255	G: 51
4066	R: 255	G: 51
4069	R: 255	G: 51
4072	R: 255	G: 51
4075	R: 255	G: 51
4078	R: 255	G: 51
4081	R: 255	G: 51
4084	R: 255	G: 51
4087	R: 255	G: 51
4090	R: 255	G: 51
4093	R: 255	G: 51
4096	R: 255	G: 51
4099	R: 255	G: 51
4102	R: 255	G: 51
4105	R: 255	G: 51
4108	R: 255	G: 51
4111	R: 255	G: 51
4114	R: 255	G: 51
4117	R: 255	G: 51
4120	R: 255	G: 51
4123	R: 255	G: 51
4126	R: 255	G: 51
4129	R: 255	G: 51
4132	R: 255	G: 51
4135	R: 255	G: 51
4139	R: 255	G: 51
4142	R: 255	G: 51
4145	R: 255	G: 51
4148	R: 255	G: 51
4151	R: 255	G: 51
4154	R: 255	G: 51
4157	R: 255	G: 51
4160	R: 255	G: 51
4163	R: 255	G: 51
4166	R: 255	G: 51
4169	R: 255	G: 51
4172	R: 255	G: 51
4175	R: 255	G: 51
4178	R: 255	G: 51
4182	R: 255	G: 51
4185	R: 255	G: 51
4188	R: 254	G: 50
4191	R: 253	G: 50
4194	R: 252	G: 50
4197	R: 251	G: 50
4200	R: 250	G: 50
4203	R: 249	G: 49
4206	R: 248	G: 49
4209	R: 247	G: 49
4212	R: 246	G: 49
4215	R: 245	G: 49
4218	R: 244	G: 48
4221	R: 243	G: 48
4224	R: 242	G: 48
4227	R: 241	G: 48
4230	R: 240	G: 48
4233	R: 239	G: 47
4236	R: 238	G: 47
4239	R: 237	G: 47
4242	R: 236	G: 47
4245	R: 235	G: 47
4248	R: 234	G: 46
4251	R: 233	G: 46
4254	R: 232	G: 46
4257	R: 231	G: 46
4260	R: 230	G: 46
4263	R: 229	G: 45
4267	R: 228	G: 45
4270	R: 227	G: 45
4273	R: 226	G: 45
4276	R: 225	G: 45
4279	R: 224	G: 44
4282	R: 223	G: 44
4285	R: 222	G: 44
4288	R: 221	G: 44
4291	R: 220	G: 44
4294	R: 219	G: 43
4297	R: 218	G: 43
4300	R: 217	G: 43
4303	R: 216	G: 43
4306	R: 215	G: 43
4310	R: 214	G: 42
4313	R: 213	G: 42
4316	R: 212	G: 42
4319	R: 211	G: 42
4322	R: 210	G: 42
4325	R: 209	G: 41
4328	R: 208	G: 41
4331	R: 207	G: 41
4334	R: 206	G: 41
4337	R: 205	G: 41
4340	R: 204	G: 40
4343	R: 203	G: 40
4346	R: 202	G: 40
4349	R: 201	G: 40
4352	R: 200	G: 40
4355	R: 199	G: 39
4358	R: 198	G: 39
4361	R: 197	G: 39
4364	R: 196	G: 39
4367	R: 195	G: 39
4370	R: 194	G: 38
4373	R: 193	G: 38
4376	R: 192	G: 38
4379	R: 191	G: 38
4382	R: 190	G: 38
4385	R: 189	G: 37
4388	R: 188	G: 37
4391	R: 187	G: 37
4395	R: 186	G: 37
4398	R: 185	G: 37
4401	R: 184	G: 36
4404	R: 183	G: 36
4407	R: 182	G: 36
4410	R: 181	G: 36
4413	R: 180
4416	R: 179
4419	R: 178
4422	R: 177
4425	R: 176
4428	R: 175
4431	R: 174
4434	R: 173
4438	R: 172
4441	R: 171
4444	R: 170
4447	R: 169
4450	R: 168
4453	R: 167
4456	R: 166
4459	R: 165
4462	R: 164
4465	R: 163
4468	R: 162
4471	R: 161
4474	R: 160
4477	R: 159
4480	R: 158
4483	R: 157
4486	R: 156
4489	R: 155
4492	R: 154
4495	R: 153
4498	R: 152
4501	R: 151
4504	R: 150
4507	R: 149
4510	R: 148
4513	R: 147
4516	R: 146
4519	R: 145
4523	R: 144
4526	R: 143
4529	R: 142
4532	R: 141
4535	R: 140
4538	R: 139
4541	R: 138
4544	R: 137
4547	R: 136
4550	R: 135
4553	R: 134
4556	R: 133
4559	R: 132
4562	R: 131
4566	R: 130
4569	R: 129
4572	R: 128
4575	R: 127
4578	R: 126
4581	R: 125
4584	R: 124
4587	R: 123
4590	R: 122
4593	R: 121
4596	R: 120
4599	R: 119
4602	R: 118
4605	R: 117
4608	R: 116
4611	R: 115
4614	R: 114
4617	R: 113
4620	R: 112
4623	R: 111
4626	R: 110
4629	R: 109
4632	R: 108
4635	R: 107
4638	R: 106
4641	R: 105
4644	R: 104
4647	R: 103
4651	R: 102
4654	R: 101
4657	R: 100
4660	R: 99
4663	R: 98
4666	R: 97
4669	R: 96
4672	R: 95
4675	R: 94
4678	R: 93
4681	R: 92
4684	R: 91
4687	R: 90
4690	R: 89
4694	R: 88
4697	R: 87
4700	R: 86
4703	R: 85
4706	R: 84
4709	R: 83
4712	R: 82
4715	R: 81
4718	R: 80
4721	R: 79
4724	R: 78
4727	R: 77
4730	R: 76
4733	R: 75
4736	R: 74
4739	R: 73
4742	R: 72
4745	R: 71
4748	R: 70
4751	R: 69
4754	R: 68
4757	R: 67
4760	R: 66
4763	R: 65
4766	R: 64
4769	R: 63
4772	R: 62
4775	R: 61
4779	R: 60
4782	R: 59
4785	R: 58
4788	R: 57
4791	R: 56
4794	R: 55
4797	R: 54
4800	R: 53
4803	R: 52
4806	R: 51
4809	R: 50
4812	R: 49
4815	R: 48
4818	R: 47
4822	R: 46
4825	R: 45
4828	R: 44
4831	R: 43
4834	R: 42
4837	R: 41
4840	R: 40
4843	R: 39
4846	R: 38
4849	R: 37
4852	R: 36
4855	R: 35
4858	R: 34
4861	R: 33
4864	R: 32
4867	R: 31
4870	R: 30
STOP:4873

Geht diese Variante mit weniger Ausgaben schneller?

const byte rotPin = 5;
const byte gruenPin = 3;
const byte smokePin = 13;
bool smoker = false;

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  pinMode(rotPin, OUTPUT);
  pinMode(gruenPin, OUTPUT);
  pinMode(smokePin, OUTPUT);
}

void loop()
{
  static unsigned long lastmillis = 0;
  if (millis() - lastmillis > 2)                         // Wenn Zeit abgelaufen ist...
  {
    glut();                                              // ... rufe Funktion auf ...
    lastmillis = millis();                               // ... merke Zeit
  }
  rauch();
}

void rauch()                                             // Es soll Rauch aufgehen
{
  static bool smokeStart = false;                        // Merker für den Start der Sequenz
  static unsigned long startZeit = 0;                    // StartZeit
  if (smoker == true)                                    // Wenn die Glut ausgelöst hat ...
  {
    if (smokeStart == false)                             // ... und bisher nicht ausgelöst war ...
    {
      startZeit = millis();                              // ... Zeit merken ...
      smokeStart = true;                                 // ... vermeidet, das die Zeit wieder gestellt wird ...
    }
    if (millis() - startZeit > 1000)                     // ... Zeit abgelaufen ...
    {
      digitalWrite(smokePin, HIGH);                      // ... dann las Rauch aufsteigen ...
    }
    if (millis() - startZeit > 1100)                     // ... noch mehr Zeit abgelaufen ...
    {
      digitalWrite(smokePin, LOW);                       // ... kein Rauch mehr
      smoker = false;                                    // setze Variablen zurück
      smokeStart = false;
    }
  }
}

void glut()                                              // Diese Funktion wird nur aufgerufen, wenn oben die Zeit abgelaufen
{
  const unsigned long dunkelPause = 3000;                // Zeit in ms die der PIN LOW ist
  const unsigned long hellPause = 500;                   // Zeit in ms die der PIN Dauerhaft HIGH ist
  static unsigned long lastmillis = 0;                   // Die Variable gilt nur lokal
  const byte minRot = 30;                                // kleinster Rot-Wert
  const byte minGruen = 0;                               // kleinster Gruen-Wert
  static bool heller = true;                             // diese Variable bestimmt die Richtung: ob heller(true) oder dunkler(false) werden soll
  static byte rotWert = minRot;                          // Startwert
  if ((millis() - lastmillis > dunkelPause) && heller)   // Wenn Dunkelpause abgelaufen UND die Richtung heller ist...
  {
    rotWert++;                                           // ... Increment ...
    if (rotWert > 254)                                   // ... Am oberen Ende? ...
    {
      heller = false;                                    // ... dann soll es dunkler werden ...
      lastmillis = millis();                             // ... merke die Zeit, wann es am hellsten war
      Serial.print(millis()); Serial.print('\t');
      Serial.print("R: "); Serial.print(rotWert);
      Serial.print("\tG: "); Serial.print(rotWert / 5);
      Serial.println();                                  // Und hier ist die Funkltion einmal durchlaufen
   }
  }
  if ((millis() - lastmillis > hellPause) && !heller)    // Wenn Hellpause abgelaufen ist UND die Richtung dunkler ist...
  {
    rotWert--;                                           // ... decrement ...
    if (rotWert < minRot)                                // ... am unteren Ende? ...
    {
      rotWert = minRot;                                  // ... setze kleinsten Rotwert ...
      heller = true;                                     // ... wechsle Richtung ...
      smoker = true;                                     // ... Jetzt darf der Rauch aufsteigen
      lastmillis = millis();                             // ... merke Umschaltzeit
      Serial.print(millis()); Serial.print('\t');
      Serial.print("R: "); Serial.print(rotWert);
      Serial.print("\tG: "); Serial.print(rotWert / 5);
           Serial.print("\nSTOP");                         // Diese beiden Zeilen nur
      Serial.println();                                  // Und hier ist die Funkltion einmal durchlaufen
           while (1);                                      // zum Durchlauftest
    }
  }
  analogWrite(rotPin, rotWert);                          // schreibe auf Pin
  if (rotWert > 180)                                     // Hier ist der Einsatz, ab wann der Farbraum verändert wird ...
  {
    analogWrite(gruenPin, (rotWert - 180) * 3);          // ... der Gruenwert errechnet sich aus dem rotWert ...
  }
  else analogWrite(gruenPin, minGruen);                  // ... Wenn der rotWert nicht erreicht, schreibe kleinsten GruenWert
}                                                        // der nächste Durchlauf ist erst wieder, wenn im loop die Zeit abgelaufen ist

Im Simulator: zigarette.ino - Wokwi ESP32, STM32, Arduino Simulator

Woran es liegt, werden wir jetzt nicht klären. Fakt ist, dass die eine Simulation in Echtzeit abläuft und die andere mit Faktor 10 und das bei zwei verschiedenen Simulatoren. Ich glaube ja gern, dass das ein Simulatorproblem ist, habe hier aber aktuell nun mal nix anderes. Wenn ich übernächste Woche wieder zu Hause bin, kaufe ich Hardware und dann kann ich da richtig weiter testen - jetzt müssen wir's es erstmal dabei belassen und ich danke sehr für Eure Inputs.

Da ich mit dem hier zur Verfügung stehenden Simulator aber noch ein bisschen rumprobieren wollte (und -ich gebe es gern zu- das mit der Programmiererei der millis() nicht ausreichend verstanden habe), habe ich versucht, mittels delay() der RGB-LED Orange zuzumischen und das läuft jetzt auch - inklusive Smoker. In dem Sketch finde ich für mich auch die Stellschrauben für Smoker-Länge, Farbwert, Auf- und Abblenddauer sowie Hellphase sehr viel leichter und es läuft, wie es soll. Vermutlich belasse ich es erstmal bei dieser delay()-Version und werde mich an die millis() Problematik langsam rantasten.

Nochmals danke für Eure Hilfe!

int ledRot = 5;
int ledGruen = 3;
int smoker = 13;



void setup()

{
pinMode(ledRot, OUTPUT);
pinMode(ledGruen, OUTPUT);
pinMode(smoker, OUTPUT);

}

void loop(){
//1. gedimmt für 30 sekunden 50 Rot
analogWrite(ledRot, 50);
delay(30000);
//2. innerhalb von 0.7 sek auf 190 Rot
for (int i = 50; i <= 255; i++) {
    analogWrite(ledRot, i);
    //3. innerhalb von 0.3 sek auf 255 Orange
    if(i >= 215){
      analogWrite(ledGruen,i-215);
    }
    delay(10);
  }
//4. 1 sek halten
delay(1000);

for (int i = 255; i >= 50; i--) {
  //5. innerhalb0.3 sek auf 0 Orange
    analogWrite(ledRot, i);
    if(i >= 215){
      //6. innerhalb 0.7 sek auf 50 rot
      analogWrite(ledGruen,i-215);
    }
    delay(10);
  }
//7. pause 1 sek
delay(1000);

//8. smoker 2 sekunden
analogWrite(smoker,255);
delay(2000);
analogWrite(smoker,0);
//9. repeat
}

Das heisst, das mein Code in beiden Simulatoren mit dem Faktor 10 läuft?

Das kannst schon so machen... aber ich würde es nicht empfehlen. Versuch es gleich richtig zu verstehen, sonst wirst Du auf absehbare Zeit immer abenteuerlichere delay()-Konstruktionen basteln.

Dieses Programm hat nur Ausgaben - spätestens wenn Du irgendwann mal eine Taste oder einen Sensor einbinden willst, fällt Dir das auf die Füße. Und das tut weh.

Ja. Bei tinkercad war es mir ja aufgefallen und bei Wokwi hatte agmue es nochmal hochgeladen. In beiden Simulatoren dasselbe Verhalten. Wahrscheinlich können die Simulatoren mit irgendwas im Sketch nicht umgehen.

Wenn Du meinst. Slash wird rauchen und das mit schönem Farbwechsel an der glühenden Zigarettenspitze. Das ist mehr, als ich zunächst geplant und erhofft hatte und somit alles andere als Kacke - ich danke aber für Deine Einschätzung

Dass ich -nachdem ich dieses Projekt installiert habe- weiter versuchen werde, die Materie zu verstehen, habe ich ja schon geschrieben - hast Du vielleicht überlesen. Mir sind die Vorteile ja durchaus eingängig. Warum ich mit diesem Projekt, das jetzt schon mindestens so gut funktioniert, wie ich das mal im Kopf hatte, allerdings so lange warten sollte, bis ich exakt dasselbe Verhalten mit einem Sketch realisieren könnte, der Gnade vor den Augen der Cracks findet, erschließt sich mir nicht.

Du kannst machen, was Du willst! In #16 hatte ich Dir geschrieben, daß mehrere Wege zum Ziel führen, Du hast die Wahl.

Wenn Du nie wieder was mit Arduino machen möchtest, dann freue Dich und ich freue mich mit Dir!

Die hier Aktiven kennen aber den Gedanken "eigentlich könnte ich doch noch ...", der so manchen nicht mehr losläßt. Ich wollte mal für einen Freund ein Modellhaus beleuchten, dann wurde es ein bewegter Kran und so weiter.

Sollten Dir also in nächster Zeit irgendwelche Ideen kommen, kennst Du Deine Hausaufgabe :roll_eyes:

Ob Dir klare Fäkalsprache oder meine umständlichen Worte besser gefallen, liegt in Deiner Entscheidung, die Tatsache als solche ändert sich dadurch nicht :slightly_smiling_face:

Ich bin damit raus.
Du wirst selbst finden warum.

Ich gebe zu, etwas zu drastisch verlinkt zu haben und vielleicht hast Du mich etwas mißverstanden.

Wenn das Projekt sogar besser tut als Du es anfangs vorhattest oder dachtest: Prima, an die Wand hängen und freuen. Das ist doch ein schönes Erfolgserlebnis, weil mit eigenem Hirn selbst hinbekommen. Da freue ich mich auch mit Dir!

"Gnade" ist allerdings wirklich falsch, darum geht es nicht (bin auch kein Crack). Es geht darum, dass Du, falls es noch mehr Projekte geben wird, so früh wie möglich die Fesseln des delay() los wirst. Den Weg willst Du ja beschreiten. Hier gibt es bei Bedarf die nötige Unterstützung.