вольтмер 220V

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013
axill
Offline
Зарегистрирован: 05.09.2011

DimaP. пишет:

Unreturned скажите у вас есть информация рускоязычная по таймерам Atmega328?

Берете даташит http://www.atmel.com/Images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega4...

Открываете раздел

И смотрите описание битов буквально трех регистров (или двух, если не настраивать прерывания)

Не знаете английский - google поможетTimer/Register Description

например для 0-го таймера секция 15.9, для настройки вам нужны TCCR0A и TCCR0B, влаги прерываний TIMSK0

 

Unreturned
Offline
Зарегистрирован: 04.05.2013

у 328 камня 2 внешних прерывания, как же тогда мониторить трёхфазное напряжение?...

Snubist
Offline
Зарегистрирован: 18.02.2013

Напрашивается только один ответ по очереди, одним прерыванием. 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

как это только 2... у него можно прерывание по иземенению состояния назначить на почти все свободные лапы

axill
Offline
Зарегистрирован: 05.09.2011

Snubist пишет:

Напрашивается только один ответ по очереди, одним прерыванием. 

согласен

ставим оптопары на три фазы, заводим на три обычных пина без прерываний, а суммировав через три диода на INT0/1

Unreturned
Offline
Зарегистрирован: 04.05.2013

но тогда я не смогу проверить последовательность фаз.

в трёхфазнике каждая фаза сдвинута на треть периода, было бы неплохо следить ещё и за этим параметром, помимо напряжения. хотя может это и не интересно никому

axill
Offline
Зарегистрирован: 05.09.2011

Unreturned пишет:

но тогда я не смогу проверить последовательность фаз.

в трёхфазнике каждая фаза сдвинута на треть периода, было бы неплохо следить ещё и за этим параметром, помимо напряжения. хотя может это и не интересно никому

как раз сможете. Когда у вас сработает прерывание вы прочтете содержимое тех трех портов которые подключены индивидуально к каждой фазе и поймете какая фаза вызвала прерывание

Unreturned
Offline
Зарегистрирован: 04.05.2013

прошу прощения, не сообразил сразу. теперь всё понятно

axill
Offline
Зарегистрирован: 05.09.2011

то что описал простой вариант - даже не надо даташит открывать, достаточно ардуиновских функций

но если откроете даташит и прочитаете 10 раздел External Interrupts, особенно описание битов PCIE и регистров PCMCK, то сможете получать прерывание от каждой из трех фаз индивидуально

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

не хотит народ читать :)...нынче ето немодно :)

Unreturned
Offline
Зарегистрирован: 04.05.2013

Michal пишет:

не хотит народ читать :)...нынче ето немодно :)

читаю, только.... даже опросов не возникает - тёмный лес

axill
Offline
Зарегистрирован: 05.09.2011

Unreturned пишет:

читаю, только.... даже опросов не возникает - тёмный лес

глаза боятся руки делают )) так на руси говорили

ничего там сложного - выставляете нужные вам битики в регистрах и все заработает

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

сделайте мигалку, используя таймер, а не Delay().. и все станет ясно :)

axill
Offline
Зарегистрирован: 05.09.2011

вот вам идеи по подключению

Gres
Gres аватар
Offline
Зарегистрирован: 26.03.2013

Unreturned пишет:

читаю, только.... даже опросов не возникает - тёмный лес

Вот хорошая книжка, все очень подробно разжеванно на русском: Евстифеев А.В. Микроконтроллеры AVR семейств Tiny и Mega фирмы ATMEL, 5-е изд (2008).

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

Много хорошей и полезной информации!!!!

Есть вопрос когда мы настраиваем прерывание по счетчику Т2 мы берем тактовую частоту 16Мгц и затем с помощью делителя на 8 32 64 128 и так до 1024 выбираем к примеру 1024 и у нас получается что прерывание будет обрабатывать код с частотой 15625 Гц?  

axill
Offline
Зарегистрирован: 05.09.2011

DimaP. пишет:

Много хорошей и полезной информации!!!!

