Chciałbym zwiększyć rozdzielczość bitową PWM Arduino Uno. W tej chwili jest to 8-bit, co uważam za zbyt niskie. Czy jest to możliwe bez utraty zdolności przerwania i opóźnień?
Koen
EDYCJA Ta konfiguracja zapewnia wynik 16-bitowy
void setupPWM16() {
DDRB |= _BV(PB1) | _BV(PB2); /* set pins as outputs */
TCCR1A = _BV(COM1A1) | _BV(COM1B1) /* non-inverting PWM */
| _BV(WGM11); /* mode 14: fast PWM, TOP=ICR1 */
TCCR1B = _BV(WGM13) | _BV(WGM12)
| _BV(CS11); /* prescaler: clock / 8 */
ICR1 = 0xffff; /* TOP counter value (freeing OCR1A*/
}
/* Comments about the setup
Changing ICR1 will effect the amount of bits of resolution.
ICR1 = 0xffff; (65535) 16-bit resolution
ICR1 = 0x7FFF; (32767) 15-bit resolution
ICR1 = 0x3FFF; (16383) 14-bit resolution etc....
Changing the prescaler will effect the frequency of the PWM signal.
Frequency[Hz}=CPU/(ICR1+1) where in this case CPU=16 MHz
16-bit PWM will be>>> (16000000/8)/(65535+1)=30.5175Hz
*/
/* 16-bit version of analogWrite(). Works only on pins 9 and 10. */
void analogWrite16(uint8_t pin, uint16_t val)
{
switch (pin) {
case 9: OCR1A = val; break;
case 10: OCR1B = val; break;
}
}
źródło
ICR1
na0x1fff
, wtedy twoja częstotliwość będzie wynosić 1953 Hz (F_CPU / (TOP + 1)) z preskalerem na 1.ICR1 = 0x03FF
a przy 0 widzę niewielki puls na lunecie wystarczający do zapalenia diody LED. Jakieś pomysły?analogWrite16(pin, val)
daje cykl pracy (val + 1) / ICR1. Jako obejście tego problemuanalogWrite()
działa Arduinoif (val == 0) digitalWrite(pin, LOW); else if (val == 255) digitalWrite(pin, HIGH);
. Ale wtedy nie można uzyskać cyklu pracy 1 / ICR1 ...Po pewnej kalibracji można zsumować wyniki dwóch kanałów PWM z różnymi rezystorami ważącymi. Skrajnie możesz użyć jednego wyjścia, aby zapewnić 8 bitów rozdzielczości, a skalować drugie do 1/256 poziomu i dodać je, aby drugi kanał obejmował jeden bit zakresu, a ty (znowu hipotetycznie) uzyskasz 16 bitów rozdzielczości. Bez ogromnej opieki i dostosowania wszystko, co dostaniesz, byłoby bałaganem.
Jednak dzieląc drugi kanał przez 16 lub 32, można dodać kilka dodatkowych bitów rozdzielczości PWM. Po dodaniu 2 kanałów PWM filtrowanych wyjść analogowych dodajesz dodatkowy bit (ponieważ potencjalny zakres jest podwojony dla niezmienionego mV / bit).
Po raz kolejny (ponownie) za każdy dodatkowy podział przez 2 otrzymujesz dodatkową odrobinę rozdzielczości, ale można to zrobić tylko dla 4 lub 5 lub 6 dodatkowych bitów, przy rosnących wymaganiach dotyczących dokładności rezystorów skalujących oraz trudniejszej kalibracji i podatności na błędy .
Krótki przykład
Jeśli jeden PWM zostanie przeskalowany w dół, aby dać powiedzmy 0 - 255 mV w krokach 1 mV, wówczas zsumowanie dwóch PWM o równej amplitudzie dałoby zakres 0 - 510 mV w krokach 1 mV.
Jeśli jeden PWM zostanie zmniejszony o współczynnik 32, to zamiast dodać 255 mV do początkowego zakresu PWM, dodałby tylko 8 mV do górnego końca (0,2566,32 = 8 mV, ale rozdzielczość byłaby w 0,03125 (1/32 ) kroki mV.
Podczas gdy być może można to osiągnąć wyłącznie za pomocą sumowania rezystorów i filtrowania RC, użycie letniego wzmacniacza operacyjnego znacznie poprawiłoby wyniki.
Również tętnienia PWM można filtrować za pomocą prostego filtra RC, ale użycie jednego opampa jako bufora (lub nawet pojedynczego tranzystora jako elementu śledzącego emiter) dałoby 3 lub 5 biegunów filtrowania dolnoprzepustowego i znacznie większą szansę na uzyskanie dodatkowego PWM rozkład. Nie sprawdziłem „koherencji fazowej” wyjść PWM, ale oczekuję, że poruszają się one w sposób względny, aby nie uzyskać korzyści wygładzania przez dodanie dwóch nieskorelowanych przebiegów.
W razie potrzeby można dodać więcej komentarzy. Zapytaj, jeśli jesteś zainteresowany.
źródło