Frästisch mit elektronischer Höhenverstellung mittels Schrittmotoren.
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

Fraestisch_SFTools.ino 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465
  1. /*
  2. Steuerung für Frästisch_SFTools
  3. Diese Datei enthält den Code für die Implementierung der Steuerung eines Frästisches mit 2 Nema17 Schrittmotoren.
  4. Sie unterstützt:
  5. - Schnelles/langsames Verstellen der Fräserhöhe
  6. - Werkzeugwechsel
  7. - Automatisches Nullen mit WLS
  8. - Eintauchen mit vordefinierter Tiefe
  9. - Für obige Funktionen notwendige Konfiguration
  10. Erstellt: 05.01.2021
  11. Autor: Flo Smilari
  12. */
  13. #include <Arduino.h>
  14. #include <RotaryEncoder.h>
  15. #include <Wire.h>
  16. #include <Adafruit_GFX.h>
  17. #include <ESP_FlexyStepper.h>
  18. #include "Display.h"
  19. #include "WLS.h"
  20. #include "ExEzButton.h"
  21. #include "RouterSetup.h"
  22. #include "Status.h"
  23. #define SDA 22
  24. #define SCX 23
  25. #define STEP 2
  26. #define DIR 4
  27. #define LIMIT_SWITCH 5
  28. static const byte led_gpio = 15;
  29. static const int WLS_Pin = 34;
  30. static const int WLS_DETECT_Pin = 35;
  31. static const int GreenBtn_Pin = 12;
  32. static const int RedBtn_Pin = 13;
  33. static const int BlueBtn_Pin = 14;
  34. static const int RotEnc_Switch_Pin = 25;
  35. static const int RotEnc_Clk_Pin = 32;
  36. static const int RotEnc_Dta_Pin = 33;
  37. static const float MOVE_DOWNWARD = -1; // motor rotation counter clock wise
  38. static const float MOVE_UPWARD = 1; // motor rotation clock wise
  39. byte limitSwitchState = 1;
  40. int previousDirection = 0;
  41. int nullingTLS_intermediateState = 0;
  42. ExEzButton RedButton(RedBtn_Pin, false, 2000);
  43. ExEzButton GreenButton(GreenBtn_Pin, false, 2000);
  44. ExEzButton BlueButton(BlueBtn_Pin, false, 2000);
  45. ExEzButton RotarySwitch(RotEnc_Switch_Pin, true, 2000);
  46. WLS WlsDetect(WLS_DETECT_Pin, true);
  47. WLS Wls(WLS_Pin);
  48. RotaryEncoder encoder(RotEnc_Dta_Pin, RotEnc_Clk_Pin, RotaryEncoder::LatchMode::FOUR3);
  49. Display Display;
  50. ESP_FlexyStepper stepper;
  51. RouterSetup routerSetup;
  52. Status actualStatus;
  53. Status originStatus;
  54. String oldStatus = "";
  55. void printStatus(String actualStatus) {
  56. if (!oldStatus.equals(actualStatus)) {
  57. Serial.println(actualStatus);
  58. oldStatus = actualStatus;
  59. }
  60. }
  61. //**********************************
  62. //*** Limit switch interrupt routine
  63. //**********************************
  64. void limitSwitchHandler() {
  65. limitSwitchState = digitalRead(LIMIT_SWITCH);
  66. }
  67. //*****************************************************************************************************
  68. //*** Initialization routine. Reads the eeprom first and sets the (potentially new) configured values.
  69. //*****************************************************************************************************
  70. void Initialize() {
  71. routerSetup.readFromEEPROM();
  72. routerSetup.printValues();
  73. Display.showInitialization();
  74. //attach an interrupt to the IO pin of the limit switch and specify the handler function
  75. attachInterrupt(digitalPinToInterrupt(LIMIT_SWITCH), limitSwitchHandler, CHANGE);
  76. stepper.connectToPins(STEP, DIR);
  77. // set the speed and acceleration rates for the stepper motor
  78. stepper.setSpeedInStepsPerSecond(routerSetup.getSpeed() * routerSetup.getStepsPerRev());
  79. stepper.setStepsPerRevolution(routerSetup.getStepsPerRev());
  80. stepper.setStepsPerMillimeter(routerSetup.getStepsPerRev() / routerSetup.getPitch());
  81. stepper.setAccelerationInStepsPerSecondPerSecond(routerSetup.getAcceleration() * routerSetup.getStepsPerRev());
  82. stepper.setDecelerationInStepsPerSecondPerSecond(routerSetup.getAcceleration() * routerSetup.getStepsPerRev());
  83. stepper.startAsService(0);
  84. if (routerSetup.isToolChangOnPowerOn()) {
  85. actualStatus = TOOL_CHANGE;
  86. } else {
  87. actualStatus = IDLE;
  88. }
  89. }
  90. //**********************
  91. //*** SETUP ************
  92. //**********************
  93. void setup() {
  94. actualStatus = INITIALIZATION;
  95. Wire.begin(SDA, SCX);
  96. Serial.begin(115200);
  97. Display.init();
  98. Display.display();
  99. pinMode(led_gpio, OUTPUT);
  100. pinMode(GreenBtn_Pin, INPUT);
  101. pinMode(RedBtn_Pin, INPUT);
  102. pinMode(BlueBtn_Pin, INPUT);
  103. pinMode(RotEnc_Switch_Pin, INPUT);
  104. pinMode(RotEnc_Clk_Pin, INPUT);
  105. pinMode(RotEnc_Dta_Pin, INPUT);
  106. pinMode(LIMIT_SWITCH, INPUT);
  107. RedButton.setDebounceTime(50); // set debounce time to 50 millis
  108. GreenButton.setDebounceTime(50);
  109. BlueButton.setDebounceTime(50);
  110. WlsDetect.setDebounceTime(50);
  111. Wls.setDebounceTime(50);
  112. RotarySwitch.setDebounceTime(50);
  113. delay(1500);
  114. Display.showBrand();
  115. delay(1500);
  116. Initialize();
  117. }
  118. //**********************
  119. //*** MAIN LOOP ********
  120. //**********************
  121. void loop() {
  122. RedButton.loop(); // MUST call the loop() function first
  123. GreenButton.loop();
  124. BlueButton.loop();
  125. WlsDetect.loop();
  126. Wls.loop();
  127. RotarySwitch.loop();
  128. switch (actualStatus) {
  129. case INITIALIZATION:
  130. Initialize();
  131. break;
  132. case TOOL_CHANGE:
  133. printStatus("TOOL_CHANGE");
  134. if (RotarySwitch.isLongPressed()) {
  135. actualStatus = CONFIGURATION;
  136. } else if (BlueButton.isPressed()) {
  137. actualStatus = IDLE;
  138. }
  139. break;
  140. case CONFIGURATION:
  141. printStatus("CONFIGURATION");
  142. if (RotarySwitch.isLongPressed()) {
  143. actualStatus = INITIALIZATION;
  144. } else if (BlueButton.isPressed()) {
  145. actualStatus = IDLE;
  146. }
  147. break;
  148. case NULLING:
  149. printStatus("NULLING");
  150. if (RedButton.isPressed()) {
  151. stepper.setCurrentPositionInMillimeters(0);
  152. stepper.setTargetPositionRelativeInMillimeters(0);
  153. actualStatus = IDLE;
  154. }
  155. break;
  156. case NULLING_TLS:
  157. originStatus = NULLING_TLS;
  158. if (nullingTLS_intermediateState == 0) {
  159. printStatus("NULLING_TLS,0");
  160. //Move elevator to lowest point (lower limit switch triggers)
  161. stepper.setTargetPositionRelativeInMillimeters(300 * MOVE_DOWNWARD);
  162. actualStatus = MOVING_ELEVATOR;
  163. nullingTLS_intermediateState = 1;
  164. } else if (nullingTLS_intermediateState == 1) {
  165. printStatus("NULLING_TLS,1");
  166. if (RedButton.isPressed()) {
  167. //Move elevator until it touch the TLS (WLS_PIN goes HIGH)
  168. stepper.setTargetPositionRelativeInMillimeters(300 * MOVE_UPWARD);
  169. actualStatus = MOVING_ELEVATOR;
  170. nullingTLS_intermediateState = 2;
  171. }
  172. } else if (nullingTLS_intermediateState == 2) {
  173. printStatus("NULLING_TLS,2");
  174. //Move elevator back about toolLenghtSensorHeight (will be the 0-Position)
  175. stepper.clearLimitSwitchActive();
  176. stepper.setTargetPositionRelativeInMillimeters(routerSetup.getToolLenghtSensorHeight() * MOVE_DOWNWARD);
  177. Serial.println(String(routerSetup.getToolLenghtSensorHeight() * MOVE_DOWNWARD, 2));
  178. actualStatus = MOVING_ELEVATOR;
  179. nullingTLS_intermediateState = 3;
  180. } else { // nullingTLS_intermediateState is 3
  181. printStatus("NULLING_TLS,3");
  182. //Set the 0-Position as actual position
  183. stepper.setCurrentPositionInMillimeters(0);
  184. stepper.setTargetPositionRelativeInMillimeters(0);
  185. actualStatus = IDLE;
  186. nullingTLS_intermediateState = 0;
  187. }
  188. break;
  189. case IDLE:
  190. printStatus("IDLE");
  191. if (RedButton.isLongPressed()) {
  192. if (WlsDetect.isConnected()) {
  193. actualStatus = NULLING_TLS;
  194. } else {
  195. actualStatus = NULLING;
  196. }
  197. } else if (BlueButton.isLongPressed()) {
  198. actualStatus = TOOL_CHANGE;
  199. }
  200. break;
  201. case DIVING:
  202. break;
  203. case MOVING_ELEVATOR:
  204. printStatus("MOVING_ELEVATOR");
  205. if (limitSwitchState == LOW) {
  206. // this will cause to stop any motion that is currently going on and block further movement in the same direction as long as the switch is active
  207. stepper.setLimitSwitchActive(stepper.LIMIT_SWITCH_COMBINED_BEGIN_AND_END);
  208. delay(200);
  209. actualStatus = RELEASE_SWITCH;
  210. } else { // limitSwitchState is HIGH
  211. if (stepper.getDistanceToTargetSigned() == 0) {
  212. actualStatus = originStatus;
  213. delay(200);
  214. } else if (WlsDetect.isConnected()) {
  215. if (Wls.isPlugged()) {
  216. Serial.println("The Tool is away from WLS");
  217. stepper.clearLimitSwitchActive();
  218. } else if (Wls.isUnplugged()) {
  219. Serial.println("The Tool touched the WLS");
  220. stepper.setLimitSwitchActive(stepper.LIMIT_SWITCH_COMBINED_BEGIN_AND_END);
  221. actualStatus = originStatus;
  222. delay(200);
  223. }
  224. }
  225. stepper.clearLimitSwitchActive();
  226. previousDirection = stepper.getDirectionOfMotion();
  227. }
  228. break;
  229. case RELEASE_SWITCH:
  230. if (limitSwitchState == LOW) {
  231. stepper.moveRelativeInMillimeters(0.05 * previousDirection * -1); // move in opposite direction (away from switch)
  232. } else {
  233. actualStatus = originStatus;
  234. }
  235. break;
  236. default:
  237. break;
  238. }
  239. //*********************** OLD EXAMPLE AND EXPERIMENTAL CODE ************************************
  240. // if (WlsDetect.isPlugged()) {
  241. // Serial.println("The WLS was connected");
  242. // } else if (WlsDetect.isUnplugged()) {
  243. // Serial.println("The WLS was disconnected");
  244. // }
  245. //
  246. // if (WlsDetect.getStateRaw() == HIGH) {
  247. // if (Wls.isPlugged()) {
  248. // Serial.println("The Tool is away from WLS");
  249. // } else if (Wls.isUnplugged()) {
  250. // Serial.println("The Tool touched the WLS");
  251. // }
  252. // }
  253. //
  254. // if (RedButton.isPressed()) {
  255. // Serial.println("Red button was pressed");
  256. // digitalWrite(led_gpio, HIGH);
  257. // Serial.print("Limit Switch: ");
  258. // Serial.println(digitalRead(LIMIT_SWITCH) ? "HIGH" : "LOW");
  259. // }
  260. //
  261. // if (RedButton.isLongPressed()) {
  262. // Serial.println("Red button was long pressed");
  263. // digitalWrite(led_gpio, LOW);
  264. // }
  265. //
  266. // bool greenPressed = GreenButton.isPressed();
  267. // bool bluePressed = BlueButton.isPressed();
  268. //
  269. // if (GreenButton.isPressing() && BlueButton.isPressing()) {
  270. // Serial.println("Blue and green button were simultaneous pressed");
  271. // } else if (greenPressed) {
  272. // Serial.println("Green button was pressed");
  273. // } else if (bluePressed) {
  274. // Serial.println("Blue button was pressed");
  275. // }
  276. //
  277. // if (RotarySwitch.isPressed()) {
  278. // Serial.println("Rotary switch was pressed");
  279. // }
  280. // if (RotarySwitch.isLongPressed()) {
  281. // Serial.println("Rotary switch long was pressed");
  282. // }
  283. //
  284. // static int pos = 0;
  285. // encoder.tick();
  286. // int newPos = encoder.getPosition();
  287. // if (pos != newPos) {
  288. // Serial.print("pos:");
  289. // Serial.print(newPos);
  290. // Serial.print(" dir:");
  291. // Serial.println((int) (encoder.getDirection()));
  292. // pos = newPos;
  293. // }
  294. // if (limitSwitchState == LOW) {
  295. // stepper.setLimitSwitchActive(stepper.LIMIT_SWITCH_COMBINED_BEGIN_AND_END); // this will cause to stop any motion that is currently going on and block further movement in the same direction as long as the switch is agtive
  296. // } else {
  297. // stepper.clearLimitSwitchActive(); // clear the limit switch flag to allow movement in both directions again
  298. // }
  299. //
  300. // if (limitSwitchState == HIGH && stepper.getDistanceToTargetSigned() == 0) {
  301. // delay(100);
  302. // previousDirection *= -1;
  303. // long relativeTargetPosition = DISTANCE_TO_TRAVEL_IN_STEPS * previousDirection;
  304. // Serial.printf("Moving stepper by %ld steps\n", relativeTargetPosition);
  305. // stepper.setTargetPositionRelativeInSteps(relativeTargetPosition);
  306. // }
  307. }
  308. //void testdrawchar(void) {
  309. // OLED.clearDisplay();
  310. //
  311. // OLED.setTextSize(1); // Normal 1:1 pixel scale
  312. // OLED.setTextColor(SSD1306_WHITE); // Draw white text
  313. // OLED.setCursor(0, 0); // Start at top-left corner
  314. // OLED.cp437(true); // Use full 256 char 'Code Page 437' font
  315. //
  316. // // Not all the characters will fit on the Display. This is normal.
  317. // // Library will draw what it can and the rest will be clipped.
  318. // for (int16_t i = 0; i < 256; i++) {
  319. // if (i == '\n')
  320. // OLED.write(' ');
  321. // else
  322. // OLED.write(i);
  323. // }
  324. //
  325. // OLED.display();
  326. // delay(2000);
  327. //}
  328. //
  329. //void testdrawstyles(void) {
  330. // OLED.clearDisplay();
  331. // Display.setFont(&Rubik_Regular8pt7b);
  332. // Display.setTextSize(1); // Normal 1:1 pixel scale
  333. // Display.setTextColor(SSD1306_WHITE); // Draw white text
  334. // Display.setCursor(0, 8); // Start at top-left corner
  335. // Display.println(F("Hello, world!"));
  336. //
  337. // Display.setFont(&Rubik_Regular12pt7b);
  338. // Display.setTextSize(1); // Normal 1:1 pixel scale
  339. // Display.setTextColor(SSD1306_WHITE); // Draw white text
  340. // Display.setCursor(0, 24); // Start at top-left corner
  341. // Display.println(F("Hello, world!"));
  342. // Display.drawRect(0, 15, 128, 13, SSD1306_WHITE);
  343. // Display.setFont(&Rubik_Regular24pt7b);
  344. // Display.setTextSize(1); // Normal 1:1 pixel scale
  345. // Display.setTextColor(SSD1306_WHITE); // Draw white text
  346. // Display.setCursor(0, 55); // Start at top-left corner
  347. // Display.println(F("Hello, world!"));
  348. //
  349. // Display.display();
  350. // delay(2000);
  351. //
  352. // Display.clearDisplay();
  353. // char decimals[3];
  354. // uint16_t w = 0, h = 0;
  355. // for (int i = 0; i <= 99; i++) {
  356. // OLED.clearDisplay();
  357. // OLED.drawRect(0, 0, 128, 64, SSD1306_WHITE);
  358. // OLED.setFont(&titillium_web_semibold30pt7b);
  359. // OLED.setTextSize(1); // Normal 1:1 pixel scale
  360. // OLED.setTextColor(SSD1306_WHITE); // Draw white text
  361. // sprintf(decimals, "%02d", i);
  362. // if (i < 33) {
  363. // calculateWH("99.", w, h);
  364. // OLED.setCursor((SCREEN_WIDTH / 2 - 1) - w, SCREEN_HEIGHT / 2 + h / 2);
  365. // OLED.print("99.");
  366. // } else if (i >= 33 && i < 66) {
  367. // calculateWH("01.", w, h);
  368. // OLED.setCursor((SCREEN_WIDTH / 2 - 1) - w, SCREEN_HEIGHT / 2 + h / 2);
  369. // OLED.print("01.");
  370. // } else {
  371. // calculateWH("55.", w, h);
  372. // OLED.setCursor((SCREEN_WIDTH / 2 - 1) - w, SCREEN_HEIGHT / 2 + h / 2);
  373. // OLED.print("55.");
  374. // }
  375. // OLED.println(decimals);
  376. // OLED.display();
  377. // delay(100);
  378. // }
  379. // Display.setFont(&Rubik_Regular30pt7b);
  380. // Display.setTextSize(1); // Normal 1:1 pixel scale
  381. // Display.setTextColor(SSD1306_WHITE); // Draw white text
  382. // Display.setCursor(0, 55); // Start at top-left corner
  383. // Display.println(F("99.99"));
  384. //
  385. // Display.display();
  386. // delay(1000);
  387. //
  388. // Display.clearDisplay();
  389. //
  390. // Display.setFont(&Rubik_Regular30pt7b);
  391. // Display.setTextSize(1); // Normal 1:1 pixel scale
  392. // Display.setTextColor(SSD1306_WHITE); // Draw white text
  393. // Display.setCursor(0, 55); // Start at top-left corner
  394. // Display.println(F("01.11"));
  395. // Display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
  396. // Display.println("3.141592");
  397. //
  398. // Display.setTextSize(2); // Draw 2X-scale text
  399. // Display.setTextColor(SSD1306_WHITE);
  400. // Display.print(F("0x"));
  401. // Display.println(0xDEADBEEF, HEX);
  402. //
  403. // OLED.display();
  404. // delay(2000);
  405. //}
  406. //void calculateWH(String units, uint16_t &w, uint16_t &h) {
  407. // int x = 0;
  408. // int y = 0;
  409. // int16_t x1, y1;
  410. // uint16_t w1, h1;
  411. //
  412. // OLED.getTextBounds(units, x, y, &x1, &y1, &w1, &h1);
  413. // w = w1;
  414. // h = h1;
  415. //}