Есть вопрос когда мы настраиваем прерывание по счетчику Т2 мы берем тактовую частоту 16Мгц и затем с помощью делителя на 8 32 64 128 и так до 1024 выбираем к примеру 1024 и у нас получается что прерывание будет обрабатывать код с частотой 15625 Гц?  

По сути происходит два деления частоты

Первое происходит на так называемом prescaler - это делитель частоты источника перед тем как эта частота будет использована таймером. Если мы предполагаме частоту МК 16 и у нас в качестве источника частоты для МК выбрана его же частота, то получаем частоту на входе в счетчик как 16 / X, где X - коэффициент prescaler

После этого счетчик таймера начинает отсчитывать +1 или -1 (смотря как настроили таймер) с частотой 16 / X.

Но прерывание по timer overflow происходит только тогда когда сработало условие прерывания. Чаще всего таким условием выбирается равенство счетчика (TCNT0 на примере 0-го таймера) и регистров OCR0A/B.

тогда частота вызова обработчика прерываний будет как  частоты на входе таймера 16 / x деленная на число записанное в OCR0A/B. Я описал вариант, когда прерывание срабатывает по равенству счетчика и OCR0A/B. Есть другие режимы (например прерывание срабатывает по равенству TCNT0 0xFF) - смотрите описание управляющиех регистров, там все достаточно просто

axill
Offline
Зарегистрирован: 05.09.2011

основное, что вам нужно

здесь настройка prescaler

здесь выбор режима счета таймера

и здесь настройка прерываний

axill
Offline
Зарегистрирован: 05.09.2011

забыл сказать - все это на примере нулевого таймера, такой же подход к двум другим, нужно только учесть, что 0 и 2 таймера 8 битные (счетчик TCNT), а таймер 1 - 16-ти битный. Они отличаются еще рядом специфичных режимов. Для вашей задачи любой подойдет, лучше 1 или 2-й как я понял 0-1 использован для библиотек ардуино (в это не погружался, могу ошибиться)

Unreturned
Offline
Зарегистрирован: 04.05.2013


volatile long mks;
volatile long ms;
volatile int cntr;
long tms=0;
char flip;

void setup() {
  mks = 0; 
  ms = 0;   
  cntr = 0;
  flip = 0;
  pinMode(13, OUTPUT);     
  TCCR2A = 0; 
  TCCR2B = 2; //делитель 8
  TCNT2=59;   //счётчик переполнения, переполняется наждые 100 микросекунд, почему такая цифра - хз
  TIMSK2 |= (1 << TOIE2);  // разрешаем переполняться

}

ISR(TIMER2_OVF_vect) { //стартуем обработчик прерывания по переполнению
  TCNT2=59;            //стартуем счётчик
  mks++;               //считаем микросекунды
  cntr++;

  if(cntr>99) {        //считаем миллисекунды
    ms++;
    cntr = 0;
  }
}

void loop() {
  if (ms>tms) {
    tms = ms;
    if (tms%100==0) {
      if(flip) digitalWrite(13, HIGH);  
      else     digitalWrite(13, LOW);   
      flip = !flip;
    }
  }
}

