AC motor speed set

Hi everyone
look at the picture

I have a problem with controlling MOC3021 when i using ATMEGA16
please look at the source code and tell me what i do wrong

                         +---\/---+
         LED (D 0) PB0  1|        |40  PA0 (A 0 / D24)
             (D 1) PB1  2|        |39  PA1 (A 1 / D25)
        INT2 (D 2) PB2  3|        |38  PA2 (A 2 / D26)
         PWM (D 3) PB3  4|        |37  PA3 (A 3 / D27)
    PWM* /SS (D 4) PB4  5|        |36  PA4 (A 4 / D28)
        MOSI (D 5) PB5  6|        |35  PA5 (A 5 / D29)
 PWM** /MISO (D 6) PB6  7|        |34  PA6 (A 6 / D30)
  PWM** /SCK (D 7) PB7  8|        |33  PA7 (A 7 / D31)
                   RST  9|        |32  AREF
                   VCC 10|        |31  GND
                   GND 11|        |30  AVCC
                 XTAL2 12|        |29  PC7 (D 23)
                 XTAL1 13|        |28  PC6 (D 22)
        RX0 (D 8)  PD0 14|        |27  PC5 (D 21) TDI
        TX0 (D 9)  PD1 15|        |26  PC4 (D 20) TDO
 (RX1)/INT0 (D 10) PD2 16|        |25  PC3 (D 19) TMS
 (TX1)/INT1 (D 11) PD3 17|        |24  PC2 (D 18) TCK
        PWM (D 12) PD4 18|        |23  PC1 (D 17) SDA
        PWM (D 13) PD5 19|        |22  PC0 (D 16) SCL
       PWM* (D 14) PD6 20|        |21  PD7 (D 15) PWM
                         +--------+

#include <avr/interrupt.h>
#include <avr/io.h>						 

int diMin = 7;
int diMax = 130;
volatile int dimming = 130;

int AC_LOAD = 13;
volatile unsigned long time;
unsigned long tims;
						 
ISR (INT2_vect) //External interrupt RPM_COUNT
{
  rpm_count++;
}

ISR (INT0_vect) //External interrupt RPM_COUNT
{
 time = micros();
}

void setup() {
  pinMode(AC_LOAD, OUTPUT);
  digitalWrite(AC_LOAD, LOW);
  pinMode(14, OUTPUT);
  digitalWrite(14, LOW);
  GICR = 1 << INT0;
  GICR = 1 << INT2;
  MCUCR = 1 << ISC01 | 1 << ISC00;
  sei();
}

void loop() {
  int val = 500; //for testing minimal RPM
  dimming = map(val, 500, 4000, diMax, diMin);
  dimming = constrain(dimming, diMin, diMax) ; 
  int dimtime = (75 * dimming);
  tims = micros();                
  if (tims >= (time + dimtime)) { 
    digitalWrite(AC_LOAD, HIGH);   
    delayMicroseconds(10);   //(for 60Hz = 8.33)
    digitalWrite(AC_LOAD, LOW);  
  }
  }

after switching on, the AC Motor runs runs at maximum speed despite the value of "int val = 500;"
what is wrong?

for programming ATMEGA16 i’am using Arduino UNO + MightyCore libraries

Looks like you have dimin & dimax reversed here:

  dimming = map(val, 500, 4000, diMax, diMin);

Why is the MOC LED connected to 2 digital outputs, instead of 1 digital output and either ground or VCC?

aarg: Why is the MOC LED connected to 2 digital outputs, instead of 1 digital output and either ground or VCC?

I don't know why the board is so implemented because I found him in this condition.

Have you tried hard coding different values in dimtime?

aarg: Have you tried hard coding different values in dimtime?

Yes - i tried all values. Say me please why this code working on atmega328 and not working on Atmega16?? may be i doing something wrong??

This is a full code
but i have a problem with run_motor [/ b] procedure
with every different values for dimtime
motor run with maximum speed.
```
*/

MIGHTYCORE STANDARD PINOUT
        ATmega8535, ATmega16, ATmega32, ATmega164,
              ATmega324, ATmega644, ATmega1284

±–/—+
        LED (D 0) PB0  1|        |40  PA0 (A 0 / D24)
            (D 1) PB1  2|        |39  PA1 (A 1 / D25)
        INT2 (D 2) PB2  3|        |38  PA2 (A 2 / D26)
        PWM (D 3) PB3  4|        |37  PA3 (A 3 / D27)
    PWM* /SS (D 4) PB4  5|        |36  PA4 (A 4 / D28)
        MOSI (D 5) PB5  6|        |35  PA5 (A 5 / D29)
  PWM** /MISO (D 6) PB6  7|        |34  PA6 (A 6 / D30)
  PWM** /SCK (D 7) PB7  8|        |33  PA7 (A 7 / D31)
                  RST  9|        |32  AREF
                  VCC 10|        |31  GND
                  GND 11|        |30  AVCC
                XTAL2 12|        |29  PC7 (D 23)
                XTAL1 13|        |28  PC6 (D 22)
        RX0 (D 8)  PD0 14|        |27  PC5 (D 21) TDI
        TX0 (D 9)  PD1 15|        |26  PC4 (D 20) TDO
  (RX1)/INT0 (D 10) PD2 16|        |25  PC3 (D 19) TMS
  (TX1)/INT1 (D 11) PD3 17|        |24  PC2 (D 18) TCK
        PWM (D 12) PD4 18|        |23  PC1 (D 17) SDA
        PWM (D 13) PD5 19|        |22  PC0 (D 16) SCL
      PWM* (D 14) PD6 20|        |21  PD7 (D 15) PWM
                        ±-------+
      PWM: ATmega8535/16/32/164/324/644/1284
      PWM*: ATmega164/324/644/1284
      PWM**: ATmega1284
      PCINT ONLY ON ATmega164/324/644/1284

PCINT15-8: D7-0    : bit 1
  PCINT31-24: D15-8  : bit 3
  PCINT23-16: D23-16 : bit 2
  PCINT7-0: D31-24  : bit 0
*/
#include <avr/interrupt.h>

const int BUZZER = 16; //Buzzer
const int numeral[11] = {
  //ABCDEFG /dp
  B11111100, // 0
  B01100000, // 1
  B11011010, // 2
  B11110010, // 3
  B01100110, // 4
  B10110110, // 5
  B10111110, // 6
  B11100000, // 7
  B11111110, // 8
  B11110110, // 9
  B00000001  //DP
};

// DP, G, F, E, D, C, B, A
const int segmentPins = {31, 30, 29, 28, 27, 26, 25, 24 };
const int nbrDigits1 = 2; //number of digits of the LED indicator
const int nbrDigits2 = 3;
//разряды 0 1 2 3 4 5
const int digitPins1[nbrDigits1] = { 17, 23 };
const int digitPins2[nbrDigits2] = { 21, 18, 22 };
const int btn_up_1 = 5;  //UP button of the timer
const int btn_down_1 = 4; //DOWN button of the timer
const int btn_up_2 = 1; //UP button of the RPM Set
const int btn_down_2 = 6; //DOWN button of the RPM Set
#define btn_start 7  //START Btn
#define btn_stop 3  //STOP Btn
#define start_LED 19 //Green LED
#define stop_LED 20  //RED Led

int AC_LOAD = 13;          //Triac PIN
int RPM = 0;
volatile int rpm_count;
volatile unsigned long time;
unsigned long tims;
int encoder_pin = 0;

int diMin = 7;
int diMax = 130;
volatile int dimming = 130;

//TIMER WITHOUT DELAY
unsigned long previousMillis = 0;
const long interval = 1000;      //1 sec
int ledState = 0;

boolean btn_stop_status = 0;
int timer_val = 0; 
int second_val = 0;
int start_count = 0;
int prm_val = 5;

//Статусы кнопок
int button_old_up1 = 1;
int button_old_down1 = 1;
int button_old_up2 = 1;
int button_old_down2 = 1;
int button_old_start = 1;
int button_old_stop = 1;

ISR (INT2_vect)
{
  rpm_count++;
}

ISR (INT0_vect)
{
  time = micros();
}

void zero_crosss_int()  {
  // time = micros();
}

void setup() {
  for (int i = 0; i < 8; i++) {
    pinMode(segmentPins[i], OUTPUT);
  }
  for (int i = 0; i < nbrDigits1; i++) {
    pinMode(digitPins1[i], OUTPUT);
  }
  for (int i = 0; i < nbrDigits2; i++) {
    pinMode(digitPins2[i], OUTPUT);
  }
  pinMode(btn_up_1, INPUT_PULLUP);
  pinMode(AC_LOAD, OUTPUT);
  digitalWrite(AC_LOAD, LOW);
  pinMode(btn_down_1, INPUT_PULLUP);
  pinMode(btn_up_2, INPUT_PULLUP);
  pinMode(btn_down_2, INPUT_PULLUP);
  pinMode(btn_start, INPUT_PULLUP);
  pinMode(btn_stop, INPUT_PULLUP);
  pinMode(start_LED, OUTPUT);
  pinMode(stop_LED, OUTPUT);
  pinMode(encoder_pin, INPUT);
  ////////////INTERRUPT
  GICR = 1 << INT0;
  GICR = 1 << INT2;
  MCUCR = 1 << ISC01 | 1 << ISC00;
  sei();
  ////////////////////////
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, HIGH);
  delay(10);
  digitalWrite(BUZZER, LOW);
}

void loop() {
  if (btn_stop_status == 0) {                                   
    button_press();
  } //btn status 0 end
  else
  {
    if (timer_val != 0) {                   
      run_motor();
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
        ////////////RPM CALCULATE
        RPM = rpm_count;
        RPM = ((RPM / 6) * 60) / 100;
        rpm_count = 0;
        /////////////////////////
        if (ledState == LOW) {
          ledState = HIGH;
        } else {
          ledState = LOW;
        }
        second_val = second_val - 1;
        if (second_val == 0) {
          stop_procedure();
        }
        start_count++;
        digitalWrite(start_LED, ledState);
        if (start_count == 60) {
          timer_val = timer_val - 1;
          start_count = 0;
        }
      }
    }
  }
  if ((digitalRead(btn_stop) == LOW) && (button_old_stop == 1))
  {
    stop_procedure();
  }
  button_old_stop = digitalRead(btn_stop);
  showNumber1(timer_val);

if (btn_stop_status == 1) {
    showNumber2(RPM);
  } else {
    showNumber2(prm_val);
  }
}

void run_motor() {
  int dimtime = 10000;//(75 * dimming);
  tims = micros();                         
  if (tims >= (time + dimtime)) {   
    digitalWrite(AC_LOAD, HIGH); 
    delayMicroseconds(10);       
    digitalWrite(AC_LOAD, LOW);   
  }
}

void button_press() {
  if ((digitalRead(btn_up_1) == LOW) && (button_old_up1 == 1)) 
  {
    if (timer_val == 99) timer_val = 0;               
    else timer_val = timer_val + 1;                   
    delay(10);
  }
  if ((digitalRead(btn_down_1) == LOW) && (button_old_down1 == 1))
  {
    if (timer_val != 0) {
      timer_val = timer_val - 1;
    }
    delay(10);
  }
  if ((digitalRead(btn_up_2) == LOW) && (button_old_up2 == 1))
  {
    if (prm_val == 40) prm_val = 5;
    else prm_val = prm_val + 1;
    delay(10);
  }
  if ((digitalRead(btn_down_2) == LOW) && (button_old_down2 == 1))
  {
    if (prm_val != 5) {
      prm_val = prm_val - 1;
    }
    delay(10);
  }
  if ((digitalRead(btn_start) == LOW) && (button_old_start == 1))
  {
    if (timer_val != 0) {
      btn_stop_status =  1;                 
      if (timer_val != 0) {
        second_val = timer_val * 60;
        digitalWrite(start_LED, HIGH);
        digitalWrite(segmentPins[0], HIGH);
      }
    }
  }
  button_old_start = digitalRead(btn_start);
  button_old_up1 = digitalRead(btn_up_1);
  button_old_down1 = digitalRead(btn_down_1);
  button_old_up2 = digitalRead(btn_up_2);
  button_old_down2 = digitalRead(btn_down_2);
}

void stop_procedure() {
  digitalWrite(stop_LED, HIGH);
  digitalWrite(segmentPins[0], HIGH);
  delay(500);
  digitalWrite(BUZZER, HIGH);
  delay(100);
  digitalWrite(BUZZER, LOW);
  digitalWrite(start_LED, LOW);
  digitalWrite(stop_LED, LOW);
  digitalWrite(segmentPins[0], LOW);
  btn_stop_status =  0;
  second_val = 0;
  start_count = 0;
  timer_val = 0;
}

void showNumber1( int number)
{
  if (number == 0) {
    showDigit1( 0, nbrDigits1 - 1) ;
  } else {
    for ( int digit = nbrDigits1 - 1; digit >= 0; digit–) {
      if (number > 0) {
        showDigit1( number % 10, digit) ;
        number = number / 10;
      }
    }
  }
}

void showNumber2( int number)
{
  if (number == 0) {
    showDigit2( 0, nbrDigits2 - 1);
  } else {
    for ( int digit = nbrDigits2 - 1; digit >= 0; digit–) {
      if (number > 0) {
        showDigit2( number % 10, digit) ;
        number = number / 10;
      }
    }
  }
}

void showDigit1( int number, int digit)
{
  digitalWrite( digitPins1[digit], HIGH );
  for (int segment = 1; segment < 8; segment++) {
    boolean isBitSet = bitRead(numeral[number], segment);
    digitalWrite( segmentPins[segment], isBitSet);
  }
  delay(5);
  digitalWrite( digitPins1[digit], LOW );
}

void showDigit2( int number, int digit)
{
  analogWrite( digitPins2[digit], 150 );
  for (int segment = 1; segment < 8; segment++) {
    boolean isBitSet = bitRead(numeral[number], segment);
    digitalWrite( segmentPins[segment], isBitSet);
  }
  delay(4);
  digitalWrite( digitPins2[digit], LOW );
}**
```

did you see answer #1?

Juraj: did you see answer #1?

Dear i see 1st post - because dimming working differently. When value is 7 motor should be run in max speed and when 130 then with low speed. You see only names of value Min, Max. It does not matter.

My problem with dimming time and for testing i am changed the code to int dimtime = 10000;

relay has contact on HIGH or LOW? I think LOW

at 50Hz zero crossing is every 10000 microsecs. or? so turning power off for 10 micros when power is 0, doesn't slow the motor down.

Juraj: relay has contact on HIGH or LOW? I think LOW

at 50Hz zero crossing is every 10000 microsecs. or? so turning power off for 10 micros when power is 0, doesn't slow the motor down.

Yes, I think the OP didn't do the arithmetic. 10000 is a half cycle so a more appropriate test value would be 5000.

Dear's i thinking interrupts not working correctly because when i removing this section of code

ISR (INT0_vect)
{
  time = micros();
}

Procedure run_motor continues to work as before and motor run with maximum speed

void run_motor() {
  int dimtime = 10000;//(75 * dimming);
  tims = micros();                           
  if (tims >= (time + dimtime)) {     
    digitalWrite(AC_LOAD, HIGH); 
    delayMicroseconds(10);         
    digitalWrite(AC_LOAD, LOW);   
  }
}

I connected Oscilloscope to output of circuit and do not see a dimming i see only a sinusoid. what is wrong in my code??

read from reply #9

Juraj: read from reply #9

I read all messages what you advised me and i am tried all of things. for testing i clean section of code where diMax diMin - for dimming first of all i want to stop motor. Now I'm looking for with what parameters the motor will stop. After then i can control the motor.

I asked in which pin state is the power to motor enabled. It is controlled by pin AC_LOAD. set it to HIGH in setup and the motor will not start

Dear if i set AC_LOAD to HIGH in setup motor will run everytime in maximum speed because pin number 20 i connected to groung for controlling TRIAC from AC_LOAD pin (pin 19 of ATMEGA16)

To stop the engine in the procedure, I must find the time of zero crossing and if it coincides with the running time, then the engine will not run. in fact for 50Hz it is a 10 microsecond - but with 10 microseconds it is not working - i thinking the speed of the microcontroller for my code is not enough and the value is late. are this is real??

50 Hz is 50 oscillations per second. every oscillation has two zero crossings. 100 zero crossings per second. second has 1 milion microseconds. 1000000/100=10000 micros between zero crossings. 10000 is after the next zero crossing and the value is recalculated by then again

You absolutely right but problem in another after turning off interrupts INT2 - motor started work correctly.

Now how to read RPM's without interrupts? because after turning on second interrupts microseconds procedure not working correctly.