Commit e0511cee authored by Gabriel D'Anselmo's avatar Gabriel D'Anselmo

Conc FW

parent c45c28db
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
# Continuous Integration (CI) is the practice, in software
# engineering, of merging all developer working copies with a shared mainline
# several times a day < https://docs.platformio.org/page/ci/index.html >
#
# Documentation:
#
# * Travis CI Embedded Builds with PlatformIO
# < https://docs.travis-ci.com/user/integration/platformio/ >
#
# * PlatformIO integration with Travis CI
# < https://docs.platformio.org/page/ci/travis.html >
#
# * User Guide for `platformio ci` command
# < https://docs.platformio.org/page/userguide/cmd_ci.html >
#
#
# Please choose one of the following templates (proposed below) and uncomment
# it (remove "# " before each line) or use own configuration according to the
# Travis CI documentation (see above).
#
#
# Template #1: General project. Test it using existing `platformio.ini`.
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# install:
# - pip install -U platformio
# - platformio update
#
# script:
# - platformio run
#
# Template #2: The project is intended to be used as a library with examples.
#
# language: python
# python:
# - "2.7"
#
# sudo: false
# cache:
# directories:
# - "~/.platformio"
#
# env:
# - PLATFORMIO_CI_SRC=path/to/test/file.c
# - PLATFORMIO_CI_SRC=examples/file.ino
# - PLATFORMIO_CI_SRC=path/to/test/directory
#
# install:
# - pip install -U platformio
# - platformio update
#
# script:
# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"platformio.platformio-ide"
]
}
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
; [env:teensy40]
; platform = teensy
; board = teensy40
; framework = arduino
[env:teensy35]
platform = teensy
board = teensy35
framework = arduino
lib_deps =
https://github.com/ij96/Honeywell_ABP
https://github.com/dwerne/Sensirion_SFM3000_arduino
https://github.com/br3ttb/Arduino-PID-Library
https://github.com/teemuatlut/TMCStepper
https://github.com/evert-arias/EasyBuzzer
https://github.com/NicksonYap/digitalWriteFast
; https://github.com/mjs513/Teensy-4.x-Quad-Encoder-Library
https://github.com/loglow/PITimer
https://github.com/PaulStoffregen/Encoder
https://github.com/luni64/TeensyStep
https://github.com/SolidGeek/VescUart
https://github.com/siteswapjuggler/RAMP
https://github.com/PaulStoffregen/PWMServo
/**
G.D.
OpenBreath Project
V1.0
Copyright CERN 2020.
This source describes Open Hardware and is licensed under the CERN-OHL-S v2.
You may redistribute and modify this source and make products using it under the terms of the CERN-OHL-S v2 (https:/cern.ch/cern-ohl).
This source is distributed WITHOUT ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING OF MERCHANTABILITY, SATISFACTORY QUALITY AND FITNESS FOR A PARTICULAR PURPOSE.
Please see the CERN-OHL-S v2 for applicable conditions.
- Now using the classic step and dir interface fot the stepper driver, deprecated SPI motion control of TMC5160 (spi mc eliminates every timing problem), for compatibility with pololu style stepper driver
- Now using simple PID for the control, possibily only proportional with kp step on error range, deprecated the volumetric and cinematic model for the AMBU
- PID For volume target, PID For pressure target, PID for volume rateo, PID for pressure rateo, not only one selected by the operational mode for clearness
- Encoder reading with quadrature decoder, functioning only with first two channel, now using the classic encoder library.
This is the starting concept of the project, the first stable firmware will be published after finishing the testing part.
*/
#include <PID_v1.h>
#include <TMCStepper.h>
#include <Encoder.h>
#define EN_PIN 7 // Enable
#define DIR_PIN 8 // Direction
#define STEP_PIN 9 // Step
#define CS_PIN 10 // Chip select
#define EN_PIN_B 24 // Enable
#define DIR_PIN_B 26 // Direction
#define STEP_PIN_B 25 // Step
#define CS_PIN_B 15 // Chip select
// #define SW_MOSI 66 // Software Master Out Slave In (MOSI)
// #define SW_MISO 44 // Software Master In Slave Out (MISO)
// #define SW_SCK 64 // Software Slave Clock (SCK)
// #define SW_RX 63 // TMC2208/TMC2224 SoftwareSerial receive pin
// #define SW_TX 40 // TMC2208/TMC2224 SoftwareSerial transmit pin
// #define SERIAL_PORT Serial1 // TMC2208/TMC2224 HardwareSerial port
#define R_SENSE 0.075f // Match to your driver
// SilentStepStick series use 0.11
// UltiMachine Einsy and Archim2 boards use 0.2
// Panucatt BSD2660 uses 0.1
// Watterott TMC5160 uses 0.075
// Select your stepper driver type
//TMC2130Stepper driver = TMC2130Stepper(CS_PIN, R_SENSE); // Hardware SPI
//TMC2130Stepper driver = TMC2130Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK); // Software SPI
//TMC2208Stepper driver = TMC2208Stepper(&SERIAL_PORT, R_SENSE); // Hardware Serial0
//TMC2208Stepper driver = TMC2208Stepper(SW_RX, SW_TX, R_SENSE); // Software serial
//TMC2660Stepper driver = TMC2660Stepper(CS_PIN, R_SENSE); // Hardware SPI
//TMC2660Stepper driver = TMC2660Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);
TMC5160Stepper driver = TMC5160Stepper(CS_PIN, R_SENSE);
TMC5160Stepper driver_B = TMC5160Stepper(CS_PIN_B, R_SENSE);
//TMC5160Stepper driver = TMC5160Stepper(CS_PIN, R_SENSE, SW_MOSI, SW_MISO, SW_SCK);
//using namespace TMC2130_n;
#include <AccelStepper.h>
// AccelStepper stepper = AccelStepper(stepper.DRIVER, STEP_PIN, DIR_PIN);
// AccelStepper stepper_B = AccelStepper(stepper_B.DRIVER, STEP_PIN_B, DIR_PIN_B);
#include "TeensyStep.h"
Stepper stepper(STEP_PIN, DIR_PIN); //STEP pin = 2, DIR pin = 3
Stepper stepper_B(STEP_PIN_B, DIR_PIN_B); //STEP pin = 9, DIR pin = 10
StepControl position_controller;
RotateControl rotate_controller;
// RotateControl rotate_controller_A;
// RotateControl rotate_controller_B;
//AccelStepper stepper_B(AccelStepper::DRIVER, STEP_PIN_B, DIR_PIN_B);
//hope dfsgsfg
float Breath_frequency;
float breath_amp;
float pressure_cutoff = 50;
float volume_cutoff;
bool start_auto_breath;
int step_breath = -1;
int last_step_breath;
long ms;
long breath_timer;
long debug_timer;
long timer_auto_breath;
int END_SP;
int END_SN;
int END_SP_B;
int END_SN_B;
int buttons;
int old_buttons;
long buttons_deb;
int END_HP = 37;
int END_HM = 38;
int END_HP_B = 35;
int END_HM_B = 36;
int relay = 39;
int Knob_P_PB = 16;
int Knob_V_PB = 16;
int Knob_F_PB = 30;
bool referenced;
long timer_sampling;
float flow;
bool startup;
bool inHoming;
long loop_timer;
long loop_time;
int step_homing;
float offset_fc = 1.0;
float step_mm;
int cycle_tipe;
long timer_supervisioning;
bool fc_delay;
double Pressure_SP, InputP, OutputP;
float Out_P;
double V_SP, InputV, OutputV;
float Volume_Compliance_SP;
float Volume_SP;
float Out_V;
double RateoP_SP, InputRP, OutputRP;
float Out_RP;
double RateoV_SP, InputRV, OutputRV;
float Out_RV;
float volume;
float volumeCycle;
long timer_picco;
int durata_picco;
bool old_fc;
float PEEP = 0;
float rateo_P_avg;
float rateo_V_avg;
float last_V;
long timer_rateo;
int t_sampling = 2;
int irP = 0;
int irV = 0;
float last_P;
float rateo_P_avg_a[10];
float rateo_V_avg_a[10];
float speed_profile;
long timer_respiro;
float durata_respiro;
float durata_espiro;
int breath_measured_time;
int debreath_measured_time;
int total_time;
float estimated_breath_frequency;
float speed_debreath;
float ratio_breath_debreath = 33.3; //1 sec breat 2 sec debreath percentage
int start_position_debreath;
float ramp_time = 0;
int ramp_measured_time;
bool fault_enca = 0;
bool fault_encb = 0;
bool ena_motA = 1;
bool ena_motB = 1;
long timer_hmi;
long timer_gui;
float compliance = 10;
int j;
float avgPGui[10];
float avgP;
int cycle_tipe_temp;
float Pressure_SP_temp;
float Volume_SP_temp;
float Breath_frequency_temp;
float ratio_breath_debreath_temp;
int driver_rms_temp;
int driver_B_rms_temp;
float ramp_time_temp;
float pressure_cutoff_temp;
float volume_cutoff_temp;
int cont_resp;
float leak_volume;
float leak_volume_offset;
float leak_volume_ratio;
float exp_peak;
float last_flow;
float last_flow_z;
long flow_peak_time;
long flow_peak_time_z;
long last_us;
long us;
int microstepping;
int maxspeed;
IntervalTimer pres_stop;
#include "Honeywell_ABP.h"
// create Honeywell_ABP instance
// refer to datasheet for parameters
Honeywell_ABP abp(
0x28, // I2C address
-1, // minimum pressure
1, // maximum pressure
"psi" // pressure unit
);
#include <sfm3000wedo.h>
//#include "QuadEncoder.h"
uint32_t mCurPosValue;
uint32_t old_position = 0;
uint32_t mCurPosValue1;
uint32_t old_position1 = 0;
uint32_t mCurPosValue2;
uint32_t old_position2 = 0;
// QuadEncoder encA(1, 0, 1, 0); // Encoder on channel 1 of 4 available
// // // Phase A (pin0), PhaseB(pin1), Pullups Req(0)
// QuadEncoder encB(2, 2, 3, 0); // Encoder on channel 1 of 4 available
// // // Phase A (pin0), PhaseB(pin1), Pullups Req(0)
// // QuadEncoder knobF(3, 4, 5, 1); // Encoder on channel 1 of 4 available
// // // // Phase A (pin0), PhaseB(pin1), Pullups Req(0)
Encoder knobP(22, 23);
Encoder knobV(4, 17);
Encoder knobF(5, 6);
Encoder encA(0, 1);
Encoder encB(3, 2);
//Specify the links and initial tuning parameters
PID Pressure_PID(&InputP, &OutputP, &Pressure_SP, 1, 0.01, 0, DIRECT); //P_ON_M specifies that Proportional on Measurement be used //P_ON_E (Proportional on Error) is the default behavior
PID Volume_PID(&InputV, &OutputV, &V_SP, 0.5, 0.1, 0, DIRECT);
PID RateoP_PID(&InputRP, &OutputRP, &RateoP_SP, 0.15, 1, 0, DIRECT);
PID RateoV_PID(&InputRV, &OutputRV, &RateoV_SP, 0.15, 1, 0, DIRECT);
SFM3000wedo measflow(64);
int offset = 32768; // Offset for the sensor
float scale = (140.0); // Scale factor for Air and N2 is 140.0, O2 is 142.8
float pressure;
#include <EasyBuzzer.h>
void enable(int motor, bool status)
{
if (motor == 1)
{
if (!status)
{
digitalWriteFast(EN_PIN, HIGH);
}
else
{
digitalWriteFast(EN_PIN, LOW);
}
}
if (motor == 2)
{
if (!status)
{
digitalWriteFast(EN_PIN_B, HIGH);
}
else
{
digitalWriteFast(EN_PIN_B, LOW);
}
}
}
void beep(int b) // Buzzer
{
EasyBuzzer.beep(
10, // Breath_frequencyuency in hertz(HZ).
100, // On Duration in milliseconds(ms).
100, // Off Duration in milliseconds(ms).
b, // The number of beeps per cycle.
200, // Pause duration.
1 // The number of cycle.
);
};
void homing() // Homing routine
{
if (step_homing == 0 and !referenced)
{
Serial.println("homing");
step_homing = 1;
delay(100);
enable(1, 1);
enable(2, 1);
}
switch (step_homing)
{
case 1: //Homing A
Serial.println("homing1");
inHoming = true;
fault_enca = 0;
stepper.setMaxSpeed(maxspeed / 20 * -1);
stepper_B.setMaxSpeed(maxspeed / 20 * -1);
if (!rotate_controller.isRunning() && !digitalReadFast(END_HM))
{
rotate_controller.rotateAsync(stepper);
}
delay(1);
if (digitalReadFast(END_HM))
{
rotate_controller.emergencyStop();
stepper.setPosition(0 - long(offset_fc * step_mm));
beep(2);
END_SP = 7200; // Homing on quote
step_homing = 2; // Homing on quote
}
break;
case 2: //Homing A
Serial.println("homing_B");
inHoming = true;
fault_enca = 0;
stepper.setMaxSpeed(-500);
stepper_B.setMaxSpeed(-500);
if (!rotate_controller.isRunning() && !digitalReadFast(END_HM_B))
{
rotate_controller.rotateAsync(stepper_B);
}
delay(1);
if (digitalReadFast(END_HM_B))
{
rotate_controller.emergencyStop();
stepper_B.setPosition(0 - long(offset_fc * step_mm));
beep(2);
END_SP_B = 200 * 2 * microstepping; // Homing on quote
step_homing = 3; // Homing on quote
}
break;
case 10: // Homing fc+
// stepper.setSpeed(500);
// stepper_B.setSpeed(500);
delay(1);
if (digitalReadFast(END_HP))
{
// stepper.stop();
// stepper_B.stop();
rotate_controller.emergencyStop();
END_SP = stepper.getPosition() - long(offset_fc * step_mm);
beep(2);
step_homing = 3;
}
break;
case 3: //Positioning in software end stop -
stepper.setMaxSpeed(3000);
stepper_B.setMaxSpeed(3000);
stepper.setTargetAbs(END_SN);
stepper_B.setTargetAbs(END_SN);
if (!position_controller.isRunning())
{
position_controller.moveAsync(stepper, stepper_B);
}
if (stepper.getPosition() == END_SN && stepper_B.getPosition() == END_SN && !position_controller.isRunning())
{
step_homing = 0;
referenced = true;
inHoming = false;
delay(100);
encA.write(0);
encB.write(0);
enable(1, 0);
enable(2, 0);
beep(3);
}
break;
}
}
void homingds() //ikea test bench homing
{
step_homing = 0;
referenced = true;
inHoming = false;
END_SP = 3200 * 2;
start_auto_breath = 0;
beep(3);
}
void supervisioning()
{
if ((((encA.read() * 2) - stepper.getPosition() > 100) || ((encA.read() * 2) - stepper.getPosition() < -100)) && referenced)
{
start_auto_breath = 0;
position_controller.emergencyStop();
enable(1, 0);
rotate_controller.emergencyStop();
step_breath = -1;
referenced = 0;
fault_enca = 1;
Serial.print("Missstep, Stepper: ");
Serial.print(stepper.getPosition());
Serial.print(" Encoder: ");
Serial.print(encA.read() * 2);
Serial.print(" error: ");
Serial.println((encA.read() * 2) - stepper.getPosition());
beep(5);
}
if ((((encB.read() * 2) - stepper_B.getPosition() > 100) || ((encB.read() * 2) - stepper_B.getPosition() < -100)) && referenced)
{
fault_encb = 1;
enable(2, 0);
beep(5);
}
if ((digitalReadFast(END_HM) || digitalReadFast(END_HP)) && !inHoming)
{
start_auto_breath = 0;
position_controller.emergencyStop();
rotate_controller.emergencyStop();
referenced = 0;
enable(1, 0);
enable(2, 0);
step_breath = -1;
}
if ((digitalReadFast(END_HM_B) || digitalReadFast(END_HP_B)) && !inHoming)
{
start_auto_breath = 0;
position_controller.emergencyStop();
rotate_controller.emergencyStop();
referenced = 0;
enable(1, 0);
enable(2, 0);
step_breath = -1;
}
}
void hmi()
{
if (knobP.read() > 40)
{
knobP.write(40);
}
if (knobP.read() < 0)
{
knobP.write(0);
}
if (knobV.read() > 600)
{
knobV.write(600);
}
if (knobV.read() < 0)
{
knobV.write(0);
}
if (knobF.read() > 30)
{
knobF.write(30);
}
if (knobF.read() < 0)
{
knobF.write(0);
}
if (ms - buttons_deb > 100)
{
buttons_deb = ms;
if (!digitalReadFast(Knob_P_PB))
{
if (!start_auto_breath)
{
start_auto_breath = 1;
step_breath = 1;
Serial.println("start");
beep(1);
}
else
{
start_auto_breath = 0;
step_breath = 0;
Serial.println("stop respiro");
beep(1);
}
}
else if (!digitalReadFast(Knob_V_PB))
{
if (cycle_tipe == 2)
{
cycle_tipe = 0;
Serial.println("standard");
beep(1);
}
else if (cycle_tipe == 0)
{
cycle_tipe = 1;
Serial.println("pressure");
beep(1);
}
else if (cycle_tipe == 1)
{
cycle_tipe = 2;
Serial.println("volume");
beep(1);
}
}
}
}
void sampling()
{
t_sampling = (micros() - last_us);
abp.update();
pressure = abp.pressure() * 70.307;
InputP = pressure;
if (pressure < PEEP || PEEP == 0)
{
PEEP = pressure;
}
durata_respiro = (((60.0 / Breath_frequency)) / 100.0) * ratio_breath_debreath;
durata_espiro = (((60.0 / Breath_frequency)) / 100.0) * (100.0 - ratio_breath_debreath);
RateoP_SP = ((Pressure_SP - PEEP) / (ramp_time * (durata_respiro / 100.0)));
durata_picco = ((durata_respiro - (ramp_time * (durata_respiro / 100.0))) * 1000.0);
rateo_P_avg_a[irP] = ((pressure - last_P) / (t_sampling)) * 1000000.0; //cmh2o/s
last_P = pressure;
irP = irP + 1;
if (irP >= 1)
{
irP = 0;
}
for (int i = 0; i < 2; i++)
{
rateo_P_avg = rateo_P_avg + rateo_P_avg_a[i];
}
rateo_P_avg = rateo_P_avg / 2;
InputRP = rateo_P_avg;
flow = (((float)measflow.getvalue() - offset) / scale) * 1.0; //*1000*-1; ??? rallenta tutto
volume = volume + (((flow / 60.0) / (1000000 / t_sampling))) * 1000.0;
rateo_V_avg = (((flow / 60.0))) * 1000.0;
InputRV = rateo_V_avg;
if (step_breath == 4)
{
volumeCycle = volume;
}
InputV = volume;
last_us = micros();
}
void breathing()
{
Volume_PID.Compute();
RateoV_PID.Compute();
Pressure_PID.Compute();
RateoP_PID.Compute();
Volume_Compliance_SP = compliance * (Pressure_SP - PEEP);
// if (compliance < 0)
// {
// compliance = 10.0;
// }
if (cycle_tipe == 1)
{
RateoV_SP = ((Volume_SP - 0) / (ramp_time * (durata_respiro / 100.0)));
V_SP = Volume_SP;
Out_V = OutputV / Volume_SP;
}
else if (cycle_tipe == 2)
{
RateoV_SP = ((Volume_Compliance_SP - 0) / (ramp_time * (durata_respiro / 100.0)));
V_SP = Volume_Compliance_SP;
Out_V = OutputV / Volume_Compliance_SP;
}
Out_RV = OutputRV / RateoV_SP;
Out_P = OutputP / Pressure_SP;
if (Out_P > 1)
{
Out_P = 1;
}
Out_RP = OutputRP / RateoP_SP;
if (Out_RP > 1)
{
Out_RP = 1;
}
if (Out_RV > 1)
{
Out_RV = 1;
}
switch (cycle_tipe) //Full automatic cycle
{
case 1: //Automatic breath in Volume Control mode V2
switch (step_breath)
{
case 0:
RateoV_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
RateoV_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
RateoV_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Volume_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
Volume_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
Volume_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
speed_profile = RateoV_SP / Volume_SP;
timer_respiro = ms;
enable(1, 1);
enable(2, 1);
volume = 0;
step_breath = 1;
if (!start_auto_breath)
{
step_breath = -1;
enable(1, 0);
enable(2, 0);
}
// stepper.setMaxSpeed(13000 * speed_profile);
// stepper_B.setMaxSpeed(13000 * speed_profile);
stepper.setMaxSpeed(maxspeed);
stepper_B.setMaxSpeed(maxspeed);
//float treshold;
return;
break;
case 1: //respirazione
if (Volume_SP - volume > 5)
{
if (rotate_controller.isRunning())
{
if (((speed_profile) * (Out_RV)*maxspeed) > maxspeed)
{
rotate_controller.overrideSpeed(1.0); // * (OutputP * 0.5));
}
else
{
rotate_controller.overrideSpeed((speed_profile) * (Out_RV)); // * (OutputP * 0.5));
}
}
}
else
{
if (rotate_controller.isRunning())
{
rotate_controller.overrideSpeed(Out_V);
}
}
if (!rotate_controller.isRunning())
{
rotate_controller.rotateAsync(stepper, stepper_B);
}
// stepper_B.setTargetAbs(END_SP);
// stepper.setTargetAbs(1000000);
if (stepper.getPosition() >= END_SP || stepper_B.getPosition() >= END_SP || (volume >= Volume_SP - 3) || (pressure >= (pressure_cutoff - 2)) || (ms - timer_respiro >= (durata_respiro * 1000.0)))
{
compliance = volume / (pressure - PEEP);
rotate_controller.overrideSpeed(0);
rotate_controller.stop();
ramp_measured_time = ms - timer_respiro;
Serial.print("15,");
Serial.println(ramp_measured_time);
timer_picco = ms;
step_breath = 2;
leak_volume_offset = volume;
return;
}
break;
case 2: //picco
rotate_controller.overrideSpeed(0);
if (ms - timer_respiro >= (durata_respiro * 1000.0))
{
breath_measured_time = ms - timer_respiro;
Serial.print("20,");
Serial.println(breath_measured_time);
timer_respiro = ms;
start_position_debreath = stepper.getPosition();
speed_debreath = (start_position_debreath / durata_espiro) * 2;
rotate_controller.stop();
if (!rotate_controller.isRunning())
{
leak_volume = volume - leak_volume_offset;
leak_volume_ratio = leak_volume / ((ms - timer_picco) / 1000.0);
step_breath = 3;
cont_resp = cont_resp + 1;
return;
}
}
break;
case 3: //espirazione
if (!position_controller.isRunning())
{
if ((speed_debreath * 2) <= maxspeed)
{
stepper.setMaxSpeed(speed_debreath * 2);
stepper_B.setMaxSpeed(speed_debreath * 2);
}
else
{
stepper.setMaxSpeed(maxspeed);
stepper_B.setMaxSpeed(maxspeed);
}
stepper.setTargetAbs(END_SN);
stepper_B.setTargetAbs(END_SN);
position_controller.moveAsync(stepper, stepper_B);
}
if (stepper.getPosition() == END_SN && stepper_B.getPosition() == END_SN && !position_controller.isRunning())
{
step_breath = 4;
enable(1, 0);
enable(2, 0);
return;
}
break;
case 4: //fine espirazione
if (ms - timer_respiro >= (durata_espiro * 1000.0))
{
PEEP = 0;
debreath_measured_time = ms - timer_respiro;
Serial.print("30,");
Serial.println(debreath_measured_time);
//stepper.stop();
step_breath = 0;
enable(1, 0);
enable(2, 0);
cycle_tipe = cycle_tipe_temp;
Pressure_SP = Pressure_SP_temp;
Volume_SP = Volume_SP_temp;
Breath_frequency = Breath_frequency_temp;
ratio_breath_debreath = ratio_breath_debreath_temp;
driver.rms_current(driver_rms_temp);
driver_B.rms_current(driver_B_rms_temp);
ramp_time = ramp_time_temp;
pressure_cutoff = pressure_cutoff_temp;
volume_cutoff = volume_cutoff_temp;
return;
}
break;
}
break;
case 2: //Automatic breath in Volume Control mode on compliance
switch (step_breath)
{
case 0:
volume = 0;
RateoV_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
RateoV_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
RateoV_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Volume_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
Volume_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
Volume_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
RateoP_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
RateoP_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
RateoP_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Pressure_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
Pressure_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
Pressure_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Volume_Compliance_SP = (Pressure_SP - PEEP) * compliance;
speed_profile = RateoV_SP / Volume_Compliance_SP;
timer_respiro = ms;
enable(1, 1);
enable(2, 1);
step_breath = 1;
if (!start_auto_breath)
{
step_breath = -1;
enable(1, 0);
enable(2, 0);
}
stepper.setMaxSpeed(13000);
stepper_B.setMaxSpeed(13000);
//rotate_controller.overrideAcceleration(1);
return;
break;
case 1: //respirazione
float tresh;
tresh = (float(rotate_controller.getCurrentSpeed()) / 13000.0) * 8;
if (Pressure_SP - pressure > tresh)
{
if (rotate_controller.isRunning())
{
//corr = ((0.0000000133*(pow(float(stepper.getPosition()),2)))-(0.000233*float(stepper.getPosition()))+1);
if (rotate_controller.isRunning())
{
if (((((speed_profile) * (Out_RV)*13000))) > 13000)
{
rotate_controller.overrideSpeed(1.0); // * (OutputP * 0.5));
}
else
{
rotate_controller.overrideSpeed(((speed_profile) * (Out_RV))); // * (OutputP * 0.5));
}
}
}
}
else
{
if (rotate_controller.isRunning())
{
rotate_controller.overrideSpeed(Out_P);
}
}
if (!rotate_controller.isRunning())
{
rotate_controller.rotateAsync(stepper, stepper_B);
}
// stepper_B.setTargetAbs(END_SP);
// stepper.setTargetAbs(1000000);
if (stepper.getPosition() >= END_SP || stepper_B.getPosition() >= END_SP || (pressure >= Pressure_SP - 1) || (volume >= volume_cutoff) || (ms - timer_respiro >= (durata_respiro * 1000.0)))
{
compliance = volume / (pressure - PEEP);
if ((volume >= volume_cutoff))
{
rotate_controller.overrideSpeed(0);
}
else
{
rotate_controller.overrideSpeed(Out_P);
}
rotate_controller.stop();
ramp_measured_time = ms - timer_respiro;
Serial.print("15,");
Serial.println(ramp_measured_time);
timer_picco = ms;
step_breath = 2;
leak_volume_offset = volume;
return;
}
break;
case 2: //picco
if ((volume >= volume_cutoff))
{
rotate_controller.overrideSpeed(0);
}
else
{
rotate_controller.overrideSpeed(Out_P);
}
if (ms - timer_respiro >= (durata_respiro * 1000.0))
{
breath_measured_time = ms - timer_respiro;
Serial.print("20,");
Serial.println(breath_measured_time);
timer_respiro = ms;
start_position_debreath = stepper.getPosition();
speed_debreath = (start_position_debreath / durata_espiro) * 2;
rotate_controller.stop();
if (!rotate_controller.isRunning())
{
leak_volume = volume - leak_volume_offset;
leak_volume_ratio = leak_volume / ((ms - timer_picco) / 1000.0);
step_breath = 3;
cont_resp = cont_resp + 1;
beep(3);
return;
}
}
break;
case 3: //espirazione
if (!position_controller.isRunning())
{
if ((speed_debreath * 2) <= 13000)
{
stepper.setMaxSpeed(speed_debreath * 2);
stepper_B.setMaxSpeed(speed_debreath * 2);
}
else
{
stepper.setMaxSpeed(13000);
stepper_B.setMaxSpeed(13000);
}
stepper.setTargetAbs(END_SN);
stepper_B.setTargetAbs(END_SN);
position_controller.moveAsync(stepper, stepper_B);
}
if (stepper.getPosition() == END_SN && stepper_B.getPosition() == END_SN && !position_controller.isRunning())
{
step_breath = 4;
enable(1, 0);
enable(2, 0);
return;
}
break;
case 4: //fine espirazione
if (ms - timer_respiro >= (durata_espiro * 1000.0))
{
PEEP = 0;
debreath_measured_time = ms - timer_respiro;
Serial.print("30,");
Serial.println(debreath_measured_time);
//stepper.stop();
step_breath = 0;
enable(1, 0);
enable(2, 0);
cycle_tipe = cycle_tipe_temp;
Pressure_SP = Pressure_SP_temp;
Volume_SP = Volume_SP_temp;
Breath_frequency = Breath_frequency_temp;
ratio_breath_debreath = ratio_breath_debreath_temp;
driver.rms_current(driver_rms_temp);
driver_B.rms_current(driver_B_rms_temp);
ramp_time = ramp_time_temp;
pressure_cutoff = pressure_cutoff_temp;
volume_cutoff = volume_cutoff_temp;
return;
}
break;
}
break;
case 3: //Automatic breath in Volume Control mode on compliance cpap
switch (step_breath)
{
case 0:
RateoV_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
RateoV_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
RateoV_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Volume_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
Volume_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
Volume_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
RateoP_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
RateoP_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
RateoP_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Pressure_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
Pressure_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
Pressure_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Volume_Compliance_SP = (Pressure_SP - PEEP) * compliance;
speed_profile = RateoP_SP / Pressure_SP;
timer_respiro = ms;
exp_peak = 0;
if (!start_auto_breath)
{
step_breath = -1;
enable(1, 0);
enable(2, 0);
}
stepper.setMaxSpeed(13000);
stepper_B.setMaxSpeed(13000);
//rotate_controller.overrideAcceleration(1);
if (flow < -2.0)
{
step_breath = 1;
enable(1, 1);
enable(2, 1);
return;
}
if (flow > 2)
{
step_breath = 5;
enable(1, 1);
enable(2, 1);
return;
}
break;
case 1:
if (ms - flow_peak_time > 25)
{
if (flow < exp_peak)
{
exp_peak = flow;
last_flow = flow;
}
if (flow > exp_peak && flow > (exp_peak * 0.90))
{
exp_peak = -200;
step_breath = 5;
return;
}
flow_peak_time = ms;
}
break;
case 5: //respirazione
if ((ms - flow_peak_time > 25) && flow > 0)
{
if (flow > exp_peak)
{
exp_peak = flow;
}
last_flow = flow;
flow_peak_time = ms;
}
if (stepper.getPosition() < END_SP - 500 || stepper_B.getPosition() < END_SP - 500)
{
if (rotate_controller.isRunning())
{
if (pressure < 3.0)
{
if ((Out_P * 2 * 13000) < 13000)
{
rotate_controller.overrideSpeed(Out_P * 2);
}
else
{
rotate_controller.overrideSpeed(1);
}
}
else
{
if ((Out_P * 1 * 13000) < 13000)
{
rotate_controller.overrideSpeed(Out_P * 1);
}
else
{
rotate_controller.overrideSpeed(1);
}
}
}
}
else
{
if (rotate_controller.isRunning())
{
rotate_controller.overrideSpeed(0);
}
}
if (!rotate_controller.isRunning())
{
rotate_controller.rotateAsync(stepper, stepper_B);
}
// stepper_B.setTargetAbs(END_SP);
// stepper.setTargetAbs(1000000);
if (last_flow < (exp_peak * 0.10))
{
compliance = volume / (pressure - PEEP);
breath_measured_time = ms - timer_respiro;
Serial.print("20,");
Serial.println(exp_peak);
start_position_debreath = stepper.getPosition();
rotate_controller.stop();
if (!rotate_controller.isRunning())
{
//rotate_controller.overrideSpeed(1);
leak_volume = volume - leak_volume_offset;
leak_volume_ratio = leak_volume / ((ms - timer_picco) / 1000.0);
cont_resp = cont_resp + 1;
breath_measured_time = ms - timer_respiro;
Serial.print("20,");
Serial.println(breath_measured_time);
timer_respiro = ms;
beep(3);
step_breath = 20;
return;
}
}
break;
case 20: //espirazione
if (!position_controller.isRunning())
{
stepper.setMaxSpeed(12000);
stepper_B.setMaxSpeed(12000);
stepper.setTargetAbs(END_SN);
stepper_B.setTargetAbs(END_SN);
position_controller.moveAsync(stepper, stepper_B);
}
if (stepper.getPosition() == END_SN && stepper_B.getPosition() == END_SN && !position_controller.isRunning())
{
step_breath = 30;
enable(1, 0);
enable(2, 0);
return;
}
break;
case 30: //fine espirazione
if (true)
{
PEEP = 0;
debreath_measured_time = ms - timer_respiro;
Serial.print("30,");
Serial.println(debreath_measured_time);
//stepper.stop();
estimated_breath_frequency = 60 / ((debreath_measured_time + breath_measured_time) / 1000.0);
Serial.print("40,");
Serial.println(estimated_breath_frequency);
enable(1, 0);
enable(2, 0);
cycle_tipe = cycle_tipe_temp;
Pressure_SP = Pressure_SP_temp;
Volume_SP = Volume_SP_temp;
Breath_frequency = Breath_frequency_temp;
ratio_breath_debreath = ratio_breath_debreath_temp;
driver.rms_current(driver_rms_temp);
driver_B.rms_current(driver_B_rms_temp);
ramp_time = ramp_time_temp;
pressure_cutoff = pressure_cutoff_temp;
volume_cutoff = volume_cutoff_temp;
step_breath = 0;
return;
}
break;
}
break;
case 4:
switch (step_breath) //Automatic breath in Direct Pressure Control mode
{
case 0:
volume = 0;
RateoP_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
RateoP_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
RateoP_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
Pressure_PID.SetOutputLimits(0.0, 1.0); // Forces minimum up to 0.0
Pressure_PID.SetOutputLimits(-1.0, 0.0); // Forces maximum down to 0.0
Pressure_PID.SetOutputLimits(0, 1000); // Set the limits back to normal
speed_profile = RateoP_SP / Pressure_SP;
timer_respiro = ms;
enable(1, 1);
enable(2, 1);
step_breath = 1;
if (!start_auto_breath)
{
step_breath = -1;
enable(1, 0);
enable(2, 0);
}
stepper.setMaxSpeed(13000);
stepper_B.setMaxSpeed(13000);
return;
break;
case 1: //respirazione
int tresh;
if (RateoP_SP > 30.0)
{
tresh = 4;
}
else
{
tresh = 1;
}
if (Pressure_SP - pressure > (tresh))
{
if (rotate_controller.isRunning())
{
//rotate_controller.overrideSpeed(Out_RP+speed_profile);
if (((speed_profile) * (Out_RP)*13000) > 13000)
{
rotate_controller.overrideSpeed(1.0); // * (OutputP * 0.5));
}
else
{
rotate_controller.overrideSpeed((speed_profile) * (Out_RP)); // * (OutputP * 0.5));
}
}
}
else
{
if (rotate_controller.isRunning())
{
rotate_controller.overrideSpeed(Out_P);
}
}
if (!rotate_controller.isRunning())
{
rotate_controller.rotateAsync(stepper, stepper_B);
}
if (stepper.getPosition() >= END_SP || stepper_B.getPosition() >= END_SP || (pressure >= (Pressure_SP - 0.5)) || (ms - timer_respiro >= (durata_respiro * 1000.0)))
{
compliance = volume / (pressure - PEEP);
rotate_controller.overrideSpeed(0);
rotate_controller.stop();
ramp_measured_time = ms - timer_respiro;
Serial.print("15,");
Serial.println(ramp_measured_time);
timer_picco = ms;
step_breath = 2;
return;
}
break;
case 2: //picco
rotate_controller.overrideSpeed(Out_P);
if (ms - timer_respiro >= (durata_respiro * 1000.0))
{
breath_measured_time = ms - timer_respiro;
Serial.print("20,");
Serial.println(breath_measured_time);
timer_respiro = ms;
start_position_debreath = stepper.getPosition();
speed_debreath = (start_position_debreath / durata_espiro) * 2;
rotate_controller.stop();
if (!rotate_controller.isRunning())
{
step_breath = 3;
beep(3);
return;
}
}
break;
case 3: //espirazione
if (!position_controller.isRunning())
{
if ((speed_debreath * 2) <= 13000)
{
stepper.setMaxSpeed(speed_debreath * 2);
stepper_B.setMaxSpeed(speed_debreath * 2);
}
else
{
stepper.setMaxSpeed(13000);
stepper_B.setMaxSpeed(13000);
}
stepper.setTargetAbs(END_SN);
stepper_B.setTargetAbs(END_SN);
position_controller.moveAsync(stepper, stepper_B);
}
if (stepper.getPosition() == END_SN && stepper_B.getPosition() == END_SN && !position_controller.isRunning())
{
step_breath = 4;
enable(1, 0);
enable(2, 0);
return;
}
break;
case 4: //fine espirazione
if (ms - timer_respiro >= (durata_espiro * 1000.0))
{
PEEP = 0;
debreath_measured_time = ms - timer_respiro;
Serial.print("30,");
Serial.println(debreath_measured_time);
rotate_controller.stopAsync();
if (!position_controller.isRunning())
{
step_breath = 0;
enable(1, 0);
enable(2, 0);
cycle_tipe = cycle_tipe_temp;
Pressure_SP = Pressure_SP_temp;
Volume_SP = Volume_SP_temp;
Breath_frequency = Breath_frequency_temp;
ratio_breath_debreath = ratio_breath_debreath_temp;
driver.rms_current(driver_rms_temp);
driver_B.rms_current(driver_B_rms_temp);
ramp_time = ramp_time_temp;
pressure_cutoff = pressure_cutoff_temp;
volume_cutoff = volume_cutoff_temp;
cont_resp = cont_resp + 1;
return;
}
}
break;
}
break;
}
last_step_breath = step_breath;
}
void GUI()
{
Serial.print("10");
Serial.print(",");
avgPGui[j] = pressure;
j = j + 1;
if (j > 2)
{
j = 0;
}
avgP = (avgPGui[0] + avgPGui[1] + avgPGui[2]) / 3;
Serial.print(pressure);
//Serial.print(avgP);
Serial.print(",");
Serial.print(Pressure_SP);
Serial.print(",");
Serial.print(rateo_P_avg);
Serial.print(",");
Serial.print(Out_RV);
Serial.print(",");
Serial.print(RateoP_SP);
Serial.print(",");
Serial.print(PEEP);
Serial.print(",");
Serial.print(rotate_controller.getCurrentSpeed());
Serial.print(",");
Serial.print(flow); //8
Serial.print(",");
Serial.print(RateoV_SP); //9
Serial.print(",");
Serial.print(rateo_V_avg); //10
Serial.print(",");
Serial.print(volume); //11
Serial.print(",");
Serial.print(speed_profile); //11
Serial.print(",");
Serial.print(compliance); //11
Serial.print(",");
Serial.print(Volume_Compliance_SP); //11
Serial.print(",");
Serial.print(stepper.getPosition()); //11
Serial.print(",");
// float corr;
// corr = ((0.0000000325520833*(pow(float(stepper.getPosition()),2)))-(0.0003645833*float(stepper.getPosition()))+1);
Serial.print(Volume_SP); //11
Serial.print(",");
Serial.print(pressure_cutoff);
Serial.print(",");
Serial.print(volume_cutoff);
Serial.print(",");
Serial.println(step_breath);
// ((speed_profile) * (Out_RV))* (1-(stepper.getPosition()/6400))
}
void debug()
{
// Serial.println(String("step ") + String(step_breath));
// Serial.println(String("Breath_frequencyuenza ") + String(Breath_frequency));
// Serial.println(String("intervallo ") + String(timer_auto_breath));
// Serial.println(String("Remaining ms for breath ") + String(timer_auto_breath - (ms - breath_timer)));
// Serial.println(String("current position: ") + String(stepper.getPosition() + String(" step | ") + String(stepper.getPosition() / step_mm) + String(" mm")));
// Serial.println(String("Pression: ") + String(pressure, 4) + String(" psi | FlowRate: ") + String(flow) + String(" slm"));
// Serial.println(String("volumeCycel: ") + String(volumeCycle) + String("volume") + String(volume));
// Serial.println(" ");
// Serial.println(String("input: ") + String(InputP) + String(" output ") + String(OutputP));
if (digitalReadFast(END_HP))
{
Serial.println("FC+");
}
if (digitalReadFast(END_HM))
{
Serial.println("FC-");
}
// Serial.print("Referenced: ");
// Serial.println(referenced);
// Serial.print("Referenhommingstepced: ");
// Serial.println(step_homing);
// Serial.print("timer: ");
// Serial.println(fc_delay);
// Serial.print("cur_a = ");
// Serial.println(driver.cur_a(), DEC);
// Serial.print("cur_b = ");
// Serial.println(driver.cur_b(), DEC);
// if (!referenced)
// {
// Serial.println("homing");
// }
// Serial.print(pressure * 1);
// Serial.print(",");
// //Serial.print(last_P * 1);
// Serial.print(",");
// Serial.print(Pressure_SP * 1);
// Serial.print(",");
// // Serial.print(volume);
// // Serial.print(",");
// // Serial.print(step_breath);
// // Serial.print(",");
// // Serial.print(Volume_SP);
// // Serial.print(",");
// // Serial.print(Breath_frequency);
// // Serial.print(",");
// Serial.print(rateo_P_avg);
// Serial.print(",");
// Serial.print(RateoP_SP);
// Serial.print(",");
// Serial.println(Out_RP);
//Serial.print(",");
//Serial.println(rateo_V_avg);
// Serial.print(knobP.read());
// Serial.print(",");
// Serial.print(knobV.read());
// Serial.print(",");
// Serial.print(knobF.read());
// Serial.print(",");
// Serial.print(encA.read());
// Serial.print(",");
// Serial.println(encB.read());
// Serial.print("misstep");
// Serial.print("Missstep, Stepper: ");
// Serial.print(stepper.getPosition() );
// Serial.print(" Encoder: ");
// Serial.print(encA.read() * 2);
// Serial.print(" error: ");
// Serial.println((encA.read() * 2)-stepper.getPosition() );
// Serial.print(",");
// Serial.println( analogRead(23));
// Serial.print(",");
Serial.print("50,");
Serial.print(Breath_frequency);
Serial.print(",");
Serial.print(Volume_SP);
Serial.print(",");
Serial.print(cycle_tipe);
Serial.print(",");
Serial.print(driver.rms_current());
Serial.print(",");
Serial.print(ratio_breath_debreath);
Serial.print(",");
Serial.print(ramp_time);
Serial.print(",");
Serial.print(fault_enca);
Serial.print(",");
Serial.print(fault_encb);
Serial.print(",");
Serial.print(driver_B.rms_current());
Serial.print(",");
Serial.print(cont_resp);
Serial.print(",");
Serial.print(leak_volume);
Serial.print(",");
Serial.println(leak_volume_ratio);
timer_auto_breath = (60 / Breath_frequency) * 1000;
if (Serial.available() > 0)
{
char inChar = (char)Serial.read();
Serial.println(inChar);
switch (inChar) //Automatic breath in Pressure Control mode
{
case 'a':
start_auto_breath = 0;
//measflow.init();
Serial.println("stop respiro");
beep(1);
return;
break;
case 'b':
start_auto_breath = 1;
if (step_breath == -1)
{
cont_resp = 0;
step_breath = 0;
}
Serial.println("avvio respiro");
beep(1);
return;
break;
case 'c':
if (!referenced)
{
start_auto_breath = 0;
step_breath = -1;
referenced = 0;
fault_enca = 0;
fault_encb = 0;
}
return;
break;
case 'd':
if (step_breath == 3 || step_breath == 4 || start_auto_breath == 0)
{
Serial.read(); //next character is comma, so skip it using this
cycle_tipe_temp = (Serial.readStringUntil(',')).toInt();
Pressure_SP_temp = (Serial.readStringUntil(',')).toFloat();
Volume_SP_temp = (Serial.readStringUntil(',')).toFloat();
Breath_frequency_temp = (Serial.readStringUntil(',')).toFloat();
ratio_breath_debreath_temp = (Serial.readStringUntil(',')).toFloat();
driver_rms_temp = (Serial.readStringUntil(',')).toInt();
//driver.rms_current((Serial.readStringUntil(',')).toInt());
driver_B_rms_temp = (Serial.readStringUntil(',')).toInt();
//driver_B.rms_current((Serial.readStringUntil(',')).toInt());
ramp_time_temp = ((Serial.readStringUntil(',')).toFloat());
pressure_cutoff_temp = (Serial.readStringUntil(',')).toFloat();
volume_cutoff_temp = ((Serial.readStringUntil('\0')).toFloat());
if (start_auto_breath == 0)
{
cycle_tipe = cycle_tipe_temp;
Pressure_SP = Pressure_SP_temp;
Volume_SP = Volume_SP_temp;
Breath_frequency = Breath_frequency_temp;
ratio_breath_debreath = ratio_breath_debreath_temp;
driver.rms_current(driver_rms_temp);
driver_B.rms_current(driver_B_rms_temp);
ramp_time = ramp_time_temp;
pressure_cutoff = pressure_cutoff_temp;
volume_cutoff = volume_cutoff_temp;
}
}
beep(2);
return;
break;
}
}
}
void pressurestop()
{
if (pressure > Pressure_SP)
{
//rotate_controller.emergencyStop();
}
}
void setup()
{
// open I2C communication
microstepping = 16;
maxspeed = (812 * microstepping);
step_mm = ((200 * microstepping) / 12.5);
Wire.begin();
Wire.setClock(400000);
SPI.begin();
Serial.begin(4608000);
driver.push();
driver_B.push();
pinMode(CS_PIN, OUTPUT);
pinMode(CS_PIN_B, OUTPUT);
pinMode(EN_PIN, OUTPUT);
pinMode(EN_PIN_B, OUTPUT);
pinMode(END_HP, INPUT_PULLUP);
pinMode(END_HM, INPUT_PULLUP);
pinMode(END_HP_B, INPUT_PULLUP);
pinMode(END_HM_B, INPUT_PULLUP);
pinMode(relay, OUTPUT);
pinMode(Knob_P_PB, INPUT_PULLUP);
pinMode(Knob_V_PB, INPUT_PULLUP);
pinMode(Knob_F_PB, INPUT_PULLUP);
pinMode(14, OUTPUT);
// digitalWriteFast(CS_PIN, HIGH);
driver.begin(); // Initiate pins and registeries
driver.rms_current(800); // Set stepper current to 600mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
driver.en_pwm_mode(1); // Enable extremely quiet stepping
driver.pwm_autoscale(1);
driver.microsteps(microstepping);
//digitalWriteFast(CS_PIN, LOW);
stepper.setMaxSpeed(15000);
stepper.setAcceleration(70000);
// stepper.setEnablePin(EN_PIN);
// stepper.setPinsInverted(false, false, true);
// enable(1,1);
// digitalWriteFast(CS_PIN_B, HIGH);
driver_B.begin(); // Initiate pins and registeries
driver_B.rms_current(1500); // Set stepper current to 600mA. The command is the same as command TMC2130.setCurrent(600, 0.11, 0.5);
driver_B.en_pwm_mode(1); // Enable extremely quiet stepping
driver_B.pwm_autoscale(1);
driver_B.microsteps(microstepping);
stepper_B.setMaxSpeed(15000);
stepper_B.setAcceleration(70000);
// stepper_B.setEnablePin(EN_PIN_B);
// stepper_B.setPinsInverted(false, false, true);
// enable(2,1);
breath_timer = 0;
END_SP = 3200 * (3);
END_SN = 0;
breath_timer = 0;
EasyBuzzer.setPin(14);
measflow.init();
delay(200);
Pressure_PID.SetMode(AUTOMATIC);
Pressure_PID.SetOutputLimits(0, 1000); //not work directly in float??
Volume_PID.SetMode(AUTOMATIC);
Volume_PID.SetOutputLimits(0, 1000);
RateoP_PID.SetMode(AUTOMATIC);
RateoP_PID.SetOutputLimits(0, 1000);
RateoV_PID.SetMode(AUTOMATIC);
RateoV_PID.SetOutputLimits(0, 1000);
Pressure_PID.SetSampleTime(1); //check if work in sincro with the call with millis() or set to 0 (change sampletime in the library pid)
Volume_PID.SetSampleTime(1);
RateoP_PID.SetSampleTime(1);
RateoV_PID.SetSampleTime(1);
step_homing = 0;
cycle_tipe = 1;
/* Initialize the ENC module. */ //
// encA.setInitConfig();
// encA.EncConfig.INDEXTriggerMode = RISING_EDGE;
// encA.init();
// encB.setInitConfig();
// encB.EncConfig.INDEXTriggerMode = RISING_EDGE;
// encB.init();
Pressure_SP = 20.0;
knobP.write(Pressure_SP);
Volume_SP = 400.0;
knobV.write(Volume_SP);
Breath_frequency = 10;
knobF.write(Breath_frequency);
timer_auto_breath = (60 / Breath_frequency) * 1000;
start_auto_breath = 0;
abp.update();
pressure = abp.pressure() * 70.307;
PEEP = pressure;
enable(1, 0);
enable(2, 0);
digitalWriteFast(relay, HIGH);
pres_stop.begin(pressurestop, 10); // blinkLED to run every 0.15 seconds
volume=0;
delay(1000);
}
void loop()
{
ms = millis();
if (!startup)
{
beep(1);
}
if (!referenced and !fault_enca) //Homing at startup
{
homing();
}
if (ms - timer_hmi > 50) // Supervisioning
{
hmi();
timer_hmi = ms;
}
if (ms - timer_supervisioning > 5) // Supervisioning
{
supervisioning();
timer_supervisioning = ms;
}
if (micros() - timer_sampling >= 1000)
{ //pressure reading 10Hz
sampling();
timer_sampling = micros();
}
breathing();
if ((ms - flow_peak_time_z > 25) && cycle_tipe == 3 && (flow < -2 || flow > 2))
{
if (flow > 0 && last_flow_z < 0)
{
volume = 0;
}
last_flow_z = flow;
flow_peak_time_z = ms;
}
if (ms - timer_gui > 50) //debug
{
GUI();
timer_gui = ms;
}
if (ms - debug_timer > 250) //debug
{
debug();
debug_timer = ms;
}
EasyBuzzer.update();
if (!startup) //first cycle
{
startup = true;
}
}
This directory is intended for PIO Unit Testing and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PIO Unit Testing:
- https://docs.platformio.org/page/plus/unit-testing.html
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment