Hallo,
ich suche ein Programm Snipped für die Erzeugung eines einzelnen Pulses (ca. 100ms bis 2 s) an einem Ausgangspin. Das Besondere dabei ist allerdings, dass der Arduino nachdem der Ausgangspuls aktiviert wurde, weiterarbeitet. Also nicht nach dem üblichen Weg: Pin an, delay(x), Pin aus.
Habe schon google befragt, aber nichts passendes gefunden. Das müsste eigentlich mit einem Timer realisierbar sein, ich habe aber noch keinen Weg gefunden, dass der Timer nur einmal abläuft. Eventuell kann man mit Ablaufen des Timers einen Interrupt auslösen, der in der ISR dafür sorgt, dass der Timer gestoppt wird. Ich bin in der Programmierung direkt mit Registern nicht so firm, vieleicht hat ja jemand eine anderer Idee, wie das Problem zu lösen ist.
Reinhard
Was ihr immer mit Timern habt... 100 ms ist für einen Mikrocontroller, der mit 16 MHz getaktet ist, eine wahnsinnig lange Zeit. Timer würde ich an sich nur bei zeitkritischen Sachen verwenden. Scha dir einfach mal das Beispiel "Blink without Delay" an, dort wird ziemlich genu das gemacht, was du willst.
@sth77
das geht in die richtige Richtung, ist aber noch nicht genau das, was ich will. Bei dieser Lösung muss ich in der Loop immer wieder überprüfen, ob der Ausgang noch HIGH sein muss, oder ob "seine Zeit schon abgelaufen ist". Das müsste ich dann auch in jeder anderen Programmschleife tun, z.B. auch, wenn ich auf eine Eingabe warte.
Ich suchte ehr nach einer Lösung, wo ich mich nach dem Einschalten im weiteren Programm nicht mehr darum kümmern muss, dass irgendwann abgeschaltet werden muss.
@Uwe,
ist leider auch nicht das, was ich mir vorstelle. Es wird zwar einiges im Hintergrund versteckt, aber die Abfrage des Status muss immer noch in jeder Schleife passieren.
Ich habe mich mal mit den Timern beschäftigt und das Datenblatt gewälzt. Herausgekommen ist dabei folgendes Programm
// #include <avr/interrupt.h>
// #include <avr/io.h>
#define INIT_TIMER_COUNT 0
#define RESET_TIMER1L TCNT1L = INIT_TIMER_COUNT
#define RESET_TIMER1H TCNT1H = INIT_TIMER_COUNT
volatile int int_counter = 0;
unsigned long count;
int LEDPin = 11;
// Arduino runs at 16 Mhz, so we have 0.23 Overflows per second or every 4.2s with prescaler of 1024
// 16000000 / 1024 / 256 / 256) = 0.2384
ISR(TIMER1_COMPA_vect) {
int_counter++; // only for demonstration and check in the main loop
digitalWrite(LEDPin, LOW); // set the LED off
};
void setup() {
pinMode(LEDPin, OUTPUT);
// digitalWrite(LEDPin, HIGH); // set the LED off
Serial.begin(9600);
Serial.println("Initializing timerinterrupt");
TCCR1A = 0; // setup timer 1 for CTC mode
TCCR1B = 0;
TCCR1B |= ((1 << CS12) | (1 << CS10)); // prescaler 1024
// TCCR1B |= (1 << CS12); // change to prescaler 256 for shorter pulses
TCCR1B |= (1 << WGM12); // Counter reset on compare
TIMSK1 |= (1 << OCIE1A); // interrupt compare
OCR1AH = 0x4F; // set 0x4FFF for approx. 1s at 1024 prescaler
OCR1AL = 0xFF;
RESET_TIMER1H;
RESET_TIMER1L;
sei();
}
void loop() {
Serial.println("Please select");
Serial.println("1 - generate pulse with last preset value");
Serial.println("2 - change to short pulse and generate one");
Serial.println("3 - change to long pulse and generate one\n");
while(!Serial.available()){} // generating pulses and resetting while in the loop
switch(Serial.read())
{
case '1':
newPulse(); // select preset lenght
break;
case '2':
newPulseComp(0x0FFF); // change pulse width and generate one
break;
case '3':
newPulseComp(0x8FFF); // change pulse width and generate one
break;
default:
break;
}
}
void newPulse() // to generate a new pulse with last comparator value
{
digitalWrite(LEDPin, HIGH);
RESET_TIMER1H;
RESET_TIMER1L;
}
void newPulseComp(unsigned int compare) // to generate a new pulse with new pulsewidth
{
OCR1AH = ((compare & 0xFF00) >> 8) ;
OCR1AL = compare & 0x00FF;
digitalWrite(LEDPin, HIGH);
RESET_TIMER1H;
RESET_TIMER1L;
}
Ich benutze den Timer1 des Arduino Mega2560 mit vorgewählten Comparatorwerten und schalte im Interrupthandler den Puls wieder aus. Das Programm zeigt ein Beispiel. Während man in der Eingabeschleife hängt, wird der Puls wieder abgeschaltet. Als Basis wird nur relativ wenig Code benötigt. Das Beispiel sollte sich relativ leicht auf andere Prozessoren adaptieren lassen. Es müssen tw. nur die Registerbezeichnungen angepasst werden.
Hallo erni-berni
Entschuldige, daß ich wiederhole was sth77 bereits gesagt hat:
Schau dir einfach mal das Beispiel "Blink without Delay" an, dort wird ziemlich genau das gemacht, was du willst.
Das ist die Einfachste Lösung.
ein "Serial.begin(9600);" schlukt auch einiges an Zeit; verwende eine höher Baudrate.
Grüße Uwe