Last active
December 28, 2015 20:59
-
-
Save speters/7561037 to your computer and use it in GitHub Desktop.
Elektronische Leitspindel für eine Drehmaschine mit dem Arduino Mega2560.Version 1a von http://www.chipmaker.ru/files/file/9787/ Urspungsthema in http://www.chipmaker.ru/topic/97701/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/pgmspace.h> | |
// ***** LCD ***** | |
#include <LiquidCrystal.h> | |
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); | |
char LCD_Row_1[17]; | |
char LCD_Row_2[17]; | |
// ***** Stepper Motor ***** | |
//#define Motor_X_Step_Per_Revolution 2400 | |
//#define Motor_Y_Step_Per_Revolution 2400 | |
#define MotorPort PORTL // под моторы выделен весь порт "L", | |
#define MotorInitialization() DDRL=B11111111 // сконфигурирован как выход | |
#define Motor_X_SetPulse() MotorPort &= ~(1<<0) // Pin49 1 | |
#define Motor_X_RemovePulse() MotorPort |= (1<<0) // Pin49 0 | |
#define Motor_Y_SetPulse() MotorPort &= ~(1<<1) // Pin48 1 | |
#define Motor_Y_RemovePulse() MotorPort |= (1<<1) // Pin48 0 | |
#define Motor_X_Forward() MotorPort |= (1<<2) // Pin47 0 | |
#define Motor_X_Reverse() MotorPort &= ~(1<<2) // Pin47 1 | |
#define Motor_Y_Forward() MotorPort |= (1<<3) // Pin46 0 | |
#define Motor_Y_Reverse() MotorPort &= ~(1<<3) // Pin46 1 | |
#define Motor_X_Enable() MotorPort |= (1<<4) // Pin45 0 | |
#define Motor_X_Disable() MotorPort &= ~(1<<4) // Pin45 1 | |
#define Motor_Y_Enable() MotorPort |= (1<<5) // Pin44 0 | |
#define Motor_Y_Disable() MotorPort &= ~(1<<5) // Pin44 1 | |
boolean Step_On_flag=false; // Флаг разрешаем/запрещаем счет до "шагать" | |
boolean Mode_On_flag=false; // Флаг On/Off режим | |
// ***** Taho ***** | |
#define TahoPort PORTL | |
#define TahoSetPulse() TahoPort |= (1<<6) // Pin43 1 | |
#define TahoRemovePulse() TahoPort &= ~(1<<6) // Pin43 0 | |
// ***** Encoder ***** | |
#define Enc_Line_per_Revolution 1800 // Кол-во линий энкодера | |
#define Enc_Line Enc_Line_per_Revolution*2 // Рабочее кол-во тиков | |
#define EncoderPort PORTD | |
#define EncoderInitialization() DDRD=B00000000 // Под энкодер выделен весь порт "D", сконфигурирован на вход | |
#define Enc_Read() (PIND & B00000010) | |
volatile int Enc_Pos=0; // Счетчик положения энкодера | |
volatile byte Ks_Count=0; // Счетчик для "Подача", "Резьба" целая часть | |
volatile int Km_Count=0; // Счетчик для "Подача", "Резьба" дробная часть | |
byte Ks_Divisor=0; // Делитель для "Подача", "Резьба" целая часть | |
int Km_Divisor=0; // Делитель для "Подача", "Резьба" дробная часть | |
int Enc_Pos_tmp=0; | |
long Spindle_Angle=0; | |
//***** Sensor ***** | |
#define SensorPort PORTD | |
#define Sensor PIND | |
#define Sensor_Left_Mask B00001000 | |
#define Sensor_Right_Mask B00000100 | |
char Sensor_Mask = B00000000; | |
enum Pressed_Key | |
{ | |
Key_None, | |
Key_Right, | |
Key_Up, | |
Key_Down, | |
Key_Left, | |
Key_Select | |
}; | |
byte Pressed_Key=Key_None; | |
boolean key_flag=false; // флаг нажатой/отжатой кнопки | |
// ***** Mode ***** | |
enum Mode | |
{ | |
Mode_Thread_Left=1, | |
Mode_Feed_Left, | |
Mode_Divider, | |
Mode_Feed_Right, | |
Mode_Thread_Right | |
}; | |
byte Mode = Mode_Divider; | |
// ***** Feeds ***** | |
// Enc_Line/(Step_Per_Revolution/Feed_Screw*Feed_mm) | |
#define Total_Feeds 10 // Кол-во подач | |
typedef struct | |
{ | |
byte s_Divisor; // Делитель для "Подача" целая часть | |
char Text[7]; | |
} | |
FEED_INFO; | |
FEED_INFO Feed_Info[Total_Feeds] = | |
{ | |
{ 113, "0.02mm" }, | |
{ 56, "0.04mm" }, | |
{ 38, "0.06mm" }, | |
{ 28, "0.08mm" }, | |
{ 23, "0.10mm" }, | |
{ 19, "0.12mm" }, | |
{ 16, "0.14mm" }, | |
{ 14, "0.16mm" }, | |
{ 13, "0.18mm" }, | |
{ 11, "0.20mm" }, | |
}; | |
byte Feed_Step = 3; // выборка из массива по умолчанию (0.08mm) | |
// ***** Threads ***** | |
// Enc_Line/(Step_Per_Revolution/Feed_Screw*Thread_mm) | |
#define Total_Threads 36 // Кол-во резьб | |
typedef struct | |
{ | |
byte s_Divisor; // Делитель для "Резьба" целая часть | |
int m_Divisor; // Делитель для "Резьба" дробная часть | |
char Text[7]; | |
} | |
THREAD_INFO; | |
THREAD_INFO Thread_Info[Total_Threads] = | |
{ | |
{ 11, 2500, "0.20mm" }, | |
{ 9, 0, "0.25mm" }, | |
{ 7, 5000, "0.30mm" }, | |
{ 6, 4286, "0.35mm" }, | |
{ 5, 6250, "0.40mm" }, | |
{ 4, 5000, "0.50mm" }, | |
{ 3, 7500, "0.60mm" }, | |
{ 3, 2143, "0.70mm" }, | |
{ 3, 0, "0.75mm" }, | |
{ 2, 8125, "0.80mm" }, | |
{ 2, 2500, "1.00mm" }, | |
{ 1, 8000, "1.25mm" }, | |
{ 1, 5000, "1.50mm" }, | |
{ 1, 2857, "1.75mm" }, | |
{ 1, 1250, "2.00mm" }, | |
{ 7, 866, "80tpi " }, | |
{ 6, 3780, "72tpi " }, | |
{ 5, 6693, "64tpi " }, | |
{ 5, 3150, "60tpi " }, | |
{ 4, 9606, "56tpi " }, | |
{ 4, 2520, "48tpi " }, | |
{ 3, 8976, "44tpi " }, | |
{ 3, 5433, "40tpi " }, | |
{ 3, 1890, "36tpi " }, | |
{ 2, 8347, "32tpi " }, | |
{ 2, 4803, "28tpi " }, | |
{ 2, 3917, "27tpi " }, | |
{ 2, 3032, "26tpi " }, | |
{ 2, 1260, "24tpi " }, | |
{ 1, 9488, "22tpi " }, | |
{ 1, 7717, "20tpi " }, | |
{ 1, 6831, "19tpi " }, | |
{ 1, 5945, "18tpi " }, | |
{ 1, 4173, "16tpi " }, | |
{ 1, 2402, "14tpi " }, | |
{ 1, 0630, "12tpi " }, | |
}; | |
byte Thread_Step = 10; // выборка из массива по умолчанию (1.0mm) | |
// ***** Interrupts ***** | |
#define EnableINT0() EIMSK |= (1 << INT0) | |
#define DisableINT0() EIMSK &= ~(1 << INT0) | |
#define Init_INT0_Any() EICRA = B00000001 | |
//********************************************************* | |
void setup() | |
{ | |
TIMSK0=0; // !Отключаем таймер! (он что-то свое делает в фоновом режиме) | |
EncoderInitialization(); | |
PORTD=B00001111; // подтяжка PIN_21, 20, 19, 18 | |
MotorInitialization(); | |
Init_INT0_Any(); | |
EnableINT0(); | |
lcd.begin(16, 2); | |
} | |
//********************************************************** | |
void loop() | |
{ | |
Enc_Pos_tmp = Enc_Pos; // в "void Divider" читаем повторно и сравниваем | |
if ((Mode == Mode_Divider) || !Mode_On_flag) | |
{ | |
Motor_X_Disable(); | |
// Motor_Y_Disable(); | |
} | |
else | |
{ | |
Motor_X_Enable(); | |
// Motor_Y_Enable(); | |
} | |
menu(); | |
Sensors(); | |
} | |
// ********** Функция обработки событий в главном меню ********** | |
void menu() | |
{ | |
int ADC_value = analogRead(A0); | |
if (ADC_value < 65) Pressed_Key=Key_Right; | |
else if (ADC_value < 220) Pressed_Key=Key_Up; | |
else if (ADC_value < 390) Pressed_Key=Key_Down; | |
else if (ADC_value < 600) Pressed_Key=Key_Left; | |
else if (ADC_value < 870) Pressed_Key=Key_Select; | |
else Pressed_Key = Key_None; | |
if (!key_flag) | |
{ | |
switch (Pressed_Key) | |
{ | |
case Key_Left: | |
MenuKeyLeftPressed(); | |
break; | |
case Key_Right: | |
MenuKeyRightPressed(); | |
break; | |
case Key_Up: | |
MenuKeyUpPressed(); | |
break; | |
case Key_Down: | |
MenuKeyDownPressed(); | |
break; | |
case Key_Select: | |
MenuKeySelectPressed(); | |
break; | |
} | |
} | |
if (Pressed_Key == Key_None) key_flag = false; | |
SelectWorkMode(); // вызов выбранного рабочего режима | |
} | |
// ********** Обработчик нажатия кнопки Select ********** | |
void MenuKeySelectPressed() | |
{ | |
switch (Mode) | |
{ | |
case Mode_Thread_Left: | |
case Mode_Thread_Right: | |
case Mode_Feed_Left: | |
case Mode_Feed_Right: | |
Step_On_flag = false; | |
Mode_On_flag = !Mode_On_flag; // переворачиваем значение на противоположное | |
Ks_Count = 0; | |
Km_Count = 0; | |
break; | |
case Mode_Divider: | |
Enc_Pos=0; | |
break; | |
} | |
key_flag = true; | |
} | |
// ********** Обработчик нажатия кнопки Up ********** | |
void MenuKeyUpPressed() | |
{ | |
switch (Mode) | |
{ | |
case Mode_Thread_Left: | |
case Mode_Thread_Right: | |
if (Thread_Step < Total_Threads-1) | |
{ | |
Mode_On_flag = false; | |
Step_On_flag = false; | |
Ks_Count=0; | |
Km_Count=0; | |
Thread_Step++; | |
} | |
break; | |
case Mode_Feed_Left: | |
case Mode_Feed_Right: | |
if (Feed_Step < Total_Feeds-1) | |
{ | |
Ks_Count=0; | |
Feed_Step++; | |
} | |
break; | |
} | |
key_flag = true; | |
} | |
// ********** Обработчик нажатия кнопки Down ********** | |
void MenuKeyDownPressed() | |
{ | |
switch (Mode) | |
{ | |
case Mode_Thread_Left: | |
case Mode_Thread_Right: | |
if (Thread_Step > 0) | |
{ | |
Mode_On_flag = false; | |
Step_On_flag = false; | |
Ks_Count=0; | |
Km_Count=0; | |
Thread_Step--; | |
} | |
break; | |
case Mode_Feed_Left: | |
case Mode_Feed_Right: | |
if (Feed_Step > 0) | |
{ | |
Ks_Count=0; | |
Feed_Step--; | |
} | |
break; | |
} | |
key_flag = true; | |
} | |
// ********** Обработчик нажатия кнопки Left ********** | |
void MenuKeyLeftPressed() | |
{ | |
switch (Mode) | |
{ | |
case Mode_Feed_Left: | |
case Mode_Divider: | |
case Mode_Feed_Right: | |
case Mode_Thread_Right: | |
Mode_On_flag = false; | |
Step_On_flag = false; | |
Ks_Count=0; | |
Km_Count=0; | |
Mode--; | |
break; | |
} | |
key_flag = true; | |
} | |
// ********** Обработчик нажатия кнопки Right ********** | |
void MenuKeyRightPressed() | |
{ | |
switch (Mode) | |
{ | |
case Mode_Thread_Left: | |
case Mode_Feed_Left: | |
case Mode_Divider: | |
case Mode_Feed_Right: | |
Mode_On_flag = false; | |
Step_On_flag = false; | |
Ks_Count=0; | |
Km_Count=0; | |
Mode++; | |
break; | |
} | |
key_flag = true; | |
} | |
// ********** Выбор режима работы ********** | |
void SelectWorkMode() | |
{ | |
switch (Mode) | |
{ | |
case Mode_Thread_Left: | |
Thread_Left(); | |
break; | |
case Mode_Feed_Left: | |
Motor_X_Reverse(); | |
Feed_Left(); | |
break; | |
case Mode_Divider: | |
Divider(); | |
break; | |
case Mode_Feed_Right: | |
Motor_X_Forward(); | |
Feed_Right(); | |
break; | |
case Mode_Thread_Right: | |
Thread_Right(); | |
} | |
} | |
//*************************************** | |
void Thread_Left() | |
{ | |
Sensor_Mask = Sensor_Left_Mask; | |
Ks_Divisor=Thread_Info[Thread_Step].s_Divisor; | |
Km_Divisor=Thread_Info[Thread_Step].m_Divisor; | |
snprintf(LCD_Row_1, 17, (Mode_On_flag==true) ? "Mode: ON " : "Mode: OFF "); | |
snprintf(LCD_Row_2, 17, "Thread <= %s", Thread_Info[Thread_Step].Text); | |
Print(); | |
} | |
void Feed_Left() | |
{ | |
Sensor_Mask = Sensor_Left_Mask; | |
Ks_Divisor=Feed_Info[Feed_Step].s_Divisor; | |
snprintf(LCD_Row_1, 17, (Mode_On_flag==true) ? "Mode: ON " : "Mode: OFF "); | |
snprintf(LCD_Row_2, 17, "Feed <= %s", Feed_Info[Feed_Step].Text); | |
Print(); | |
} | |
void Divider() | |
{ | |
if (Enc_Pos == Enc_Pos_tmp) | |
{ | |
Spindle_Angle=(Enc_Pos*360000/(Enc_Line)); | |
} | |
snprintf(LCD_Row_1, 17, "Mode: Divider "); | |
snprintf(LCD_Row_2, 17, "Angle: %3ld.%03ld ", Spindle_Angle/1000, Spindle_Angle%1000); | |
Print(); | |
} | |
void Feed_Right() | |
{ | |
Sensor_Mask = Sensor_Right_Mask; | |
Ks_Divisor=Feed_Info[Feed_Step].s_Divisor; | |
snprintf(LCD_Row_1, 17, (Mode_On_flag==true) ? "Mode: ON " : "Mode: OFF "); | |
snprintf(LCD_Row_2, 17, "Feed => %s", Feed_Info[Feed_Step].Text); | |
Print(); | |
} | |
void Thread_Right() | |
{ | |
Sensor_Mask = Sensor_Right_Mask; | |
Ks_Divisor=Thread_Info[Thread_Step].s_Divisor; | |
Km_Divisor=Thread_Info[Thread_Step].m_Divisor; | |
snprintf(LCD_Row_1, 17, (Mode_On_flag==true) ? "Mode: ON " : "Mode: OFF "); | |
snprintf(LCD_Row_2, 17, "Thread => %s", Thread_Info[Thread_Step].Text); | |
Print(); | |
} | |
//****************************************************************** | |
void Print() | |
{ | |
lcd.setCursor(0, 0); | |
lcd.print(LCD_Row_1); | |
lcd.setCursor(0, 1); | |
lcd.print(LCD_Row_2); | |
} | |
//****************************************************************** | |
void Sensors() | |
{ | |
if (!(Sensor & Sensor_Mask) ) | |
{ | |
Mode_On_flag = false; | |
} | |
} | |
//****************************************************************** | |
ISR(INT0_vect) | |
{ | |
TahoRemovePulse(); | |
Motor_X_RemovePulse(); | |
if (!Enc_Read()) // Вращение шпинделя вправо | |
{ | |
Enc_Pos++; | |
if (Enc_Pos == Enc_Line) // полный оборот | |
{ | |
Enc_Pos = 0; | |
TahoSetPulse(); // при проходе 0 генерим сигнал Taho | |
Step_On_flag = (Mode_On_flag == true); // проверка режима на ON/OFF, только! после прохода 0 разрешаем счет до к.деления | |
} | |
if (Step_On_flag) | |
{ | |
if (!(Sensor & Sensor_Mask) ) | |
{ | |
Step_On_flag = false; | |
return; | |
} | |
if (Mode == Mode_Feed_Left) | |
{ | |
if (Ks_Count == Ks_Divisor) | |
{ | |
Motor_X_SetPulse(); | |
Ks_Count = 0; | |
} | |
Ks_Count++; | |
} | |
else if (Mode == Mode_Feed_Right) | |
{ | |
if (Ks_Count == Ks_Divisor) | |
{ | |
Motor_X_SetPulse(); | |
Ks_Count = 0; | |
} | |
Ks_Count++; | |
} | |
else if (Mode == Mode_Thread_Left) | |
{ | |
if (Ks_Count > Ks_Divisor) | |
{ | |
Motor_X_Reverse(); | |
Motor_X_SetPulse(); | |
Km_Count = Km_Count + Km_Divisor; | |
if (Km_Count > Km_Divisor) | |
{ | |
Km_Count = Km_Count - 10000; | |
Ks_Count = 0; | |
} | |
else | |
{ | |
Ks_Count = 1; | |
} | |
} | |
Ks_Count++; | |
} | |
else if (Mode == Mode_Thread_Right) | |
{ | |
if (Ks_Count > Ks_Divisor) | |
{ | |
Motor_X_Forward(); | |
Motor_X_SetPulse(); | |
Km_Count = Km_Count + Km_Divisor; | |
if (Km_Count > Km_Divisor) | |
{ | |
Km_Count = Km_Count - 10000; | |
Ks_Count = 0; | |
} | |
else | |
{ | |
Ks_Count = 1; | |
} | |
} | |
Ks_Count++; | |
} | |
} | |
} | |
else | |
{ // Вращение шпинделя влево | |
Enc_Pos--; | |
if (Enc_Pos < 0) | |
{ | |
Enc_Pos = Enc_Line - 1; | |
TahoSetPulse(); | |
Step_On_flag = (Mode_On_flag == true); // проверка режима на ON/OFF, только! после прохода 0 разрешаем счет до к.деления | |
} | |
if (Step_On_flag) | |
{ | |
if (!(Sensor & Sensor_Mask) ) | |
{ | |
Step_On_flag = false; | |
return; | |
} | |
if (Mode == Mode_Feed_Left) | |
{ | |
if (Ks_Count == 0) | |
{ | |
Motor_X_SetPulse(); | |
Ks_Count = Ks_Divisor; | |
} | |
Ks_Count--; | |
} | |
if (Mode == Mode_Feed_Right) | |
{ | |
if (Ks_Count == 0) | |
{ | |
Motor_X_SetPulse(); | |
Ks_Count = Ks_Divisor; | |
} | |
Ks_Count--; | |
} | |
if (Mode == Mode_Thread_Left) | |
{ | |
if (Ks_Count == 0) | |
{ | |
Motor_X_Forward(); | |
Motor_X_SetPulse(); | |
Km_Count = Km_Count - Km_Divisor; | |
if (Km_Count < 1) | |
{ | |
Km_Count = Km_Count + 10000; | |
Ks_Count = Ks_Divisor + 1; | |
} | |
else | |
{ | |
Ks_Count = Ks_Divisor; | |
} | |
} | |
Ks_Count--; | |
} | |
if (Mode == Mode_Thread_Right) | |
{ | |
if (Ks_Count == 0) | |
{ | |
Motor_X_Reverse(); | |
Motor_X_SetPulse(); | |
Km_Count = Km_Count - Km_Divisor; | |
if (Km_Count < 1) | |
{ | |
Km_Count = Km_Count + 10000; | |
Ks_Count = Ks_Divisor + 1; | |
} | |
else | |
{ | |
Ks_Count = Ks_Divisor; | |
} | |
} | |
Ks_Count--; | |
} | |
} | |
} | |
} | |
//******************************************************************* | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment