AC motor control loop feedback

Hi guys,

Im having trouble to control the firing triac pulses when I use a rotary sensor on my project. The question is when I enable 2 interrupts (one for sincronizing the zero crossing and fire the triac and another to read the rotary sensor attached to the motor) the interrupt of the sensor interfere on the zero crossing where I fire the triac. Is there anyway you could sugest me to do it?

How large are your ISR (interrupt service routines)? Please post your code.
HowToPostCode

Hi Outsider,

That's the code. I need to detect the zero crossing, then fire the triac to set a certain voltage at the motor. Also I have to read the rotary sensor and calculate the rpm (that i didn't do yet) to maintain the same rotation to the motor.

PS. Don't mind about involt functions, its just to create the interface.

enum PinAssignments {
  encoderPinA = 18,   // right (labeled DT on our decoder, yellow wire)
  encoderPinB = 19   // left (labeled CLK on our decoder, green wire)
};

int rpm = 0;
int    involtPin[14] = {}; //equals involt.pin.P in app
String involtString[2] ={}; //equals involt.pin.S in app
volatile int cont = 0;;  //contador ****
int disparo = 3; //disparo
int on = 0;
int pulso_count=0;
volatile  int encoderPos = 0;  // a counter for the dial
int lastReportedPos = 1;   // change management
static boolean rotating=false;      // debounce management
// interrupt service routine vars
boolean A_set = false;              
boolean B_set = false;

char involt[16];

/*
  String for responding to function received from app.
*/
String fname;

void setup() {
 //Connection speed must be same as app.
 pinMode(encoderPinA, INPUT_PULLUP); // new method of enabling pullups
 //pinMode(encoderPinB, INPUT_PULLUP); 
 pinMode(disparo, OUTPUT);
 attachInterrupt(0,zero_crossing,FALLING);//Interrupção ZC pino 2
  attachInterrupt(5, doEncoderA, CHANGE); //Interrupção Sensor Pino 18
// attachInterrupt(5, doEncoderB, CHANGE);
 Serial.begin(57600);
}

void loop() {

involtReceive();

//doEncoderA();

rotating = true;  // reset the debouncer
  if (encoderPos == -1 ){
    encoderPos = 0;
    lastReportedPos = 1;
  }
  else
  {if (lastReportedPos != encoderPos) {
    lastReportedPos = encoderPos;
  }}

if (involtPin[5] == 255){
on=1; //Liga

}
if (involtPin[5] == 0){
on=0; //Desliga
cont=0;
}


rpm = (encoderPos*60)/25;
involtSend(0, rpm);
involtSend(1, pulso_count);
  fname = "";
}

/*
  INVOLT FUNCTIONS
  ------------------------------------------------------

  involtReceive
  ------------------------------------------------------ 
  read the data from app and parse the values received 
  into proper array. The read until is used due to
  issues with missing chars when reading direct strings.
  
  involtSend, involtSendString
  ------------------------------------------------------
  send int or string to app. Multiple prints are to
  reduce the sketch size (compared to sprintf()).

  involtSendFunction
  ------------------------------------------------------
  send function name to trigger it in app.
*/

void involtReceive(){
  if(Serial.available()>0) {
    Serial.readBytesUntil('\n',involt,sizeof(involt));
    int pin;
    if (involt[0] == 'P'){
      int value;
      sscanf(involt, "P%dV%d", &pin, &value);
      involtPin[pin] = value;
    }
    else if (involt[0] == 'S'){
      char value[sizeof(involt)];
      sscanf(involt, "S%dV%s", &pin, &value);
      involtString[pin] = value;
    }
    else if (involt[0] == 'F'){
      char value[sizeof(involt)];
      sscanf(involt, "F%s", &value);
      fname = value;
    };
    memset(involt,0,sizeof(involt));
  };
};

void involtSend(int pinNumber, int sendValue){
  Serial.print('A'); 
  Serial.print(pinNumber); 
  Serial.print('V'); 
  Serial.print(sendValue); 
  Serial.println('E');
  Serial.flush();
};

void involtSendString(int pinNumber, String sendString){
  Serial.print('A'); 
  Serial.print(pinNumber); 
  Serial.print('V'); 
  Serial.print(sendString); 
  Serial.println('E'); 
  Serial.flush();

};

void involtSendFunction(String functionName){
  Serial.print('F'); 
  Serial.print(functionName); 
  Serial.println('E'); 
  Serial.flush();
};


void zero_crossing() {
  pulso_count++;
  if(on>0){
  delayMicroseconds(4500);
  digitalWrite(disparo,HIGH);
  delayMicroseconds(333);
  digitalWrite(disparo,LOW);
  delayMicroseconds(1); 
  } 
}

  
//Interrupt on A changing state
void doEncoderA(){
  if ( rotating ) delay (1);  // wait a little until the bouncing is done
  // Test transition, did things really change? 
  if( digitalRead(encoderPinA) != A_set ) {  // debounce once more
    A_set = !A_set;
   // adjust counter + if A leads B
    if ( A_set ) 
      encoderPos += 1;
     rotating = false;  // no more debouncing until loop() hits again
  }
  }

You have substantial delays in your zero-crossing ISR, blocking anything else.

You might try adding

void zero_crossing() {
  pulso_count++;
  if(on>0){
  interrupts() ; // re-enable other interrupts
  delayMicroseconds(4500);
  digitalWrite(disparo,HIGH);
  delayMicroseconds(333);
  digitalWrite(disparo,LOW);
  delayMicroseconds(1);  // this line isn't doing anything useful!
  }
}