я мозг сломал, боюсь дальше блинка дело не пойдёт... :(

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

найди в инете avrcalc, поможет с настройкой таймеров и др. устройств АВРор

DimaP.
Offline
Зарегистрирован: 21.04.2013

Michal разрешите у вас спросить 

Вот мы имеем переменное напряжение

с частотой 50 Гц

после подачи опорного напряжения мы получаем синусоиду относительно 2 В

Теперь мы запускаем прерывание по таймеру примеру Т2 

вот расчеты по калькулятору 

если мы берем средне квадратическое напряжение получается

то запуская таймер каждые 10 мсек (наверно)е измеряем напряжение на аналоговых входах в обработчике прерывания сохраняем эти значения в массив!!! поправте пожалуйста есля что напутал!

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

да все так

можно и реже запускать, в моменты когда вам нужны значения(вы же не забывайте вам еще математику считать)... главное для интегрирования ети 10 или 20 мс точно выдерживать.

Кстати, есть два способа замера. Первый как я предлагаю - таймером отсекаем 10-20мс, ацп в режиме автозапуска, а второй вариант настроить ацп на запуск по переполнению таймера, т.е настроили таймер на 1мс, сняли 10-20 показаний, посчитали(единстенное тут с временм интегрирования не очень), но как вариант(пример такой расматривали в теме "Измеряем Ток")

 

Unreturned
Offline
Зарегистрирован: 04.05.2013

так, с математикой у меня вдруг возник вопрос, если на переменке один такт - это от максимального до минимального, то напряжение снимать надо не на 10-той мс, а на 5-той? ну это если считать от нуля.

ссори, дуплюсь с прерываниями, тема для меня новая, большая нагрузка на неокрепший подростковый 37-ми летний мозг, туплю...

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

та все равно на какой секунде... главное сколько.... если весь период Т снимаете получаете искомый результат(после степеней и корней), если пол периода, то результат на 2 умножаете и т.д.

DimaP.
Offline
Зарегистрирован: 21.04.2013

Т.е. к примеру запускаем таймер через каждые 0.5 секунд и снимаем к примеру 10 показаний чрез 1 мсек

сохраняем в векторе прерывания эти данные массив и и усредняем, потом в основной программе умножаем на два и возводим в квадрат, и извлекаем корень, ну и потом дальнейшие математические преобразования!!

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

да по времени съема да... а по математике смотрите свой пост #44, действующее значение на 2 умножаем....

т.е. каждое значение в массиве в квадрат, потом все сложить, взять корень из суммы, поделить на кол-во измерений и для получения в вольтах умножить на коэф. пересчета и умножить на 2... кажись так :)

DimaP.
Offline
Зарегистрирован: 21.04.2013

Ну так вот что мне удалось узнать по поводу прерывания по счетчику!!!

1.счетчик Т1 считает до FF это примерно 256 следовательно при частоте 16 МГц он переполнится через 16 мксек это слишком быстро для моей программы даже введя предделитель на 1024 переполнение будет происходить каждые 16,3мсек , т.е опять же слишком часто!

int LEDPIN = 13;
volatile int cntr;

void setup()  
{ 
  cntr=0;
  TIMSK2 &= ~(1<<OCIE2A);                   // запрещение прерывания по совпадению таймера/счетчика Т2  
    TCCR2B = (1<<CS22)|(1<<CS21)|(0<<CS20); // прескалер на 256
    TCCR2A &= ~((1<<WGM22) | (1<<WGM20));   // Режим работы таймера/счетчика устанавливаю в
    TCCR2B |= (1<<WGM22);                   // Режим работы таймера/счетчика 
    ASSR &= ~(1<<AS2);                      // Выбор источника синхронизации таймера если
                                            // AS2=0 от системного генератора 
    OCR2A = 250;                            // срабатывание таймера 16000000/256/250=250 раз в секунду
    TIMSK2 |= (1<<OCIE2A);                  //Разрешение прерывания по совпадению. 
    pinMode(LEDPIN, OUTPUT);

}


void loop()  
{ 
 
}  


//****************обработчик прерывания******************** 
ISR(TIMER2_COMPA_vect)  
{ 
  cntr++;
  if (cntr>124) { // через каждые 125 вызовов прерывания перекидываем состояние светодиода
    digitalWrite(LEDPIN, !digitalRead(LEDPIN));
    cntr=0;
  }
} 

 

step962
Offline
Зарегистрирован: 23.05.2011

DimaP. пишет:

 даже введя предделитель на 1024 переполнение будет происходить каждые 16,3мсек , т.е опять же слишком часто!

Слишком часто для чего?

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

вот кусок с программы, тут таймера настраиваются (кварц 16Мгц)

//======================================================================
//настройка Т0 на 5кГц
//за 20 мс снимаем 100 показаний = 5кГц
TCCR0 = 0x03;      //делитель на 64
TCNT0 = 0xCE;      // или 0x31
TOIE0_bit = 1;


