Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add PWM support for controlling Laser (Intensity) and CNC (rpm) #524

Open
wants to merge 2 commits into
base: work092
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion src/ArduinoAVR/Repetier/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -769,12 +769,20 @@ and G0 moves have it disables.

In any case, laser only enables while moving. At the end of a move it gets
automatically disabled.

Laser Types
LASER_ON_OFF only enable an disable the Laser
LASER_PWM use a PWM to control the output power (M3 Sxxx 0-255)
Note: PWM can not be used with Servos
*/

#define SUPPORT_LASER 0 // set 1 to enable laser support
//#define LASER_TYPE LASER_TYPE_PWM
#define LASER_TYPE LASER_TYPE_ONOFF
#define LASER_PIN -1 // set to pin enabling laser
#define LASER_ON_HIGH 1 // Set 0 if low signal enables laser


// ##########################################################################################
// ## CNC configuration ##
// ##########################################################################################
Expand All @@ -793,7 +801,9 @@ It also can add a delay to wait for spindle to run on full speed.
#define CNC_ENABLE_WITH 1 // Set 0 if low enables spindle
#define CNC_DIRECTION_PIN -1 // Set to pin if direction control is possible
#define CNC_DIRECTION_CW 1 // Set signal required for clockwise rotation

#define CNC_PWM_PIN -1 // PWM pin for controlling Speed (RPM)
#define CNC_PWM_INV 0 //Invert the PWM
#define CNC_MAX_RPM 12000 // MAX RPM of the Tool

