Hi, complete newbie here. Sorry for any mistakes/missing information, please update me and I will include it. I don't really remember/know much about PID usage either, sorry about that.
Currently, I amm referencing the filament extrusion machine code from Electronoobs at: Electronoobs Video.
If I missed out on providing any basic details, perhaps some of these details can be found here on his blog at:
Electronoobs Blog
I have assembled the PCB along with corresponding hardware and am currently using the hardware as follows:
Arduino Nano
Nema 17 Motor
12V 40W heating element and thermistor
LCD display
12V 5A power supply
Just one single push button, Button 1 that starts/stops the motor
I do NOT have the potentiometer soldered on top of the Arduino, I do not trust my soldering skills for this task.
I am facing two problems:
-
The motor appears to be rotating very slowly, supposedly due to the lines of code governing the LCD behavior. If I use a 250ms delay, then it takes 4 steps per second, once every 0.25s. Currently, I am using a 100ms delay at "800 rpm", but it is still terribly slow. Is my understanding even correct here?
-
The temperature set point for the heating element and thermistor pair does not appear to work. I set the setpoint to 220C, it heated up to 240C and showed no signs of stopping. I have no idea what is causing this. Is it simply unsuitable PID constants?
I would like to:
- set the motor to run at a specific speed which I can have greater control over
- set the heating element to reach towards and maintain temperature at the point I set.
Please, any insight or guidance at all would be very valuable. Please advise, and thank you very much.
The code I am using is pasted as follows:
//LCD config
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27,16,2); //sometimes the adress is not 0x3f. Change to 0x27 if it dosn't work.
//Thermistor needed libraries
#include <thermistor.h> //Download it here: https://electronoobs.com/eng_arduino_thermistor.php
thermistor therm1(A0,0); //Connect thermistor on A0, 0 represents TEMP_SENSOR_0 ( configuration.h for more)
//I/O
int PWM_pin = 5; //Pin for PWM signal to the MOSFET driver (the BJT npn with pullup)
int speed_pot = A1;
int but1 = 7;
int EN = 2;
int STEP = 3;
int DIR = 4;
int LED = 13;
//Variables
float set_temperature = 210; //Default temperature setpoint. Leave it 0 and control it with rotary encoder
float temperature_read = 0.0;
float PID_error = 0;
float previous_error = 0;
float elapsedTime, Time, timePrev;
float PID_value = 0;
int button_pressed = 0;
int menu_activated=0;
float last_set_temperature = 0;
int max_PWM = 255;
//Stepper Variables
int max_speed = 1000;
int main_speed = 0;
bool but1_state = true;
bool activate_stepper = false;
int rotating_speed = 0;
#include <AccelStepper.h>
// Define a stepper and the pins it will use
AccelStepper stepper1(1, STEP, DIR); // (Type of driver: with 2 pins, STEP, DIR)
//PID constants
//////////////////////////////////////////////////////////
int kp = 90; int ki = 30; int kd = 80;
//////////////////////////////////////////////////////////
int PID_p = 0; int PID_i = 0; int PID_d = 0;
float last_kp = 0;
float last_ki = 0;
float last_kd = 0;
int PID_values_fixed =0;
void setup() {
pinMode(EN, OUTPUT);
digitalWrite(EN, HIGH); //Stepper driver is disbled
stepper1.setMaxSpeed(max_speed);
pinMode(but1, INPUT_PULLUP);
pinMode(speed_pot, INPUT);
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
pinMode(PWM_pin,OUTPUT);
TCCR0B = TCCR0B & B11111000 | B00000010; // D6 adn D6 PWM frequency of 7812.50 Hz
Time = millis();
TCCR1A = 0; //Reset entire TCCR1A register
TCCR1B = 0; //Reset entire TCCR1B register
TCCR1A |= B00000010; // /8
TCNT1 = 0; //Reset Timer 1 value to 0
lcd.init();
lcd.backlight();
}
void loop() {
if(!digitalRead(but1) && but1_state){
but1_state = false;
activate_stepper = !activate_stepper;
delay(10);
}
else if(digitalRead(but1) && !but1_state){
but1_state = true;
}
if(activate_stepper){
digitalWrite(LED, HIGH);
digitalWrite(EN, LOW); //We activate stepper driver
rotating_speed = 800;
stepper1.setSpeed(800);
stepper1.runSpeed();
}
else
{
digitalWrite(EN, HIGH); //We deactivate stepper driver
digitalWrite(LED, LOW);
stepper1.setSpeed(0);
stepper1.runSpeed();
}
// First we read the real value of temperature
temperature_read = therm1.analog2temp(); // read temperature
//Next we calculate the error between the setpoint and the real value
PID_error = set_temperature - temperature_read + 6;
//Calculate the P value
PID_p = 0.01*kp * PID_error;
//Calculate the I value in a range on +-6
PID_i = 0.01*PID_i + (ki * PID_error);
//For derivative we need real time to calculate speed change rate
timePrev = Time; // the previous time is stored before the actual time read
Time = millis(); // actual time read
elapsedTime = (Time - timePrev) / 1000;
//Now we can calculate the D calue
PID_d = 0.01*kd*((PID_error - previous_error)/elapsedTime);
//Final total PID value is the sum of P + I + D
PID_value = PID_p + PID_i + PID_d;
//We define PWM range between 0 and 255
if(PID_value < 0){
PID_value = 0;
}
if(PID_value > max_PWM){
PID_value = max_PWM;
}
//Now we can write the PWM signal to the mosfet on digital pin D5
analogWrite(PWM_pin,PID_value);
previous_error = PID_error; //Remember to store the previous error for next loop.
delay(100); //Refresh rate + delay of LCD print
lcd.clear();
lcd.setCursor(0,0);
lcd.print("T: ");
lcd.print(temperature_read,1);
lcd.print(" S: ");
lcd.print(rotating_speed);
lcd.setCursor(0,1);
lcd.print("PID: ");
lcd.print(PID_value);
}//Void loop end
ISR(TIMER1_COMPA_vect){
TCNT1 = 0; //First, set the timer back to 0 so it resets for next interrupt
stepper1.runSpeed();
}