//======================================================================
//настройка тамера T1  0.5c
 CS12_bit = 1;
 CS11_bit = 0;     // делитель 1024
 CS10_bit = 1;
 WGM12_bit = 1;//  сброс по сравнению OCR1A
 OCR1AH = 0x1e;    //
 OCR1AL = 0x83;
 OCIE1A_bit = 0;   //выключен
 //======================================================================
//Настройка АЦП
 //ион - 5 vcc, выравнивание вправо, нулевой канал
 ADMUX = (0<<REFS1)|(1<<REFS0)|(0<<ADLAR)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(0<<MUX0);
 //вкл. ацп, режим одиночного преобр., разрешение прерывания, F преобр. = FCPU/128 125кГц
 ADCSRA = (1<<ADEN)|(0<<ADSC)|(0<<ADFR)|(1<<ADIE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);

а это п/прораммы обработчиков перерываний

void T0_Ovf_ISR()org IVT_ADDR_TIMER0_OVF{
PORTC5_bit = ~PORTC5_bit; //для осцилографа :) самая лучшая отладка
ADSC_bit = 1; //запуск ацп
TCNT0 = 0xCE; // перезаряжаем  таймер
}
void ADC_ISR()org IVT_ADDR_ADC{
*p = ADCL;
*(p+1) = ADCH;        //для 10разрядов переписать
p++;
k++;
if(k>maxp)TOIE0_bit = 0; // набили массив, отрубили таймер
}

в основной програмее нужно чо то типа такого сделать (файлы не сохранил, давно ето было)

while (1)
{
 k=0;
 TOIE0_bit = 1;           //запустили Т0 на maxp преобразований
 while(k<=maxp);        //ждем пока не набьется массив значениями
 
далше работа с массивом, вывод  и т.п.
}

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

