Arduino Uno 10-Bit PWM Problem / Timer1

Hallo,
Ich habe ein Problem mit meinem Arduino Uno.
Ich möchte Pin 9 des Arduinos benutzen um eine Led Konstanstromquelle anzusteuern.
Da mir 8-Bit zu wenig sind würde ich gerne 10-Bit verwenden, welches auch soweit funktioniert.
Den Timer1 des Arduinos habe ich wie folgt konfiguriert:
-Fast PWM, 10bit
-Prescaling auf 8

void setup()
{  
noInterrupts();
/**********************************************************************************/
// Set pwm clock divider Clock / 8
/**********************************************************************************/ 
 TCCR1B &= ~(1 << CS12);
 TCCR1B  |=   (1 << CS11);
 TCCR1B &= ~(1 << CS10);
  
/**********************************************************************************/
// Set pwm resolution to mode 7 / Fast PWM 10 bit
/**********************************************************************************/ 

TCCR1B &= ~(1 << WGM13);    // Timer B clear bit 4
TCCR1B |= (1 << WGM12);     // set bit 3

TCCR1A |= (1 << WGM11);     //  Timer A set bit 1
TCCR1A |= (1 << WGM10);     //  set bit 0
interrupts();

pinMode(redpin, OUTPUT); 
}

Zum Testen besteht mein Loop aus folgendem Code:

  analogWrite(redpin, 100);
  delay(2000);  
  analogWrite(redpin, 255);
  delay(2000); 
  analogWrite(redpin, 256);
  delay(2000);  
  analogWrite(redpin, 500);
  delay(2000); 
  analogWrite(redpin, 510);
  delay(2000); 
  analogWrite(redpin, 1023);
  delay(2000);

Das funktioniert soweit auch, bis auf den Wert 255.
Genau an dieser Stelle leuchtet meine Led mit der maximalen Helligkeit,
als ob der maximale Wert des 8-Bit Bereichs erreicht werden würde.
Danach läuft der Verlauf normal weiter, wie es bei 10-Bit sein sollte.

Hat vielleicht einer eine Idee woran das liegen könnte?

Mfg. Ardion

Du musst auf das Standard analogWrite() verzichten. Das ist nämlich das drin:

	if (val == 0)
	{
		digitalWrite(pin, LOW);
	}
	else if (val == 255)
	{
		digitalWrite(pin, HIGH);
	}

Also bei den Extrem-Werten wird gar kein PWM gemacht

Am besten du schreibt dir eine eigene analogWrite() Variante die das anders macht. Siehe wiring_analog.c für was da die IDE macht.

Ahh,
Danke :slight_smile:

Ich habe mir jetzt die passenden Ausschnitte für Timer1 aus der wiring_analog.c heraus kopiert und
die Überprüfung von val==255 auf 1023 abgeändert.
Damit scheint es zu funktionieren.

void PWMOut(uint8_t pin, int val)
{
  pinMode(pin, OUTPUT);
  if (val == 0)
  {
    digitalWrite(pin, LOW);
  }
  else if (val == 1023)
  {
    digitalWrite(pin, HIGH);
  }
  else
  {
    switch (digitalPinToTimer(pin))
    {
#if defined(TCCR1A) && defined(COM1A1)
      case TIMER1A:
        // connect pwm to pin on timer 1, channel A
        sbi(TCCR1A, COM1A1);
        OCR1A = val; // set pwm duty
        break;
#endif

#if defined(TCCR1A) && defined(COM1B1)
      case TIMER1B:
        // connect pwm to pin on timer 1, channel B
        sbi(TCCR1A, COM1B1);
        OCR1B = val; // set pwm duty
        break;
#endif

#if defined(TCCR1A) && defined(COM1C1)
      case TIMER1C:
        // connect pwm to pin on timer 1, channel B
        sbi(TCCR1A, COM1C1);
        OCR1C = val; // set pwm duty
        break;
#endif

      case NOT_ON_TIMER:
      default:
        if (val < 128) {
          digitalWrite(pin, LOW);
        } else {
          digitalWrite(pin, HIGH);
        }
    }
  }
}

:slight_smile:

Du könntest es auch so machen, dass das normale analogWrite() aufgerufen wird wenn der Pin nicht zu Timer1 gehört. Kann aber auch sein, dass du das nicht brauchst.