hello ppl
first sorry for bad english
i need some little help.
im making pid motor controller for 1800W universal motor.
i have problems with triac missing needed delay and im getting spikes on output
code is simple
im using pid_v1 library
and two interrupts one for rpm reading and on for zero cross.
pid output limits are set as delay for triac
potentiometer is for speed control
i cant figure out whare is problem.
pid works ok( tested in front end)
but im still getting spikes, because triac is getting unwanted delay someware and missing.
i dont want to put the triac fiering part in interrupt rutine because i want it to be short as possible.
if i put triac fiering code in interrupt rutine im spending to much time in routine and have no time to calculate pid and do rest of the code.
dont know if rpm interrupt is messing thing up. but i did some crude calculation and in max speed im getting about 7 microseconds of delay more, that is to low to interfire much .
// TRIAC
#define triac_control 5 // Triac control - pin
//RPM control
#define sensorPin A0 // potentiometer or MACH3 - pin
//Power
#define powerOn 4 // Power switch - pin
#define powerIndicator 6 // indicator GREEN LED -pin
//Zero Detect
#define zero_detect 2 //Zero detect - pin
// when using values in the main routine and IRQ routine must be volatile value
volatile byte zero_bit = LOW; // declare IRQ flag
// HIGH = 1, LOW = 0
// HALL SENSOR
#define hallsensor 3 //- pin
//LCD
//LiquidCrystal::LiquidCrystal(rs, enable, d0, d1, d2, d3)
#include <Wire.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(13, 11, 7, 8, 9, 10);
// PID
#include <PID_v1.h>
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Define the aggressive and conservative Tuning Parameters
//double consKp=4, consKi=0.2, consKd=1;
//double consKp=0.4, consKi=0.001, consKd=1;
//double consKp=4, consKi=0.2, consKd=1;
//double consKp=1, consKi=0.4, consKd=0.01; //100% work
//double consKp=0.4, consKi=0.001, consKd=1;
double consKp=0.0821, consKi=0.725, consKd=0.028;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
unsigned int analogValue;
float kDev = 38; // rpm to analog - exp: max rpm = 22000 , analogmax = 920 : rpm/analogmax = kDev = 25
volatile byte rpmcount;
unsigned int rpm;
unsigned long timeold;
unsigned long timenow;
void setup()
{
//Triac control setup
pinMode(triac_control, OUTPUT);
digitalWrite(triac_control, 0); // LED off
//Power switch
pinMode(powerIndicator, OUTPUT);
digitalWrite(powerIndicator, 0); // LED off
pinMode(powerOn, INPUT);
digitalWrite(powerOn, 1); // pull up on
//Zero detect
pinMode(zero_detect, INPUT);
// digitalWrite(zero_detect, 1); // pull up on
attachInterrupt(0, zero_fun, RISING); // interrupt 0 digital pin 2 connected ZC circuit
// Hall sensor
pinMode(hallsensor, INPUT);
// digitalWrite(hallsensor, 1); // pull up on
attachInterrupt(1, rpm_fun, RISING); // interrupt 1 digital pin 3 connected hall sensor
rpmcount = 0;
rpm = 0;
timeold = 0;
timenow = 0;
// LCD detect
lcd.begin(16,2); // initialize the lcd
lcd.home (); // go home
lcd.print("Hello, ARDUINO ");
lcd.setCursor ( 0, 1 ); // go to the next line
lcd.print (" vSpindel-2.0 ");
delay(1000);
lcd.clear();
//PID
analogValue =0;
Input = rpm;
Setpoint = analogValue;
//turn the PID on
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(1000, 9999);
}
void loop()
{
//Power switch and indicator = ON/OFF
if (!digitalRead(powerOn))
{
digitalWrite(powerIndicator, 1);
}
else
{
digitalWrite(powerIndicator, 0);
}
//RPM counter and show on LCD
if (rpmcount >= 100)
{
//Update RPM every 20 counts, increase this for better RPM resolution,
//decrease for faster update
timenow =micros();
rpm = 30000000.0/(float)(timenow-timeold)*(float)rpmcount;
rpmcount = 0; //reset
timeold = timenow; //set time
}
lcd.setCursor ( 0, 0 );
lcd.print ("RPM:");
lcd.setCursor ( 5, 0 );
lcd.print (rpm);
//PID
analogValue = analogRead(sensorPin);
Input = rpm;
Setpoint = analogValue*kDev;
myPID.Compute();
//TRIAC delay control
if ((zero_bit == 1) && (digitalRead(powerOn)== 0))
{
if (analogRead(sensorPin) > 200)
{
delayMicroseconds(10000-Output); // set value between 4 and 14
digitalWrite(triac_control, 1); //triac on
delayMicroseconds(10); //triac propogotional delay
digitalWrite(triac_control, 0); //triac off
zero_bit = 0; // clear flag
}
}
}
void zero_fun() // set bit
{
zero_bit = 1;
// if zero detect set bit == 1
}
void rpm_fun()
{
rpmcount++;
//Each rotation, this interrupt function is run twice
}
please help
and agin sorry for my english
Vspindle_V6.pde (4.08 KB)