я думал что разобрался в этом оказывается нисколечки((( 

Ладно продолжу изучать даташит, особенно строки 21-23 где настроики для аналогового компаратора!!

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

ну я просто для АВР пишу в microC, но вы можете попробовать в прерывании по таймеру использовать ардуиновскую analogread()

axill
Offline
Зарегистрирован: 05.09.2011

Michal пишет:

ну я просто для АВР пишу в microC, но вы можете попробовать в прерывании по таймеру использовать ардуиновскую analogread()

а мне понравился режим преобразования по переполнению таймера, когда не нужно самому инициировать измерения - зачетная штука, правда в этом случае таймер должет срабатывать уже с нужными интервалами для замеров. Мы ничего не пишем в функции обработки прерывания по таймеру (для этих нужд обработчик по таймеру совсем не нужен), а только собираем как готовые пирожки готовые измерения в прерывании по готовности ADC. Это наверно один из примеров когда средствами ардуино нельзя грамотно сделать то, что умеет atmega если ею управлять напрямую без всяких analogRead. Кстати если и время преобразования через analogRead будет дольше, если почитать даташит, то там различается время первого преобразования и время последующего. analogread каждый раз переключает канал на ADC, а это значит, что она каждый раз инициирует первое измерение - самое длинное. Разница почти в два раза - 25 циклов против 13. Когда мы измеряем всего один канал у нас нет потребности в переключении. Но конечно не всегда эта разница в скорости критична, но стоит все просчитать. Что не маловажно - по даташиту требуется, чтобы для 10 битного режима ADC если мы хотим качественное преобразование то частота работы ADC не должна превышать 200кГц, а это как раз уже может наложить ограничения на скорость измерений

п.с. обнаружил интересную вещь в mega328 - встроенный в чип датчик температуры, почему-то нив  одной конструкции не видел его использования

axill
Offline
Зарегистрирован: 05.09.2011

DimaP. пишет:

Ну так вот что мне удалось узнать по поводу прерывания по счетчику!!!

1.счетчик Т1 считает до FF это примерно 256 следовательно при частоте 16 МГц он переполнится через 16 мксек это слишком быстро для моей программы даже введя предделитель на 1024 переполнение будет происходить каждые 16,3мсек , т.е опять же слишком часто!

вы про mega328? т.е. про arduino UNO? у нее счетчик T1 16-ти разрядный, это значит, что считать может до 65535, а с учетом prescaler максимальный счет будет 65535 * 1024 = 67107840, 16 мгц превратятся в 0,24 Гц

диапазон для выбора более чем достаточный

DimaP.
Offline
Зарегистрирован: 21.04.2013

axill пишет:

DimaP. пишет:

Ну так вот что мне удалось узнать по поводу прерывания по счетчику!!!

1.счетчик Т1 считает до FF это примерно 256 следовательно при частоте 16 МГц он переполнится через 16 мксек это слишком быстро для моей программы даже введя предделитель на 1024 переполнение будет происходить каждые 16,3мсек , т.е опять же слишком часто!

вы про mega328? т.е. про arduino UNO? у нее счетчик T1 16-ти разрядный, это значит, что считать может до 65535, а с учетом prescaler максимальный счет будет 65535 * 1024 = 67107840, 16 мгц превратятся в 0,24 Гц

диапазон для выбора более чем достаточный

Да я теперь понял о чем был разговор!!!

DimaP.
Offline
Зарегистрирован: 21.04.2013

axill пишет:

DimaP. пишет:

Ну так вот что мне удалось узнать по поводу прерывания по счетчику!!!

1.счетчик Т1 считает до FF это примерно 256 следовательно при частоте 16 МГц он переполнится через 16 мксек это слишком быстро для моей программы даже введя предделитель на 1024 переполнение будет происходить каждые 16,3мсек , т.е опять же слишком часто!

вы про mega328? т.е. про arduino UNO? у нее счетчик T1 16-ти разрядный, это значит, что считать может до 65535, а с учетом prescaler максимальный счет будет 65535 * 1024 = 67107840, 16 мгц превратятся в 0,24 Гц

диапазон для выбора более чем достаточный

Я просто сразу не разобрался и кинулся в панику!!!

DimaP.
Offline
Зарегистрирован: 21.04.2013

Я то думал настроить счетчик Т2 на прерывания через каждые о.4 - 0.5 секунд, потом догнал что он же восьмибитный а это значит что считает он всего навсего до 255, т.е о половине минуты и разговора не какого не может идти!!!

Т1 замечательно подйдет на эту роль!! Возникает вопрос если я настрою прерывание к примеру через каждые 0.3 секунды, и в обработчике прерывания буду использовать 

analogRead(ADC0)

и сохранять значения в переменную, то как писал Michal мы должны будем измерять либо весь период либо половину, к примеру весь период будет составлять 20 мсек, а при частоте 16МГц мы сделаем примерно320000 измерений!!!

Объясните ине не грамотному в обработчике прерывания скорость какая будет 16МГц или же мы сможем настроиками выбрать любую скорость обработки ?

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

лениво вечером лезть в даташит... на тактирование АЦП есть делитель... у меня он 100 показаний шлепал за 20 мс... я же настроил ацп на одиночное преобразование и запускал по таймеру....вон ахилл тоже хороший способ подсказал, там таже процедура как и у меня толко все аппаратно. Я то программку лет 5 назад ваял :)

DimaP.
Offline
Зарегистрирован: 21.04.2013

Michal пишет:

лениво вечером лезть в даташит... на тактирование АЦП есть делитель... у меня он 100 показаний шлепал за 20 мс... я же настроил ацп на одиночное преобразование и запускал по таймеру....вон ахилл тоже хороший способ подсказал, там таже процедура как и у меня толко все аппаратно. Я то программку лет 5 назад ваял :)

вопрос лишь в том можно ли предложенный axill вариант реализовать на Arduino?

DimaP.
Offline
Зарегистрирован: 21.04.2013

А про снижение скорости работы в обработчике прерывания ничего похожего я не нашел!!

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

axill Скажите а можно взглянуть на варианты настроек для режим преобразования по переполнению таймера!! я о таком в даташите информации не нашел!!

axill
Offline
Зарегистрирован: 05.09.2011

читайте описание битов конфигурации ADATE и ADTS

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

или все тот же codevision возьмите и в помощнике настройки оборудования врубите нужный способ работы АЦП... CV выдаст код настройки

axill
Offline
Зарегистрирован: 05.09.2011

Michal пишет:

или все тот же codevision возьмите и в помощнике настройки оборудования врубите нужный способ работы АЦП... CV выдаст код настройки

точно!)) для начала можно и так, посмотрел сейчас - если в codewisard включить ADC то там в списке auto trigger source есть Timer0/1 overflow - это то о чем я писал

