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

[ Firing Pin Issue #7 ] Updated PWM functionality for laser #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
181 changes: 145 additions & 36 deletions Marlin/laser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,39 +28,70 @@
laser_t laser;

void timer3_init(int pin) {

digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT);
analogWrite(pin, 1); // let Arduino setup do it's thing to the PWM pin

TCCR3B = 0x00; // stop Timer4 clock for register updates
TCCR3A = 0x82; // Clear OC3A on match, fast PWM mode, lower WGM3x=14
ICR3 = labs(F_CPU / LASER_PWM); // clock cycles per PWM pulse
OCR3A = labs(F_CPU / LASER_PWM) - 1; // ICR3 - 1 force immediate compare on next tick
TCCR3B = 0x18 | 0x01; // upper WGM4x = 14, clock sel = prescaler, start running

noInterrupts();
TCCR3B &= 0xf8; // stop timer, OC3A may be active now
TCNT3 = labs(F_CPU / LASER_PWM); // force immediate compare on next tick
ICR3 = labs(F_CPU / LASER_PWM); // set new PWM period
TCCR3B |= 0x01; // start the timer with proper prescaler value
interrupts();

// Setup timer3 to fast PWM with OC w/ ICR3 as TOP
noInterrupts();

TCCR3A = 0x00;
TCCR3B = 0x00; // stop Timer3 clock for register updates
ICR3 = labs(F_CPU / LASER_PWM); // set clock cycles per PWM pulse (OC Top value)

if (pin == 2) {
TCCR3A = _BV(COM3B1) | _BV(COM3B0) | _BV(WGM31); // Fast PWM (WGM31) / (Clear OC3B/pin 2 on compare match (set output to low level)
OCR3B = 0;
}

if (pin == 3) {
TCCR3A = _BV(COM3C1) | _BV(COM3C0) | _BV(WGM31); // Fast PWM (WGM31) / Clear OC3C/pin 3 on compare match (set output to low level)
OCR3C = 0;
}

if (pin == 5) {
TCCR3A = _BV(COM3A1) | _BV(COM3A0) | _BV(WGM31); // Fast PWM (WGM31) / Clear OC3A/pin 5 on compare match (set output to low level)
OCR3A = 0;
}

TCCR3B = _BV(CS30) | _BV(WGM33) | _BV(WGM32); // Fast PWM / clkIo/1 (No prescaling)

interrupts();
}

void timer4_init(int pin) {

digitalWrite(pin, HIGH);
pinMode(pin, OUTPUT);
analogWrite(pin, 1); // let Arduino setup do it's thing to the PWM pin

TCCR4B = 0x00; // stop Timer4 clock for register updates
TCCR4A = 0x82; // Clear OC4A on match, fast PWM mode, lower WGM4x=14
ICR4 = labs(F_CPU / LASER_PWM); // clock cycles per PWM pulse
OCR4A = labs(F_CPU / LASER_PWM) - 1; // ICR4 - 1 force immediate compare on next tick
TCCR4B = 0x18 | 0x01; // upper WGM4x = 14, clock sel = prescaler, start running

noInterrupts();
TCCR4B &= 0xf8; // stop timer, OC4A may be active now
TCNT4 = labs(F_CPU / LASER_PWM); // force immediate compare on next tick
ICR4 = labs(F_CPU / LASER_PWM); // set new PWM period
TCCR4B |= 0x01; // start the timer with proper prescaler value
interrupts();

// Setup timer4 to fast PWM with OC w/ ICR4 as TOP
noInterrupts();

TCCR4A = 0x00;
TCCR4B = 0x00; // stop Timer4 clock for register updates
TCCR4C = 0x00;

ICR4 = labs(F_CPU / LASER_PWM); // set clock cycles per PWM pulse (OC Top value)

if (pin == 6) {
TCCR4A = _BV(COM4A1) | _BV(COM4A0) | _BV(WGM41); // Fast PWM (WGM41) / Clear OC4A/pin 5 on compare match (set output to low level)
OCR4A = 0;
}

if (pin == 7) {
TCCR4A = _BV(COM4B1) | _BV(COM4B0) | _BV(WGM41); // Fast PWM (WGM41) / (Clear OC4B/pin 2 on compare match (set output to low level)
OCR4B = 0;
}

if (pin == 8) {
TCCR4A = _BV(COM4C1) | _BV(COM4C0) | _BV(WGM41); // Fast PWM (WGM41) / Clear OC4C/pin 4 on compare match (set output to low level)
OCR4C = labs(F_CPU / LASER_PWM); // Set OCR4C to TOP value so it doesnt compare
}

TCCR4B = _BV(CS40) | _BV(WGM43) | _BV(WGM42); // Fast PWM / clkIo/1 (No prescaling)

interrupts();

}

void laser_init()
Expand Down Expand Up @@ -112,31 +143,109 @@ void laser_init()

laser_extinguish();
}
void laser_fire(int intensity = 100.0){
void laser_fire(int intensity = 100.0) {

laser.firing = LASER_ON;
laser.last_firing = micros(); // microseconds of last laser firing

if (intensity > 100.0) intensity = 100.0; // restrict intensity between 0 and 100
if (intensity < 0) intensity = 0;

pinMode(LASER_FIRING_PIN, OUTPUT);
#if LASER_CONTROL == 1
analogWrite(LASER_FIRING_PIN, labs((intensity / 100.0)*(F_CPU / LASER_PWM)));
#if LASER_FIRING_PIN == 2
OCR3B = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_FIRING_PIN == 3
OCR3C = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_FIRING_PIN == 5
OCR3A = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_FIRING_PIN == 6
OCR4A = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_FIRING_PIN == 7
OCR4B = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_FIRING_PIN == 8
OCR4C = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#endif

#if LASER_CONTROL == 2
analogWrite(LASER_INTENSITY_PIN, labs((intensity / 100.0)*(F_CPU / LASER_PWM)));
digitalWrite(LASER_FIRING_PIN, HIGH);
#if LASER_INTENSITY_PIN == 2
OCR3B = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_INTENSITY_PIN == 3
OCR3C = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_INTENSITY_PIN == 5
OCR3A = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_INTENSITY_PIN == 6
OCR4A = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_INTENSITY_PIN == 7
OCR4B = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
#if LASER_INTENSITY_PIN == 8
OCR4C = labs((intensity / 100.0)*(F_CPU / LASER_PWM));
#endif
digitalWrite(LASER_FIRING_PIN, LOW);
#endif

if (laser.diagnostics) {
SERIAL_ECHOLN("Laser fired");
SERIAL_ECHOLN("Laser fired");
}
}

void laser_extinguish(){
if (laser.firing == LASER_ON) {
laser.firing = LASER_OFF;

// Engage the pullup resistor for TTL laser controllers which don't turn off entirely without it.
digitalWrite(LASER_FIRING_PIN, LOW);
#if LASER_CONTROL == 1
#if LASER_FIRING_PIN == 2
OCR3B = 0;
#endif
#if LASER_FIRING_PIN == 3
OCR3C = 0;
#endif
#if LASER_FIRING_PIN == 5
OCR3A = 0;
#endif
#if LASER_FIRING_PIN == 6
OCR4A = 0;
#endif
#if LASER_FIRING_PIN == 7
OCR4B = 0;
#endif
#if LASER_FIRING_PIN == 8
OCR4C = 0;
#endif
#endif

#if LASER_CONTROL == 2
#if LASER_INTENSITY_PIN == 2
OCR3B = 0;
#endif
#if LASER_INTENSITY_PIN == 3
OCR3C = 0;
#endif
#if LASER_INTENSITY_PIN == 5
OCR3A = 0;
#endif
#if LASER_INTENSITY_PIN == 6
OCR4A = 0;
#endif
#if LASER_INTENSITY_PIN == 7
OCR4B = 0;
#endif
#if LASER_INTENSITY_PIN == 8
OCR4C = 0;
#endif
digitalWrite(LASER_FIRING_PIN, HIGH);
#endif

laser.time += millis() - (laser.last_firing / 1000);

if (laser.diagnostics) {
Expand Down