Bug in pins_teensy.c

Elmue

Well-known member
The current code is :

Code:
void analogWrite(uint8_t pin, int val)
{
     .....
     .....

	max = 1 << analog_write_res;
	if (val <= 0) {
		digitalWrite(pin, LOW);
		pinMode(pin, OUTPUT);	// TODO: implement OUTPUT_LOW
		return;
	} else if (val >= max) {
		digitalWrite(pin, HIGH);
		pinMode(pin, OUTPUT);	// TODO: implement OUTPUT_HIGH
		return;
	}
     ....
}

What does this code do ?

If the val is 0 it switches the line to LOW.
If the val is max it switches the line to HIGH.

But the calulation of max is wrong.

max is 256 for 8 bit and 4096 for 12 bit resolution.

Correct would be:

Code:
max = (1 << analog_write_res) - 1;

because the highest value for 8 bit is 255 and for 12 bit it is 4095.
______________________

If you study the equivalent Arduino code you see that it is implemented correctly in wiring_analog.c

Code:
if (val == 0)
{
     digitalWrite(pin, LOW);
}
else if (val == 255)
{
     digitalWrite(pin, HIGH);
}
else
{
     ......
 
Last edited:
If you study the equivalent Arduino code you see that it is implemented correctly in wiring_analog.c

Arduino's code has a minor known issue. Whether this is a considered a bug is a matter of opinion.

If you want to observe it, try running something like this on both Teensy and Arduino, and watch the DC voltage at pin 5.

Code:
void loop() {
  for (int i=250; i <= 255; i++) {
    analogWrite(5, i);
    delay(5000);
  }
}
 
FWIW, I've never been really happy about this approach with changing the pin from PWM to plain output, mainly because it has such different timing (immediate) than double buffered PWM updates. But in a reality of prioritizing issues, this minor timing concern falls to about the very bottom of any realistic list.
 
What you currently have imlemented is inconistent.

It is not only incompatible with Arduino code.

It is even inconsistent in itself:
Passing the lowest 8 bit value (zero) turns off the PWM signal and outputs a steady LOW.
Passing the highest 8 bit value (255) generates a PWM signal.


> I've never been really happy about this approach with changing the pin from PWM to plain output,

Yes it is strange.
And some servos dont like that.
They turn off the motor if no signal is coming (for example the HS485).

But you still output a steady LOW for the value zero.

So to make it consistent you should also remove that.
 
Before you ask again, please do a simple DC voltmeter test. Measure the voltage at analogWrite 253, 254, 255, and then with digitalWrite HIGH. Post those 4 numbers, than then we'll talk, ok?
 
Back
Top