Bit-banging PWM ohne delay?

Hallo,

stehe grade etwas auf dem Schlauch.

Wenn ich folgenden Code in einen Code ohne delay übersetzen möchte, brauche ich 2 unterschiedliche Blink without delay Schleifen ooder kkann ich das in einer kombinieren?

void setup()
{
  pinMode(13, OUTPUT);
}

void loop()
{
  digitalWrite(13, HIGH);
  delayMicroseconds(100); // Approximately 10% duty cycle @ 1KHz
  digitalWrite(13, LOW);
  delayMicroseconds(1000 - 100);
}

Danke für alle Antworten.

Nicht getestet, aber so sollte es funktionieren:

int time;
int wait_time;
int last_state;

void setup()
{
  pinMode(13,OUTPUT);
  time = millis();
  last_state = 0;
  wait_time = 100;
}

void loop()
{
  if (time + wait_time == millis())
  {
    if (last_state == 0)
    {
      digitalWrite(13,HIGH);
      last_state = 1;
    }
    else
    {
      digitalWrite(13,LOW);
      last_state = 0;
    }
    time = millis();
  }
}

LG

Fipsi

Edit: Und nachdem ich dann noch ne halbe Minute gesucht hab, fand ich das: Tutorial: Blink without Delay

Hi,

Danke für deine Antwort.

Dein Sketch erzeugt einen Rhytmmus der 1:1 ist oder als DutyCycle ausgedrückt 50%. Die OnZeit zur Offzeit muß aber variabel sein.

Gruß

Dann sollte das hier passen:

int time;
int time_on;
int time_off;
int last_state;

void setup()
{
  pinMode(13,OUTPUT);
  time = millis();
  last_state = 0;
  time_on = 100;
  time_off = 1000;
}

void loop()
{
  if ((last_state == 0) && (time + time_off == millis()))
  {
    digitalWrite(13,HIGH);
    last_state = 1;
    time = millis();
  }
  
  if ((last_state == 1) && (time + time_on == millis()))
  {
    digitalWrite(13,LOW);
    last_state = 0;
    time = millis();
  }
}

LG

Fipsi

Hi Fipsi,

geht leider auch nicht. Versuche aber paralle daran zu arbeiten und die Sache zu lösen.

Was daran geht denn nicht?

LG
Fipsi

Wenn ich z.B. ein Verhältniss von 1 Sekunde an und 9 Sekunden aus einstelle, blinkt es nur 2 mal und dann nicht wieder.

Wenn ich das als Beispiel nehme, benötige ich eine Periodendauer von 10 Sekunden, in der ich das Verhältniss von an zu aus einstellen kann.

Habs gerade mal ausprobiert, kann ähnliches berichten:
3x an, 2x aus.. jetzt immer dauerleuchten..

Weiß jetzt auch warum:
Es darf nicht heißen:

 if ((last_state == 0) && (time + time_off == millis()))

sondern if ((last_state == 0) && (time + time_off <= millis()))
weil sonst das Timing exakt auf die ms passen muss.. und das tut es nicht unbedingt.

int time;
int time_on;
int time_off;
int last_state;

void setup()
{
  pinMode(13,OUTPUT);
  time = millis();
  last_state = 0;
  time_on = 1000;
  time_off = 10000;
}

void loop()
{
  if ((last_state == 0) && (time + time_off <= millis()))
  {
    digitalWrite(13,HIGH);
    last_state = 1;
    time = millis();
  }
  
  if ((last_state == 1) && (time + time_on <= millis()))
  {
    digitalWrite(13,LOW);
    last_state = 0;
    time = millis();
  }
}

LG

Fipsi

Hi Fipsi,

nach 2 mal richtigen Ablauf kommt es wieder zu Problemen und die LED ist auf einmal dauer an.

Gruß

Ich habs gerade noch mal ein wenig umgeschrieben, bleib aber ebenfalls nach wie vor beim Fehler, dass die LED aus bleibt.. vorhin hatte ich mich zu früh gefreut..
Mein aktueller Code:

int time;
int time_on;
int time_off;
int last_state;

void setup()
{
  pinMode(13,OUTPUT);
  time = millis();
  last_state = 0;
  time_on = 1000;
  time_off = 9000;
}

void loop()
{
  if ((last_state == 0) && (time <= millis()))
  {
    digitalWrite(13,HIGH);
    last_state = 1;
    time = millis() + time_on;
  }
  
  if ((last_state == 1) && (time <= millis()))
  {
    digitalWrite(13,LOW);
    last_state = 0;
    time = millis() + time_off;
  }
}

(Ob die LED zu Beginn an ist, entscheidest du hierbei mir last_state im setup).

Ich glaub, da muss jetzt wer andres ran.. ich erkenn einfach nicht, warum er aufhört, sorry.

LG

Fipsi

Hi Fipsi,

trotzdem vielen Dank!

Wenn ich mehr finde, dann werde ich es hier posten.

Gruß

Hallo!

Wenn mit millis() gearbeitet wird müssen die Variablen die damit zu tun haben immer unsigned long sein weil millis() auch unsigned long ist. Also so:

unsigned long time;
unsigned long time_on;
unsigned long time_off;
...

So funktioniert der Code schon mal, obwohl er nicht sehr elegant ist und möglicherweise, wenn er überläuft (nach ca. 49 Tagen), zu Fehler führen könnte. Besser wäre das Intervall von millis() abzuziehen.

Hier noch mal eine Zusammenfassung, wenn man mit millis() arbeitet:
unsigned long für Zeitvariable verwenden (und nicht long oder int)
einen Startzeitpunkt festhalten
den Startzeitpunkt von der aktuellen Zeit subtrahieren um auf die Differenz zu kommen
überprüfen ob diese Differenz größer ist als das gewünschte Intervall

Gruß
Udo