Christian-Marty.ch´s Electric Things

Bit Angle Modulation

January 24, 2016

Die einfachste Art eine LED mit einem Mikrocontroller zu dimmen ist PWM.

Die meisten Mikrocontroller haben eingebaute Hardware, welche PWM-Signale erzeugen kann.Die Anzahl von Hardware-PWM Kanälen ist jedoch meisten eher gering.

Was jedoch, wenn man viele LEDs dimmen möchte?

Eine Möglichkeit ist die Implementation von Software-PWM. Software-PWM kann jedoch je nach gewünschter Frequenz und Auflösung sehr rechenintensiv sein. Eine gute Alternative ist die Verwendung von Bit Angle Modulation.

Das Prinzip hinter der Bit Angle Modulation

Gleich wie bei der Pulsweitenmodulation wird auch bei der Bit Angle Modulation das Verhältnis zwischen Ein- und Ausschaltdauer variiert. Jedoch ist die Verteilung von Ein- und Ausschaltdauer anders.

In der obenstehenden Grafik wir die Wertigkeit des jeweiligen Bits mit der relativen Ein- bzw. Ausschaltzeit dargestellt. Bit 0 entspricht einer Einschaltdauer von 1, Bit 7 einer Einschaltdauer von 128. Die gesamteinschaltdauer von allen Bits beträgt 255.

Für das Dimmen einer LED werden die einzelnen Bits nacheinander mit ihrer jeweiligen Einschaltdauer ausgegeben.

Um dies zu verdeutlichen ein Beispiel:

Es soll eine LED mit 8-Bit Auflösung und einer Frequenz von ca. 3.922kHz (255us Periodendauer) gedimmt werden. Der aktuelle Dimmwert ist 168. Das Puls-/Pausenverhältnis beträgt also 168us zu 87us bzw. der Tastgrad (Englisch: duty cycle) 66%.

Bei der Pulsweitenmodulation wird die LED für 168us eingeschaltet und danach für 87us ausgeschaltet.

Bei der Bit Angle Modulation wird die LED zuerst für 7us ausgeschaltet, danach für 8us eingeschaltet dann für 16us ausgeschaltet usw. Die gesamte Einschaltzeit pro Periode beträgt schlussendlich 168us und die Ausschaltdauer 87us und ist somit gleich wie bei der Pulsweitenmodulation.

 

Was sind nun die Vor- und Nachteile gegenüber der Pulsweitenmodulation?

Vorteile:

Nachteile:

Demosoftware

BAM-Demo.c

/***********************************************************************
*
*  Date        : 24.01.2016
*  Description : BAM Test for Mocca board
*  Author	    : Christian Marty
*
***********************************************************************/
#include 
#include 

void initTimer2(void);
void updateBam(void);

uint8_t ledValue[8] = {1,2,4,8,16,32,64,128}; // Set dimming values for LEDs here
	
volatile uint8_t bamBitTime = 0;	
volatile uint8_t bamPortOutput;
volatile uint8_t bamPosition = 0;

int main(void)
{
	DDRA = 0xFF;	// LED-Port as output
	sei();			// Enable Interrupts
	
	initTimer2();	// Initialize BAM timer

	while(1)
    {
		// Run your app here
    }
}

//--------------------------------------------------------------------------------------------
// Initialize Timer 2 for BAM
//--------------------------------------------------------------------------------------------
void initTimer2(void)
{
	TCCR2A = 0b00000000; // Timer Mode Setting -> Normal Mode
	TCCR2B = 0b00000110; // Prescaler 256 -> 16Mhz / 256 = 62.5kHz
	TIMSK2 = 0b00000001; // Enable Timer Overflow Interrupt
}

//--------------------------------------------------------------------------------------------
// Timer Interrupt Handler
//--------------------------------------------------------------------------------------------
ISR(TIMER2_OVF_vect)
{
	TCNT2 = bamBitTime;		// Set time until next update
	PORTA = bamPortOutput;	// Set Output
	updateBam();			// Calculate values for next update
}

//--------------------------------------------------------------------------------------------
// Calculate the data for the next BAM Cycle
//--------------------------------------------------------------------------------------------
void updateBam(void)
{
	// Calculate the Output for LED-PORT
	bamPortOutput = 0;
	for(uint8_t i= 0; i<8; i++)
	{
		bamPortOutput = (bamPortOutput <<1);
		bamPortOutput |= ((ledValue[i] >> bamPosition) & 0x01);
	}
	
	// Calculate the length of the next BAM Cycle
	bamBitTime = (0xFF << bamPosition+1); 
	
	// Calculate the position of the next BAM Cycle
	bamPosition ++;
	if(bamPosition >= 8) bamPosition = 0;
}