Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /********* Pleasedontcode.com **********
- Pleasedontcode thanks you for automatic code generation! Enjoy your code!
- - Terms and Conditions:
- You have a non-exclusive, revocable, worldwide, royalty-free license
- for personal and commercial use. Attribution is optional; modifications
- are allowed, but you're responsible for code maintenance. We're not
- liable for any loss or damage. For full terms,
- please visit pleasedontcode.com/termsandconditions.
- - Project: **Syringe Control**
- - Source Code NOT compiled for: ESP32 DevKit V1
- - Source Code created on: 2025-05-17 02:06:03
- ********* Pleasedontcode.com **********/
- /****** SYSTEM REQUIREMENTS *****/
- /****** SYSTEM REQUIREMENT 1 *****/
- /* motor doesnt work */
- /****** END SYSTEM REQUIREMENTS *****/
- /* START CODE */
- /****** DEFINITION OF LIBRARIES *****/
- #include <Adafruit_GFX.h> //https://github.com/adafruit/Adafruit-GFX-Library
- #include <SPI.h>
- #include <Adafruit_ST7735.h> // Added for TFT display support
- // -----------------------
- // Pin Definitions
- // -----------------------
- const int stepPin1 = 16; // coil 1
- const int stepPin2 = 17; // coil 2
- const int stepPin3 = 18; // coil 3
- const int stepPin4 = 19; // coil 4
- const int selectButtonPin = 25; // Updated pin to avoid conflict
- const int validateButtonPin = 14;
- const int resetButtonPin = 21;
- const int emergencyStopPin = 25; // avoid conflict
- const int fsrPin = 34; // FSR402 analog input
- #define TFT_CS 5
- #define TFT_RST 15
- #define TFT_DC 2
- #define TFT_MOSI 23
- #define TFT_SCLK 18
- #define TFT_MISO 19
- // -----------------------
- // Operational Constants
- // -----------------------
- const float mmPerStep = 0.01; // mm per step
- const int MIN_VOLUME = 1;
- const int MAX_VOLUME = 50;
- const int MIN_RATE = 1;
- const int MAX_RATE = 50;
- const int NUM_CAPACITIES = 4;
- const int allowedCapacities[NUM_CAPACITIES] = {20, 30, 40, 50};
- int syringeCapacityIndex = 0;
- int syringeCapacity = allowedCapacities[syringeCapacityIndex];
- const int DEBOUNCE_DELAY = 50;
- const int BUTTON_DELAY = 300;
- const int SYRINGE_SAMPLE_COUNT = 3;
- // FSR analog threshold (0-4095)
- int fsrThreshold = 1000;
- // -----------------------
- // State Machine
- // -----------------------
- enum State {
- SELECT_SYRINGE_CAPACITY,
- WAIT_SYRINGE,
- SELECT_VOLUME,
- SELECT_RATE,
- READY,
- INJECTING,
- FINISHED,
- ERROR,
- ERROR_RESOLVED,
- EMERGENCY_STOP
- };
- State currentState = SELECT_SYRINGE_CAPACITY;
- State lastState = currentState;
- bool firstDisplayUpdate = true;
- int selectedVolume = 10;
- int selectedRate = 10;
- long totalSteps = 0;
- unsigned long injectionTimeMs = 0;
- unsigned long stepDelayMs = 0;
- unsigned long currentStep = 0;
- Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);
- // -----------------------
- // Function Prototypes
- // -----------------------
- float getSyringeInnerDiameter(int capacity);
- bool isButtonPressed(int pin);
- bool isSyringePresentStable();
- void updateDisplayForState(State s);
- void performInjection();
- bool isErrorResolved();
- void stepClockwise();
- void stepCounterClockwise();
- void setup(void)
- {
- // put your setup code here, to run once:
- Serial.begin(9600);
- Serial.println("Syringe Injector Initialized");
- // Motor pins
- pinMode(stepPin1, OUTPUT);
- pinMode(stepPin2, OUTPUT);
- pinMode(stepPin3, OUTPUT);
- pinMode(stepPin4, OUTPUT);
- // Buttons
- pinMode(selectButtonPin, INPUT_PULLUP);
- pinMode(validateButtonPin, INPUT_PULLUP);
- pinMode(resetButtonPin, INPUT_PULLUP);
- pinMode(emergencyStopPin, INPUT_PULLUP);
- // FSR analog input
- analogReadResolution(12); // 0-4095
- pinMode(fsrPin, INPUT);
- // TFT
- tft.initR(INITR_BLACKTAB);
- tft.setRotation(2);
- tft.fillScreen(ST77XX_BLACK);
- tft.setTextColor(ST77XX_WHITE);
- tft.setTextSize(1);
- updateDisplayForState(currentState);
- }
- void loop(void)
- {
- // put your main code here, to run repeatedly:
- // Emergency stop
- if (digitalRead(emergencyStopPin) == LOW && currentState != EMERGENCY_STOP) {
- currentState = EMERGENCY_STOP;
- }
- // Reset
- if (isButtonPressed(resetButtonPin)) {
- currentState = WAIT_SYRINGE;
- selectedVolume = 10;
- selectedRate = 10;
- currentStep = 0;
- delay(BUTTON_DELAY);
- }
- // Display update
- if (firstDisplayUpdate || currentState != lastState) {
- updateDisplayForState(currentState);
- lastState = currentState;
- firstDisplayUpdate = false;
- }
- // State handling
- switch (currentState) {
- case SELECT_SYRINGE_CAPACITY:
- if (isButtonPressed(selectButtonPin)) {
- syringeCapacityIndex = (syringeCapacityIndex + 1) % NUM_CAPACITIES;
- syringeCapacity = allowedCapacities[syringeCapacityIndex];
- tft.fillRect(0, 20, tft.width(), 20, ST77XX_BLACK);
- tft.setCursor(0, 20);
- tft.print(syringeCapacity);
- tft.print(" mL (");
- tft.print(getSyringeInnerDiameter(syringeCapacity));
- tft.println(" mm)");
- delay(BUTTON_DELAY);
- }
- if (isButtonPressed(validateButtonPin)) {
- currentState = WAIT_SYRINGE;
- delay(BUTTON_DELAY);
- }
- break;
- case WAIT_SYRINGE:
- if (isSyringePresentStable()) {
- currentState = SELECT_VOLUME;
- delay(BUTTON_DELAY);
- }
- break;
- case SELECT_VOLUME:
- if (!isSyringePresentStable()) {
- currentState = WAIT_SYRINGE;
- updateDisplayForState(currentState);
- break;
- }
- if (isButtonPressed(selectButtonPin)) {
- selectedVolume = (selectedVolume % MAX_VOLUME) + 1;
- tft.fillRect(0, 20, tft.width(), 20, ST77XX_BLACK);
- tft.setCursor(0, 20);
- tft.print(selectedVolume);
- delay(BUTTON_DELAY);
- }
- if (isButtonPressed(validateButtonPin)) {
- currentState = SELECT_RATE;
- delay(BUTTON_DELAY);
- }
- break;
- case SELECT_RATE:
- if (!isSyringePresentStable()) {
- currentState = WAIT_SYRINGE;
- updateDisplayForState(currentState);
- break;
- }
- if (isButtonPressed(selectButtonPin)) {
- selectedRate = (selectedRate % MAX_RATE) + 1;
- tft.fillRect(0, 20, tft.width(), 20, ST77XX_BLACK);
- tft.setCursor(0, 20);
- tft.print(selectedRate);
- delay(BUTTON_DELAY);
- }
- if (isButtonPressed(validateButtonPin)) {
- currentState = READY;
- delay(BUTTON_DELAY);
- }
- break;
- case READY: {
- if (isButtonPressed(validateButtonPin)) {
- float diameter = getSyringeInnerDiameter(syringeCapacity);
- float area = PI * sq(diameter / 2.0);
- float V_mm3 = selectedVolume * 1000.0;
- float displacement = V_mm3 / area;
- totalSteps = (long)ceil(displacement / mmPerStep);
- injectionTimeMs = (unsigned long)((selectedVolume * 60000.0) / selectedRate);
- stepDelayMs = injectionTimeMs / totalSteps;
- currentState = INJECTING;
- delay(BUTTON_DELAY);
- }
- break;
- }
- case INJECTING:
- performInjection();
- break;
- case FINISHED:
- // idle
- break;
- case ERROR:
- if (isErrorResolved()) currentState = ERROR_RESOLVED;
- break;
- case ERROR_RESOLVED:
- if (!isErrorResolved()) currentState = ERROR;
- if (isButtonPressed(validateButtonPin)) {
- currentState = INJECTING;
- delay(BUTTON_DELAY);
- }
- break;
- case EMERGENCY_STOP:
- if (isButtonPressed(validateButtonPin)) {
- currentState = INJECTING;
- delay(BUTTON_DELAY);
- }
- break;
- }
- }
- // -----------------------
- // Motor Step Functions
- // -----------------------
- void stepClockwise() {
- digitalWrite(stepPin1, HIGH); digitalWrite(stepPin2, LOW);
- digitalWrite(stepPin3, LOW); digitalWrite(stepPin4, LOW);
- delay(stepDelayMs);
- digitalWrite(stepPin1, LOW); digitalWrite(stepPin2, HIGH);
- digitalWrite(stepPin3, LOW); digitalWrite(stepPin4, LOW);
- delay(stepDelayMs);
- digitalWrite(stepPin1, LOW); digitalWrite(stepPin2, LOW);
- digitalWrite(stepPin3, HIGH); digitalWrite(stepPin4, LOW);
- delay(stepDelayMs);
- digitalWrite(stepPin1, LOW); digitalWrite(stepPin2, LOW);
- digitalWrite(stepPin3, LOW); digitalWrite(stepPin4, HIGH);
- delay(stepDelayMs);
- }
- void stepCounterClockwise() {
- digitalWrite(stepPin1, LOW); digitalWrite(stepPin2, LOW);
- digitalWrite(stepPin3, LOW); digitalWrite(stepPin4, HIGH);
- delay(stepDelayMs);
- digitalWrite(stepPin1, LOW); digitalWrite(stepPin2, LOW);
- digitalWrite(stepPin3, HIGH); digitalWrite(stepPin4, LOW);
- delay(stepDelayMs);
- digitalWrite(stepPin1, LOW); digitalWrite(stepPin2, HIGH);
- digitalWrite(stepPin3, LOW); digitalWrite(stepPin4, LOW);
- delay(stepDelayMs);
- digitalWrite(stepPin1, HIGH); digitalWrite(stepPin2, LOW);
- digitalWrite(stepPin3, LOW); digitalWrite(stepPin4, LOW);
- delay(stepDelayMs);
- }
- // -----------------------
- // Injection Routine
- // -----------------------
- void performInjection() {
- bool aborted = false;
- Serial.println("Starting injection..."); // Debugging output
- for (; currentStep < totalSteps; currentStep++) {
- if (!isSyringePresentStable() || digitalRead(emergencyStopPin) == LOW) {
- aborted = true;
- break;
- }
- stepClockwise(); // Make sure motor is stepping
- Serial.print("Step: "); Serial.println(currentStep); // Debugging output
- }
- currentState = aborted ? ERROR : FINISHED;
- }
- // -----------------------
- // Utilities
- // -----------------------
- bool isButtonPressed(int pin) {
- if (digitalRead(pin) == LOW) {
- delay(DEBOUNCE_DELAY);
- if (digitalRead(pin) == LOW) {
- while (digitalRead(pin) == LOW) {}
- delay(DEBOUNCE_DELAY);
- return true;
- }
- }
- return false;
- }
- // Lecture FSR analogique et stabilisation
- bool isSyringePresentStable() {
- int count = 0;
- for (int i = 0; i < SYRINGE_SAMPLE_COUNT; i++) {
- int val = analogRead(fsrPin);
- if (val >= fsrThreshold) count++;
- delay(2);
- }
- return count >= (SYRINGE_SAMPLE_COUNT - 1);
- }
- bool isErrorResolved() {
- return digitalRead(emergencyStopPin) == HIGH && isSyringePresentStable();
- }
- float getSyringeInnerDiameter(int capacity) {
- switch (capacity) {
- case 20: return 19.66;
- case 30: return 22.70;
- case 40: return 25.00;
- case 50: return 29.00;
- default: return 0.0;
- }
- }
- void updateDisplayForState(State s) {
- tft.fillScreen(ST77XX_BLACK);
- tft.setCursor(0, 0);
- switch (s) {
- case SELECT_SYRINGE_CAPACITY:
- tft.print("Select Syringe Capacity");
- tft.setCursor(0, 20);
- tft.print(syringeCapacity);
- tft.print(" mL (");
- tft.print(getSyringeInnerDiameter(syringeCapacity));
- tft.println(" mm)");
- tft.setCursor(0, 40);
- tft.print("SELECT = change");
- tft.setCursor(0, 60);
- tft.print("VALIDATE = confirm");
- break;
- case WAIT_SYRINGE:
- tft.print("Insert Syringe");
- break;
- case SELECT_VOLUME:
- tft.print("Select Volume (mL):");
- tft.setCursor(0, 20);
- tft.print(selectedVolume);
- tft.setCursor(0, 40);
- tft.print("SELECT = change");
- tft.setCursor(0, 60);
- tft.print("VALIDATE = confirm");
- break;
- case SELECT_RATE:
- tft.print("Select Rate (mL/min):");
- tft.setCursor(0, 20);
- tft.print(selectedRate);
- tft.setCursor(0, 40);
- tft.print("SELECT = change");
- tft.setCursor(0, 60);
- tft.print("VALIDATE = confirm");
- break;
- case READY:
- tft.print("Ready to Inject");
- tft.setCursor(0, 20);
- tft.print("Vol: "); tft.print(selectedVolume); tft.print(" mL");
- tft.setCursor(0, 40);
- tft.print("Rate: "); tft.print(selectedRate); tft.print(" mL/min");
- tft.setCursor(0, 60);
- tft.print("VALIDATE = start");
- break;
- case INJECTING:
- tft.print("Injecting...");
- break;
- case FINISHED:
- tft.print("Injection Completed");
- tft.setCursor(0, 20);
- tft.print("RESET to restart");
- break;
- case ERROR:
- tft.print("ERROR DETECTED");
- tft.setCursor(0, 20);
- tft.print("Injection paused");
- if (!isSyringePresentStable()) {
- tft.setCursor(0, 40);
- tft.print("No syringe");
- }
- if (digitalRead(emergencyStopPin) == LOW) {
- tft.setCursor(0, 60);
- tft.print("Emergency stop");
- }
- break;
- case ERROR_RESOLVED:
- tft.print("Error Resolved");
- tft.setCursor(0, 20);
- tft.print("VALIDATE = resume");
- break;
- case EMERGENCY_STOP:
- tft.print("Emergency Stop");
- tft.setCursor(0, 20);
- tft.print("VALIDATE = continue");
- tft.setCursor(0, 40);
- tft.print("RESET = restart");
- break;
- }
- }
- /* END CODE */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement