Advertisement
pleasedontcode

**Syringe Control** rev_01

May 16th, 2025
441
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Arduino 12.30 KB | None | 0 0
  1. /********* Pleasedontcode.com **********
  2.  
  3.     Pleasedontcode thanks you for automatic code generation! Enjoy your code!
  4.  
  5.     - Terms and Conditions:
  6.     You have a non-exclusive, revocable, worldwide, royalty-free license
  7.     for personal and commercial use. Attribution is optional; modifications
  8.     are allowed, but you're responsible for code maintenance. We're not
  9.     liable for any loss or damage. For full terms,
  10.     please visit pleasedontcode.com/termsandconditions.
  11.  
  12.     - Project: **Syringe Control**
  13.     - Source Code NOT compiled for: ESP32 DevKit V1
  14.     - Source Code created on: 2025-05-17 02:06:03
  15.  
  16. ********* Pleasedontcode.com **********/
  17.  
  18. /****** SYSTEM REQUIREMENTS *****/
  19. /****** SYSTEM REQUIREMENT 1 *****/
  20.     /* motor doesnt work */
  21. /****** END SYSTEM REQUIREMENTS *****/
  22.  
  23. /* START CODE */
  24.  
  25. /****** DEFINITION OF LIBRARIES *****/
  26. #include <Adafruit_GFX.h>   //https://github.com/adafruit/Adafruit-GFX-Library
  27. #include <SPI.h>
  28. #include <Adafruit_ST7735.h> // Added for TFT display support
  29.  
  30. // -----------------------
  31. // Pin Definitions
  32. // -----------------------
  33. const int stepPin1 = 16;   // coil 1
  34. const int stepPin2 = 17;   // coil 2
  35. const int stepPin3 = 18;   // coil 3
  36. const int stepPin4 = 19;   // coil 4
  37.  
  38. const int selectButtonPin   = 25; // Updated pin to avoid conflict
  39. const int validateButtonPin = 14;
  40. const int resetButtonPin    = 21;
  41. const int emergencyStopPin  = 25;  // avoid conflict
  42. const int fsrPin            = 34;  // FSR402 analog input
  43.  
  44. #define TFT_CS    5
  45. #define TFT_RST   15
  46. #define TFT_DC    2
  47. #define TFT_MOSI  23
  48. #define TFT_SCLK  18
  49. #define TFT_MISO  19
  50.  
  51. // -----------------------
  52. // Operational Constants
  53. // -----------------------
  54. const float mmPerStep = 0.01;  // mm per step
  55. const int MIN_VOLUME = 1;
  56. const int MAX_VOLUME = 50;
  57. const int MIN_RATE   = 1;
  58. const int MAX_RATE   = 50;
  59.  
  60. const int NUM_CAPACITIES = 4;
  61. const int allowedCapacities[NUM_CAPACITIES] = {20, 30, 40, 50};
  62. int syringeCapacityIndex = 0;
  63. int syringeCapacity = allowedCapacities[syringeCapacityIndex];
  64.  
  65. const int DEBOUNCE_DELAY   = 50;
  66. const int BUTTON_DELAY     = 300;
  67. const int SYRINGE_SAMPLE_COUNT = 3;
  68.  
  69. // FSR analog threshold (0-4095)
  70. int fsrThreshold = 1000;
  71.  
  72. // -----------------------
  73. // State Machine
  74. // -----------------------
  75. enum State {
  76.   SELECT_SYRINGE_CAPACITY,
  77.   WAIT_SYRINGE,
  78.   SELECT_VOLUME,
  79.   SELECT_RATE,
  80.   READY,
  81.   INJECTING,
  82.   FINISHED,
  83.   ERROR,
  84.   ERROR_RESOLVED,
  85.   EMERGENCY_STOP
  86. };
  87. State currentState = SELECT_SYRINGE_CAPACITY;
  88. State lastState    = currentState;
  89. bool firstDisplayUpdate = true;
  90.  
  91. int selectedVolume = 10;
  92. int selectedRate   = 10;
  93. long totalSteps = 0;
  94. unsigned long injectionTimeMs = 0;
  95. unsigned long stepDelayMs = 0;
  96. unsigned long currentStep = 0;
  97.  
  98. Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
  99.  
  100. // -----------------------
  101. // Function Prototypes
  102. // -----------------------
  103. float getSyringeInnerDiameter(int capacity);
  104. bool isButtonPressed(int pin);
  105. bool isSyringePresentStable();
  106. void updateDisplayForState(State s);
  107. void performInjection();
  108. bool isErrorResolved();
  109. void stepClockwise();
  110. void stepCounterClockwise();
  111.  
  112. void setup(void)
  113. {
  114.     // put your setup code here, to run once:
  115.   Serial.begin(9600);
  116.   Serial.println("Syringe Injector Initialized");
  117.  
  118.   // Motor pins
  119.   pinMode(stepPin1, OUTPUT);
  120.   pinMode(stepPin2, OUTPUT);
  121.   pinMode(stepPin3, OUTPUT);
  122.   pinMode(stepPin4, OUTPUT);
  123.  
  124.   // Buttons
  125.   pinMode(selectButtonPin,   INPUT_PULLUP);
  126.   pinMode(validateButtonPin, INPUT_PULLUP);
  127.   pinMode(resetButtonPin,    INPUT_PULLUP);
  128.   pinMode(emergencyStopPin,  INPUT_PULLUP);
  129.  
  130.   // FSR analog input
  131.   analogReadResolution(12); // 0-4095
  132.   pinMode(fsrPin, INPUT);
  133.  
  134.   // TFT
  135.   tft.initR(INITR_BLACKTAB);
  136.   tft.setRotation(2);
  137.   tft.fillScreen(ST77XX_BLACK);
  138.   tft.setTextColor(ST77XX_WHITE);
  139.   tft.setTextSize(1);
  140.  
  141.   updateDisplayForState(currentState);
  142. }
  143.  
  144. void loop(void)
  145. {
  146.     // put your main code here, to run repeatedly:
  147.   // Emergency stop
  148.   if (digitalRead(emergencyStopPin) == LOW && currentState != EMERGENCY_STOP) {
  149.     currentState = EMERGENCY_STOP;
  150.   }
  151.  
  152.   // Reset
  153.   if (isButtonPressed(resetButtonPin)) {
  154.     currentState = WAIT_SYRINGE;
  155.     selectedVolume = 10;
  156.     selectedRate   = 10;
  157.     currentStep = 0;
  158.     delay(BUTTON_DELAY);
  159.   }
  160.  
  161.   // Display update
  162.   if (firstDisplayUpdate || currentState != lastState) {
  163.     updateDisplayForState(currentState);
  164.     lastState = currentState;
  165.     firstDisplayUpdate = false;
  166.   }
  167.  
  168.   // State handling
  169.   switch (currentState) {
  170.     case SELECT_SYRINGE_CAPACITY:
  171.       if (isButtonPressed(selectButtonPin)) {
  172.         syringeCapacityIndex = (syringeCapacityIndex + 1) % NUM_CAPACITIES;
  173.         syringeCapacity = allowedCapacities[syringeCapacityIndex];
  174.         tft.fillRect(0, 20, tft.width(), 20, ST77XX_BLACK);
  175.         tft.setCursor(0, 20);
  176.         tft.print(syringeCapacity);
  177.         tft.print(" mL (");
  178.         tft.print(getSyringeInnerDiameter(syringeCapacity));
  179.         tft.println(" mm)");
  180.         delay(BUTTON_DELAY);
  181.       }
  182.       if (isButtonPressed(validateButtonPin)) {
  183.         currentState = WAIT_SYRINGE;
  184.         delay(BUTTON_DELAY);
  185.       }
  186.       break;
  187.  
  188.     case WAIT_SYRINGE:
  189.       if (isSyringePresentStable()) {
  190.         currentState = SELECT_VOLUME;
  191.         delay(BUTTON_DELAY);
  192.       }
  193.       break;
  194.  
  195.     case SELECT_VOLUME:
  196.       if (!isSyringePresentStable()) {
  197.         currentState = WAIT_SYRINGE;
  198.         updateDisplayForState(currentState);
  199.         break;
  200.       }
  201.       if (isButtonPressed(selectButtonPin)) {
  202.         selectedVolume = (selectedVolume % MAX_VOLUME) + 1;
  203.         tft.fillRect(0, 20, tft.width(), 20, ST77XX_BLACK);
  204.         tft.setCursor(0, 20);
  205.         tft.print(selectedVolume);
  206.         delay(BUTTON_DELAY);
  207.       }
  208.       if (isButtonPressed(validateButtonPin)) {
  209.         currentState = SELECT_RATE;
  210.         delay(BUTTON_DELAY);
  211.       }
  212.       break;
  213.  
  214.     case SELECT_RATE:
  215.       if (!isSyringePresentStable()) {
  216.         currentState = WAIT_SYRINGE;
  217.         updateDisplayForState(currentState);
  218.         break;
  219.       }
  220.       if (isButtonPressed(selectButtonPin)) {
  221.         selectedRate = (selectedRate % MAX_RATE) + 1;
  222.         tft.fillRect(0, 20, tft.width(), 20, ST77XX_BLACK);
  223.         tft.setCursor(0, 20);
  224.         tft.print(selectedRate);
  225.         delay(BUTTON_DELAY);
  226.       }
  227.       if (isButtonPressed(validateButtonPin)) {
  228.         currentState = READY;
  229.         delay(BUTTON_DELAY);
  230.       }
  231.       break;
  232.  
  233.     case READY: {
  234.       if (isButtonPressed(validateButtonPin)) {
  235.         float diameter = getSyringeInnerDiameter(syringeCapacity);
  236.         float area = PI * sq(diameter / 2.0);
  237.         float V_mm3 = selectedVolume * 1000.0;
  238.         float displacement = V_mm3 / area;
  239.         totalSteps = (long)ceil(displacement / mmPerStep);
  240.         injectionTimeMs = (unsigned long)((selectedVolume * 60000.0) / selectedRate);
  241.         stepDelayMs = injectionTimeMs / totalSteps;
  242.         currentState = INJECTING;
  243.         delay(BUTTON_DELAY);
  244.       }
  245.       break;
  246.     }
  247.  
  248.     case INJECTING:
  249.       performInjection();
  250.       break;
  251.  
  252.     case FINISHED:
  253.       // idle
  254.       break;
  255.  
  256.     case ERROR:
  257.       if (isErrorResolved()) currentState = ERROR_RESOLVED;
  258.       break;
  259.  
  260.     case ERROR_RESOLVED:
  261.       if (!isErrorResolved()) currentState = ERROR;
  262.       if (isButtonPressed(validateButtonPin)) {
  263.         currentState = INJECTING;
  264.         delay(BUTTON_DELAY);
  265.       }
  266.       break;
  267.  
  268.     case EMERGENCY_STOP:
  269.       if (isButtonPressed(validateButtonPin)) {
  270.         currentState = INJECTING;
  271.         delay(BUTTON_DELAY);
  272.       }
  273.       break;
  274.   }
  275. }
  276.  
  277. // -----------------------
  278. // Motor Step Functions
  279. // -----------------------
  280. void stepClockwise() {
  281.   digitalWrite(stepPin1, HIGH); digitalWrite(stepPin2, LOW);
  282.   digitalWrite(stepPin3, LOW);  digitalWrite(stepPin4, LOW);
  283.   delay(stepDelayMs);
  284.   digitalWrite(stepPin1, LOW);  digitalWrite(stepPin2, HIGH);
  285.   digitalWrite(stepPin3, LOW);  digitalWrite(stepPin4, LOW);
  286.   delay(stepDelayMs);
  287.   digitalWrite(stepPin1, LOW);  digitalWrite(stepPin2, LOW);
  288.   digitalWrite(stepPin3, HIGH); digitalWrite(stepPin4, LOW);
  289.   delay(stepDelayMs);
  290.   digitalWrite(stepPin1, LOW);  digitalWrite(stepPin2, LOW);
  291.   digitalWrite(stepPin3, LOW);  digitalWrite(stepPin4, HIGH);
  292.   delay(stepDelayMs);
  293. }
  294.  
  295. void stepCounterClockwise() {
  296.   digitalWrite(stepPin1, LOW);  digitalWrite(stepPin2, LOW);
  297.   digitalWrite(stepPin3, LOW);  digitalWrite(stepPin4, HIGH);
  298.   delay(stepDelayMs);
  299.   digitalWrite(stepPin1, LOW);  digitalWrite(stepPin2, LOW);
  300.   digitalWrite(stepPin3, HIGH); digitalWrite(stepPin4, LOW);
  301.   delay(stepDelayMs);
  302.   digitalWrite(stepPin1, LOW);  digitalWrite(stepPin2, HIGH);
  303.   digitalWrite(stepPin3, LOW);  digitalWrite(stepPin4, LOW);
  304.   delay(stepDelayMs);
  305.   digitalWrite(stepPin1, HIGH); digitalWrite(stepPin2, LOW);
  306.   digitalWrite(stepPin3, LOW);  digitalWrite(stepPin4, LOW);
  307.   delay(stepDelayMs);
  308. }
  309.  
  310. // -----------------------
  311. // Injection Routine
  312. // -----------------------
  313. void performInjection() {
  314.   bool aborted = false;
  315.   Serial.println("Starting injection..."); // Debugging output
  316.   for (; currentStep < totalSteps; currentStep++) {
  317.     if (!isSyringePresentStable() || digitalRead(emergencyStopPin) == LOW) {
  318.       aborted = true;
  319.       break;
  320.     }
  321.     stepClockwise(); // Make sure motor is stepping
  322.     Serial.print("Step: "); Serial.println(currentStep); // Debugging output
  323.   }
  324.   currentState = aborted ? ERROR : FINISHED;
  325. }
  326.  
  327. // -----------------------
  328. // Utilities
  329. // -----------------------
  330. bool isButtonPressed(int pin) {
  331.   if (digitalRead(pin) == LOW) {
  332.     delay(DEBOUNCE_DELAY);
  333.     if (digitalRead(pin) == LOW) {
  334.       while (digitalRead(pin) == LOW) {}
  335.       delay(DEBOUNCE_DELAY);
  336.       return true;
  337.     }
  338.   }
  339.   return false;
  340. }
  341.  
  342. // Lecture FSR analogique et stabilisation
  343. bool isSyringePresentStable() {
  344.   int count = 0;
  345.   for (int i = 0; i < SYRINGE_SAMPLE_COUNT; i++) {
  346.     int val = analogRead(fsrPin);
  347.     if (val >= fsrThreshold) count++;
  348.     delay(2);
  349.   }
  350.   return count >= (SYRINGE_SAMPLE_COUNT - 1);
  351. }
  352.  
  353. bool isErrorResolved() {
  354.   return digitalRead(emergencyStopPin) == HIGH && isSyringePresentStable();
  355. }
  356.  
  357. float getSyringeInnerDiameter(int capacity) {
  358.   switch (capacity) {
  359.     case 20: return 19.66;
  360.     case 30: return 22.70;
  361.     case 40: return 25.00;
  362.     case 50: return 29.00;
  363.     default: return 0.0;
  364.   }
  365. }
  366.  
  367. void updateDisplayForState(State s) {
  368.   tft.fillScreen(ST77XX_BLACK);
  369.   tft.setCursor(0, 0);
  370.   switch (s) {
  371.     case SELECT_SYRINGE_CAPACITY:
  372.       tft.print("Select Syringe Capacity");
  373.       tft.setCursor(0, 20);
  374.       tft.print(syringeCapacity);
  375.       tft.print(" mL (");
  376.       tft.print(getSyringeInnerDiameter(syringeCapacity));
  377.       tft.println(" mm)");
  378.       tft.setCursor(0, 40);
  379.       tft.print("SELECT = change");
  380.       tft.setCursor(0, 60);
  381.       tft.print("VALIDATE = confirm");
  382.       break;
  383.  
  384.     case WAIT_SYRINGE:
  385.       tft.print("Insert Syringe");
  386.       break;
  387.  
  388.     case SELECT_VOLUME:
  389.       tft.print("Select Volume (mL):");
  390.       tft.setCursor(0, 20);
  391.       tft.print(selectedVolume);
  392.       tft.setCursor(0, 40);
  393.       tft.print("SELECT = change");
  394.       tft.setCursor(0, 60);
  395.       tft.print("VALIDATE = confirm");
  396.       break;
  397.  
  398.     case SELECT_RATE:
  399.       tft.print("Select Rate (mL/min):");
  400.       tft.setCursor(0, 20);
  401.       tft.print(selectedRate);
  402.       tft.setCursor(0, 40);
  403.       tft.print("SELECT = change");
  404.       tft.setCursor(0, 60);
  405.       tft.print("VALIDATE = confirm");
  406.       break;
  407.  
  408.     case READY:
  409.       tft.print("Ready to Inject");
  410.       tft.setCursor(0, 20);
  411.       tft.print("Vol: "); tft.print(selectedVolume); tft.print(" mL");
  412.       tft.setCursor(0, 40);
  413.       tft.print("Rate: "); tft.print(selectedRate); tft.print(" mL/min");
  414.       tft.setCursor(0, 60);
  415.       tft.print("VALIDATE = start");
  416.       break;
  417.  
  418.     case INJECTING:
  419.       tft.print("Injecting...");
  420.       break;
  421.  
  422.     case FINISHED:
  423.       tft.print("Injection Completed");
  424.       tft.setCursor(0, 20);
  425.       tft.print("RESET to restart");
  426.       break;
  427.  
  428.     case ERROR:
  429.       tft.print("ERROR DETECTED");
  430.       tft.setCursor(0, 20);
  431.       tft.print("Injection paused");
  432.       if (!isSyringePresentStable()) {
  433.         tft.setCursor(0, 40);
  434.         tft.print("No syringe");
  435.       }
  436.       if (digitalRead(emergencyStopPin) == LOW) {
  437.         tft.setCursor(0, 60);
  438.         tft.print("Emergency stop");
  439.       }
  440.       break;
  441.  
  442.     case ERROR_RESOLVED:
  443.       tft.print("Error Resolved");
  444.       tft.setCursor(0, 20);
  445.       tft.print("VALIDATE = resume");
  446.       break;
  447.  
  448.     case EMERGENCY_STOP:
  449.       tft.print("Emergency Stop");
  450.       tft.setCursor(0, 20);
  451.       tft.print("VALIDATE = continue");
  452.       tft.setCursor(0, 40);
  453.       tft.print("RESET = restart");
  454.       break;
  455.   }
  456. }
  457.  
  458. /* END CODE */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement