main.cpp
#include <Arduino.h>
#include <PID_v1.h>
#include <LiquidCrystal.h>
#include <system.h>
#include <UserInterface.h>
System sys;
UserInterface UI;
//################################### Laser PID #################################
//###############################################################################
double Setpoint; //target value
double Input; //Temperature sensor (pyrometer)
double Output; //ouput value of the PID controller
//PID parameters:
double Kp = 0.1, Ki = 6, Kd = 0;
//Laser PID
PID laserPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);
void setup()
{
Serial1.begin(baudRate_1); //Serial 1 = Laser Serial Communication (RS232)
//Initialize Pyrometer & Laser
sys.Init_Pyrometer(); //initialize Pyrometer
sys.Init_LaserStart(); //initialize Laser PIN
sys.Init_PF(); //initialize Powder Feeder
//Initialize UI
UI.BeginConfig(); //Begining Configurations
//Laser PID Setup
Input = 0; //Tempreature Reading Value ("TR") [ºC]. Defined by Pyrometer input values.
Setpoint = 0; //Temperature Target Value ("TT") [ºC]. Defined in "UI".
laserPID.SetMode(AUTOMATIC); //Turn PID ON
laserPID.SetTunings(Kp, Ki, Kd); //Set defined Kp, Ki and Kd
laserPID.SetSampleTime(10); //Sample time = 10 [ms]
laserPID.SetOutputLimits(10, 100); //Output limits = Diode Current (10-100% of Max Laser Power)
}
void loop()
{
//UI Configurations Start (Running Once)
UI.Config(); //UI request for desired Target Temperature ("TT") and Mass Flow Rate ("MFR").
Setpoint = UI.TempTarget; //PID Setpoint, user desired value "TT".
UI.Laser_ON(); //UI intruction to user requesting laser start.
sys.Laser_InitCOM(); //Establish initial communications to laser. Check "system.cpp".
UI.PF_Config(); //User Configurations ("TT" and "MFR")
sys.PF_CompRPM(); //Compute Powder Feeder RPM%
UI.PF_Purge(); //Powder Feeder Purge
UI.Ready2Print(); //Processing Ready to Deposit
if (UI.Ready == true)
{
//temperature reading [ºC]
sys.TempReading(); //Recieve Pyrometer Readings
Input = sys.TempReading(); //Tempreature Reading Value ("TR") [ºC]. Defined by Pyrometer input values.
//PID Computation
laserPID.Compute(); //PID Output Computation
//Laser Output
//sys.Laser_Output(Output); //Laser Output Instructions (Serial Communication, RS232)
sys.Laser_Output_testing();
//Powder Feeder Control
sys.PF_CompRPM(); //Compute RPM% that the PF requires to turn at the desired MFR
sys.PF_Output(); //Output RPM% to Powder Feeder
//Display Temperatures (Target & Read) and Mass Flow Rate on the LCD
UI.ProcessingDisplay(Output);
}
//SAFE function to test laser communication
//sys.laser_testing();
}
system.cpp
#include <system.h>
#include <LiquidCrystal.h>
#include <UserInterface.h>
UserInterface UIsys;
//############################################## SETUP FUNCTIONS ##############################################
//#############################################################################################################
//############################################# INITIALIZE PINS #############################################
void System::Init_LaserStart()
{
pinMode(LaserStart_IN, INPUT); //Start laser pin (ON/OFF INPUT pin)
}
void System::Init_Pyrometer()
{
pinMode(Pyrometer_IN, INPUT); //pyrometer pin is INPUT
}
void System::Init_PF()
{
pinMode(D1_rpm_OUT, OUTPUT);
pinMode(D2_rpm_OUT, OUTPUT);
}
//############################################## LOOP FUNCTIONS ##############################################
//############################################################################################################
//###################################### TEMPERATURE READINGS FUNCTIONS ######################################
double System::TempReading()
{
Temp_Reading_V = analogRead(Pyrometer_IN); //Temperature read by pyrometer
Temp_Reading_C = map(Temp_Reading_V, 205, 1023, 600, 2300); //Voltage to [ºC] conversion. Pyrometer Range = 600 to 2300 [ºC]
return Temp_Reading_C;
}
//############################################# LASER FUNCTIONS #############################################
void System::Laser_InitCOM()
{
if (InitCOM == false)
{
if (Serial1.available())
{
char laser_DMOD[32] = "EMOD";
Serial1.write(laser_DMOD); // Enable Modulation
Serial1.write('\r');
Serial1.write('\n');
}
if (Serial1.available())
{
char laser_DEC[32] = "DEC";
Serial1.write(laser_DEC); // Disable External Control
Serial1.write('\r');
Serial1.write('\n');
}
if (Serial1.available())
{
char laser_ELE[32] = "DLE";
Serial1.write(laser_ELE); // Disable Hardware Emission Control
Serial1.write('\r');
Serial1.write('\n');
}
if (Serial1.available())
{
char laser_EMON[32] = "EMON";
Serial1.write(laser_EMON); // Emission ON
Serial1.write('\r');
Serial1.write('\n');
}
InitCOM = true;
}
}
void System::Laser_Output(double input)
{
duration = pulseIn(LaserStart_IN, HIGH, 1100); //How long is laserStart_pin HIGH (HIGH = laser emission OFF)
if (duration <= 1000 && duration != 0) //Laser ON
{
if (Serial1.available())
{
char laser_SDC[32] = "SDC "; // Set Diode Current.
char laser_PID_input[32];
itoa(input, laser_PID_input, 10);
Serial1.write(laser_SDC);
Serial1.write(laser_PID_input); //PID_value = Diode Current (10-100% of Max Laser Power)
Serial1.write('\r');
Serial1.write('\n');
//Debug Serial Communication:
// UIsys.debugSDC(laser_SDC, laser_PID_input);
}
}
if (duration == 0 || duration > 1000) //Laser OFF
{
if (Serial1.available())
{
char laser_SDC0[32] = "SDC 0"; // Set Diode Current to 0% (OFF).
Serial1.write(laser_SDC0);
Serial1.write('\r');
Serial1.write('\n');
//Debug Serial Communication:
// char laser_SDC000[32] = "00";
// UIsys.debugSDC(laser_SDC0, laser_SDC000);
}
}
}
void System::Laser_Output_testing()
{
duration = pulseIn(LaserStart_IN, HIGH, 1100); //How long is laserStart_pin HIGH (HIGH = laser emission OFF)
if (duration <= 1000 && duration != 0) //Laser ON
{
if (Serial1.available())
{
char laser_ABN[32] = "ABN";
Serial1.write(laser_ABN); // Guide laser ON
Serial1.write('\r');
Serial1.write('\n');
}
}
if (duration == 0 || duration > 1000) //Laser OFF
{
if (Serial1.available())
{
char laser_ABF[32] = "ABF";
Serial1.write(laser_ABF); // Guide laser OFF
Serial1.write('\r');
Serial1.write('\n');
}
}
}
//Laser Testing
void System::laser_testing() //Laser comunication testing code (SAFE)
{
if (Serial1.available())
{
char laser_ABN[32] = "ABN";
Serial1.write(laser_ABN); // Guide laser ON
Serial1.write('\r');
Serial1.write('\n');
}
delay(1000);
if (Serial1.available())
{
char laser_ABF[32] = "ABF";
Serial1.write(laser_ABF); // Guide laser OFF
Serial1.write('\r');
Serial1.write('\n');
}
delay(1000);
}
//############################################# POWDER FEEDER FUNCTIONS #############################################
void System::PF_CompRPM()
{
//rpm_perc = UIsys.MFRTarget; //Percentagem de RPM em função do Mass Flow Rate
rpm_perc = 20; //testing
rpm_1 = map(rpm_perc, 0, 100, 0, 255);
rpm_2 = map(rpm_perc, 0, 100, 0, 255);
}
void System::PF_Output()
{
if (UIsys.D1start == true) //Disk 1 ON
{
analogWrite(D1_rpm_OUT, rpm_1);
}
if (UIsys.D2start == true) //Disk 2 ON
{
analogWrite(D2_rpm_OUT, rpm_2);
}
if (UIsys.D1start == false) //Disk 1 OFF
{
analogWrite(D1_rpm_OUT, 0);
}
if (UIsys.D2start == false) //Disk 2 OFF
{
analogWrite(D2_rpm_OUT, 0);
}
}
void System::PF_PurgeOutput()
{
if (UIsys.D1start == true) //Disk 1 ON
{
analogWrite(D1_rpm_OUT, rpm_1);
}
if (UIsys.D2start == true) //Disk 2 ON
{
analogWrite(D2_rpm_OUT, rpm_2);
}
if (UIsys.D1start == false) //Disk 1 OFF
{
analogWrite(D1_rpm_OUT, 0);
}
if (UIsys.D2start == false) //Disk 2 OFF
{
analogWrite(D2_rpm_OUT, 0);
}
}
system.h
#ifndef _system_
#define _system_
#include <Arduino.h>
#include <LiquidCrystal.h>
#include <UserInterface.h>
class System
{
private:
#define baudRate_1 57600
public:
//Pins:
const int Pyrometer_IN = A12; //Pyrometer IN
const int LaserStart_IN = 35; //Communication from RAMPS GCode (START/STOP Processing/extruding)
const int Start_pin = 50; //Communication from RAMPS (deposition started = HIGH; depsition STOPED/ENDED == LOW)
//Powder Feeder Pins:
const int D1_rpm_OUT = 46; //Output Disk 1 Rotation
const int D2_rpm_OUT = 44; //Output Disk 2 Rotation
//################################## SETUP ####################################
//###############################################################################
void Init_Pyrometer(); //Initialize Pyrometer Readings Pin
void Init_LaserStart(); //Initialize RAMPS-Laser Communication Pin
void Init_PF(); //Initialize Powder Feeder Output Pins
//################################## LOOP #####################################
//###############################################################################
//########################## TEMPERATURE READINGS #############################
//pyrometer functions (check "system.cpp"):
double TempReading();
//temperature variables/constants:
int Temp_Reading_V = 0; //temperature read by Pyrometer in [Volts]
double Temp_Reading_C = 0; //temperature read by Pyrometer in [ºC]
//################################ LASER ####################################
//Initialize Laser Serial Communication
void Laser_InitCOM(); //Laser Initial Serial Communication (RS232). To run once.
boolean InitCOM = false; //Initial COM Flag
//laser functions (check "system.cpp"):
void Laser_Output(double input); //Laser Output Instructions
void Laser_Output_testing();
int duration = 0;
//################################ POWDER FEEDER ############################
int rpm_1;
int rpm_2;
int rpm_perc;
void PF_CompRPM(); //Compute Powder Feeder RPM%
void PF_Output(); //Output RPM% to Powder Feeder
void PF_PurgeOutput(); //Used in "UserInterface.cpp"
int PurgeDuration = 1500;
////################################## TESTING ################################
//###############################################################################
void laser_testing(); //SAFE code to test laser SERIAL COMS
};
#endif