#include "syringefilled.h" //CONSTRUCTORS SyringeFilled :: SyringeFilled() : Motor (&ISRStepper) //pb with my motor constructor { set_exchange_throughput_uL_per_sec(1); set_exchange_volume_mL(1); set_remaining_volume_mL(1); set_push(true); set_id_syringe("300912"); set_screw_thread_mm(4); set_clockwise_equals_push(true); set_emergency(false); } //SET METHODS void SyringeFilled :: set_exchange_throughput_uL_per_sec(float exchange_throughput_uL_per_sec) { SyringeFilledJSON["exchange_throughput_uL_per_sec"] = exchange_throughput_uL_per_sec; } void SyringeFilled :: set_exchange_volume_mL(float exchange_volume_mL) { SyringeFilledJSON["exchange_volume_mL"] = exchange_volume_mL; } void SyringeFilled :: set_remaining_volume_mL(float remaining_volume_mL) { SyringeFilledJSON["remaining_volume_mL"] = remaining_volume_mL; } void SyringeFilled :: set_push(bool push) { SyringeFilledJSON["push"] = push; } void SyringeFilled :: set_id_syringe(Syringe* id_syringe){ SyringeFilledJSON["id_syringe"] = id_syringe; } void SyringeFilled :: set_screw_thread_mm(float screw_thread_mm) { SyringeFilledJSON["screw_thread_mm"] = screw_thread_mm; } void SyringeFilled :: set_clockwise_equals_push(bool clockwise_equals_push) { SyringeFilledJSON["clockwise_equals_push"] = clockwise_equals_push; } void SyringeFilled :: set_emergency(bool emergency) { SyringeFilledJSON["emergency"] = emergency; } //GET METHODS float SyringeFilled :: get_exchange_throughput_uL_per_sec() { return SyringeFilledJSON["exchange_throughput_uL_per_sec"].as<float>(); } float SyringeFilled :: get_exchange_volume_mL() { return SyringeFilledJSON["exchange_volume_mL"].as<float>(); } float SyringeFilled :: get_remaining_volume_mL() { return SyringeFilledJSON["remaining_volume_mL"].as<float>(); } bool SyringeFilled :: get_push() { return SyringeFilledJSON["push"].as<bool>(); } Syringe* SyringeFilled :: get_id_syringe() { return SyringeFilledJSON["id_syringe"].as<Syringe*>(); } float SyringeFilled :: get_screw_thread_mm() { return SyringeFilledJSON["screw_thread_mm"].as<float>(); } bool SyringeFilled :: get_clockwise_equals_push() { return SyringeFilledJSON["clockwise_equals_push"].as<float>(); } bool SyringeFilled :: get_emergency() { return SyringeFilledJSON["emergency"].as<bool>(); } //CONVERSIONS float SyringeFilled::volume_to_distance(float volume_mL, Syringe* id_syringe) /*** -Argument : Volume in mL. -Return : The distance to cover associated in mm. -Action : / ***/ { float volume_mm3 = 1000*volume_mL; //mL->mm3 float piston_surface_mm2 = id_syringe->get_internal_diameter_mm(); float distance_mm = volume_mm3/piston_surface_mm2; return distance_mm; } float SyringeFilled::distance_to_volume(float distance_mm, Syringe* id_syringe) /*** -Argument : distance in mm. -Return : The volume associated in mL. -Action : / ***/ { float piston_surface_mm2 = id_syringe->get_internal_diameter_mm(); float volume_mm3 = distance_mm*piston_surface_mm2; return volume_mm3; } //MOVEMENTS float SyringeFilled :: move() /*** -Argument : / (We're using informations stored in the class itself) -Return : / -Action : Move the syringe filled to deliver or recover the volume expected ***/ { //Conversions of volumes float remaining_volume_mm3 = get_remaining_volume_mL()*1000; float exchange_volume_mm3 = get_exchange_volume_mL()*1000; //Find the section float radius = get_id_syringe()->get_internal_diameter_mm(); float section_mm2 = M_PI*radius*radius; setSpeedMmPerSec(get_exchange_throughput_uL_per_sec()/section_mm2); if (whereStep() == 0) //If we are putting the syringe for the first time { moveToMm(syringe_pump_length_mm - remaining_volume_mm3/section_mm2); } else { float initial_position_mm = syringe_pump_length_mm - remaining_volume_mm3/section_mm2; if (get_push()) //If we want to deliver some liquid { moveToMm(initial_position_mm + exchange_volume_mm3/section_mm2); } else //If we want to recover some liquid { moveToMm(initial_position_mm - exchange_volume_mm3/section_mm2); } } } void SyringeFilled :: go_to_zero() /*** -Argument : / (We're using informations stored in the class itself) -Return : / -Action : Move the syringe filled to deliver or recover the volume expected ***/ { if (get_emergency()) return; else { resetPosition(); moveToMm(-syringe_pump_length_mm); } } //LIMIT SWITCH void SyringeFilled::manage_emergency (bool pressed, bool at_zero) /*** -Argument : two boolean to know the position of the limit switch and if we are a the zero -Return : / -Action : Manage different emergency cases (move the pump if necessary) ***/ { if (pressed) //if the limit switch is pressed { set_emergency(true); if (at_zero) //if we are at te initialisation place { run_from_emergency(); } else { Serial.printf("EMERGENCY: Pressed by someone\n"); } } else { set_emergency(false); Serial.printf("EMERGENCY: released\n"); stayHere(); resetPosition(); //zero is here again Serial.printf("ZERO: reset\n"); } } void SyringeFilled::run_from_emergency() /*** -Argument : / -Return : / -Action : Move the pump slowly until the limit switch is released ***/ { if (get_emergency()) { Serial.printf("EMERGENCY: running away slowly\n"); setSpeedMmPerSec(-1); resetPosition(); moveToMm(syringe_pump_length_mm); } } //CONFIGURATION bool SyringeFilled :: check_configuration() /*** -Argument : / -Return : A boolean true(everything is fine), false(at least one attribut is'nt correct) -Action : Check if the values are correct. ***/ { if (get_id_syringe()->get_internal_diameter_mm() <= 0) return false; if (get_exchange_volume_mL() < 0) return false; if (get_remaining_volume_mL() <= 0) return false; if (get_exchange_throughput_uL_per_sec() <= 0) return false; return true; } void SyringeFilled :: show_configuration() /*** -Argument : / -Return : / -Action : Displays syringe filled attributes ***/ { Motor::showConfiguration(); auto step = whereStep(); Serial.printf("# push clockwise: %s\n" "# diameter: %g mm\n" "# capacity: %g uL\n" "# rate: %g uL/s = %g mm/s\n" "# volume remaining: %g uL (target)\n" "# direction: %s\n" "# emergency: %d\n" "# current position: %g mm\n", get_clockwise_equals_push()? "yes": "no", get_id_syringe()->get_internal_diameter_mm(), get_id_syringe()->get_total_volume_mL(), get_exchange_throughput_uL_per_sec(), volume_to_distance(get_exchange_throughput_uL_per_sec(), get_id_syringe()), get_remaining_volume_mL(), get_push()? "infuse": "withdraw", get_emergency(), stepToMm(step)); } //Example : File f = ({ InterruptLock lock; filesystem->open(filename, "w"); }); and the f becomes the argument output_stream //useful in web.cpp via a button to save data void SyringeFilled :: write_Json (Stream& output_stream) //file_name sera le nom du fichier Json, doc sera la structure Json qu'on veut transformer en fichier { /*** -Argument : output_stream (= serial or a file) -Return : / -Action : Save the Json structure in a file (convert it to text) ***/ InterruptLock lock; //useful thanks to its constructor (so a is not visible in the code) serializeJson(SyringeFilledJSON, output_stream); } //useful in setup of pousse-seringue.cpp(to check at the begining what has already been saved) and web.cpp via a button to recover data void SyringeFilled :: read_Json (Stream& input_stream) //file_name sera le nom du fichier Json, doc sera la structure Json qu'on veut transformer en fichier { /*** -Argument : input_stream (= serial or a file) -Return : / -Action : Check if a Json Document alredy exist or not ***/ InterruptLock lock; //useful thanks to its constructor (so a is not visible in the code) deserializeJson(SyringeFilledJSON, input_stream); }