Arduino
-
- Příspěvky: 1012
- Registrován: 15. 11. 2009, 2:17
Mám 2 různé programy pro Arduino mega 2560 a potřeboval bych vyřešit aby se daly oba spouštět na jednom Arduinu, třeba tak že by se n některý PIN Arduina dal přepínač a dle úrovně na pinu 1 či 0 po zapnutí by se spustil jeden nebo druhý program. Bohužel s programováním nemám žádnou zkušenost a moc mi to do hlavy nejde. zvladam tak pouze upravit nějaké hodnoty. Pomohl by mi někdo?
Asi těžko dostaneš univerzální odpověď.
Záleží na tom, co jsou to za programy - jestli je to něco velkého a kompexního (třeba něco jako GRBL) nebo naopak nějaká blbost typu klíkání LED. No a samozřejmě pak jestli to máš ve formě zdrojáků nebo jak.
Záleží na tom, co jsou to za programy - jestli je to něco velkého a kompexního (třeba něco jako GRBL) nebo naopak nějaká blbost typu klíkání LED. No a samozřejmě pak jestli to máš ve formě zdrojáků nebo jak.
-
- Příspěvky: 1012
- Registrován: 15. 11. 2009, 2:17
Chápu, jsou to docela jednoduché programy, jedno je v podstatě program pro ovládání delicky a druhý je zase jen pro řízení otáček delicky v různém převodovém poměru vůči vřetenu. Oba programy každý na několik stranek. Bohužel autoři jsou rusové tak ve zdojaku pozbamky v azbuce. Oba programy jsem pouze upravoval aby mi sedělo zapojení displeje a klávesnice na stejné piny.
Bez přesné znalosti programu to nejde určit.
Můžeš načíst společně knihovny, případně pořešit proměné apod (pokud to dá paměť)
Hlavní smyčky pak zabalit do instrukce if, nebo while a kontrolovat při každém průchodu nějaký pin.
To je hodně primitivní.
Jenže tohle bude mít nějaké zpoždění a nemusí to být funkční.
Tedy šupni sem oba programy
Můžeš načíst společně knihovny, případně pořešit proměné apod (pokud to dá paměť)
Hlavní smyčky pak zabalit do instrukce if, nebo while a kontrolovat při každém průchodu nějaký pin.
To je hodně primitivní.
Jenže tohle bude mít nějaké zpoždění a nemusí to být funkční.
Tedy šupni sem oba programy
Na konci poznávacího procesu je omyl zcela vyvrácen a my nevíme nic. Zato to víme správně.
-
- Příspěvky: 1012
- Registrován: 15. 11. 2009, 2:17
U PC budu až zítra, tet jsem na mobilu tak to pošlu.
-
- Příspěvky: 1012
- Registrován: 15. 11. 2009, 2:17
otočný stůl dělička:
/*
This works on the Uno
In this version I will modify step calculation
4x4 matrix keypad amd a 20 x 4 LCD.
Edit Rotation & TableRatio(# of turns for 360 degrees)in line 29
A4988 Stepstick/Pololu driver
5/2/2015
*/
// **************define Debug Macro**************
//#define DEBUG 1 //delete slashes for printing debug info to serial monitor
#ifdef DEBUG
#define DEBUG_Print(x) Serial.print(x)
#define DEBUG_PrintDec(x,y) Serial.print(x,y)
#define DEBUG_Println(x) Serial.println(x)
#else
#define DEBUG_Print(x)
#define DEBUG_PrintDec(x,y)
#define DEBUG_Println(x)
#endif
#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <EEPROM.h>
const byte ROWS = 4;
const byte COLS = 4;
//****************USER DEFINED**************
//setup vars
int StepsPerRotation = 2376; // Set Steps per rotation of stepper NOTE the driver is set to Half step
int TableRatio = 10; // ratio of rotary table
int stepdelay = 1; //this is in microseconds
int delay1 = 200; //this is used for initial Splash Screen display time
const int delay2 = 500; //this is used for subsequent Splash screens
char key;
//**For pro micro
/* const int stp = 8; // connect pin D8 to step
const int dir = 9; // connect pin D9 to dir
byte colPINS[ROWS] = {18,19,20,21}; //pin 1 of keypad to pin 10
byte rowPINS[COLS] = {10,16,14,15};*/
//**************
///*for mega 2560 r3
const int stp = 49;
const int dir = 47;
const int enable = 45;
byte colPINS[ROWS] = {34,36,38,40}; //pin 1 of keypad to pin 12 //řádky
byte rowPINS[COLS] = {26,28,30,32}; //sloupce
//***************
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
//char LCD_Row_1[17];
//char LCD_Row_2[17];
//LiquidCrystal_I2C lcd(0x38,20,4); // set the LCD address as determined by I2C scanner
// SCL - 21, SDA - 20, VCC - +5, Gnd - Gnd
//***********************************************
int isteps, itable;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};
Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);
int moved;
long Multiplier;
long cumSteps = 0;
float Degrees = 0.; // Degrees from keypad
long ToMove = 0; // Steps to move
float bob = 0.; //this tracks current position in degrees
int cho = 0;
void setup()
{
lcd.begin(20,4);
// lcd.init(); // initialize the lcd
// lcd.init(); // initialize the lcd
// lcd.backlight();
EEPROM.get(0,TableRatio);
EEPROM.get(2,StepsPerRotation);
EEPROM.get(4,stepdelay);
//from EEPROM
#ifdef DEBUG
Serial.begin(115200);
#endif
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);
// Print welcome message to the LCD.
lcd.print("Rotary Table Control");
lcd.setCursor(3,3);
lcd.print("EEPROM 2018 beta2");
delay(delay1);
/*check if key pad A is held down if it is
* then jump to getRatios and input new rations
*/
int i=0;
key = kpd.getKey();
DEBUG_Print("EEPROM Table = "); DEBUG_Print(TableRatio);DEBUG_Println(":1");
DEBUG_Print("EEPROM Steps = "); DEBUG_Println(StepsPerRotation);
DEBUG_Print("EEPROM Deelay = "); DEBUG_Println(stepdelay);
delay1=delay2;
// lcd.init();
//*****************************************
cho = 0;
// *************************************************
key = kpd.getKey();
/* lcd.print("Enter Selection:");
lcd.setCursor(0,1);
lcd.print("Degrees = A");
lcd.setCursor(0,2);
lcd.print("Divisions = B");
lcd.setCursor(0,3);
lcd.print("JOG = C");*/
lcd.setCursor(0,0);
lcd.print("Degrees = A");
lcd.setCursor(0,1);
lcd.print("Divisions = B");
lcd.setCursor(0,2);
lcd.print("JOG = C");
lcd.setCursor(0,3);
lcd.print("Settings = D");
while(cho == 0)
{
key = kpd.getKey();
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees=getdegrees();
lcd.clear();
cho = 1;
break;
case 'B':
Degrees=getdivisions();
cho=2;
break;
case 'C':
Degrees=getjog();
lcd.clear();
cho=3;
break;
case 'D':
Settings();
EEPROM.get(0,TableRatio);
EEPROM.get(2,StepsPerRotation);
EEPROM.get(4,stepdelay);
lcd.clear();
cho=0;
lcd.setCursor(0,0);
lcd.print("Degrees = A");
lcd.setCursor(0,1);
lcd.print("Divisions = B");
lcd.setCursor(0,2);
lcd.print("JOG = C");
lcd.setCursor(0,3);
lcd.print("Settings = D");
break;
} // end case
} // end while cho=0
DEBUG_Print("Table Ratio = "); DEBUG_Println(TableRatio);
DEBUG_Print("Steps per Rotation = "); DEBUG_Println(StepsPerRotation);
Multiplier = (long)TableRatio * StepsPerRotation;
DEBUG_Print("Multiplier = "); DEBUG_Println(Multiplier);
} // end setup
void loop() // MAIN LOOP
{
lcd.clear();
char key = kpd.getKey();
bob = 0;
cumSteps=0;
lcd.setCursor(7,0);lcd.print("Total: ");lcd.print(" ");lcd.setCursor(14,0);lcd.print(bob,2); // total steps
lcd.setCursor(0,3);lcd.print("FOR=A REV=B X=C");
while(key != 'C') // C will return to start menu
{
lcd.setCursor(0,0);lcd.print(abs(Degrees),2);lcd.print((char)223);
key = kpd.getKey();
if (key !=NULL){DEBUG_Print("Key is ");DEBUG_Println(key);}
if(key == 'A') // FORWARD
{
bob = bob + Degrees;
ToMove=(long)((float)(bob/360 * Multiplier + 0.5 - cumSteps));
cumSteps=cumSteps+ToMove;
digitalWrite(dir, LOW);
printadvance();
}
if(key=='B') // REVERSE
{
bob = bob - Degrees;
ToMove=(long)((float)(cumSteps+0.5 - (bob * Multiplier)/360));
cumSteps=cumSteps-ToMove;
digitalWrite(dir, HIGH); // pin 13
printadvance();
}
} // end while not C loop
// lcd.init();
setup();
} // end main VOID
float getjog() // used to set mechanical ratio and steps per revelution
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(6,0);lcd.print("Jogging");
lcd.setCursor(0,1);lcd.print("A=1 B=5 C=25 Degrees");
lcd.setCursor(0,2);lcd.print("Choose Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees = 1;
lcd.setCursor(16,2);lcd.print(Degrees,1);
break;
case 'B':
Degrees = 5;
lcd.setCursor(16,2);lcd.print(Degrees,1);
break;
case 'C':
Degrees = 25;
lcd.setCursor(16,2);lcd.print(Degrees,1);
break;
case 'D':
num=0.00;
lcd.setCursor(15,2);lcd.print(" ");
lcd.setCursor(15,2);
break;
}
key = kpd.getKey();
}
return Degrees;
}
float getdivisions()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,1);lcd.print("Enter Division:");
lcd.setCursor(0,3);lcd.print("OK = # ");
lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(16,1);
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;
case 'D':
num=0.00;
lcd.setCursor(16,1);lcd.print(" ");
lcd.setCursor(16,1);
break;
}
Degrees = (float)(360/num);
key = kpd.getKey();
}
return Degrees; //num;
}
float getdegrees()
{
//int key = 0;
float num = 0.00;
float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
lcd.clear();
//lcd.init();
char key = kpd.getKey();
lcd.setCursor(0,1);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(15,1);
bool decOffset = false;
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;
case 'D':
num=0.00;
lcd.setCursor(15,1);lcd.print(" ");
lcd.setCursor(15,1);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;
} //end case
decnum = num / pow(10, counter);
key = kpd.getKey();
} //end while not #
return decnum;
} // end getdegrees
void printadvance() // print function
{
lcd.setCursor(6,1);lcd.print("Moving");
lcd.setCursor(4,2);lcd.print("Steps ");lcd.print(ToMove);lcd.setCursor(13,0); lcd.print(" ");
lcd.setCursor(14,0);lcd.print(bob,2);
rotation(ToMove,0);
lcd.setCursor(6,1);lcd.print(" ");
}
void rotation(long tm, int d)
{
DEBUG_Print("Total Degrees = "); DEBUG_PrintDec(bob,3); DEBUG_Print(" Steps to move = "); DEBUG_Print(tm); DEBUG_Print(" Total Steps = "); DEBUG_Println(cumSteps);
for(long i = 0; i < tm; i++)
{
digitalWrite(stp, HIGH);
delayMicroseconds(stepdelay);
digitalWrite(stp, LOW);
delayMicroseconds(stepdelay);
}
}
void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
// get first value Table Ratio
void Settings()
{
//first get Table Ratio
lcd.clear();
lcd.setCursor(0,0);lcd.print("TableRatio = ");
TableRatio = getInt(TableRatio);
DEBUG_Print("New Table = "); DEBUG_Print(TableRatio);DEBUG_Println(":1");
//Now get steps per Rev
lcd.clear();
lcd.setCursor(0,0);lcd.print("Steps per Rev = ");
StepsPerRotation = getInt(StepsPerRotation);
DEBUG_Print("New Steps = "); DEBUG_Println(StepsPerRotation);
//Now get step delay
lcd.clear();
lcd.setCursor(0,0);lcd.print("Step delay = ");
stepdelay = getInt(stepdelay);
DEBUG_Print("New Delay = "); DEBUG_Println(stepdelay);
lcd.clear();
EEPROM.put(0,TableRatio);
EEPROM.put(2,StepsPerRotation);
EEPROM.put(4,stepdelay);
}
int getInt(int curVal){
int newVal ;
lcd.print(curVal);
lcd.setCursor(0,1);lcd.print("New value ");
lcd.setCursor(0,3);lcd.print("OK = # ");
lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(10,1);
delay(500);
newVal=0;
key = kpd.getKey();
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
newVal = newVal* 10 + (key - '0');
lcd.print(key);
break;
case 'D':
newVal=0;
lcd.setCursor(9,1);lcd.print(" ");
lcd.setCursor(10,1);
break;
}
key = kpd.getKey();
}
if (newVal ==0)
{ newVal = curVal;}
DEBUG_Print("newVal = "); DEBUG_Println(newVal);
return newVal;
}
/*
This works on the Uno
In this version I will modify step calculation
4x4 matrix keypad amd a 20 x 4 LCD.
Edit Rotation & TableRatio(# of turns for 360 degrees)in line 29
A4988 Stepstick/Pololu driver
5/2/2015
*/
// **************define Debug Macro**************
//#define DEBUG 1 //delete slashes for printing debug info to serial monitor
#ifdef DEBUG
#define DEBUG_Print(x) Serial.print(x)
#define DEBUG_PrintDec(x,y) Serial.print(x,y)
#define DEBUG_Println(x) Serial.println(x)
#else
#define DEBUG_Print(x)
#define DEBUG_PrintDec(x,y)
#define DEBUG_Println(x)
#endif
#include <Wire.h>
//#include <LiquidCrystal_I2C.h>
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <EEPROM.h>
const byte ROWS = 4;
const byte COLS = 4;
//****************USER DEFINED**************
//setup vars
int StepsPerRotation = 2376; // Set Steps per rotation of stepper NOTE the driver is set to Half step
int TableRatio = 10; // ratio of rotary table
int stepdelay = 1; //this is in microseconds
int delay1 = 200; //this is used for initial Splash Screen display time
const int delay2 = 500; //this is used for subsequent Splash screens
char key;
//**For pro micro
/* const int stp = 8; // connect pin D8 to step
const int dir = 9; // connect pin D9 to dir
byte colPINS[ROWS] = {18,19,20,21}; //pin 1 of keypad to pin 10
byte rowPINS[COLS] = {10,16,14,15};*/
//**************
///*for mega 2560 r3
const int stp = 49;
const int dir = 47;
const int enable = 45;
byte colPINS[ROWS] = {34,36,38,40}; //pin 1 of keypad to pin 12 //řádky
byte rowPINS[COLS] = {26,28,30,32}; //sloupce
//***************
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
//char LCD_Row_1[17];
//char LCD_Row_2[17];
//LiquidCrystal_I2C lcd(0x38,20,4); // set the LCD address as determined by I2C scanner
// SCL - 21, SDA - 20, VCC - +5, Gnd - Gnd
//***********************************************
int isteps, itable;
char keys[ROWS][COLS] = {
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'.','0','#','D'}
};
Keypad kpd = Keypad(makeKeymap(keys),rowPINS,colPINS, ROWS, COLS);
int moved;
long Multiplier;
long cumSteps = 0;
float Degrees = 0.; // Degrees from keypad
long ToMove = 0; // Steps to move
float bob = 0.; //this tracks current position in degrees
int cho = 0;
void setup()
{
lcd.begin(20,4);
// lcd.init(); // initialize the lcd
// lcd.init(); // initialize the lcd
// lcd.backlight();
EEPROM.get(0,TableRatio);
EEPROM.get(2,StepsPerRotation);
EEPROM.get(4,stepdelay);
//from EEPROM
#ifdef DEBUG
Serial.begin(115200);
#endif
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);
// Print welcome message to the LCD.
lcd.print("Rotary Table Control");
lcd.setCursor(3,3);
lcd.print("EEPROM 2018 beta2");
delay(delay1);
/*check if key pad A is held down if it is
* then jump to getRatios and input new rations
*/
int i=0;
key = kpd.getKey();
DEBUG_Print("EEPROM Table = "); DEBUG_Print(TableRatio);DEBUG_Println(":1");
DEBUG_Print("EEPROM Steps = "); DEBUG_Println(StepsPerRotation);
DEBUG_Print("EEPROM Deelay = "); DEBUG_Println(stepdelay);
delay1=delay2;
// lcd.init();
//*****************************************
cho = 0;
// *************************************************
key = kpd.getKey();
/* lcd.print("Enter Selection:");
lcd.setCursor(0,1);
lcd.print("Degrees = A");
lcd.setCursor(0,2);
lcd.print("Divisions = B");
lcd.setCursor(0,3);
lcd.print("JOG = C");*/
lcd.setCursor(0,0);
lcd.print("Degrees = A");
lcd.setCursor(0,1);
lcd.print("Divisions = B");
lcd.setCursor(0,2);
lcd.print("JOG = C");
lcd.setCursor(0,3);
lcd.print("Settings = D");
while(cho == 0)
{
key = kpd.getKey();
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees=getdegrees();
lcd.clear();
cho = 1;
break;
case 'B':
Degrees=getdivisions();
cho=2;
break;
case 'C':
Degrees=getjog();
lcd.clear();
cho=3;
break;
case 'D':
Settings();
EEPROM.get(0,TableRatio);
EEPROM.get(2,StepsPerRotation);
EEPROM.get(4,stepdelay);
lcd.clear();
cho=0;
lcd.setCursor(0,0);
lcd.print("Degrees = A");
lcd.setCursor(0,1);
lcd.print("Divisions = B");
lcd.setCursor(0,2);
lcd.print("JOG = C");
lcd.setCursor(0,3);
lcd.print("Settings = D");
break;
} // end case
} // end while cho=0
DEBUG_Print("Table Ratio = "); DEBUG_Println(TableRatio);
DEBUG_Print("Steps per Rotation = "); DEBUG_Println(StepsPerRotation);
Multiplier = (long)TableRatio * StepsPerRotation;
DEBUG_Print("Multiplier = "); DEBUG_Println(Multiplier);
} // end setup
void loop() // MAIN LOOP
{
lcd.clear();
char key = kpd.getKey();
bob = 0;
cumSteps=0;
lcd.setCursor(7,0);lcd.print("Total: ");lcd.print(" ");lcd.setCursor(14,0);lcd.print(bob,2); // total steps
lcd.setCursor(0,3);lcd.print("FOR=A REV=B X=C");
while(key != 'C') // C will return to start menu
{
lcd.setCursor(0,0);lcd.print(abs(Degrees),2);lcd.print((char)223);
key = kpd.getKey();
if (key !=NULL){DEBUG_Print("Key is ");DEBUG_Println(key);}
if(key == 'A') // FORWARD
{
bob = bob + Degrees;
ToMove=(long)((float)(bob/360 * Multiplier + 0.5 - cumSteps));
cumSteps=cumSteps+ToMove;
digitalWrite(dir, LOW);
printadvance();
}
if(key=='B') // REVERSE
{
bob = bob - Degrees;
ToMove=(long)((float)(cumSteps+0.5 - (bob * Multiplier)/360));
cumSteps=cumSteps-ToMove;
digitalWrite(dir, HIGH); // pin 13
printadvance();
}
} // end while not C loop
// lcd.init();
setup();
} // end main VOID
float getjog() // used to set mechanical ratio and steps per revelution
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(6,0);lcd.print("Jogging");
lcd.setCursor(0,1);lcd.print("A=1 B=5 C=25 Degrees");
lcd.setCursor(0,2);lcd.print("Choose Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case 'A':
Degrees = 1;
lcd.setCursor(16,2);lcd.print(Degrees,1);
break;
case 'B':
Degrees = 5;
lcd.setCursor(16,2);lcd.print(Degrees,1);
break;
case 'C':
Degrees = 25;
lcd.setCursor(16,2);lcd.print(Degrees,1);
break;
case 'D':
num=0.00;
lcd.setCursor(15,2);lcd.print(" ");
lcd.setCursor(15,2);
break;
}
key = kpd.getKey();
}
return Degrees;
}
float getdivisions()
{
float Degrees = 0;
float num = 0.00;
char key = kpd.getKey();
lcd.clear();
lcd.setCursor(0,1);lcd.print("Enter Division:");
lcd.setCursor(0,3);lcd.print("OK = # ");
lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(16,1);
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
num = num * 10 + (key - '0');
lcd.print(key);
break;
case 'D':
num=0.00;
lcd.setCursor(16,1);lcd.print(" ");
lcd.setCursor(16,1);
break;
}
Degrees = (float)(360/num);
key = kpd.getKey();
}
return Degrees; //num;
}
float getdegrees()
{
//int key = 0;
float num = 0.00;
float decimal = 0.00;
float decnum = 0.00;
int counter = 0;
lcd.clear();
//lcd.init();
char key = kpd.getKey();
lcd.setCursor(0,1);lcd.print("Enter Degrees:");lcd.setCursor(0,3);lcd.print("OK = # ");lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(15,1);
bool decOffset = false;
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case '.':
if(!decOffset)
{
decOffset = true;
}
lcd.print(key);
break;
case 'D':
num=0.00;
lcd.setCursor(15,1);lcd.print(" ");
lcd.setCursor(15,1);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
if(!decOffset)
{
num = num * 10 + (key - '0');
lcd.print(key);
}
else if((decOffset) && (counter <= 1))
{
num = num * 10 + (key - '0');
lcd.print(key);
counter++;
}
break;
} //end case
decnum = num / pow(10, counter);
key = kpd.getKey();
} //end while not #
return decnum;
} // end getdegrees
void printadvance() // print function
{
lcd.setCursor(6,1);lcd.print("Moving");
lcd.setCursor(4,2);lcd.print("Steps ");lcd.print(ToMove);lcd.setCursor(13,0); lcd.print(" ");
lcd.setCursor(14,0);lcd.print(bob,2);
rotation(ToMove,0);
lcd.setCursor(6,1);lcd.print(" ");
}
void rotation(long tm, int d)
{
DEBUG_Print("Total Degrees = "); DEBUG_PrintDec(bob,3); DEBUG_Print(" Steps to move = "); DEBUG_Print(tm); DEBUG_Print(" Total Steps = "); DEBUG_Println(cumSteps);
for(long i = 0; i < tm; i++)
{
digitalWrite(stp, HIGH);
delayMicroseconds(stepdelay);
digitalWrite(stp, LOW);
delayMicroseconds(stepdelay);
}
}
void software_Reset() // Restarts program from beginning but does not reset the peripherals and registers
{
asm volatile (" jmp 0");
}
// get first value Table Ratio
void Settings()
{
//first get Table Ratio
lcd.clear();
lcd.setCursor(0,0);lcd.print("TableRatio = ");
TableRatio = getInt(TableRatio);
DEBUG_Print("New Table = "); DEBUG_Print(TableRatio);DEBUG_Println(":1");
//Now get steps per Rev
lcd.clear();
lcd.setCursor(0,0);lcd.print("Steps per Rev = ");
StepsPerRotation = getInt(StepsPerRotation);
DEBUG_Print("New Steps = "); DEBUG_Println(StepsPerRotation);
//Now get step delay
lcd.clear();
lcd.setCursor(0,0);lcd.print("Step delay = ");
stepdelay = getInt(stepdelay);
DEBUG_Print("New Delay = "); DEBUG_Println(stepdelay);
lcd.clear();
EEPROM.put(0,TableRatio);
EEPROM.put(2,StepsPerRotation);
EEPROM.put(4,stepdelay);
}
int getInt(int curVal){
int newVal ;
lcd.print(curVal);
lcd.setCursor(0,1);lcd.print("New value ");
lcd.setCursor(0,3);lcd.print("OK = # ");
lcd.print((char)60);lcd.print((char)45);lcd.print(" D");
lcd.setCursor(10,1);
delay(500);
newVal=0;
key = kpd.getKey();
while(key != '#')
{
switch (key)
{
case NO_KEY:
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
newVal = newVal* 10 + (key - '0');
lcd.print(key);
break;
case 'D':
newVal=0;
lcd.setCursor(9,1);lcd.print(" ");
lcd.setCursor(10,1);
break;
}
key = kpd.getKey();
}
if (newVal ==0)
{ newVal = curVal;}
DEBUG_Print("newVal = "); DEBUG_Println(newVal);
return newVal;
}
-
- Příspěvky: 1012
- Registrován: 15. 11. 2009, 2:17
otočný stůl odval:
#include <avr/pgmspace.h>
// ***** LCD *****
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
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--;
}
}
}
}
//*******************************************************************
#include <avr/pgmspace.h>
// ***** LCD *****
#include <LiquidCrystal.h>
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
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--;
}
}
}
}
//*******************************************************************
-
- Příspěvky: 1012
- Registrován: 15. 11. 2009, 2:17
Tak se mi povedlo nahrát oba dva programy.
Prvně si je sem mohl dát v textovém souboru
Za druhé nejsem žádný profík, je to jen názor jak bych to řešil já.
Jinak v děličce je hlavní smička void loop() // MAIN LOOP v otočném stolu void loop().
Takže bych z těchto smyček udělal podprogramy, například void delicka a void otocnystul.
V hlavní části void loop bych udělal jen výběr podle potřeby a volal bych co je potřeba.
Třeba podle stavu nějakého pinu.
No a to co je nejhorší, že se ti nesmí nic duplovat.
Takže musíš projít celé deklarace na začátku, aby si programy nealokovali stejné piny nebo proměnné.
Pokud ano je třeba název sjednotit.
A pokud ve smyčce void setup je opět duplicita tak se musí vyřešit, nebo udělat rozhodnutí i tam.
Ale nejspíše by to mělo jít.
Za druhé nejsem žádný profík, je to jen názor jak bych to řešil já.
Jinak v děličce je hlavní smička void loop() // MAIN LOOP v otočném stolu void loop().
Takže bych z těchto smyček udělal podprogramy, například void delicka a void otocnystul.
V hlavní části void loop bych udělal jen výběr podle potřeby a volal bych co je potřeba.
Třeba podle stavu nějakého pinu.
No a to co je nejhorší, že se ti nesmí nic duplovat.
Takže musíš projít celé deklarace na začátku, aby si programy nealokovali stejné piny nebo proměnné.
Pokud ano je třeba název sjednotit.
A pokud ve smyčce void setup je opět duplicita tak se musí vyřešit, nebo udělat rozhodnutí i tam.
Ale nejspíše by to mělo jít.
Na konci poznávacího procesu je omyl zcela vyvrácen a my nevíme nic. Zato to víme správně.
Čau,
snažím se napsat nějaký program, kde už si nevystačím s prvními lekcemi arduina ve stylu "blink" a podobně. Chtěl bych používat "class" a zjistil jsem, že dobře napsaných instruktáží je málo, alespoň já jsem je nechápal. Zatím se mi zdá, že tady
https://paulmurraycbr.github.io/ArduinoTheOOWay.html
je to dost dobře podané, ještě jsem to nedočetl a nevyzkoušel. Víte někdo o nějakém dalším dobrém zdroji informací o OOP pro arduino?
snažím se napsat nějaký program, kde už si nevystačím s prvními lekcemi arduina ve stylu "blink" a podobně. Chtěl bych používat "class" a zjistil jsem, že dobře napsaných instruktáží je málo, alespoň já jsem je nechápal. Zatím se mi zdá, že tady
https://paulmurraycbr.github.io/ArduinoTheOOWay.html
je to dost dobře podané, ještě jsem to nedočetl a nevyzkoušel. Víte někdo o nějakém dalším dobrém zdroji informací o OOP pro arduino?
Připrav se, hrajem...
https://www.youtube.com/watch?v=HzjNAnEfvxc
https://www.youtube.com/watch?v=HzjNAnEfvxc
No celý SW Arduino je objektový.
Když použiješ
Serial.begin(9600);
tak voláš metodu "begin" objektu "Serial".
U dobrého kompilátoru rozdíl moc velký nebude. Samozřejmě jde o to, jak to objektové programování budeš používat. I v objektovém C++ se dá psát neobjektově, a naopak v neobjektovém C se zase dá psát víceméně objektově.
Kompilátor Arduina je přiohnuté C++. Před vlastním překladem se tam jen preprocesorem změní ty podivnosti jako "setup()" a "loop()" na běžnou strukturu programu, doplní se implicitní definice a deklarace, připojí defaultní moduly atd.
Jde mi o to, že chci pomocí arduina dělat více věcí současně a pochopil jsem, že správný přístup je OOP. Právě že mi taky přijde, že je OOP na to co potřebuju overkill. Chtěl bych měřit teplotu, tu vyhodnotit pomocí PID a topit, současně hlídat tlačítka a několik čidel. Všechno pak ještě v nějakém časovém plánu.
Řeknu příklad:
přístroj je zapnutý,
tlačítkem odstartuju program,
zapne se topení s PID,
až dojde k ustálení teploty zapnu další věci, většinou s různým spožděním,
pomocí čidel sleduju probíhající proces
pokud nastane chyba proces ukončím
pokud stisknu tlačítko, proces ukončím
proces po ukončení stále potřebuje dochlazení, takže je stále co hlídat
o všech procesech informace na LCD
Nechci se utopit v kilometrovém kódu, proto bych chtěl oddělit jednotlivé úkoly a proměnné.
Chtěl bych mít PID extra, časování jednotlivých procesů extra, informace na LCD extra, a ještě by bylo fajn mít možnost si pro odladění vypisovat data na seriový port, abych věděl, jak se co chová. Zkusil jsem, že hodně jde udělat s funkcemi, nicméně z funkce nedostanu více, než jednu proměnnou (mám na to použít struktury?).
Hodně také pomáhají záložky, kdy si kód rozdělím - každou funkci na jednu záložku. Navíc se mi líbí myšlenka, že si v jednom programu "vymazlím" třeba to PID, a pak to budu používat v různých projektech a nebudu do toho už muset rýt, prostě jen zadám, odkud bere informace o teplotě, kterým pinem spíná topení a odladím si konstanty. Děsím se, že bych musel neustále kvůli drobnostem procházet celý kód. Navíc jedntlivé funkce budu přidávat postupně a chtěl bych je mít odladěné, optimálně kažkou zvlášť.
Vymýšlím blbost? Jak se to dělá správně?
Řeknu příklad:
přístroj je zapnutý,
tlačítkem odstartuju program,
zapne se topení s PID,
až dojde k ustálení teploty zapnu další věci, většinou s různým spožděním,
pomocí čidel sleduju probíhající proces
pokud nastane chyba proces ukončím
pokud stisknu tlačítko, proces ukončím
proces po ukončení stále potřebuje dochlazení, takže je stále co hlídat
o všech procesech informace na LCD
Nechci se utopit v kilometrovém kódu, proto bych chtěl oddělit jednotlivé úkoly a proměnné.
Chtěl bych mít PID extra, časování jednotlivých procesů extra, informace na LCD extra, a ještě by bylo fajn mít možnost si pro odladění vypisovat data na seriový port, abych věděl, jak se co chová. Zkusil jsem, že hodně jde udělat s funkcemi, nicméně z funkce nedostanu více, než jednu proměnnou (mám na to použít struktury?).
Hodně také pomáhají záložky, kdy si kód rozdělím - každou funkci na jednu záložku. Navíc se mi líbí myšlenka, že si v jednom programu "vymazlím" třeba to PID, a pak to budu používat v různých projektech a nebudu do toho už muset rýt, prostě jen zadám, odkud bere informace o teplotě, kterým pinem spíná topení a odladím si konstanty. Děsím se, že bych musel neustále kvůli drobnostem procházet celý kód. Navíc jedntlivé funkce budu přidávat postupně a chtěl bych je mít odladěné, optimálně kažkou zvlášť.
Vymýšlím blbost? Jak se to dělá správně?
Připrav se, hrajem...
https://www.youtube.com/watch?v=HzjNAnEfvxc
https://www.youtube.com/watch?v=HzjNAnEfvxc