на Megа 2560 с этим кодом энкодер работает
(для просмотра содержимого нажмите на ссылку)
// encoder pin on interrupt 0 (pin 2)
attachInterrupt(0, encoderPinChangeA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, encoderPinChangeB, CHANGE);
encoder0Pos = 0; //reseet the encoder position to 0
}
void loop() {
//do stuff dependent on encoder position here
//such as move a stepper motor to match encoder position
//if you want to make it 1:1 ensure the encoder res matches the motor res by dividing/multiplying
Serial.println(encoder0Pos);
delay(100);
}
void encoderPinChangeA() {
// look for a low-to-high on channel A
if (digitalRead(encoder0PinA) == HIGH) {
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
else // must be a high-to-low edge on channel A
{
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
}
void encoderPinChangeB() {
// look for a low-to-high on channel B
if (digitalRead(encoder0PinB) == HIGH) {
// check channel A to see which way encoder is turning
if (digitalRead(encoder0PinA) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
// Look for a high-to-low on channel B
else {
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinA) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
}
а вот код проекта нет) помогите хрен знает куда копать
электроная гитара на токарный станок
#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 12 // Кол-во подач
typedef struct
{
byte s_Divisor; // Делитель для "Подача" целая часть
char Text[7];
}
FEED_INFO;
FEED_INFO Feed_Info[Total_Feeds] =
{
{ 180, "0.02mm" },
{ 90, "0.04mm" },
{ 60, "0.06mm" },
{ 45, "0.08mm" },
{ 36, "0.10mm" },
{ 30, "0.12mm" },
{ 26, "0.14mm" },
{ 23, "0.16mm" },
{ 20, "0.18mm" },
{ 18, "0.20mm" },
{ 16, "0.22mm" },
{ 15, "0.24mm" },
};
byte Feed_Step = 3; // выборка из массива по умолчанию (0.08mm)
// ***** Threads *****
// Enc_Line/(Step_Per_Revolution/Feed_Screw*Thread_mm)
#define Total_Threads 40 // Кол-во резьб
typedef struct
{
byte s_Divisor; // Делитель для "Резьба" целая часть
int m_Divisor; // Делитель для "Резьба" дробная часть
char Text[7];
}
THREAD_INFO;
THREAD_INFO Thread_Info[Total_Threads] =
{
{ 18, 0000, "0.20mm" },
{ 14, 4000, "0.25mm" },
{ 12, 0000, "0.30mm" },
{ 10, 2857, "0.35mm" },
{ 9, 0000, "0.40mm" },
{ 7, 2000, "0.50mm" },
{ 6, 0000, "0.60mm" },
{ 5, 1429, "0.70mm" },
{ 4, 8000, "0.75mm" },
{ 4, 5000, "0.80mm" },
{ 3, 6000, "1.00mm" },
{ 2, 8800, "1.25mm" },
{ 2, 4000, "1.50mm" },
{ 2, 0571, "1.75mm" },
{ 1, 8000, "2.00mm" },
{ 1, 4400, "2.50mm" },
{ 1, 2000, "3.00mm" },
{ 11, 3386, "80tpi " },
{ 10, 2047, "72tpi " },
{ 9, 0707, "64tpi " },
{ 8, 5039, "60tpi " },
{ 7, 9370, "56tpi " },
{ 6, 8031, "48tpi " },
{ 6, 2362, "44tpi " },
{ 5, 6693, "40tpi " },
{ 5, 1024, "36tpi " },
{ 4, 5354, "32tpi " },
{ 3, 9685, "28tpi " },
{ 3, 8268, "27tpi " },
{ 3, 6850, "26tpi " },
{ 3, 4016, "24tpi " },
{ 3, 1181, "22tpi " },
{ 2, 8346, "20tpi " },
{ 2, 6929, "19tpi " },
{ 2, 5512, "18tpi " },
{ 2, 2677, "16tpi " },
{ 1, 9843, "14tpi " },
{ 1, 8425, "13tpi " },
{ 1, 7008, "12tpi " },
{ 1, 5591, "11tpi " },
};
byte Thread_Step = 12; // выборка из массива по умолчанию (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_Forward();
Feed_Left();
break;
case Mode_Divider:
Divider();
break;
case Mode_Feed_Right:
Motor_X_Reverse();
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--;
}
}
}
}
//*******************************************************************
attachInterrupt(0, encoderPinChangeA, CHANGE);
// encoder pin on interrupt 1 (pin 3)
attachInterrupt(1, encoderPinChangeB, CHANGE);
encoder0Pos = 0; //reseet the encoder position to 0
}
void loop() {
//do stuff dependent on encoder position here
//such as move a stepper motor to match encoder position
//if you want to make it 1:1 ensure the encoder res matches the motor res by dividing/multiplying
Serial.println(encoder0Pos);
delay(100);
}
void encoderPinChangeA() {
// look for a low-to-high on channel A
if (digitalRead(encoder0PinA) == HIGH) {
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
else // must be a high-to-low edge on channel A
{
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinB) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
}
void encoderPinChangeB() {
// look for a low-to-high on channel B
if (digitalRead(encoder0PinB) == HIGH) {
// check channel A to see which way encoder is turning
if (digitalRead(encoder0PinA) == HIGH) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
// Look for a high-to-low on channel B
else {
// check channel B to see which way encoder is turning
if (digitalRead(encoder0PinA) == LOW) {
encoder0Pos = encoder0Pos + 1; // CW
}
else {
encoder0Pos = encoder0Pos - 1; // CCW
}
}
}
а вот код проекта нет) помогите хрен знает куда копать
электроная гитара на токарный станок
#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 12 // Кол-во подач
typedef struct
{
byte s_Divisor; // Делитель для "Подача" целая часть
char Text[7];
}
FEED_INFO;
FEED_INFO Feed_Info[Total_Feeds] =
{
{ 180, "0.02mm" },
{ 90, "0.04mm" },
{ 60, "0.06mm" },
{ 45, "0.08mm" },
{ 36, "0.10mm" },
{ 30, "0.12mm" },
{ 26, "0.14mm" },
{ 23, "0.16mm" },
{ 20, "0.18mm" },
{ 18, "0.20mm" },
{ 16, "0.22mm" },
{ 15, "0.24mm" },
};
byte Feed_Step = 3; // выборка из массива по умолчанию (0.08mm)
// ***** Threads *****
// Enc_Line/(Step_Per_Revolution/Feed_Screw*Thread_mm)
#define Total_Threads 40 // Кол-во резьб
typedef struct
{
byte s_Divisor; // Делитель для "Резьба" целая часть
int m_Divisor; // Делитель для "Резьба" дробная часть
char Text[7];
}
THREAD_INFO;
THREAD_INFO Thread_Info[Total_Threads] =
{
{ 18, 0000, "0.20mm" },
{ 14, 4000, "0.25mm" },
{ 12, 0000, "0.30mm" },
{ 10, 2857, "0.35mm" },
{ 9, 0000, "0.40mm" },
{ 7, 2000, "0.50mm" },
{ 6, 0000, "0.60mm" },
{ 5, 1429, "0.70mm" },
{ 4, 8000, "0.75mm" },
{ 4, 5000, "0.80mm" },
{ 3, 6000, "1.00mm" },
{ 2, 8800, "1.25mm" },
{ 2, 4000, "1.50mm" },
{ 2, 0571, "1.75mm" },
{ 1, 8000, "2.00mm" },
{ 1, 4400, "2.50mm" },
{ 1, 2000, "3.00mm" },
{ 11, 3386, "80tpi " },
{ 10, 2047, "72tpi " },
{ 9, 0707, "64tpi " },
{ 8, 5039, "60tpi " },
{ 7, 9370, "56tpi " },
{ 6, 8031, "48tpi " },
{ 6, 2362, "44tpi " },
{ 5, 6693, "40tpi " },
{ 5, 1024, "36tpi " },
{ 4, 5354, "32tpi " },
{ 3, 9685, "28tpi " },
{ 3, 8268, "27tpi " },
{ 3, 6850, "26tpi " },
{ 3, 4016, "24tpi " },
{ 3, 1181, "22tpi " },
{ 2, 8346, "20tpi " },
{ 2, 6929, "19tpi " },
{ 2, 5512, "18tpi " },
{ 2, 2677, "16tpi " },
{ 1, 9843, "14tpi " },
{ 1, 8425, "13tpi " },
{ 1, 7008, "12tpi " },
{ 1, 5591, "11tpi " },
};
byte Thread_Step = 12; // выборка из массива по умолчанию (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_Forward();
Feed_Left();
break;
case Mode_Divider:
Divider();
break;
case Mode_Feed_Right:
Motor_X_Reverse();
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--;
}
}
}
}
//*******************************************************************