Innerhalb eines grösseren Projekts verzweifle ich gerade an einer einfachen Detailfunktion. Im Prinzip ist es die Anwendung des "Blink Without Delay" Bespiels. Ich möchte einen Ausgang zwei mal in Folge kurz ansteuern, dann soll eine längere Pause folgen.
Der Code sieht wie folgt aus (gekürzt):
// variables for ringing
int RING_PIN_STATE = LOW;
unsigned long previousMillis = 0;
unsigned long previousMillis2 = 0;
const long intervallRing = 1000; //intervall klingeln (ms)
const long intervallBreak = 10000; //intervall Pause zwischen klingeln (ms)
void loop() {
unsigned long currentMillis = millis();
unsigned long currentMillis2 = millis();
// Klingeln nach Zufallszeit (intervallBreak)
else if (currentMillis - previousMillis >= intervallBreak){
previousMillis = currentMillis;
//Zweimal Klingeln
for (int i = 0; i <= 3; i++) {
if (currentMillis2 - previousMillis2 >= intervallRing) {
previousMillis2 = currentMillis2;
if (RING_PIN_STATE == LOW) {
RING_PIN_STATE = HIGH;
} else {
RING_PIN_STATE = LOW;
}
}
}
digitalWrite(RING_PIN, RING_PIN_STATE);
Das Problem ist nun, dass der Ausgang im Takt von "intervallBreak" toggelt. Eigentlich soll der Ausgang viermal für die Zeit "intervallRing" toggeln und dann soll für die Zeit "intervallBreak" nichts passieren.
Das Ganze läuft auf einem Teensy 4.0, der unterstützt leider kein Debugging
Ich hoffe jemand unabhängiges sieht den Fehler direkt.
Das ist Mist. Wer soll sich denn da einen reim drauf machen.
// Ich möchte einen Ausgang zwei mal in Folge kurz ansteuern, dann soll eine längere Pause folgen.
// Eigentlich soll der Ausgang viermal für die Zeit "intervallRing" toggeln und dann soll für die Zeit "intervallBreak" nichts passieren.
// variables for ringing
constexpr byte ringPin {3};
constexpr unsigned long intervallRing {1000}; //intervall klingeln (ms)
constexpr unsigned long intervallBreak {10000}; //intervall Pause zwischen klingeln (ms)
unsigned long breakTime = intervallRing;
unsigned long lastmillis;
byte zaehler = 0;
void setup()
{
pinMode(ringPin, OUTPUT);
digitalWrite(ringPin, LOW);
}
void loop()
{
machSwitchFunktion();
}
void machSwitchFunktion()
{
if (millis() - lastmillis > breakTime)
{
lastmillis = millis();
switch (zaehler)
{
case 0 ... 3:
digitalWrite(ringPin, !digitalRead(ringPin));
if (zaehler == 3)
{
breakTime = intervallBreak;
}
break;
case 4:
breakTime = intervallRing;
digitalWrite(ringPin, LOW);
break;
default:
zaehler = 0;
break;
}
zaehler++;
}
}
Herzlich Willkommen im weltbesten Arduino Forum der Welt.
Hier kommt eine angepasste Version des "Blink Without Delay" Bespiels.
Ich habe ein array eingelötet, das die unterscheidlichen Zeiten für das Interval enthält.
// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN;// the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
uint8_t indexCounter;
uint8_t ringState=HIGH;
// constants won't change:
const long interval[] {1000,1000,10000,1000}; // intervals at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval[indexCounter]) {
// save the last time you blinked the LED
previousMillis = currentMillis;
indexCounter=(indexCounter+1)%(sizeof(interval)/sizeof(interval[0]));
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState and ringState);
}
}
Das könnte auch als nur 1 Zyklus interpretiert weden, von z.B. insgesamt 4 sec.
In den ersten 500 ms an, dann aus, von 1000 bis 1500 ms wieder an, dann aus, bis die 4000 ms erreicht sind.
Vielen Dank für den schnellen und zahlreichen Support!
Das Beispiel von paulpaulson habe ich umgesetzt und der Blinktakt funktioniert auch. Nun möchte ich den Blinktakt jeweils nach Zeitspanne "intervalBreak" starten, daran scheitere ich gerade. Eigentlich sollte die Logik doch gleich sein, nur veschachtelt.
Probier mal die folgende Modifikation des Sketches aus.
Evt. muss die Zeit in der Variable mit dem Namen intervallBreak noch angepasst werden.
// constants won't change. Used here to set a pin number:
const int ledPin = LED_BUILTIN;// the number of the LED pin
// Variables will change:
int ledState = LOW; // ledState used to set the LED
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis = 0; // will store last time LED was updated
unsigned long previousMillis2 = 0;
uint8_t indexCounter;
uint8_t ringState = HIGH;
const long intervallBreak = 30000; //intervall Pause zwischen klingeln (ms)
// constants won't change:
const long interval[] {1000, 1000, 10000, 1000}; // intervals at which to blink (milliseconds)
void setup() {
// set the digital pin as output:
pinMode(ledPin, OUTPUT);
}
void loop() {
// here is where you'd put code that needs to be running all the time.
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis = millis();
unsigned long currentMillis2 = millis();
// Start Blinksequenz nach Zeit intervallBreak
if (currentMillis2 - previousMillis2 >= intervallBreak) {
previousMillis2 = currentMillis2;
ringState = ringState ? LOW : HIGH;
}
if (currentMillis - previousMillis >= interval[indexCounter]) {
// save the last time you blinked the LED
previousMillis = currentMillis;
indexCounter = (indexCounter + 1) % (sizeof(interval) / sizeof(interval[0]));
// if the LED is off turn it on and vice-versa:
if (ledState == LOW) {
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(ledPin, ledState and ringState);
}
}
Ich wünche einen geschmeidigen Tag und viel Spaß beim Programmieren in C++.
Hab jetzt eine Zustandsautomaten nach dem Bespiel aus #3 gebaut.
// Ich möchte einen Ausgang zwei mal in Folge kurz ansteuern, dann soll eine längere Pause folgen.
// Eigentlich soll der Ausgang viermal für die Zeit "intervallRing" toggeln und dann soll für die Zeit "intervallBreak" nichts passieren.
#define RING_PIN 1
// variables for ringing
constexpr byte ringPin {3};
constexpr unsigned long intervallRing {1000}; //intervall klingeln (ms)
constexpr unsigned long intervallBreak {10000}; //intervall Pause zwischen klingeln (ms)
unsigned long breakTime = intervallRing;
unsigned long lastmillis;
byte zaehler = 0;
void setup()
{
pinMode(RING_PIN, OUTPUT);
digitalWrite(RING_PIN, LOW);
}
void loop()
{
machSwitchFunktion();
}
void machSwitchFunktion()
{
if (millis() - lastmillis > breakTime)
{
lastmillis = millis();
switch (zaehler)
{
case 0 ... 3:
digitalWrite(RING_PIN, !digitalRead(RING_PIN));
if (zaehler == 3)
{
breakTime = intervallBreak;
}
break;
case 4:
breakTime = intervallRing;
digitalWrite(RING_PIN, LOW);
break;
default:
zaehler = 0;
break;
}
zaehler++;
}
}
Im ersten Durchgang funktionier es, danach ist Ausgang für 10s HIGH (anstatt LOW für intervallBreak). Die Zeit intervallBreak wird doch nur in case 4 geschrieben, in diesem case wird der Ausgang doch automatisch auf LOW gesetzt.
Nein die wird im ersten case gesetzt, wenn der Zaehler 3 ist.
Damit ist beim nächsten Umlauf breakTime 10000 Sekunden.
Das heisst es dauert genau so lange bis case 4 erreicht wird.
Empfehlung: Wenn der zaehler == 3 die breakTime setzt, in dem selben Funktionsblock den ringPin LOW setzen, oder noch spannender:
// Ich möchte einen Ausgang zwei mal in Folge kurz ansteuern, dann soll eine längere Pause folgen.
// Eigentlich soll der Ausgang viermal für die Zeit "intervallRing" toggeln und dann soll für die Zeit "intervallBreak" nichts passieren.
// variables for ringing
constexpr byte ringPin {1};
constexpr unsigned long intervallRing {1000}; //intervall klingeln (ms)
constexpr unsigned long intervallBreak {10000}; //intervall Pause zwischen klingeln (ms)
unsigned long breakTime = intervallRing;
unsigned long lastmillis;
byte zaehler = 0;
void setup()
{
pinMode(ringPin, OUTPUT);
digitalWrite(ringPin, LOW);
}
void loop()
{
machSwitchFunktion();
}
void machSwitchFunktion()
{
if (millis() - lastmillis > breakTime)
{
lastmillis = millis();
switch (zaehler)
{
case 0 ... 3:
digitalWrite(ringPin, !digitalRead(ringPin));
if (zaehler == 3)
{
}
break;
case 4:
breakTime = intervallBreak;
digitalWrite(ringPin, LOW);
break;
case 5:
breakTime = intervallRing;
break;
default:
zaehler = 0;
break;
}
zaehler++;
}
}
Du kannst statt einer LED natürlich auch einen Buzzer anschließen.
Du nimmst einfach den Effekt für die Rhythm LED und setzt deine Zeiten:
/*
Rhythm LED
by noiasca
*/
#include <Noiasca_led.h> // download library from http://werner.rothschopf.net/microcontroller/202202_tools_led_en.htm
#include <utility/Noiasca_discrete.h> // use the discrete pins on the Arduino/Microcontroller
RhythmPin rhythmLed {13}; // declare LED and assign pin
void setup() {
rhythmLed.begin(); // you have to call the .begin() method for the LED
// ON OFF ON OFF
rhythmLed.setInterval(1000, 1000, 1000, 10000);
rhythmLed.on(); // you can switch the effect on
}
void loop() {
rhythmLed.update(); // you have to call update() for the LED
}
sollte das geblinke abgeschaltet werden müssen ruf einfach ein