Помогите с таймерами при прерывании программы

Тема в разделе "Arduino & Shields", создана пользователем gada94, 21 янв 2017.

  1. gada94

    gada94 Нуб

    Код (C++):
    int incomingByte = 0;  // for incoming serial data
    int AC_LOAD = 3;    // Output to Opto Triac pin
    volatile int dimming = 119;
    int dimming2=0;// Dimming level (0-128)  0 = ON, 128 = OFF
      int temp_PIN=0; // Порт датчика температуры
    int vid=0;
    unsigned long time;


    void setup() {
      Serial.begin(9600);
       pinMode(vccPin, OUTPUT); digitalWrite(vccPin, HIGH);
      pinMode(gndPin, OUTPUT); digitalWrite(gndPin, LOW);

        pinMode(AC_LOAD, OUTPUT);      // Set the AC Load as output
      attachInterrupt(0, zero_crosss_int, RISING);  // Choose the zero cross interrupt # from the table above
      }


    void zero_crosss_int()  // function to be fired at the zero crossing to dim the light
    {
      // Firing angle calculation :: 50Hz-> 10ms (1/2 Cycle)
      // (10000us - 10us) / 128 = 75 (Approx)
      int dimtime = (75*dimming);  
      delayMicroseconds(dimtime);    // Off cycle
      digitalWrite(AC_LOAD, HIGH);  // triac firing
      delayMicroseconds(10);        // triac On propogation delay
      digitalWrite(AC_LOAD, LOW);    // triac Off
    }




    void loop() {
    time = millis()/1000;

    while(chas<60){

      dimming++;
      if(dimming>=127)dimming=0;

    delay(1000);
    int chas = (millis()/1000) -time;

      }

    }

    Вот выше пример кода, нужно каждую секунду увеличивать переменную "diming" на 1, тем самым выполнять прерывания программы и выполнять цикл 60 секунд. Если не менять переменную "diming" то таймеры работают нормально и отсчет идет правильно, а вот когда выполняется прерывание то таймеры и задержка вообще не понятно как работают, помогите выполнить Правила отсчет таймера
     
  2. ostrov

    ostrov Гуру

    Вот вас специально где то учат так формулировать вопрос что нифига не понятно что спросить хотели?

    В вашем коде я вижу как в лупе происходит абсолютно бесполезный подсчет какой то переменной которая сбрасывается в ноль каждые 127 минут ни на что не влияя и ничего не вызывая. Что хотели изначально?
     
  3. gada94

    gada94 Нуб

    функция void zero_crosss_int() должно плавно регулировать мощность лампы накаливания 220 ,через симистор, через переменную diming встоновлюем мощность лампы. Єтот код в качестве примера, основное что нужно это правильный отсчет времени при прерывании
     
  4. ostrov

    ostrov Гуру

    Прерывание настроено не на таймер, а на переход пина 2 из состояние LOW в состоянии HIGH. Откуда берется эта команда?

    И еще, в функции zero_crossing вы ШИМ имитируете что ли? Зачем?
     
  5. gada94

    gada94 Нуб

  6. gada94

    gada94 Нуб

    подключено по схеме више, а как лучше регулиривать мощность лампи накаливание?
     
  7. ostrov

    ostrov Гуру

    Что устройство должно делать?
     
  8. gada94

    gada94 Нуб

    Чтобы было лучше понятно скажу так, нужно регулировать температуру лампы 220V. То есть к обычной лампы цепляю термопару и снимаю температуру лампы. С компьютера через Serial Port задаю с какой температурой должна работать лампа и сколько времени она должна работать. Если температура лампы меньше заданной то нужно увеличить мощность лампы, если температура лампы превысила заданную то уменьшить мощность. Регулировка мощности лампы обязательно должно быть плавная, то есть лампа не должна мигать.
     
  9. ostrov

    ostrov Гуру

    Термостат на основе диммера? Причем с ручным управлением.
     
  10. gada94

    gada94 Нуб

    да, все верно, что скажите как лучше ето реализовать?
     
  11. Jedi

    Jedi Гик

    Тема заезжена уже. Это не ШИМ, это ФИМ. Фазо-импульсная модуляция.
    В прерываниях delay() не работает. Используйте micros(). Только учтите, что, если я не ошибаюсь, то шаг micros() что-то около 4мкс.
     
  12. rkit

    rkit Гуру

    Пока выполняется одно прерывание другие прерывания заблокированы. Когда у вас в одном прерывании задержки по 9 мс, то ни на какие millis, delay, и прочее надеяться нельзя.
    По пересечению нуля не ждите, а ставьте другое прерывание, и выходите из этого как можно быстрее.
     
  13. Jedi

    Jedi Гик

    Ну да :) Как-то так. Поймали ноль, взвели таймер на задержку, вывалились. Таймер сработал, дернули симистор, сбросили таймер, вывалились.
     
  14. qwone

    qwone Гик

    Код (C++):
    /*to_gada94.ino
      прерывание -> 2
      на лампу -> 3 ( Lamp_pin)
    */

    //#1 ШИМ
    volatile const byte Lamp_pin = 3;
    volatile bool Lamp ;
    volatile uint32_t past = 0;
    uint32_t Time_0N=5000;// для частоты 50Гц, полуволна 100Гц /Time_0N =0 (0%),10000 (100%)
    void zero_cros() {
      past = micros();
      digitalWrite(Lamp_pin, Lamp = 1);
    }
    void setup() {
      //#1 ШИМ
      pinMode(Lamp_pin, OUTPUT);
      digitalWrite(Lamp_pin, Lamp = 0);
      attachInterrupt(0, zero_cros, RISING);
    }

    void loop() {
      //#1 ШИМ
      if (Lamp && micros() - past >= Time_0N)
        digitalWrite(Lamp_pin, Lamp = 0);
    }
     
  15. ИгорьК

    ИгорьК Гуру

  16. gada94

    gada94 Нуб

    Я и делал по вашему примеру, вот только ваш код мне совсем не понятен, я просто новичок в том всем.
    Вот например где в коде обозначение Нога для подключения детектора перехода и нога управление триаком?
    у вас прописано так:
    // INT1 - PD3. Нога для подключения детектора перехода
    // A1=3. А1 - управление триаком.
    Но они Коментарии обичние....
    Что ето все такое:
    Код (C++):
     // Port C - инициализация. PC1 - нога A1 Arduino
        // Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=Out Bit0=In
        DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (1<<DDC1) | (0<<DDC0);

        // Timer/Counter 1 инициализация
        // Clock source: System Clock
        // Clock value: 16,000 kHz
        // Mode: Normal top=0xFFFF
        // OC1A output: Disconnected
        // OC1B output: Disconnected
        // Noise Canceler: Off
        // Input Capture on Falling Edge
        // Timer Period: 4,1943 s
        // Timer1 Overflow Interrupt: Off
        // Input Capture Interrupt: Off
        // Compare A Match Interrupt: On
        // Compare B Match Interrupt: Off
        TCCR1A=(0<<COM1A1) | (0<<COM1A0) | (0<<COM1B1) | (0<<COM1B0) | (0<<WGM11) | (0<<WGM10);
        TCCR1B=(0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (1<<CS12) | (0<<CS11) | (1<<CS10);
        TCNT1H=0x00;
        TCNT1L=0x00;
        ICR1H=0x00;
        ICR1L=0x00;
        OCR1AH=0x00;
        OCR1AL=0xA0;
        OCR1BH=0x00;
        OCR1BL=0x00;

        // Timer/Counter 1 Interrupt(s) initialization
        TIMSK1=(0<<ICIE1) | (0<<OCIE1B) | (1<<OCIE1A) | (0<<TOIE1);
        // External Interrupt(s) initialization
        // INT0: Off
        // INT1: On
        // INT1 Mode: Rising Edge
        // Interrupt on any change on pins PCINT0-7: Off
        // Interrupt on any change on pins PCINT8-14: Off
        // Interrupt on any change on pins PCINT16-23: Off
        EICRA=(1<<ISC11) | (1<<ISC10) | (0<<ISC01) | (0<<ISC00);
        EIMSK=(1<<INT1) | (0<<INT0);
        EIFR=(1<<INTF1) | (0<<INTF0);
        PCICR=(0<<PCIE2) | (0<<PCIE1) | (0<<PCIE0);
    ?
    Извините просто ране с таким кодом не сталкивался.
     
  17. gada94

    gada94 Нуб


    то есть меняя значение переменной Time_0N меняется мощность лампи? если я правильно понял, тогда не работает. она все время светится.
     
  18. qwone

    qwone Гик

    Ну это понятно. Симистор надо включать не переходе через ноль, а когда Time_0N закончился. Так что надо немного поменять схему или скетч. Я же вашей схемы не вижу.
    Код (C++):
    /*to_gada94.ino
      прерывание -> 2
      на лампу -> 3 ( Lamp_pin)
    */

    //#1 ШИМ
    volatile const byte Lamp_pin = 3;
    volatile bool Lamp ;
    const bool logic = 0; // уровень при котором вкл симистор.
    volatile uint32_t past = 0;
    uint32_t Time_0N = 5000; // для частоты 50Гц, полуволна 100Гц /Time_0N =0 (0%),10000 (100%)
    void zero_cros() {
      past = micros();
      Lamp = 1;
      digitalWrite(Lamp_pin, Lamp ^ logic);
    }
    void setup() {
      //#1 ШИМ
      pinMode(Lamp_pin, OUTPUT);
      Lamp = 0;
      digitalWrite(Lamp_pin, Lamp ^ logic);
      attachInterrupt(0, zero_cros, RISING);
    }

    void loop() {
      //#1 ШИМ
      if (Lamp && micros() - past >= Time_0N) {
        Lamp = 0;
        digitalWrite(Lamp_pin, Lamp ^ logic);
      }
    }
     
    Последнее редактирование: 21 янв 2017
  19. gada94

    gada94 Нуб

    micros() он кажется работает но не совсем правильно. вот например мне нужно проверять температуру лампы и менять ее мощность каждую секунду. я делая вот так:
    Код (C++):

    unsigned long time;
    void setup(){....}
    void loop(){
    time = micros();
    дальше код проверки температур и регулировка мощности по прерыванию...
    delayMicroseconds(1000000) // задержка на 1 секунду
    int t= (micros() - time) / 1000000;  // вычисление сколько прошло времени
    }
    так вот разница времени t у меня всегда 0, почему?
     
  20. gada94

    gada94 Нуб

    вот схема [​IMG] то есть пин 2проверка перехода через 0 и пин 3 для управления