gnea / grbl-Mega

An open source, embedded, high performance g-code-parser and CNC milling controller written in optimized C that will run on an Arduino Mega2560
https://github.com/gnea/grbl/wiki
Other
496 stars 229 forks source link

Spindle PWM Pin Swap #52

Closed knightmg1983 closed 6 years ago

knightmg1983 commented 6 years ago

I'm wondering if there is a reason why the spindle PWM was set up to use OCR4A for the top value instead of simply using the fixed 10bit timer/counter. I had been trying to change the PWM output pin from Arduino Mega D8 to pin D6 and believe I have it working by changing timer4 to use the ICR4 register for the top value, OCR4A to set the duty cycle, and OC4A for the PWM output.

It may have been a simpler route to use a different OCR4x register for the top value but I could not figure out how to get that working. It also seems to me that just using the timer in fixed 10bit fast PWM would make setup easier.

I am by no means an expert and am only just now diving into GRBL while trying to get a laser diode setup. I am also new to the GitHub workflow so I apologize if this should be brought up elsewhere. BTW I have an Arduino Mega with Ramps 1.4.

Edit: I'm not familiar with driving a spindle but would a variable frequency be desired? In that case it would make sense to use those particular settings for the timer.

chamnit commented 6 years ago

Certain laser drivers run optimally at certain frequencies. If I recall correctly, OCR4A sets that frequency. Variable frequency is desirable for lasers, because material response to laser pulses is not uniform. Eventually I'll get to add that option, but not right now.

knightmg1983 commented 6 years ago

@chamnit That does indeed make sense and so it seems that we would want to preserve the ability to vary the frequency. I believe that the changes I have made do preserve that ability with the exception of being able to change frequency on the fly since the ICR4 register is not double buffered.

Anyhow... My goal was to change the Spindle PWM pin to use Arduino Mega pin D6 so that I could feed the laser driver a 5V PWM signal. For whatever reason I couldn't seem to find any reference on how to do this so I thought that I would share the changes that I made to the cpu_map.h file to achieve the pin swap:

// Advanced Configuration Below You should not need to touch these variables
  // Set Timer up to use TIMER4A which is attached to Digital Pin 6 - Ramps 1.4 Servo Pin 2
  #define SPINDLE_PWM_MAX_VALUE     1024.0 // Translates to about 1.9 kHz PWM frequency at 1/8 prescaler, 15.6 kHz with a prescaler of 1
  #ifndef SPINDLE_PWM_MIN_VALUE
  #define SPINDLE_PWM_MIN_VALUE   1   // Must be greater than zero.
  #endif
  #define SPINDLE_PWM_OFF_VALUE     0
  #define SPINDLE_PWM_RANGE         (SPINDLE_PWM_MAX_VALUE-SPINDLE_PWM_MIN_VALUE)

  //Control Digital Pin 6 which is Servo 2 signal pin on Ramps 1.4 board
  #define SPINDLE_TCCRA_REGISTER    TCCR4A
  #define SPINDLE_TCCRB_REGISTER    TCCR4B
  #define SPINDLE_OCR_REGISTER      OCR4A //was OCR4C, the value of this register sets the duty cycle
  #define SPINDLE_COMB_BIT          COM4A1 //was COM4C1

  // 1/8 Prescaler, 16-bit Fast PWM mode
  #define SPINDLE_TCCRA_INIT_MASK (1<<WGM41)) //removed (1<<WGM40), now using ICR4 to hold the TOP value
  #define SPINDLE_TCCRB_INIT_MASK ((1<<WGM42) | (1<<WGM43) | (1<<CS41)) // replacing (1<<CS41) with (1<<CS40) will change prescaler to 1
  #define SPINDLE_OCRA_REGISTER   ICR4 // 16-bit Fast PWM mode requires top reset value stored here.
  #define SPINDLE_OCRA_TOP_VALUE  0x0400 // PWM counter reset value. Should be the same as PWM_MAX_VALUE in hex.

  // Define spindle output pins.
  #define SPINDLE_PWM_DDR   DDRH
  #define SPINDLE_PWM_PORT  PORTH
  #define SPINDLE_PWM_BIT   3 // MEGA2560 Digital Pin 6 (Ramps1.4 Servo 2)

Disclaimer: I am not an expert in this subject so errors may be possible. I just wanted to share what seemed to work for me so that others trying to do the same may benefit.

chamnit commented 6 years ago

I'm not intimately familiar with the Mega2560, as I am with the 328p. I'd have to look at the data sheets, but changing pins is usually tricky, especially when using a built-in peripheral like hardware PWM. BTW, most of the spindle configuration stuff was done by several helpful users. I didn't implement them personally. I just remember that the Mega2560 has lots of different ports and pins, each with a specific set of thing they can do and can't. Enough to make my head spin. Sorry, I don't think I can help you much more.

knightmg1983 commented 6 years ago

No problem at all. The changes posted above appear to work well enough. My intent was to better understand the original implementation and how the changes that I made might affect the rest of GRBL before posting them.

Thanks go to you and everyone else that has made this project into what it is today.