/* Select the default mode when the printer gets enables. Possible values are
PRINTER_MODE_FFF 0
Expand Down
32 changes: 32 additions & 0 deletions src/ArduinoAVR/Repetier/Drivers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ void LaserDriver::initialize()
{
#if LASER_PIN > -1
SET_OUTPUT(LASER_PIN);
WRITE(LASER_PIN, !LASER_ON_HIGH); // be sure laser is off!
#endif
}
changeIntensity(0);
Expand All @@ -126,7 +127,11 @@ void LaserDriver::changeIntensity(uint8_t newIntensity)
{
// Default implementation
#if LASER_PIN > -1
#if (LASER_TYPE == LASER_ON_OFF)
WRITE(LASER_PIN,(LASER_ON_HIGH ? newIntensity > 199 : newIntensity < 200));
#elif (LASER_TYPE == LASER_PWM)
HAL::setPWM(LASER_PIN, newIntensity, !LASER_ON_HIGH);
#endif
#endif
}
}
Expand All @@ -151,6 +156,10 @@ void CNCDriver::initialize()
#endif
#if CNC_DIRECTION_PIN > -1
SET_OUTPUT(CNC_DIRECTION_PIN);
#endif
#if CNC_PWM_PIN > -1
SET_OUTPUT(CNC_PWM_PIN);
WRITE(CNC_PWM_PIN, CNC_PWM_INV);
#endif
}
}
Expand All @@ -163,6 +172,9 @@ void CNCDriver::spindleOff()
if(direction == 0) return; // already off
if(EVENT_SPINDLE_OFF)
{
#if CNC_PWM_PIN > -1
HAL::setPWM(0, CNC_PWM_PIN, CNC_PWM_INV);
#endif
#if CNC_ENABLE_PIN > -1
WRITE(CNC_ENABLE_PIN,!CNC_ENABLE_WITH);
#endif
Expand All @@ -182,6 +194,16 @@ void CNCDriver::spindleOnCW(int32_t rpm)
spindleOff();
direction = 1;
if(EVENT_SPINDLE_CW(rpm)) {
#if CNC_PWM_PIN > -1
#if defined(CNC_MAX_RPM)
if(rpm > CNC_MAX_RPM) {
rpm = CNC_MAX_RPM;
}
HAL::setPWM((uint8_t)(rpm/(CNC_MAX_RPM/TOOL_PWM_STEPS)), CNC_PWM_PIN, CNC_PWM_INV);
#else
HAL::setPWM(rpm, CNC_PWM_PIN, CNC_PWM_INV);
#endif
#endif
#if CNC_DIRECTION_PIN > -1
WRITE(CNC_DIRECTION_PIN, CNC_DIRECTION_CW);
#endif
Expand All @@ -203,6 +225,16 @@ void CNCDriver::spindleOnCCW(int32_t rpm)
spindleOff();
direction = -1;
if(EVENT_SPINDLE_CW(rpm)) {
#if CNC_PWM_PIN > -1
#if defined(CNC_MAX_RPM)
if(rpm > CNC_MAX_RPM) {
rpm = CNC_MAX_RPM;
}
HAL::setPWM((uint8_t)(rpm/(CNC_MAX_RPM/TOOL_PWM_STEPS)), CNC_PWM_PIN, CNC_PWM_INV);
#else
HAL::setPWM(rpm, CNC_PWM_PIN, CNC_PWM_INV);
#endif
#endif
#if CNC_DIRECTION_PIN > -1
WRITE(CNC_DIRECTION_PIN, !CNC_DIRECTION_CW);
#endif
Expand Down
118 changes: 118 additions & 0 deletions src/ArduinoAVR/Repetier/HAL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ uint8 osAnalogInputPos = 0; // Current sampling position
#if FEATURE_WATCHDOG
bool HAL::wdPinged = false;
#endif

#if (FEATURE_TOOL_PWM)
t_tool_pwm_cfg HAL::tool_cfg;
#endif

//extern "C" void __cxa_pure_virtual() { }

HAL::HAL()
Expand Down Expand Up @@ -246,6 +251,25 @@ void HAL::setupTimer()
TCCR1B = (_BV(WGM12) | _BV(CS10)); // no prescaler == 0.0625 usec tick | 001 = clk/1
OCR1A=65500; //start off with a slow frequency.
TIMSK1 |= (1<<OCIE1A); // Enable interrupt


#if (FEATURE_TOOL_PWM)
TCCR3A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8
TCNT3 = 0; // clear the timer count
#if defined(__AVR_ATmega128__)
TIFR |= _BV(OCF3A); // clear any pending interrupts;
ETIMSK |= _BV(OCIE3A);// enable the output compare interrupt
#else
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
TIMSK3 = _BV(OCIE3A); // enable the output compare interrupt
#endif
tool_cfg.pin = -1;
tool_cfg.inv = false;
tool_cfg.pwm = 0;
tool_cfg.state = 0;
#endif

#if FEATURE_SERVO
#if SERVO0_PIN>-1
SET_OUTPUT(SERVO0_PIN);
Expand Down Expand Up @@ -510,6 +534,100 @@ unsigned char HAL::i2cReadNak(void)
return TWDR;
}


#if (FEATURE_TOOL_PWM)

#define TOOL_PERIOD ((F_CPU/8)/TOOL_PWM_HZ)
#define TOOL_STEP (TOOL_PERIOD/TOOL_PWM_STEPS)

void HAL::setPWM(uint8_t val, int8_t pin, bool inv) {

if(tool_cfg.pin > -1) {
#if defined(__AVR_ATmega128__)
ETIMSK &= ~_BV(OCIE3A); // disable the output compare interrupt
#else
TIMSK3 = 0; // disable the output compare interrupt
#endif
//disable old PWM
digitalWrite(tool_cfg.pin, tool_cfg.inv);
}


if(val > TOOL_PWM_STEPS) {
val = TOOL_PWM_STEPS;
}

tool_cfg.pwm = val;
tool_cfg.pin = pin;
tool_cfg.inv = inv;

if(tool_cfg.pin > -1) {
return;
}

if(val == 0) {
digitalWrite(tool_cfg.pin, tool_cfg.inv);
#if defined(__AVR_ATmega128__)
ETIMSK &= ~_BV(OCIE3A); // disable the output compare interrupt
#else
TIMSK3 = 0; // disable the output compare interrupt
#endif
} else if(val == TOOL_PWM_STEPS) {
digitalWrite(tool_cfg.pin, !tool_cfg.inv);
#if defined(__AVR_ATmega128__)
ETIMSK &= ~_BV(OCIE3A); // disable the output compare interrupt
#else
TIMSK3 = 0; // disable the output compare interrupt
#endif
} else {
digitalWrite(tool_cfg.pin, !tool_cfg.inv);
tool_cfg.state = true;
OCR3A = (TOOL_STEP * val);
#if defined(__AVR_ATmega128__)
TIFR |= _BV(OCF3A); // clear any pending interrupts;
ETIMSK |= _BV(OCIE3A);// enable the output compare interrupt
#else
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
TIMSK3 = _BV(OCIE3A); // enable the output compare interrupt
#endif
}
}


void HAL::timer3_irq() {
if(tool_cfg.pin <= -1) {
#if defined(__AVR_ATmega128__)
ETIMSK &= ~_BV(OCIE3A); // disable the output compare interrupt
#else
TIMSK3 = 0; // disable the output compare interrupt
#endif
}
if(tool_cfg.pwm <= 0) {
digitalWrite(tool_cfg.pin, tool_cfg.inv);
OCR3A = TOOL_PERIOD;
} else if(tool_cfg.pwm >= TOOL_PWM_STEPS) {
digitalWrite(tool_cfg.pin, !tool_cfg.inv);
OCR3A = TOOL_PERIOD;
} else {
if(tool_cfg.state == false) {
digitalWrite(tool_cfg.pin, !tool_cfg.inv);
tool_cfg.state = true;
OCR3A = (TOOL_STEP * tool_cfg.pwm);
} else {
digitalWrite(tool_cfg.pin, tool_cfg.inv);
tool_cfg.state = false;
OCR3A = (TOOL_STEP * (TOOL_PWM_STEPS - tool_cfg.pwm));
}
}
}

SIGNAL (TIMER3_COMPA_vect) {
TCNT3 = 0;
HAL::timer3_irq();
}
#endif


#if FEATURE_SERVO
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__) || defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
#define SERVO2500US F_CPU/3200
Expand Down
17 changes: 17 additions & 0 deletions src/ArduinoAVR/Repetier/HAL.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,15 @@ typedef uint8_t ufast8_t;
#define SERIAL_TX_BUFFER_MASK 63
#endif

#if (FEATURE_TOOL_PWM)
typedef struct {
int8_t pin;
uint8_t pwm;
bool state;
bool inv;
} t_tool_pwm_cfg;
#endif

struct ring_buffer
{
uint8_t buffer[SERIAL_BUFFER_SIZE];
Expand Down Expand Up @@ -706,6 +715,14 @@ class HAL
static uint8_t i2cReadAck(void);
static uint8_t i2cReadNak(void);


// Software PWM
#if (FEATURE_TOOL_PWM)
static t_tool_pwm_cfg tool_cfg;
static void setPWM(uint8_t val, int8_t pin, bool inv);
static void timer3_irq(void);
#endif

// Watchdog support

inline static void startWatchdog()
Expand Down
40 changes: 40 additions & 0 deletions src/ArduinoAVR/Repetier/Repetier.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,46 @@ usage or for searching for memory induced errors. Switch it off for production,

#include "Configuration.h"


// HAL Tool PWM
#define FEATURE_TOOL_PWM 0
#ifndef TOOL_PWM_HZ
#define TOOL_PWM_HZ 100
#endif
#ifndef TOOL_PWM_STEPS
#define TOOL_PWM_STEPS 255
#endif

// Laser Type
#define LASER_TYPE_OFF 0
#define LASER_TYPE_ONOFF 1
#define LASER_TYPE_PWM 2

#if defined(SUPPORT_LASER) && SUPPORT_LASER
#ifndef LASER_TYPE
#define LASER_TYPE LASER_TYPE_ONOFF
#endif
#if ((LASER_TYPE == LASER_TYPE_PWM) && (LASER_PIN > -1))
// enable TOOL PWM
#undef FEATURE_TOOL_PWM
#define FEATURE_TOOL_PWM 1
#endif
#endif


#if defined(SUPPORT_CNC) && SUPPORT_CNC
#if defined(CNC_PWM_PIN) && (CNC_PWM_PIN > -1)
// enable TOOL PWM
#undef FEATURE_TOOL_PWM
#define FEATURE_TOOL_PWM 1
#endif
#endif

#if (defined(FEATURE_SERVO) && FEATURE_SERVO) && (defined(FEATURE_TOOL_PWM) && FEATURE_TOOL_PWM)
#error Servos and Tool PWM not possible on the same time
#endif


#ifndef SHARED_EXTRUDER_HEATER
#define SHARED_EXTRUDER_HEATER 0
#endif
Expand Down