Hi. How can i do smooth pwm using delay loops ? I tied like this:
It works bad....
int period = 50;
int i = 0;
while(true)
{
i++;
PORTB = PORTB & B11111110; // Turn LED off
_delay(i);
PORTB = PORTB | B00000001; // Turn LED on
_delay(period - i);
if (i >= period)
{
i = 0;
}
}
while(true)
{
// Do things here
}
while(true)
{
turn_on();
delay(duty_cycle);
turn_off();
delay(period-duty_cycle);
}
Other way 'round - decreasing pulses. I figured that was what he was after.What are you trying to achieve with this code?
What the code will do is cause a PWM with a duty cycle that increases from 0 to 100% then repeats.
@wdariuswwdariusw said:This is what i want :
1. PA0 turn On LED;
2. PA0 LED light slowly goes out.
3. PA1 turn On LED;
4. PA1 LED light slowly goes out.
5. PA2 turn On LED;
6. PA2 LED light slowly goes out.
.......................................................until PA7 is reached..
for(int pin=0;pin<3;pin++)
FadeLED(pin);
void FadeLED(int pin)
{
int period=10; // 10mS cycles (100Hz).
int mark=period+1; // Pulse length, starts at 100% duty-cycle.
int space;
while(mark)
{
mark--;
space=period-mark;
for(int holdTime=0;holdTime<10;holdTime++) // Provide a hold time at each duty cycle.
{ // 100mS with current values.
setPin(pin,HIGH); // *Substitute call to suit your compiler
_delay(mark);
setPin(pin,LOW); // *Substitute call to suit your compiler
_delay(space);
}
}
return;
}
// PWMwithoutTimer2
void setup()
{
pinMode(0,OUTPUT);
pinMode(1,OUTPUT);
pinMode(2,OUTPUT);
}
void loop()
{
for(int pin=0;pin<3;pin++) // Cycle through the 3 LEDs forever.
FadeLED(pin);
}
void FadeLED(int pin)
{
int period=10000;
int mark=period+50;
int space;
while(mark)
{
mark-=50;
space=period-mark;
digitalWrite(pin,HIGH);
delayMicroseconds(mark);
digitalWrite(pin,LOW);
delayMicroseconds(space);
}
return;
}
TRISB=%11111000 ' Output to LED1 on RB0,
' output to LED2 on RB1,
' output to LED3 on RB2,
' others unused, (inputs).
Init:
HIGH 0 ' LED1 flash on startup
pause 500
LOW 0
Main:
for pin=0 to 2 ' Cycle through the 3 LEDs forever.
gosub FadeLED
next
goto Main
'---------------------------------------------------------------
' Subroutines:-
FadeLED:
period=10000 ' 10mS cycles (100Hz).
mark=period+50
while (mark>0)
mark=mark-50
space=period-mark
HIGH pin
pauseus mark
LOW pin
pauseus space
wend
return
I have the avr-gcc compiler here too, in the Win-AVR package, but haven't even got as far as working out how to install it all properly yet. I struck makefile problems. Been too busy with other stuff.I'm working with atmega32 , and AVR studio with avr-gcc compiler. Will try all of yours offered codes today after work and will report results here, thanks !
DDRB=0b00000111; // Make PB0 TO 3 outputs, all others inputs.
for(int pin=0;pin<3;pin++)
{
FadeLED(pin);
}
goto Loop;
}
void FadeLED(int pin)
{
int period=10000;
int mark=period+50;
int space;
while(mark)
{
mark-=50;
space=period-mark;
PORTB=PORTB ^ (1<<pin); // Toggles pin.
_delay_us(mark);
PORTB=PORTB ^ (1<<pin); // Toggles pin again.
_delay_us(space);
}
return;
}
Again, post your code. I'm working in the dark here.Very strange thing...Finally "almost" got pretty soft PWM, bet with minimum duty cycle (my rigol scope shows 100mV) led still is on.
Your code throws errors on both _delay_us() lines when I try to compile it.
Error 1 __builtin_avr_delay_cycles expects an integer constant.
Error 2 __builtin_avr_delay_cycles expects an integer constant.
Not that it really matters. I don't need this code. Personally, I'd use a timer.
And it looks to me like your code 'brightens' a LED, rather than 'fading' it.
I've got it working, fading, using a timer now. No errors for me this way.![]()
You ignored all of my questions, including several requests to post your code, yet expect me to jump and upload more code for you?Do you have avr-gcc code ?![]()
// Set up prescaling:-
// 0x00=stopped, 0x01=CLK/1, 0x02=CLK/8, 0x03=CLK/64, 0x04=CLK/256, 0x05=CLK/1024
TCCR0B = 0x05;
// Initialize the counter:-
TCNT0 = 0;
// Start timer:-
TCCR0A |= (1 << CS00);
if (TCNT0 >= pulse) // Must be <= 255 or Timer0 overflows! (8-bit timer.)
{
PORTD ^= (1 << 0); // Toggles the led.
TCNT0 = 0; // Reset the counter.
}