Skip to content

Conversation

@ikalafat
Copy link

@ikalafat ikalafat commented Sep 3, 2017

Hi everyone,

First of all, I'd like to say big thanks to authors and contributors of this repository!

I have usecase where laser driver only has TTL (pwm) input, and no dedicated Enable pin.
In order for M3 S0, M4 S0 and M5 to work in my environment, i have introduced SPINDLE_LASER_PWM_ACTS_AS_ENABLE flag which sets PWM value to 0 on M3 S0, M4 S0 and M5 commands.

When SPINDLE_LASER_PWM_ACTS_AS_ENABLE == true, then SPINDLE_LASER_ENABLE_PIN isn't used at all.

Let me know your thoughts on this.

PS:
This is my first PR to this repo, so please, have some patience with me :)

@ikalafat
Copy link
Author

ikalafat commented Nov 3, 2017

Hi @thinkyhead

I see that you've made some changes to this branch/PR. Thank you for attention to this PR.

However, I'm confused with changes made to configuration_adv.h (your last commit)

It seems that it contains code from marlin_main.cpp (code isn't identical though).

Can you doublecheck this? :)

@thinkyhead
Copy link
Member

thinkyhead commented Nov 6, 2017

Hi @ikalafat — I'll look it over shortly. Meanwhile, I thought it would be fun to share this useful function I wrote to get any PWM timing under the sun out of Timer 5 A, B, and/or C…

/**
 * Set Timer 5 PWM frequency in Hz, from 3.8Hz up to ~16MHz
 * with a minimum resolution of 100 steps.
 *
 * DC values -1.0 to 1.0. Negative duty cycle inverts the pulse.
 */
uint16_t set_pwm_frequency_hz(const float &hz, const float dca, const float dcb, const float dcc) {
  float count = 0;
  if (hz > 0 && (dca || dcb || dcc)) {
    count = float(F_CPU) / hz;            // 1x prescaler, TOP for 16MHz base freq.
    uint16_t prescaler;                   // Range of 30.5Hz (65535) 64.5KHz (>31)

         if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); }
    else if (count >= 255. * 64.)  { prescaler = 256;  SET_CS(5,  PRESCALER_256); }
    else if (count >= 255. * 8.)   { prescaler = 64;   SET_CS(5,   PRESCALER_64); }
    else if (count >= 255.)        { prescaler = 8;    SET_CS(5,    PRESCALER_8); }
    else                           { prescaler = 1;    SET_CS(5,    PRESCALER_1); }

    count /= float(prescaler);
    pwm_top = round(count);               // Get the rounded count

    ICR5 = (uint16_t)pwm_top - 1;         // Subtract 1 for TOP
    OCR5A = pwm_top * FABS(dca);          // Update and scale DCs
    OCR5B = pwm_top * FABS(dcb);
    OCR5C = pwm_top * FABS(dcc);
    _SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes
    _SET_COM(5, B, dcb ? (dcb < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);
    _SET_COM(5, C, dcc ? (dcc < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);

    SET_WGM(5, FAST_PWM_ICRn);            // Fast PWM with ICR5 as TOP

    //SERIAL_ECHOLNPGM("Timer 5 Settings:");
    //SERIAL_ECHOLNPAIR("  Prescaler=", prescaler);
    //SERIAL_ECHOLNPAIR("        TOP=", ICR5);
    //SERIAL_ECHOLNPAIR("      OCR5A=", OCR5A);
    //SERIAL_ECHOLNPAIR("      OCR5B=", OCR5B);
    //SERIAL_ECHOLNPAIR("      OCR5C=", OCR5C);
  }
  else {
    // Restore the default for Timer 5
    SET_WGM(5, PWM_PC_8);                 // PWM 8-bit (Phase Correct)
    SET_COMS(5, NORMAL, NORMAL, NORMAL);  // Do nothing
    SET_CS(5, PRESCALER_64);              // 16MHz / 64 = 250KHz
    OCR5A = OCR5B = OCR5C = 0;
  }
  return round(count);
}

First, it can be called to set the PWM frequency. For example:

set_pwm_frequency_hz(25000); // Good for a laser tool

Then the duty cycle can be changed on the fly, as in this Temperature:: method…

// Set laser power 0-255. Scale for DC to 0.0-1.0.
static void setLaserPower(const uint8_t power) {
  if (tool_type != TOOL_TYPE_LASER) return;
  #if PIN_EXISTS(LASER_PWM)
    const float min_dc = 0.01 * (LASER_MIN_DUTY_CYCLE),
                dc = min_dc + (1.0 - min_dc) * power / 255.0;
    set_pwm_frequency_hz(power ? 25000 : 0, dc);
  #endif
  WRITE(LASER_POWER_PIN, power ? HIGH : LOW);
}

@thinkyhead
Copy link
Member

Sorry I didn't notice sooner that this is targeted to the wrong branch. We don't accept PRs targeted to release branches.

Please redo this PR building on the bugfix-1.1.x branch and target that branch.

@thinkyhead thinkyhead closed this Nov 7, 2017
@thinkyhead thinkyhead added Needs: Rebase S: Don't Merge Work in progress or under discussion. labels Nov 7, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S: Don't Merge Work in progress or under discussion.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants