From 3d8bd4e0cfd089ea279bef5f9a94a878d5c4fdd0 Mon Sep 17 00:00:00 2001 From: -help Date: Thu, 15 Feb 2024 20:21:11 +0200 Subject: [PATCH] Adding current monitoring code --- platformio.ini | 1 + src/Current/CurrentMonitor.cpp | 80 ++++++++++++++++++++++++++++++++++ src/Current/CurrentMonitor.h | 23 ++++++++++ src/PID/PidController.cpp | 10 +++-- src/displays/oled.cpp | 6 ++- src/globals.cpp | 55 +++++++---------------- src/globals.h | 12 +++-- src/main.cpp | 18 +++++--- 8 files changed, 152 insertions(+), 53 deletions(-) create mode 100644 src/Current/CurrentMonitor.cpp create mode 100644 src/Current/CurrentMonitor.h diff --git a/platformio.ini b/platformio.ini index 9a9ce09..9ffb27c 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,6 +29,7 @@ lib_deps = https://github.com/PowerBroker2/FireTimer.git https://github.com/adafruit/Adafruit_SSD1306.git https://github.com/RobTillaart/Stopwatch_RT.git@0.3.5 + https://github.com/RobTillaart/ACS712.git SPI Wire diff --git a/src/Current/CurrentMonitor.cpp b/src/Current/CurrentMonitor.cpp new file mode 100644 index 0000000..2ef04fc --- /dev/null +++ b/src/Current/CurrentMonitor.cpp @@ -0,0 +1,80 @@ +#include "CurrentMonitor.h" + +CurrentMonitor::CurrentMonitor() +{ + + +} + +CurrentMonitor::~CurrentMonitor() +{ +} + +int CurrentMonitor::getSystemCurrentMiliVolts() +{ + int current = currentSensor.mA_DC(); + if (current < 0) + { + current = abs(current); + } + else + { + } + + return current; +} + +float CurrentMonitor::getSystemCurrentAmps() +{ + + int current = getSystemCurrentMiliVolts(); + float currentAmps = current / 1000.0f; + return trimFloat(currentAmps, 2); +} + +/** + * @brief Trims a floating-point value to the specified precision. + * + * This function takes a floating-point value and trims it to the specified precision. + * The precision is defined as the number of decimal places to keep. + * + * @param value The floating-point value to be trimmed. + * @param precision The number of decimal places to keep. + * @return The trimmed floating-point value. + */ +float CurrentMonitor::trimFloat(float value, int precision) +{ + float factor = pow(10.0, precision); // Calculate the factor (10^decimals) + return round(value * factor) / factor; // Round the value and return +} + +uint8_t CurrentMonitor::calculateMaxPwm() +{ + uint8_t maxPwm = 255; + // Start with 255 duty cycle and ramp up slowly to get the max duty cycle + + Serial.println("Calculating max PWM"); + + for (int i = 255; i > 0; i--) + { + analogWrite(17, i); + Serial.println("PWM: " + String(i)); + int current = getSystemCurrentMiliVolts(); + Serial.println("Current: " + String(current)); + float readInputVoltage = analogRef.calculateInputVoltage(); + Serial.println("Voltage: " + String(readInputVoltage)); + + if (current > 6000 || readInputVoltage < 22) + { + + Serial.println("Limit reached at PWM: " + String(i)) + " Current: " + String(current) + " Voltage: " + String(readInputVoltage); + maxPwm = i; + break; + } + + delay(500); + } + + analogWrite(17, 255); + return 255-maxPwm; +} diff --git a/src/Current/CurrentMonitor.h b/src/Current/CurrentMonitor.h new file mode 100644 index 0000000..81fb9da --- /dev/null +++ b/src/Current/CurrentMonitor.h @@ -0,0 +1,23 @@ +#ifndef CURRENT_MONITOR_H +#define CURRENT_MONITOR_H + +#include "Arduino.h" +#include "globals.h" + +class CurrentMonitor { +public: + CurrentMonitor(); + ~CurrentMonitor(); + + int getSystemCurrentMiliVolts(); + float getSystemCurrentAmps(); + float static trimFloat(float value, int precision); + uint8_t calculateMaxPwm(); + + uint8_t calculatedMaxPwm; + +private: + // Add private members and methods here +}; + +#endif // CURRENT_MONITOR_H diff --git a/src/PID/PidController.cpp b/src/PID/PidController.cpp index 6e59e13..5c37898 100644 --- a/src/PID/PidController.cpp +++ b/src/PID/PidController.cpp @@ -14,7 +14,7 @@ PidController::PidController(PidControllerData *data) this->data = data; controller.begin(&(this->data->currentTemp), &(this->data->setPoint), &(this->data->targetTemp), PID_P, PID_I, PID_D); - // controller.reverse(); + // controller.reverse(); controller.setOutputLimits(PID_OUTPUT_MIN, PID_OUTPUT_MAX); controller.setSampleTime(PID_SAMPLE_TIME); controller.setWindUpLimits(PID_WINDUP_MIN, PID_WINDUP_MAX); @@ -46,11 +46,13 @@ void PidController::loop() data->currentTemp = tempController.getPlateTemperature(); // float sysVoltage = analogRef.calculateSystemVoltage(); + + float inVoltage = analogRef.calculateInputVoltage(); compute(); - //Reverseal of the PWM value is needed because the PID controller is set to work with a normal direction, Creates fopr a better PID control - //255= off, 0=full power - analogWrite(MOSTFET_PIN, 255- data->setPoint); + // Reverseal of the PWM value is needed because the PID controller is set to work with a normal direction, Creates for a better PID control + // 255= off, 0=full power + analogWrite(MOSTFET_PIN, 255 - data->setPoint); } void PidController::stop() diff --git a/src/displays/oled.cpp b/src/displays/oled.cpp index d77cc27..c49b07a 100644 --- a/src/displays/oled.cpp +++ b/src/displays/oled.cpp @@ -348,10 +348,14 @@ void OledDisplay::handleReflowState() // SysV topright // #ifdef DEBUG - display.setCursor(25, 15); + display.setCursor(15, 15); display.setTextSize(1, 1); display.print(analogRef.calculateInputVoltage()); // #endif + int current = currentSensor.mA_DC(); + display.setCursor(75, 15); + display.setTextSize(1, 1); + display.print(current); display.display(); } diff --git a/src/globals.cpp b/src/globals.cpp index a2fe597..227594f 100644 --- a/src/globals.cpp +++ b/src/globals.cpp @@ -4,16 +4,12 @@ #include "thermistors/TemperatureController.h" - - - WrappedState reflowProcessState = WrappedState(INITIALIZING); AnalogRef analogRef(5.0); ThermistorLookup thermistorLookup = ThermistorLookup(); - // Calibration data for 100K thermistors ->https://datasheet.lcsc.com/lcsc/1810161311_Nanjing-Shiheng-Elec-MF58-104F3950_C123399.pdf ->Glass thermistor NTC 3950 100K TempCalibration calibration_100K_3950 = {25, 100000, 107, 4957, 167, 1000}; // Initalize the 3950 100K thermistors with ACTUAL reference resistor measurnment(Measured between Left pin and GND when the board is powered off) using the default calibration data for 100K thermistor @@ -31,28 +27,28 @@ TempCalibration calibration_100K_3950 = {25, 100000, 107, 4957, 167, 1000}; // To measure the resistence turn off the controller completley and measure between GND and the left pin of the connector with the thermistor unplugged // 2.5k reference = Best accuracy around 138C - Thermistor thermistor2(THERMISTOR2_PIN, 2125, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE); //- > 2125Kohm set refrence - Thermistor thermistor3(THERMISTOR3_PIN, 9100, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE_LOW_TEMP);// -> 9100Kohm set refrence//// 9k reference = Best accuracy around 90C -> This thermistor is used for the preheat phase if attached - Thermistor thermistor4(THERMISTOR4_PIN, 564, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE_HIGH_TEMP);//-> 564Kohm set refrence // 564R reference = Best accuracy around 210C - Thermistor thermistor1(THERMISTOR1_PIN, 2545 , ThermistorZ_Placement::ON_PCB, ThermistorXY_Placement::MIDDLE);// -> 2545Kohm set refrence -> This thermistor is set directly touching the PCB to be soldered -// Unused by defualt, keep unplugged - Thermistor thermistor5(THERMISTOR4_PIN, 564, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE_HIGH_TEMP); - Thermistor thermistor6(THERMISTOR5_PIN,5727, ThermistorZ_Placement::TOP, ThermistorXY_Placement::MIDDLE_LOW_TEMP); +Thermistor thermistor1(THERMISTOR1_PIN, 2545, ThermistorZ_Placement::ON_PCB, ThermistorXY_Placement::MIDDLE); // -> 2545Kohm set refrence -> This thermistor is set directly touching the PCB to be soldered +Thermistor thermistor2(THERMISTOR2_PIN, 9100, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE_LOW_TEMP); //- > 2125Kohm set refrence +Thermistor thermistor3(THERMISTOR3_PIN, 2040, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE); // -> 9100Kohm set refrence//// 9k reference = Best accuracy around 90C -> This thermistor is used for the preheat phase if attached +Thermistor thermistor4(THERMISTOR4_PIN, 564, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE_HIGH_TEMP); //-> 564Kohm set refrence // 564R reference = Best accuracy around 210C +// Unused by defualt, keep unplugged +Thermistor thermistor5(THERMISTOR5_PIN, 564, ThermistorZ_Placement::BOTTOM, ThermistorXY_Placement::MIDDLE_HIGH_TEMP); +Thermistor thermistor6(THERMISTOR6_PIN, 5727, ThermistorZ_Placement::TOP, ThermistorXY_Placement::MIDDLE_LOW_TEMP); //--------------------------------------------------------------------------------------------------------------------------------------- // This line is here because TAKUMIII IS a bot and he will not let me remove it Thermistor thermistors[6] = {thermistor1, thermistor2, thermistor3, thermistor4, thermistor5, thermistor6}; +//Define the current sensor 20A version +ACS712 currentSensor = ACS712(ACS712_PIN, 5.0, 1023,100); + // Which Color to use for the reflow process markers uint16_t preheat_COLOR = 0x6800; uint16_t soak_COLOR = 0x6b60; uint16_t reflow_COLOR = 0x0201; uint16_t cool_COLOR = 0x00a8; - - - // These are the reflow profiles that you can choose from, you can add more if you want (up to 5) but you will have to change the nReflowProfiles variable to the number of profiles you have int nReflowProfiles = 4; @@ -61,38 +57,19 @@ ReflowProfile reflowProfiles[] = { // 138c profile Sn42Bi58 ReflowProfile(new ReflowStep[5]{ ReflowStep(ReflowProcessState::PREHEAT, 100, 100, EASE_OUT), - ReflowStep(ReflowProcessState::SOAK, 90, 140,EASE_IN_OUT), + ReflowStep(ReflowProcessState::SOAK, 90, 140, EASE_IN_OUT), ReflowStep(ReflowProcessState::REFLOW, 90, 170, HALF_SINE), ReflowStep(ReflowProcessState::COOL, 50, 85, EASE_IN), ReflowStep(ReflowProcessState::DONE, 0, 0)}, "138c Sn42Bi58\0"), + // The profile target says to get to 100c in 30 seconds but our hotplate can not do that so we extended the time to 120 seconds and combine the 150 and 183c steps into one step + // With a 12V PSU it also takes a while to reach these high temps so we increase the times a bit, experemintation is needed for different boards. + ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 120, 100, EASE_OUT), ReflowStep(ReflowProcessState::SOAK, 160, 183, EASE_IN), ReflowStep(ReflowProcessState::REFLOW, 110, 235, EASE_OUT), ReflowStep(ReflowProcessState::COOL, 30, 80, EASE_OUT), ReflowStep(ReflowProcessState::DONE, 0, 0)}, "183C Sn63 Pb37 \0"), -// The profile target says to get to 100c in 30 seconds but our hotplate can not do that so we extended the time to 120 seconds and combine the 150 and 183c steps into one step -// With a 12V PSU it also takes a while to reach these high temps so we increase the times a bit, experemintation is needed for different boards. - ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 120, 100,EASE_OUT), - ReflowStep(ReflowProcessState::SOAK, 160, 183,EASE_IN), - ReflowStep(ReflowProcessState::REFLOW, 110, 235, EASE_OUT), - ReflowStep(ReflowProcessState::COOL, 30, 80,EASE_OUT), - ReflowStep(ReflowProcessState::DONE, 0, 0)}, - "183C Sn63 Pb37 \0"), + ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 120, 77, LINEAR), ReflowStep(ReflowProcessState::SOAK, 180, 135, LINEAR), ReflowStep(ReflowProcessState::REFLOW, 110, 211, LINEAR), ReflowStep(ReflowProcessState::COOL, 30, 80, EASE_OUT), ReflowStep(ReflowProcessState::DONE, 0, 0)}, "RAMP HOLD 235c\0"), - - ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 120, 77,LINEAR), - ReflowStep(ReflowProcessState::SOAK, 180, 135,LINEAR), - ReflowStep(ReflowProcessState::REFLOW, 110, 211, LINEAR), - ReflowStep(ReflowProcessState::COOL, 30, 80,EASE_OUT), - ReflowStep(ReflowProcessState::DONE, 0, 0)}, - "RAMP HOLD 235c\0"), - - - ReflowProfile(new ReflowStep[5]{ReflowStep( - ReflowProcessState::PREHEAT, 200, 100,MID_RAMP_HOLD), - ReflowStep(ReflowProcessState::SOAK, 150, 150,FAST_RAMP_HOLD), - ReflowStep(ReflowProcessState::REFLOW, 150, 220, SLOW_RAMP_HOLD), - ReflowStep(ReflowProcessState::COOL, 200, 0,LINEAR), - ReflowStep(ReflowProcessState::DONE, 0, 0)}, - "Tuning Profile \0"), + ReflowProfile(new ReflowStep[5]{ReflowStep(ReflowProcessState::PREHEAT, 200, 100, MID_RAMP_HOLD), ReflowStep(ReflowProcessState::SOAK, 150, 150, FAST_RAMP_HOLD), ReflowStep(ReflowProcessState::REFLOW, 150, 220, SLOW_RAMP_HOLD), ReflowStep(ReflowProcessState::COOL, 200, 0, LINEAR), ReflowStep(ReflowProcessState::DONE, 0, 0)}, "Tuning Profile \0"), }; diff --git a/src/globals.h b/src/globals.h index a21b2a1..0a76904 100644 --- a/src/globals.h +++ b/src/globals.h @@ -10,7 +10,7 @@ #include "./PID/PidController.h" #include "./thermistors/TemperatureController.h" - +#include "ACS712.h" @@ -39,7 +39,7 @@ //PID Controller values #define PID_P 3 #define PID_I 5 -#define PID_D 100 +#define PID_D 10 #define PID_WINDUP_MIN -100 #define PID_WINDUP_MAX 200 @@ -48,11 +48,14 @@ //The actual PWM of the mosfet is 0 for max and 255 for off //This gets inverted after the setpoint is grabbed from the PID controller in the main loop #define PID_OUTPUT_MIN 0 -#define PID_OUTPUT_MAX 130 + +//Adjust the MAX PWM value according to your power supply some power supplies can cut off if the current is too high +#define PID_OUTPUT_MAX 140 ////////////////////////////////////// +#define PID_SAMPLE_TIME 200 -#define PID_SAMPLE_TIME 20 +#define ACS712_PIN 29 @@ -83,6 +86,7 @@ extern uint16_t cool_COLOR; extern ThermistorLookup thermistorLookup; +extern ACS712 currentSensor; diff --git a/src/main.cpp b/src/main.cpp index 60fe0bb..4840423 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,7 @@ #include "tools/ExecutionTimer.h" #include "StopWatch.h" #include "thermistors/Thermistor.h" - +#include "Current/CurrentMonitor.h" #define MOSTFET_PIN 17 @@ -25,8 +25,9 @@ double pwmValue = 255; ExecutionTimer executionTimer; -TemperatureController tempController ; +CurrentMonitor currentMonitor = CurrentMonitor(); +TemperatureController tempController; Buttons buttons = Buttons(); LEDS leds = LEDS(); @@ -47,7 +48,7 @@ void setup() Serial.begin(38400); - //Serial.println("Starting OLED"); + // Serial.println("Starting OLED"); // Set PWM frequency to 64 kHz analogWriteFrequency(64); @@ -68,6 +69,8 @@ void setup() thermMilisTimer.setResolution(StopWatch::Resolution::MILLIS); Serial.println("Setup done"); + + // currentMonitor.calculateMaxPwm(); } void loop() { @@ -116,7 +119,7 @@ void loop() pidController.start(); thermMilisTimer.start(); thermTimer.start(); - //Serial.println("Time,Therm1,Therm2,Therm3,Therm4,Therm5,Therm6,,Scaling1,Scaling2,Scaling3,Scaling4,Scaling5,Scaling6,Averaged1,Weighting1,Weighting2,Weighting3"); + // Serial.println("Time,Therm1,Therm2,Therm3,Therm4,Therm5,Therm6,,Scaling1,Scaling2,Scaling3,Scaling4,Scaling5,Scaling6,Averaged1,Weighting1,Weighting2,Weighting3"); } } state = newState; @@ -128,8 +131,13 @@ void loop() { pidController.loop(); - // #ifdef DEBUG pidController.debug(); + float amps = currentMonitor.getSystemCurrentAmps(); + Serial.println("Current: " + String(amps)); + float inVoltage = analogRef.calculateInputVoltage(); + Serial.println("Voltage: " + String(inVoltage)); + // #ifdef DEBUG + // #endif tftDisplay.drawRealTemp(pidController.getInput(), chosenReflowProfile.getPercentage());