Closed suuuehgi closed 3 years ago
How do you measure the output voltage? With a volt-meter? You should check it with an oscilloscope. With the volt-meter you measure the average voltage of an alternative signal dependent on the PWM duty cycle.
I used an Oscilloscope.
I just checked your code in a sketch for a bluepill board with PB9 having 10k to 5V. Sorry, but I cannot reproduce your problem, in my setup the output is a PWM with high level at 5 V. So I suggest to check your HW setup.
Thank you very much for the investigation so far! Just in case I miss something obvious, here's the complete minimal setup:
5 V ---> 1K ---> Pin PB9
|
GND --------- Oscilloscope
MWE
const int pin_pwm = PB9;
void setup() {
pinMode(pin_pwm, PWM_OPEN_DRAIN);
pwmWrite(pin_pwm, 20000);
}
void loop() {
}
The resulting signal.
The signal with the connection to PB9 pulled.
I tested with exactly the same HW and SW setup, and here is my plot:
Try with another resistor and/or board.
Same on another board from the same order. I have one last from the other batch I'm gonna test now ...
The one from the old batch gives 5 V PWM. 😒
I guess they messed up the open drain functionality within the μC. 😒 😒
Just curious, are you sure your CPU is a genuine one? There is a lot of clones/counterfeits on the market.
Just curious, are you sure your CPU is a genuine one? There is a lot of clones/counterfeits on the market.
Well, I don't know. For the sake of ST, I guess it's fake.
Tested now pin PB6-9 + PA8-10. 3.3 V PWM on all of them.
The CPU in the picture looks good.
I think I can close this as it seems to be μC-related. Thank you both for your efforts!
I got it now working in software toggling between pinMode
OUTPUT, LOW
and INPUT
HIGH
and LOW
with OUTPUT_OPEN_DRAIN
. It appears as just PWM_OPEN_DRAIN
is broken.
Can you please share how exactly you did it?
Can you please share how exactly you did it?
Yeah, sure!
#define PWM_PERIOD 313 // in microseconds / 1.6 --> ~ 2000 Hz
const int pin_pwm = PB9;
HardwareTimer timer(1);
void setup() {
pinMode(pin_pwm, OUTPUT_OPEN_DRAIN);
timer.pause();
timer.setPeriod(PWM_PERIOD);
timer.setMode(TIMER_CH1, TIMER_OUTPUT_COMPARE);
// Fire interrupt at 50 % of the counter
timer.setCompare(TIMER_CH1, timer.getOverflow()/2);
timer.attachInterrupt(TIMER_CH1, handler_pwm_high);
// Channel 0 is for overflow interrupt (update interrupt)
timer.attachInterrupt(0, handler_pwm_low);
timer.refresh();
timer.resume();
}
void loop() {
}
void handler_pwm_high(void) {
digitalWrite(pin_pwm, HIGH);
}
void handler_pwm_low(void) {
digitalWrite(pin_pwm, LOW);
}
Some additional notes:
OUTPUT_OPEN_DRAIN
works as intended and just PWM_OPEN_DRAIN
is broken. I switched to that and updated my comment above accordingly.PWM_PERIOD
is -- why ever -- not directly the inverse of the frequency but scaled by a constant factor of 1.6. Hence 500 resulted not in 2000 Hz but in 1250 Hz. Thus I used 500 / 1.6 here.attachInterrupt
method is not documented but in a source code comment.Edit Prior, I set the register during setup
once using digitalWrite(pin_pwm, LOW)
and handler_pwm_X
toggled the mode via pinMode(pin_pwm, INPUT)
/ pinMode(pin_pwm, OUTPUT)
.
I suppose that this workaround you apply only for the "fake" MCU.
This code generates the correct timing and level:
#define PWM_PIN PB9 // Timer4 Ch 4
#define PWM_PERIOD 500 // in µs, 2000 HZ
#define myTimer Timer4 // corresponding to PB9
#define myTimerChannel TIMER_CH4 // corresponding to PB9
void setup()
{
pinMode(PWM_PIN, PWM_OPEN_DRAIN);
myTimer.pause();
myTimer.setPeriod(PWM_PERIOD);
myTimer.setCompare(myTimerChannel, myTimer.getOverflow()/2); // set duty cycle
myTimer.refresh();
myTimer.resume();
}
void loop() {
// put your main code here, to run repeatedly:
}
If the PWM period or level is not correct, it can be a sign for a fake MCU, or defective MCU/board.
I suppose that this workaround you apply only for the "fake" MCU.
Yes, certainly. Otherwise I wouldn't have to use interrupts and could just let it run "in hardware".
Thank you for the double check and the hint that this might be another deviation from the original. 😒
It might be coincidence ... but I noticed that 74 MHz / 45 MHz is about 1.6. Might it be that the μC runs at 45 MHz?
Not sure about the deviation, but normally it runs with 72MHz. Maybe 72/48? That would be 1.5. Have you checked the onboard crystal?
Ah, right, I mistook it with 48 MHz. Then it's probably meaningless. The onboard crystal is the std 8 MHz.
Hey,
I connected 5 V -> 1K -> Pin PB9 on an STM32F103C8T6 with the following code
and I get a PWM signal at the pin of slightly above 3.3 V, not 5 V. So open is not really open but rather around 2 K to GND. :/