0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

A-Axisを制御したい!Arduino Mega2560 + CNC シールド v3.0 の覚書

Last updated at Posted at 2023-03-13

初めに

Arduino UnoとCNCシールドで4軸を動かしたく調べてた備忘録
⇒結局はMega2560とCNCシールドに補助シールドを起こすことで対応

使用したもの

ライブラリは下記を使用
https://github.com/mlambm/grbl

ライブラリの問題点

上記ライブラリで4軸目のA軸も無事に動いたが A軸用のリミットスイッチがない

確認した内容

A軸用のリミットスイッチを設けるためソースを見ていくと digitalWrite や analogWrite でなく ポートを直接いじっている模様
太刀打ちできんのでChatGPTに聞くも毎回珍回答ばかりで調べた結果が次の通り

ATmega328pのピン番号 ポート番号 Arduino Unoのピン番号 CNCシールド v3.0のピン名 備考
1 PC6(RESET/PCINT14)
2 PD0(PCINT16) D0 RXのため使用しない
3 PD1(PCINT17) D1 TXのため使用しない
4 PD2(PCINT18) D2 X-STEP
5 PD3(PCINT19) D3 Y-STEP
6 PD4(PCINT20) D4 Z-STEP
7 VCC 電源電圧
8 GND グランド
9 PB6(XTAL1/PCINT6) クリスタル1
10 PB7(XTAL2/PCINT7) クリスタル2
11 PD5(PCINT21) D5 X-DIR
12 PD6(PCINT22) D6 Y-DIR
13 PD7(PCINT23) D7 Z-DIR
14 PB0(PCINT0) D8 EN ドライバーの有効・無効
15 PB1(PCINT1) D9 X-EndStop Limit X-Axis
16 PB2(PCINT2) D10 Y-EndStop Limit Y-Axis
17 PB3(PCINT3) D11 Z-EndStop Limit Z-Axis
18 PB4(PCINT4) D12 SpinEnable(A.STP)
19 PB5(PCINT5) D13 SpinDir(A.DIR)
20 AVCC
21 AREF
22 AGND
23 PC0(PCINT8) D14 / A0 ABORT
24 PC1(PCINT9) D15 / A1 HOLD
25 PC2(PCINT10) D16 / A2 RESUME
26 PC3(PCINT11) D17 / A3 Coolant
27 PC4(PCINT12) D18 / A4 for I2C(SDA)?
28 PC5(PCINT13) D19 / A5 for I2C(SCL)?
CNCシールドのピン 説明
Step[XYZ] [XYZ]軸の回転方向
Probe ワークピースの位置を確認するためのセンサー
Spindle 主軸(カッター)の回転を制御するためのピン
Coolant 冷却液を制御するためのピン

schematic
pcb-font
pcb-rear
Arduino Uno
Unoの回路図

Coolant が使えるのかな
⇒使えないわけではない様だが外部割込みは一つのポートで完結しないとプログラムが大変らしい

結論その1

結論Unoだとピンが足りない!

Mega2560 に鞍替え

では沢山ポートがある Mega2560 でならので何とかなるだろう!と鞍替え
...リミットスイッチがPin Change Interrupt register に属してないといけないから自分の知識では結構難しかった💦

megaAVR® データシート

これの 13. 外部割り込み に詳細が書かれている
PCIE0, PCIE1, PCIE2は54頁

Pin Change Interrupt Enable # PIN Pin Change Enable Mask #
PCIE0 PCINT0~PCINT7 PCMSK0
PCIE1 PCINT8~PCINT15 PCMSK1
PCIE2 PCINT16~PCINT23 PCMSK2

なるほど
ATmega2560 には Pin Change Interrupt Register は3つあるが PCMSK1 は Mega2560 では使用できない事が判明

ということで次の様になった

CNCシールドのものを直接使用するのは断念しサブシールドを作成して対応

Mega2560 ポート 役割 備考
D22 PA0 X-step
D24 PA2 Y-step
D26 PA4 Z-step
D28 PA6 A-step
D31 PC6 X-dir
D33 PC4 Y-dir
D35 PC2 Z-dir
D37 PC0 A-dir
A8 PK0 X-limit PCMSK2 PCINT16
A9 PK1 Y-limit PCMSK2 PCINT17
A10 PK2 Z-limit PCMSK2 PCINT18
A11 PK3 A-limit PCMSK2 PCINT19
D50 PB3 Reset PCMSK0 PCINT3
D51 PB2 Feed Hold PCMSK0 PCINT2
D52 PB1 Sycle State PCMSK0 PCINT1
D53 PB0 Safty Door PCMSK0 PCINT0

いじったのは次のファイル

config.h
#define CPU_MAP_ATMEGA2560

#define HOMING_CYCLE_2 ((1<<A_AXIS))
limits.c, report.c
N_AXIS3 -> N_AXIS4
settings.c
// Returns limit pin mask according to Grbl internal axis indexing.
uint8_t get_limit_pin_mask(uint8_t axis_idx)
{
  if ( axis_idx == X_AXIS ) { return((1<<X_LIMIT_BIT)); }
  if ( axis_idx == Y_AXIS ) { return((1<<Y_LIMIT_BIT)); }
  if ( axis_idx == Z_AXIS ) { return((1<<Z_LIMIT_BIT)); }
  return((1<<A_LIMIT_BIT));
}
stepper.c
  #if defCPU_MAP_ATMEGA328P
    uint8_t step_bits[2];  // Stores out_bits output to complete the step pulse delay
  #else
    uint8_t step_bits;  // Stores out_bits output to complete the step pulse delay
  #endif

---

ISR(TIMER1_COMPA_vect)
{        
// SPINDLE_ENABLE_PORT ^= 1<<SPINDLE_ENABLE_BIT; // Debug: Used to time ISR
  if (busy) { return; } // The busy-flag is used to avoid reentering this interrupt
  
#ifdef CPU_MAP_ATMEGA328P
  // Set the direction pins a couple of nanoseconds before we step the steppers
  DIRECTION_PORT0 = (DIRECTION_PORT0 & ~DIRECTION_MASK0) | (st.dir_outbits & DIRECTION_MASK0);

  // Then pulse the stepping pins
  #ifdef STEP_PULSE_DELAY
    st.step_bits[0] = (STEP_PORT0 & ~STEP_MASK0) | (st.step_outbits & STEP_MASK0); // Store out_bits to prevent overwriting.
  #else  // Normal operation
    STEP_PORT0 = (STEP_PORT0 & ~STEP_MASK0) | st.step_outbits & STEP_MASK0;
  #endif  

  // Set the direction pins a couple of nanoseconds before we step the steppers
  DIRECTION_PORT1 = (DIRECTION_PORT1 & ~DIRECTION_MASK1) | ((st.dir_outbits<<4) & DIRECTION_MASK1);

  // Then pulse the stepping pins
  #ifdef STEP_PULSE_DELAY
    st.step_bits[1] = (STEP_PORT1 & ~STEP_MASK1) | ((st.step_outbits<<4) & STEP_MASK1); // Store out_bits to prevent overwriting.
  #else  // Normal operation
    STEP_PORT1 = (STEP_PORT1 & ~STEP_MASK1) | (st.step_outbits<<4) & STEP_MASK1;
  #endif
#else
  // Set the direction pins a couple of nanoseconds before we step the steppers
  DIRECTION_PORT = (DIRECTION_PORT & ~DIRECTION_MASK) | (st.dir_outbits & DIRECTION_MASK);

  // Then pulse the stepping pins
  #ifdef STEP_PULSE_DELAY
    st.step_bits = (STEP_PORT & ~STEP_MASK) | st.step_outbits; // Store out_bits to prevent overwriting.
  #else  // Normal operation
    STEP_PORT = (STEP_PORT & ~STEP_MASK) | st.step_outbits;
  #endif  
#endif

---

ISR(TIMER0_OVF_vect)
{
  // Reset stepping pins (leave the direction pins)
#ifdef CPU_MAP_ATMEGA328P
  STEP_PORT0 = (STEP_PORT0 & ~STEP_MASK0) | (step_port_invert_mask & STEP_MASK0); 
  STEP_PORT1 = (STEP_PORT1 & ~STEP_MASK1) | (step_port_invert_mask & STEP_MASK1); 
#else
  STEP_PORT = (STEP_PORT & ~STEP_MASK) | (step_port_invert_mask & STEP_MASK); 
#endif
  TCCR0B = 0; // Disable Timer0 to prevent re-entering this interrupt when it's not needed. 
}
#ifdef STEP_PULSE_DELAY
  // This interrupt is used only when STEP_PULSE_DELAY is enabled. Here, the step pulse is
  // initiated after the STEP_PULSE_DELAY time period has elapsed. The ISR TIMER2_OVF interrupt
  // will then trigger after the appropriate settings.pulse_microseconds, as in normal operation.
  // The new timing between direction, step pulse, and step complete events are setup in the
  // st_wake_up() routine.
  ISR(TIMER0_COMPA_vect) 
  { 
#ifdef CPU_MAP_ATMEGA328P
    STEP_PORT0 = st.step_bits[0]; // Begin step pulse.
    STEP_PORT1 = st.step_bits[1]; // Begin step pulse.
#else
    STEP_PORT = st.step_bits; // Begin step pulse.
#endif
  }
#endif

---

// Initialize and start the stepper motor subsystem
void stepper_init()
{
  // Configure step and direction interface pins
#ifdef CPU_MAP_ATMEGA328P
  STEP_DDR0 |= STEP_MASK0;
  STEP_DDR1 |= STEP_MASK1;
  STEPPERS_DISABLE_DDR |= 1<<STEPPERS_DISABLE_BIT;
  DIRECTION_DDR0 |= DIRECTION_MASK0;
  DIRECTION_DDR1 |= DIRECTION_MASK1;
#else
  STEP_DDR |= STEP_MASK;
  STEPPERS_DISABLE_DDR |= 1<<STEPPERS_DISABLE_BIT;
  DIRECTION_DDR |= DIRECTION_MASK;
#endif
cpu_map/cpu_map_atmega2560.h
#define X_STEP_BIT    0 // MEGA2560 Digital Pin 22
#define Y_STEP_BIT    2 // MEGA2560 Digital Pin 24
#define Z_STEP_BIT    4 // MEGA2560 Digital Pin 26
#define A_STEP_BIT    6 // MEGA2560 Digital Pin 28
#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)|(1<<A_STEP_BIT)) // All step bits

// Define step direction output pins. NOTE: All direction pins must be on the same port.
#define DIRECTION_DDR     DDRC
#define DIRECTION_PORT    PORTC
#define DIRECTION_PIN     PINC
#define X_DIRECTION_BIT   6 // MEGA2560 Digital Pin 31
#define Y_DIRECTION_BIT   4 // MEGA2560 Digital Pin 33
#define Z_DIRECTION_BIT   2 // MEGA2560 Digital Pin 35
#define A_DIRECTION_BIT   0 // MEGA2560 Digital Pin 37
#define DIRECTION_MASK ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)|(1<<A_DIRECTION_BIT)) // All direction bits

// Define stepper driver enable/disable output pin.
#define STEPPERS_DISABLE_DDR   DDRH
#define STEPPERS_DISABLE_PORT  PORTH
#define STEPPERS_DISABLE_BIT   5 // MEGA2560 Digital Pin 8
#define STEPPERS_DISABLE_MASK (1<<STEPPERS_DISABLE_BIT)

// Define homing/hard limit switch input pins and limit interrupt vectors. 
// NOTE: All limit bit pins must be on the same port
#define LIMIT_DDR       DDRK
#define LIMIT_PORT      PORTK
#define LIMIT_PIN       PINK
#define X_LIMIT_BIT     0 // MEGA2560 Analog Pin A8
#define Y_LIMIT_BIT     1 // MEGA2560 Analog Pin A9
#define Z_LIMIT_BIT     2 // MEGA2560 Analog Pin A10
#define A_LIMIT_BIT     3 // MEGA2560 Analog Pin A11
#define LIMIT_INT       PCIE2  // Pin change interrupt enable pin
#define LIMIT_INT_vect  PCINT2_vect
#define LIMIT_PCMSK     PCMSK2 // Pin change interrupt register
#define LIMIT_MASK ((1<<X_LIMIT_BIT)|(1<<Y_LIMIT_BIT)|(1<<Z_LIMIT_BIT)|(1<<A_LIMIT_BIT)) // All limit bits

// Define spindle enable and spindle direction output pins.
#define SPINDLE_ENABLE_DDR      DDRB
#define SPINDLE_ENABLE_PORT     PORTB
#define SPINDLE_ENABLE_BIT      6 // MEGA2560 Digital Pin 12
#define SPINDLE_DIRECTION_DDR   DDRB
#define SPINDLE_DIRECTION_PORT  PORTB
#define SPINDLE_DIRECTION_BIT   7 // MEGA2560 Digital Pin 13

// Define flood and mist coolant enable output pins.
// NOTE: Uno analog pins 4 and 5 are reserved for an i2c interface, and may be installed at
// a later date if flash and memory space allows.
// #define COOLANT_FLOOD_DDR     DDRH
// #define COOLANT_FLOOD_PORT    PORTH
// #define COOLANT_FLOOD_BIT     5 // MEGA2560 Digital Pin 8
#ifdef ENABLE_M7 // Mist coolant disabled by default. See config.h to enable/disable.
#define COOLANT_MIST_DDR    DDRF
#define COOLANT_MIST_PORT   PORTF
#define COOLANT_MIST_BIT    3 // MEGA2560 Analog Pin 3
#endif  

// Define user-control CONTROLs (cycle start, reset, feed hold) input pins.
// NOTE: All CONTROLs pins must be on the same port and not on a port with other input pins (limits).
#define CONTROL_DDR       DDRB
#define CONTROL_PIN       PINB
#define CONTROL_PORT      PORTB
#define RESET_BIT         3  // MEGA2560 Digital Pin 50
#define FEED_HOLD_BIT     2  // MEGA2560 Digital Pin 51
#define CYCLE_START_BIT   1  // MEGA2560 Digital Pin 52
#define SAFETY_DOOR_BIT   0  // MEGA2560 Digital Pin 53
#define CONTROL_INT       PCIE0  // Pin change interrupt enable pin
#define CONTROL_INT_vect  PCINT0_vect
#define CONTROL_PCMSK     PCMSK0 // Pin change interrupt register
#define CONTROL_MASK ((1<<RESET_BIT)|(1<<FEED_HOLD_BIT)|(1<<CYCLE_START_BIT)|(1<<SAFETY_DOOR_BIT))
#define CONTROL_INVERT_MASK CONTROL_MASK // May be re-defined to only invert certain control pins.

結論その2

これでホーミングもできるようになりましたとさ

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?