Перейти к содержанию

demiurg1978

Members
  • Постов

    361
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные demiurg1978

  1. Измерение идёт пакетно. 400 раз отмерили, отключаем таймер и АЦП, вычислили квадратный корень, перевели в значение. И по новой. Этот подход хорош тем, что нет привязки к переходу через нуль. Пакет по времени равен 8 периодам.

    В качестве примера использовался проект Ридико Леонида Ивановича.

  2. Слишком сложно и громоздко. ТТ Talema, размах хватит для АЦП, в крайнем случае rail-to-rail ОУ. Если среднеквадратичное, контроль перехода через нуль не нужен. Главное, настроить таймер так, чтобы он пинал АЦП с частотой кратной 50 Гц. Я открыл проект, у меня стоит значение 400 замеров. То есть, 8 периодов.

    Схему позже могу выложить, так получилось, что собирал макет, окончательную схему не сохранил.

    Скрытый текст
    
    //========================================================================
    #ifndef METER_H
    #define METER_H
    
    #include "meter.h"
    
    #include "main_def_func.h"
    //========================================================================
    
    //========================================================================
    #define METER_TCNT         TCNT0
    #define METER_TIMSK        TIMSK
    #define METER_OCIE         OCIE0
    #define METER_OCR          OCR0
    #define METER_TCCR         TCCR0
    #define METER_CS0          CS00
    #define METER_CS1          CS01
    #define METER_CS2          CS02
    
    #define METER_OCR_VAL      25
    //========================================================================
    
    //========================================================================
    #define V_REF   5.00
    #define ADC_RES 1023.0
    #define K_1     1.089
    #define K_2     1.061
    #define K_3     1.033
    //========================================================================
    
    //========================================================================
    #define SAMPLES 400
    //========================================================================
    
    //========================================================================
    enum
    {
       PHASE_A,   //фаза A
       PHASE_B,   //фаза B
       PHASE_C,   //фаза C
       PHASE_Usm,
    };
    //========================================================================
    
    //========================================================================
    void meter_timer_init (void);
    void meter_timer_off (void);
    
    void meter_init (void);
    void meter_off (void);
    
    u16 read_adc (u08 channel);
    
    void set_proc_meter_on (void);
    void set_proc_meter_off (void);
    void proc_meter (void);
    
    u32 calc_adc_result (u32 sqr_summ);
    
    bool get_measure_complete (void);
    //========================================================================
    
    #endif

     

    Скрытый текст
    
    //========================================================================
    #include "meter.h"
    //========================================================================
    
    //========================================================================
    bool adc_complete;
    
    static u08 phase;
    static u16 sample;
    
    static u32 phase_a_summ_sqr;
    static u32 phase_b_summ_sqr;
    static u32 phase_c_summ_sqr;
    
    static bool measure_complete;
    //========================================================================
    
    //========================================================================
    #pragma vector = TIMER0_COMP_vect
    __interrupt void meter_timer_comp (void)
    {
       u16 adc = 0;
       u16 temp = 0;
    
       u32 a = 0;
    
       METER_OCR += METER_OCR_VAL;
    
       adc = read_adc (PHASE_Usm);
    
       temp = adc;
    
       adc = read_adc (phase);
    
       if (adc >= temp)
          adc -= temp;
       else
          adc = (temp - adc);
    
       a = (long) (adc * adc);
    
       switch (phase)
       {
          case PHASE_A:
             phase_a_summ_sqr += a;
             phase = PHASE_B;
             break;
    
          case PHASE_B:
             phase_b_summ_sqr += a;
             phase = PHASE_C;
             break;
    
          case PHASE_C:
             phase_c_summ_sqr += a;
             phase = PHASE_A;
    
             if (++sample > SAMPLES)
             {
                meter_off ();
    
                measure_complete = true;
             }
             break;
       }
    }
    //========================================================================
    
    //========================================================================
    #pragma inline = forced
    void meter_timer_init (void)
    {
       METER_TCNT = 0;
       METER_OCR = METER_OCR_VAL;
       set_bit (METER_TIMSK, METER_OCIE);
       set_bit (SFIOR, PSR10);
       METER_TCCR |= ((1<<METER_CS1) | (1<<METER_CS0));
    }
    //------------------------------------------------------------------------
    #pragma inline = forced
    void meter_timer_off (void)
    {
       METER_TCCR = 0;
       clr_bit (METER_TIMSK, METER_OCIE);
       METER_TCNT = 0;
       METER_OCR = 0;
    }
    //========================================================================
    
    //========================================================================
    //#pragma inline = forced
    u16 read_adc (u08 channel)
    {
       ADMUX = ((0<<REFS1) | (0<<REFS0) | (0<<ADLAR) | channel);
    
       set_bit (ADCSRA, ADSC);
    
       while (1)
       {
          __enable_interrupt ();
    
          sleep_mode_enable ();
    
          if (adc_complete)
          {
             adc_complete = false;
             break;
          }
       }
    
       return ADC;
    }
    //========================================================================
    
    //========================================================================
    #pragma vector = ADC_vect
    __interrupt void adc_interrupt_handler (void)
    {
       adc_complete = true;
    }
    //========================================================================
    
    //========================================================================
    void meter_init (void)
    {
       phase = PHASE_A;
    
       phase_a_summ_sqr = 0;
       phase_b_summ_sqr = 0;
       phase_c_summ_sqr = 0;
    
       sample = 0;
    
       measure_complete = false;
    
       meter_timer_init ();
    }
    //------------------------------------------------------------------------
    #pragma inline = forced
    void meter_off (void)
    {
    //   ADCSRA = 0;
    //   ADMUX = 0;
    
       meter_timer_off ();
    }
    //========================================================================
    
    //========================================================================
    static u08 _proc_meter;
    
    void set_proc_meter_on (void)
    {
       ACSR = (1<<ACD);
    
       ADCSRA = ((1<<ADEN) | (0<<ADSC) | (0<<ADATE) | (1<<ADIF) | (1<<ADIE) | (1<<ADPS2) | (0<<ADPS1) | (0<<ADPS0));
    
       _proc_meter = 1;
    }
    //------------------------------------------------------------------------
    void set_proc_meter_off (void)
    {
       meter_off ();
    
       _proc_meter = 0;
    }
    //------------------------------------------------------------------------
    void proc_meter (void)
    {
       switch (_proc_meter)
       {
          case 0:
             break;
    
          case 1:
             meter_init ();
             _proc_meter = 2;
             break;
    
          case 2:
             if (get_measure_complete ())
             {
                phase = PHASE_A;
                _proc_meter = 3;
             }
             break;
    
          case 3:
             switch (phase)
             {
                case PHASE_A:
                   set_i_ph_a (calc_adc_result (phase_a_summ_sqr));
                   phase = PHASE_B;
                   break;
    
                case PHASE_B:
                   set_i_ph_b (calc_adc_result (phase_b_summ_sqr));
                   phase = PHASE_C;
                   break;
    
                case PHASE_C:
                   set_i_ph_c (calc_adc_result (phase_c_summ_sqr));
                   Set_Event (EV_ID_MEASURE_I_ABC_COMPLETE, USER_EVENT);
                   _proc_meter = 1;
                   break;
             }
             break;
       }
    }
    //========================================================================
    
    //========================================================================
    u32 calc_adc_result (u32 sqr_summ)
    {
       float a;
       u16 temp;
    
       sqr_summ /= sample;
    
       a = sqrt (sqr_summ);
       temp = (int) a;
    
       a = (float) a * (V_REF / ADC_RES);
    
       if (temp <= 50)
          a = (float) a * K_1;
       if (temp > 50 && temp < 100)
          a = (float) a * K_2;
       if (temp >= 100)
          a = (float) a * K_3;
    
       a = a * 10000;
       return (long) a;
    }
    //========================================================================
    
    //========================================================================
    bool get_measure_complete (void)
    {
       if (measure_complete == true)
          {
             measure_complete = false;
             return true;
          }
       else
          return false;
    }
    //========================================================================

     

     

    AC-1005 Jun-06.pdf

  3. AVR, книга Вольфганг Трпмперт "AVR-RISC микроконтроллеры фирмы Atmel". Программатор STK-500. Дороговато, зато, полноценная отладочная плата и программатор. Либо AVRISP MKII. Можно начать с ассемблера, параллельно штудировать си. Это в дальнейшем поможет, в случае чего залезть в дизасм, чтобы посмотреть, что да как, либо если что то не заработает. Главное, штудируйте архитектуру. Это сэкономит время вам самому в дальнейшем.

    Упс, дату не глянул... 

  4. Опорник на 2,5 вольта. Один вывод тт на выход опорника, второй на вход АЦП. Я использую тт Tahoma. Алгоритм. Сначала меряем напряжение без тока. Это ноль. Запоминаем. По таймеру запускаем АЦП. Главное, что скорости АЦП и мк хватило. Я использую AVR. Измеренный результат суммируем, потом среднеквадратичное значение.

  5. Только что, admin сказал:

    Там и выясняйте ваши отношения. Зачем это здесь?

    Потому что на днях ARV сделал то же самое на ЭТОМ форуме. За то, что происходит на ДРУГОМ форуме. Falconist может это подтвердить. Я не выясняю отношения. Для меня все это пыль под ногами. Я бы даже и не обратил внимания, как не обращал, сколько я там зарегистрирован на этом форуме? Случайно увидел.

  6. Ситуация. Зацепились мы с одним участником. На другом форуме. Также он является участником и других форумов. Так вот, когда у него закончились аргументы при АДЕКВАТНОМ диалоге, он занижает рейтинг, или, как на этом форуме минусует. Считаю поведение этого участника недостойным и мелкопаскудным. Ни как мужика, ни как профессионала. Повторю то,что сказал на радиокоте, за что меня забанили, пусть и здесь забанят. Но зато я буду знать, что всему сообществу сказал это прямо. ARV. Мелкопаскудная тварь и сволочь. Когда у него заканчиваются аргументы, он занижает или минусует рейтинг оппонента.

    Я никогда не поступал так. По моим понятиям  - время все расставляет по местам. Кто прав, кто виноват.

    false_0001.jpg

    false_0002.jpg

  7. 2 часа назад, Yurec66 сказал:

    ...

    Уделите время, пожалуйста, почитайте, в книгах в интернете, что такое синхронные двигатели, асинхронные, что такое полюса двигателей. И почему у асинхронных двигателей стандарт, к примеру, 3000, а оборотов 2880. Асинхронный двигатель само понятие подразумевает, что "а" значит "не". И 3000 ровно никогда не будет. Потому что потери.

  8. Попробовать сделать следующее: Если промежуточные реле на 24 вольта, вскрыть, если возможно, контроллер, проверить, есть ли диоды встречно параллельно реле. Если нет, поставить внешние. Если реле на 220 вольт, поставить снабберы, на пускатели тоже самое. Убрать ПЛК подальше от реле и пускателей. В идеале, проверить, если гальваническая развязка в управлении реле, вскрыть, посмотреть, стоят ли оптроны. Попробовать поставить другой блок питания. Проверить, есть ли просадка напряжения, когда включены все реле (если они на 24 вольта). Действуйте, отпишитесь о результатах проверки. И да, желательно развести низковольтную часть и высоковольтную. Есть такое предложение, силовую часть (питание, не управление!) и низковольтная часть отдельно. Управление силовое отдельно. Короче, максимально обезопасить ПЛК от помех. В том числе - убрать подальше от реле и пускателей.

    Внутрянка шкафа интересна. С бору по сосенке. Старая БУ комплектуха. Шкаф какой придется. Опечалю, шкаф придется переделывать. Взять побольше и переделать весь монтаж. Первый ярус автоматов, предохранителей. Второй ярус пускатели и вся остальная мелочевка. Третий ярус ПЛК, релюхи и что останется. Четвертый ярус клеммники. По монтажу рекомендация та же, Силовая питающая часть и низковольтная часть, но скорее всего низковольтная часть по моей рекомендации вся будет отдельно. Управляющая силовая часть отдельно.

  9. Сечение нуля равное максимальному току всех нагрузок. С небольшим запасом. Кабель брать обязательно по ГОСТ-у, а не по ТУ. По ТУ кабель зачастую наполовину меньше. Был один случай, делал полный перемонтаж выдувного станка. В том числе кабели на ТЭН-ы. Я сразу при покупке не глянул. Всучили по ТУ. А сечение в два раза меньше. В итоге при нагреве ТЭН-ов кабели ощутимо греются. Оставили так, потому что тэны нагрели зоны и отключились, дальше только поддержание температуры.

  10. У меня был маяк 2хх какой то. Стоял индикатор vfd, пикового детектора не было. Просто показывал уровень сигнала. Я потом из этого индикатора сделал что то вроде частотомера. VFD дисплей убрал. Была светодиодная линейка. Коммутатор сигналов. Объединил два канала в один. Подстроечником второй канал настроил так, что когда заканчивается диапазон индикации одного канала, начинается другой канал. Это было в конце 90 или начале 2000. Стенд для промывки инжекторов.

  11. Всю дорогу AVR-Studio использую. С 2007 года. Ассемблер, несколько лет, когда перешёл на си, сначала AVR-Studio и AVR Toolchain использовал, плюнул, перешёл на IAR. Если программа на си, пишу в IAR, отлаживаю в симуляторе AVR-Studio. Если асм, AVR-Studio.

  12. 36 минут назад, ARV сказал:

    Вы их засаливаете впрок на случай голода?

    Никогда не понимал этого стремления экономить такты и байты... Случаи бывают, не спорю, но вот чтобы делать из этого принцип....не понимаю.

    Этим страдают все железячники. Микроконтроллер должен работать на все 100.

    Непонимание как работает мк, как работает программа. Непонимание, что человекоинтерфейс это десятки и сотни миллисекунд.

    А секрет прост. Микроконтроллер крутит программу по кругу. Всегда. Кто то может сказать, а как же спящий режим. Отвечу. В этот момент он стоит. Проснётся, дальше по кругу пошел. Именно этот момент сносит железячникам мозги.

  13. Ещё со времен ассемблер не парюсь насчёт объёма памяти мк. Я активно использую конечные автоматы, программные таймеры, это как минимум на 25 процентов увеличивает выхлоп. На маленьких мк это критично. Проекты побольше, эта разница нивелируется. Если не влезает, пробую ужаться, не получается, беру более жирный мк. У меня мало серийных изделий, поэтому этой проблемы нет. 

  14. Здесь мы плавно пришли к следующему. Как только начинаешь писать на макроассемблере, пора переходить на си. Ассемблер хорош тем, что напрямую управляешь мк. Здесь все зависит только от тебя. Как успех, так и ошибки. Так же ассемблер хорош низким порогом вхождения. Я взял мк, почитал книги, написал свои первые шаги. И пошло. 

    Начиная с определённого момента дальше идут приёмы программирования. А не язык. Если точнее, проектирования. 

×
×
  • Создать...