I have a pin (PB2) that doesn't have PWM on it and used the following code to get it to do software PWN. It works, however it doesn't seem to fade all the way day to 0 brightness, any idea why this would be happening? The code implies it should go all the way down.
/*
Modified version of Ernst Christensen's code
*/
int redLED= 2;
void setup(){
//for (int z=0;z<1;z++){
pinMode(redLED,OUTPUT);
//} //for z
}
void loop(){
for (int x=0;x<255;x++){
spwm(x,redLED,15);
}
for (int x=254;x>0;x--){
spwm(x,redLED,15);
}
}
void spwm(int freq,int spin,int sp){
//on
digitalWrite(spin,HIGH);
delayMicroseconds(sp*freq);
// off
digitalWrite(spin,LOW);
delayMicroseconds(sp*(255-freq));
}
Doesn't take 0 clock cycles to execute. The LED will be on for the time it takes to do multiply sp*freq, call/return from delayMicroseconds, do the digitalWrite(LOW), etc.
You might also get a CPU interrupt in the middle of it, slowing it down even more and causing bright flashes.
Try this:
void spwm(int freq,int spin,int sp){
if (sp!=0) {
//on
digitalWrite(spin,HIGH);
delayMicroseconds(sp*freq);
// off
digitalWrite(spin,LOW);
delayMicroseconds(sp*(255-freq));
}
}
Doesn't take 0 clock cycles to execute. The LED will be on for the time it takes to do multiply sp*freq, call/return from delayMicroseconds, do the digitalWrite(LOW), etc.
You might also get a CPU interrupt in the middle of it, slowing it down even more and causing bright flashes.
Try this:
There is a long-standing bug in delayMicroseconds(), which was reported years ago but the core maintainers have chosen to ignore. If you pass zero to it, you get a very long delay instead of a very short delay. So your code will not work as expected when sp (or freq) is zero. Use "if (sp != 0) { delayMicroseconds(sp*freq); }" instead.
As fungus already explained, the various calls will take a non-zero amount of time to execute, which will also contribute to the problem.
[EDIT: The above assumes that the attiny85 core you are using has the same bug as the standard Arduino core.]