Universal motor pid controll

hello ppl
first sorry for bad english :frowning:

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 .

    #define triac_control 5 // Triac control - pin
//RPM control    
    #define sensorPin A0 // potentiometer or MACH3 - pin
    #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
    #define  hallsensor 3 //- pin
    //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   ");    
  analogValue =0;
  Input = rpm;
  Setpoint = analogValue;

  //turn the PID on
  myPID.SetOutputLimits(1000, 9999);  


void loop() 
//Power switch and indicator = ON/OFF  
  if (!digitalRead(powerOn)) 
         digitalWrite(powerIndicator, 1);        
         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);    
  analogValue = analogRead(sensorPin);
  Input = rpm; 
  Setpoint    = analogValue*kDev;  
 //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()
   //Each rotation, this interrupt function is run twice

please help
and agin sorry for my english

Vspindle_V6.pde (4.08 KB)

I've looked over your code quite a few times and I can't find any problems.

i know. me neither. that is main reason i asking for help here :(

What do you mean by spikes on the output? The motor will create spikes - but maybe you mean the arduino output.

Have you determined whether you have a firmware or hardware problem?

it is frimware problem.
im getting spikes on triac output becouse triac miss on low speed

To understand the nature of your problem it would be helpful to know how it is suppose to work. I don't know what you have tried before. Secondly, I don't have a schematic of your circuit.

I am assuming that you are starting from scratch. Have you started your design with a potentiometer connected to Arduino for a manual control of the motor speed? This method would eliminate the basic circuit problems. If you can get a low speed control this way then you have confirmed both hardware and the simple Arduino test software.

Slow speed control will need a closed loop circuit for good speed control.

ofc i tested first with simple pot. controll, hardware is ok. problem was lcd,print, and lcdsetcursor. lcd generating to much delay in code. i tried serial print also but nothing. it is working fine now, but i cant get speed displayed :(