Marlin FW - Analogwrite for PWM control

Post here first, or if you can't find a relevant section!
Post Reply
happytoto
Posts: 4
Joined: Sat Aug 29, 2020 2:24 pm

Marlin FW - Analogwrite for PWM control

Post by happytoto »

Hello,

I am currently playing with my 3D printer to add some LED strip. In the Marlin FW, the RGBW leds are controlled with an Analogwrite function such as in the standard arduino example:

Code: Select all

void loop() {
  // fade in from min to max in increments of 5 points:
  for (int fadeValue = 0 ; fadeValue <= 255; fadeValue += 5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = 255 ; fadeValue >= 0; fadeValue -= 5) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(30);
  }
}
Although this method kind of works, the brightness of the led strip is at max roughly 50% of the max possible (ie connected to +12V). I don't understand why fully (I don't have an oscilloscope to look at the output) but it is what it is.

I tried a small program based on the page
https://github.com/stm32duino/wiki/wiki ... er-library

Code: Select all

void setup() {
  TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(ledPin), PinMap_PWM);
  uint32_t channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(ledPin), PinMap_PWM));

  // Instantiate HardwareTimer object. Thanks to 'new' instantiation, HardwareTimer is not destructed when setup() function is finished.
  HardwareTimer *MyTim = new HardwareTimer(Instance);

  // Configure and start PWM
  // MyTim->setPWM(channel, pin, 5, 10, NULL, NULL); // No callback required, we can simplify the function call
  MyTim->setPWM(channel, ledPin, 5000, 10); 
  delay(5000);

  for (;;){
    for (int fadeValue = 0 ; fadeValue <= 100; fadeValue += 2) {
      MyTim->setPWM(channel, ledPin, 10000, fadeValue);
      delay(100);
    }
    
    for (int fadeValue = 100 ; fadeValue >= 0; fadeValue -= 2) {
      MyTim->setPWM(channel, ledPin, 10000, fadeValue);
      delay(100);
    }
  }
}
In that case, I am getting the full brightness at max.

Without rewriting the Marlin FW, what would you recommend to do?

Optimal solution: analogwrite directly using the PWM hardwaretimer of the STM32

Thank you for your feedback
BennehBoy
Posts: 135
Joined: Sat Jan 04, 2020 2:38 am
Answers: 1

Re: Marlin FW - Analogwrite for PWM control

Post by BennehBoy »

Is this down to DAC resolution?
User avatar
fpiSTM
Posts: 1745
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Marlin FW - Analogwrite for PWM control

Post by fpiSTM »

Strange, as if the pin has PWM capability then the HardwareTimer is used.
Except if the pin has DAC capabilities then it preferred to the PWM.
happytoto
Posts: 4
Joined: Sat Aug 29, 2020 2:24 pm

Re: Marlin FW - Analogwrite for PWM control

Post by happytoto »

Following the first feedback. in the simple arduino example, I added analogWriteResolution(4) and I then got the full brightness range. Tried with a resolution of 8 but didn't get the full brightness for fade value of 0-255. I am not quite sure why.

I am left to ponder what is the right resolution 8, 16 (SMT32 documentation) or 4, 12.
Is the 16 the better one to choose?
BennehBoy
Posts: 135
Joined: Sat Jan 04, 2020 2:38 am
Answers: 1

Re: Marlin FW - Analogwrite for PWM control

Post by BennehBoy »

You'd need to set the fade range from 0-4093 to get full brightness with a 12bit resolution.

You got full brightness with 4 bit, because that has a range of 0-15, so as soon as the fade hit 15 you would be at full brightness.

The resolution just gives you finer increments...
Last edited by BennehBoy on Fri Sep 04, 2020 3:24 pm, edited 2 times in total.
happytoto
Posts: 4
Joined: Sat Aug 29, 2020 2:24 pm

Re: Marlin FW - Analogwrite for PWM control

Post by happytoto »

After trial and error, I think there is a bug (feature?) somewhere.

If I set 12bit resolution, I get the max_brightness for 2^(res+4) or 65535. I am not quite sure why.

here is the simple code to test:

Code: Select all

#include <math.h>

int ledPin = 29;    // LED connected to digital pin 29
int max_fade;
int step_i;
int delay_i;
int res;

void setup() {
  res = 12;
  max_fade = 1 << (res+4);
  step_i = max_fade / 10;
  delay_i = 1000;

  analogWriteResolution(res);
  pinMode(ledPin, OUTPUT);
  // nothing happens in setup
}

void loop() {
  // fade in from min to max in increments of 5 points:
  for (int fadeValue = 0 ; fadeValue <= max_fade; fadeValue += step_i) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(delay_i);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = max_fade ; fadeValue >= 0; fadeValue -= step_i) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(delay_i);
  }
}
User avatar
fpiSTM
Posts: 1745
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Marlin FW - Analogwrite for PWM control

Post by fpiSTM »

Which board ? (mcu)?
happytoto
Posts: 4
Joined: Sat Aug 29, 2020 2:24 pm

Re: Marlin FW - Analogwrite for PWM control

Post by happytoto »

User avatar
fpiSTM
Posts: 1745
Joined: Wed Dec 11, 2019 7:11 pm
Answers: 91
Location: Le Mans
Contact:

Re: Marlin FW - Analogwrite for PWM control

Post by fpiSTM »

I've tested with a Nucleo F767 using pin PC9 (D29 on the REMRAM) with the same TIM3 CH4 and I see no issue without the +4, I've checked with a analyser.
pwm.png
pwm.png (73.9 KiB) Viewed 4515 times
Anyway your code never reach 100% due to the rounding of the computation ( /10) , the wrong max res value which should be (1<< res ) - 1

Code: Select all


int ledPin = PC9;    // LED connected to digital pin 29

static int step_i = 5;
static int delay_i = 2;
static int res = 8;
static int max_fade = (1 << (res)) - 1;

void setup() {
  analogWriteResolution(res);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  // fade in from min to max in increments of 5 points:
  for (int fadeValue = 0 ; fadeValue <= max_fade; fadeValue += step_i) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(delay_i);
  }

  // fade out from max to min in increments of 5 points:
  for (int fadeValue = max_fade ; fadeValue >= 0; fadeValue -= step_i) {
    // sets the value (range from 0 to 255):
    analogWrite(ledPin, fadeValue);
    // wait for 30 milliseconds to see the dimming effect
    delay(delay_i);
  }
}
Post Reply

Return to “General discussion”