-
-
LED-Steuerung und Kamera-Triggerung mit dem Mega32
Moin!
Ich bin recht neu in der µC Welt und bräuchte mal einen Ratschlag:
Ich möchte nach dem Empfang eines Zeichens über RS232 hin für eine Bestimmte Zeit eine LED mit einem PWM-Signal(niedrig) ansteuern und danach für die gleiche Dauer mit einem zweiten PWM-Signal. Außerdem soll jeweils für die Zeit ein Pin auf "1" gesetzt werden.
Die "Teilaufgaben" habe ich bis auf die Dauer schon gelöst, dh ich kann über das Hyperterminal Werte für die PWM an den Controller schicken und den Wert für die PWM ändern. Nun ist die Frage, wie ich am Besten die "Verzögerung" realisiere.
Meine Idee ist es in main auf den "Befehl" zu warten. Wenn der "Befehl" kommt möchte ich den ersten PWM-Wert laden, den Kameratrigger setzen und einen Timer starten. Wenn der Timer "überläuft" stoppe setze ich das Triggersignal auf 0, setze den zweiten PWM-Wert und ein Flag. Dann setze ich das Triggersignal wieder und starte den Timer erneut. Wenn der Timer diesmal überläuft, wird er nicht neu gestartet, das Flag zurückgesetzt und die PWM-gestoppt und das Triggersignal wird auf "0" gesetzt.
Kann jemand einen Fehler in der Logik oder dem Stil erkennen oder hat gar eine bessere Lösung?
Danke im Voraus!
P.S.: Falls es von Belang ist, ich benutze das Pollin Evaluation Board 2.0
-
Moin!
Ich habe schonmal etwas Code zusammengebastelt, kann ihn aber noch nicht "in der Praxis" testen.
Wäre nett, wenn ihn sich jemand anschauen würde und mich auf Fehler hinweisen bzw Verbesserungsvorschläge abgeben könnte.
Ach ja, das Triggersignal soll an PortD.6 ausgegeben werden und das pwm-Signal erscheint an PortB.1 (Soll es zumindest).
[php:1:2054a8c87f]#include <avr/interrupt.h>
#define BAUD 9600
#define F_CPU 16000000
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
volatile int brightness = 10;
volatile int oldBrightness = 10;
volatile int flash1 = 0;
volatile int flash2 = 0;
volatile int flashLevel = 0;
void uart_init(void)
{
// Baudrate einstellen ( Normaler Modus )
UBRRH = (unsigned char) (UBRR_BAUD>>;
UBRRL = (unsigned char) UBRR_BAUD;
// Aktivieren von Receiver und Transmitter
UCSRB = (1<<RXEN)|(1<<TXEN);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit, keine Parität
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
int write_char (unsigned char *buffer)
{
// Warten bis der Sendepuffer frei ist
while ( !( UCSRA & (1<<UDRE)) );
// Daten in den Puffer schreiben und damit senden
UDR = *buffer;
// Nach Linefeed ein Return senden
if (*buffer == 10)
{
while ( !( UCSRA & (1<<UDRE)) );
UDR = 13;
}
// Nach Return ein Linfeed senden
if (*buffer == 13)
{
while ( !( UCSRA & (1<<UDRE)) );
UDR = 10;
}
return 0;
}
int write_string(unsigned char *string)
{
while (*string != 0)
{
write_char(string);
string++;
};
return 0;
}
int read_char(unsigned char *buffer)
{
int rec;
// testen ob Daten empfangen wurden
rec = (UCSRA & (1<<RXC));
if (rec)
{
// Empfangsregister auslesen
*buffer = UDR;
}
return rec;
}
/************************************************** **
* Timer-Interruptroutine für die Belichtungszeit (330ms)
************************************************** ***/
ISR(TIMER1_OVF_vect)
{
if(flashLevel == 1)
{
//Kamera-Trigger ausschalten
Kamera_Trigger &= ~(1 << 6);
|= (1 << 6);
_CLI();
//flag für Blitzstufe erhöhen
flashLevel = 2;
//PWM-Wert für die Zweite Blitzstufe setzen
OCR0A = flash2;
sei();
//Kamera-Trigger einschalten
Kamera_Trigger |= (1 << 6);
}
else if(flashLevel == 2)
{
_CLI();
//Kamera-Trigger ausschalten
Kamera_Trigger &= ~(1 << 6);
//flag für Blitzstufe
flashLevel = 0;
sei();
//PWM-Wert für die Beleuchtung setzen
OCR0A = brightness;
}
}
/************************************************** **
* Hauptprogramm
************************************************** ***/
int main()
{
//===========================================
// Konfigurationen
//===========================================
//Buffer für Eingaben
unsigned char buffer;
// Port D 5 (LED1)wird als Ausgang bestimmt.
DDRD |= _BV(PD5);
// Port D 2 (Taster1) wird als Input festgelegt.
DDRD &= ~_BV(PD2);
uart_init();TCCR1B = (1<<CS10);
//Timer0 als PWM einstellen PortB3
TCCR0 = (1<<WGM01)|(1<<WGM00)|(1<<COM01);
//Prescaler von 256 für 62,5kHz
TCCR0 = (1<<CS02);
//Startwert für die Helligkeit initialisieren
OCR0 = brightness;
//Timer1 als Timer schalten
TCCR1 = (1<<C12); // Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)
TCNT1 = 44911; // Vergleichswert um nun 330ms zu Zählen
DDRD = (1<<6);
//Timer 0 (PWM) starten
TIMSK = (1<<OCIE0);
//Interrupts freigeben
sei();
//Startmeldung ausgeben
write_string("Controller gestartet...\n");
//===========================================
// Hauptprogramm
//===========================================
while(1)
{
// RS232 abfragen
if(read_char(&buffer))
{
int controlWord = (int)buffer & 192;
int data = (int)buffer & 63;
switch(controlWord)
{
//Helligkeit ausgeben
case 0: buffer = (char)brightness; write_string(&buffer);break;
//Helligkeit setzen
case 128:
{
if(data < 10)
{
brightness = data << 1;
_CLI();
OCR0A = brightness;
sei();
}
}; break;
//blitzstufe setzen und aufnahme starten
case 192:
{
if(data < 16)
{
flash1 = data;
flash2 = (data << 4);
_CLI();
OCR0A = flash1;
flashLevel = 1;
//Kamera-Trigger einschalten
Kamera_Trigger |= (1 << 6);
//Timer1 Starten
TIMSK |= (1<<OCIE1A);
sei();
}
}; break;
}
}
}
return 0;
}[/php:1:2054a8c87f]
-
Erfahrener Benutzer
Roboter Genie
In der TIMER1_OVF_vect cli() und sei() jeweils vor bzw. nach den ifs.
Ich weiss nicht, ob die _BV Makros in den neuen versionen des avr_gcc noch verwendet werden. Aber Du solltest die auf jeden fall einheitlich benutzen (mal hast Du _BV verwendet, ein anderes mal verwendest Du normale shifts).
-
Danke für die Antwort!
Ich habe aber das Problem in der Zwischenzeit anders gelöst. Ich habe mir nun mit _delay_ms() meine Verzögerungen gebastelt und schalte so nach gewissen Zeiten den Trigger und die PWM für die LED um. Heute habe ich den Spaß mal ausprobiert und es scheint gut zu funktionieren.
Schönes Wochenende!
Berechtigungen
- Neue Themen erstellen: Nein
- Themen beantworten: Nein
- Anhänge hochladen: Nein
- Beiträge bearbeiten: Nein
-
Foren-Regeln
Lesezeichen