erster Beitrag hier, also sorry für das schlechte Styling.
Ich arbeite an einem Gruppenprojekt und verwende einen Atmega328, ohne auf Einzelheiten einzugehen. Ich muss zwei Lüfter, zwei Servos und 1 CTC-basierte Funktion von 3 Timern ansteuern. Zu meiner Frage dann; Es gibt die Register OCRx A und B, die ich verwende, um die Lüfter mit variablen Geschwindigkeiten anzutreiben, und eine ähnliche Methode für die Servos. Beim Einrichten eines sehr einfachen PWM-Skripts habe ich festgestellt, dass beide Register einen Lüfter antreiben. Wenn ich jedoch versuche, eines der Register unabhängig voneinander zu verwenden (Lüfter 1 ein, 2 aus, dann ändern), erzeugt OCRxB keine Ausgabe.
Hier ist ein Ausschnitt meines Setup-Codes:
void setup_timers () {
// Set Timer0 to Fast PWM mode
TCCR0A |= (1 << WGM01) | (1 << WGM00);
// Set Timer0 to clear OCR0 A/B on match
TCCR0A |= (1 << COM0A1) | (1 << COM0A0) | (1 << COM0B1) | (1 << COM0B0);
TCCR0B |= (1 << CS01);
TCNT0 = 0;
// Set OCR0 A/B
DDRD = 0xFF;}
Idealerweise werden dadurch beide Register in Timer 0 für Ausgänge eingerichtet. Ich sende dieses Signal an einen Transistor, der dann die Lüfter antreibt, wie durch dieses nächste Bit bestimmt:
int main () {
setup_timers();
while (1) {
/* Timer 0; OCR0A (i = 0, L), OCR0B (i = 1, R), i = 2 denotes both fans */
for (uint8_t i = 0; i <= 3; i++) {
// Cycle Fans Left/Right/Both
for (uint8_t j = 1; j <= 4; j++) {
// Cycle Speed
if (i == 2) {
// Check motor; run timer 0 A/B as required
OCR0A = 0xFF * j / 4;
OCR0B = 0xFF * j / 4;
_delay_ms(2000);
}
else if (i == 1) {
OCR0A = 0xFF * j / 4;
OCR0B = 0;
_delay_ms(2000);
}
else if (i == 0) {
OCR0A = 0;
OCR0B = 0xFF * j / 4;
_delay_ms(2000);
}
}
}
}
return 1; }
Jetzt weiß ich, dass dies besser gemacht werden könnte, dieses Segment hat einen Haufen anderer Tests, die ausgeschnitten wurden. Das Hauptproblem hier ist, dass Lüfter 1 läuft (gesteuert von OCR0A), Lüfter 2 jedoch vollständig ignoriert wird. Ich habe das Datenblatt ein paar Mal durchgelesen, aber es war etwas unklar, ob dies tatsächlich möglich ist, es stand etwas darüber, dass OCRxB nicht gespeichert wird, und ich habe andere Beiträge gesehen, die danach fragten. Soweit ich weiß, handelt es sich um unabhängige Register, aber ist es möglich, dass OCRxA beibehalten wird, aber nach dem Schreiben von OCRxB nicht mehr ausgeführt werden kann?
Oder vielleicht liege ich auch komplett falsch, wäre sicherlich nicht das erste Mal.
Es scheint, dass es ein Problem mit den vorgegebenen Werten gab, durch Einstellen von COM1A0 und COM1B0 kann Timer 1 so konfiguriert werden, dass er unabhängige Signale gibt. Dies ist der Setup-Code, der funktioniert:
void setup_timers () {
TCCR1A |= (1 << WGM11) | (1 << WGM10);
TCCR1A |= (1 << COM1A1) | (1 << COM1A0) | (1 << COM1B1) | (1 << COM1B0);
TCCR1B |= (1 << CS11);
TCNT1 = 0;
DDRB = 0xFF;}
Ich habe immer noch Probleme damit, die Motoren richtig zu steuern, aber die Servos funktionieren gut, und es kann getan werden.
Hinweis: Timer 1 hat tatsächlich zwei getrennte Ausgänge, Timer 0/2 jedoch nicht. Um zwei Ausgänge zu erhalten, müssen Sie WGMx2 und die COMxB 0/1-Register umschalten, wenn WGMx2 eingestellt ist, wird OCRxA nicht richtig ausgegeben, OCRxB jedoch mit etwas Fummelei. Wenn WGMx2 nicht eingestellt ist, wird OCRxB deaktiviert und OCRxA funktioniert normal. Um unabhängige Ausgaben zu erhalten, müssen Sie dies berücksichtigen.
KyranF
TMa
Michael Karas
TMa
Oman
KyranF
Oman
KyranF
Oman
KyranF
KyranF
Oman
Oman