но кстати можно использовать и FreeRunning mode - в этом режиме новое измерение начинается как только закончилось предыдущее. Если потребление нас не волнует - запускаем пусть измеряет, а значения из ADCW берем так часто, как нам нужно

DimaP.
Offline
Зарегистрирован: 21.04.2013

Пробовал на досуге написать программу вольтметра вот что получилось 



volatile long Uism = 0; //Мгновенные напряяжения
volatile int cntr = 0; // счетчик в обработчике прерывания
volatile long Usumm = 0; // переменная для хранения суммы квадратов
int ADC0 = 0; // аналоговый вход 0 для переменной Ucor!
int ADC1 = 1; // вход измерения1
int Ucor = 0; // переменная будет хранить напряжение корректировки!!!
unsigned long timeOut = 0;// переменная для хранения времени!!!
int calculation = 0; // переменная для включения выключения расчетов
float real_U = 0.0; //переменная расчета рельной величины
float sqrtUsum = 0.0; //переменная расчете квадратного корня
unsigned long time = 0;
void setup()  
{ 
    TIMSK2 = 0b00000000;         // запрещение прерывания по совпадению таймера/счетчика Т2  
    TCCR2A = 0b00000010;       // режим работы СТС
    TCCR2B = 0b00000011;     // предделитель на 32
    ASSR &= ~(1<<AS2);    // Выбор источника синхронизации таймера(от системного генератора
                                         
    OCR2A = 100;           // срабатывание таймера 16000000/32/100=5000 раз в секунду 100 раз за период
    
                      
    Serial.begin(9600);

}


void loop()  
{ 
 
  if(millis() - timeOut >300)// ждем 0,3 секунды и...
 
  {
    Ucor = analogRead (ADC0); // сохраняем напряжение коррекции
    timeOut = millis();
   
    TCNT2 = 0x00; // перезарежаем таймер
    Usumm = 0;// обнуляем суммы напряжений 
    TIMSK2 |= (1<<OCIE2A); // разрешаем прерывание по совпадению
  }
  if(cntr == 100)// если прошло 100 измерений то
  {
    TIMSK2 = 0b00000000; // останавливаем таймер
    cntr = 0; //обнуляем счетчик
    calculation = 1; //разрешаем расчет
  }
  if(calculation == 1) //если расчет разрешон то
  {
    sqrtUsum = sqrt(Usumm); //вычисляем квадратный корень из суммы квадратов
   real_U = 0.010 * sqrtUsum; //0.010 полученна из( Uref * K / N * 1024)=(5*223/100*1024)=0.010 
   calculation = 0;
  }
  if(millis() - time >50)
  {
    time = millis();
  Serial.print(real_U);
  Serial.print (">>>");
  Serial.print(Usumm);
  Serial.println (">>>");
  }
  
  
  
}  


//****************обработчик прерывания******************** 
ISR(TIMER2_COMPA_vect)  
{  cntr++;
  Uism -= Ucor; // убираем подьем синусоиды на 2 вольта
   Uism = analogRead(ADC1); // считываем значения с аналогового порта 1
   Uism *= Uism;// возводим значение в квадрат
   Usumm += Uism; // склдываем квадраты измерений
 
} 

Но программа работает не коректно!!

выдает напряжение не правильное, и если его изменяешь на входе то в сериал обновляется примерно раз в 5 секунд(((

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013
27	void loop() 
28	{
3	    Ucor = analogRead (ADC0); // сохраняем напряжение коррекции
36	    TCNT2 = 0x00; // перезарежаем таймер
37	    Usumm = 0;// обнуляем суммы напряжений
            cntr = 0;
38	    TIMSK2 |= (1<<OCIE2A); // разрешаем прерывание по совпадению
39	  
40	  if(cntr == 100)// если прошло 100 измерений то
41	  {
42	   sqrtUsum = sqrt(Usumm); //вычисляем квадратный корень из суммы квадратов
49	   real_U = 0.010 * sqrtUsum; //0.010 полученна из( Uref * K / N * 1024)=(5*223/100*1024)=0.010
45	  }
46	  
55	  Serial.print(real_U);
56	  Serial.print (">>>");
57	  Serial.print(Usumm);
58	  Serial.println (">>>");
 
61	  delayms(500) ;
62	   
63	} 
64	 
65	 
66	//****************обработчик прерывания********************
67	ISR(TIMER2_COMPA_vect) 
68	{  
           if (cntr<=100)
              {
             	  Uism = analogRead(ADC1); // считываем значения с аналогового порта 1
                  Uism -= Ucor; // убираем подьем синусоиды на 2 вольта
71	          Uism *= Uism;// возводим значение в квадрат
72	          Usumm += Uism; // склдываем квадраты измерений
                  cntr++
	     }
          else  TIMSK2 = 0b00000000; // останавливаем таймер
      }           

мб еще чо то причесать надо будет

DimaP.
Offline
Зарегистрирован: 21.04.2013

Michal пробовал ваш вариант кода, спасибо что несколько подкоректировали его!!! Но расчет с 9 по 13 строку  не выполняется.

наверное это связанно что в основной программе в 6 строке мы обнуляем cntr = 0;! следовательно в 9 строке if выражение никогда не выполнится!!! нужно как то грамотно обнулять cntr? 

if(millis() - timeOut >300)// ждем 0,3 секунды и...
 
  {
    Ucor = analogRead (ADC0); // сохраняем напряжение коррекции
    timeOut = millis();
    cntr = 0;
    TCNT2 = 0x00; // перезарежаем таймер
    Usumm = 0;// обнуляем суммы напряжений 
    TIMSK2 |= (1<<OCIE2A); // разрешаем прерывание по совпадению
  }

если вот так попробовать???

 

Michal
Michal аватар
Offline
Зарегистрирован: 26.04.2013

ну я говорил что причесать еще надо :)

01	27  void loop()
02	28  {
03	3       Ucor = analogRead (ADC0); // сохраняем напряжение коррекции
04	36      TCNT2 = 0x00; // перезарежаем таймер
05	37      Usumm = 0;// обнуляем суммы напряжений
06	            cntr = 0;
07	38      TIMSK2 |= (1<<OCIE2A); // разрешаем прерывание по совпадению
08	39   
09	40   while(cntr<=100);//ждем 100 измерений 
10	41   
11	42     sqrtUsum = sqrt(Usumm); //вычисляем квадратный корень из суммы квадратов
12	49     real_U = 0.010 * sqrtUsum; //0.010 полученна из( Uref * K / N * 1024)=(5*223/100*1024)=0.010
13	45    
14	46   
15	55    Serial.print(real_U);
16	56    Serial.print (">>>");
17	57    Serial.print(Usumm);
18	58    Serial.println (">>>");
19	  
20	61    delayms(500) ;
21	62    
22	63  }
23	64  
24	65  
25	66  //****************обработчик прерывания********************
26	67  ISR(TIMER2_COMPA_vect)
27	68  { 
28	           if (cntr<=100)
29	              {
30	                  Uism = analogRead(ADC1); // считываем значения с аналогового порта 1
31	                  Uism -= Ucor; // убираем подьем синусоиды на 2 вольта
32	71            Uism *= Uism;// возводим значение в квадрат
33	72            Usumm += Uism; // склдываем квадраты измерений
34	                  cntr++
35	         }
36	          else  TIMSK2 = 0b00000000; // останавливаем таймер
37	      }

 

DimaP.
Offline
Зарегистрирован: 21.04.2013

Ну вообщем я разобрался просто в обработчике прерывания надо было в строчке

if (cntr<=100)

поменять число на 99