реклама на сайте
подробности

 
 
4 страниц V  « < 2 3 4  
Reply to this topicStart new topic
> Неверный результат измерения потреблённой энергии, Не могу найти ошибку
Stanislav_S
сообщение May 7 2008, 14:28
Сообщение #46


извечный пессимист
*****

Группа: Свой
Сообщений: 1 113
Регистрация: 9-10-06
Из: Днепропетровск
Пользователь №: 21 125



Цитата(Владимир_КПИ @ May 7 2008, 14:31) *
Не могу понять как это? У меня есть непрерывний меняющийся сигнал напряжения. И я должен периодически измерять мгновенные значения. С какой частотой? И что дальше с ними делать?

Поскольку у вас два канала измерения, то логично будет установить делитель для АЦП на 128, таким образом на канал у вас будет примерно по 6кГц. Заводите АЦП на непрерывный режим работы в прерывании вычисляете скользящее среднее, для начала сделайте это.


--------------------
Slaves are those of this world
Given freedom to lay chains upon The Master
The wolf is no longer free
Release the chains and come for me
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 7 2008, 17:06
Сообщение #47


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Владимир_КПИ @ May 7 2008, 08:57) *
Как такое возможно? Если я пишу в EEPROM, я никак в это же время не могу делать что-то другое.
когда Вы пишите в EEPROM Вы можете делать все что угодно кроме
второй записи/чтения в EEPROM, запрещать прерывания нужно только на 2 команды запуска
записи в EEPROM.
Ваша основная проблема в том что Вы не можете правильно спроектировать прогу так
что бы все операции работали параллельно, поэтому я и предложил Вам написать тестовую
прогу с чтением/рассчетом данных с АЦП и параллельной записью в EEPROM,
Вам это просто необходимо для того чтобы понять основы проектирования прог в реалтайме,
когда много разных процессов должны работать одновременно(почти одновременно).

Ну а по Вашему коду можно тоже слегка пройтись, раз уж Вы настаиваете... smile.gif
Код
void EEPROM_write(unsigned int addr, unsigned char val) //описание функции записи в EEPROM
{  
#asm("cli");
/* Wait for completion of previous write */
while(EECR & (1<<EEWE))
;
/* Set up address and data registers */
EEAR = addr;
EEDR = val;
/* Write logical one to EEMWE */
EECR |= (1<<EEMWE);
/* Start eeprom write by setting EEWE */
EECR |= (1<<EEWE);
#asm("sei");
}
Это конечно здорово запрещать прерывания перед записью в EEPROM,
НО, учитывая то что запись в EEPROM у Вас вызывается только из прерывания,
очень интересным является #asm("sei"); в конце функции который просто разрешает
нам вложенные прерывания.... 07.gif
Обычно в начале критической части сохраняют текущий статус разрешения прерываний а
потом его восстанавливают, те если было запрещенно то так и должно остаться.

Код
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)      //функция обработки внешнего прерываня по переднему фронту INT0
{
..........................
...........................
  if (count==3000)   //время через которое происходит запись значения мощности в EEPROM (через определённое количество периодов синусоиды)
  {
.......    
  EEPROM_write(addr, *pntr); //пишем в текущую ячейку EEPROM первый байт 32-битного числа float
.......
  EEPROM_write(addr, *pntr); // повторили еще 3 раза
......
  EEPROM_write(addr, *pntr);
......
  EEPROM_write(addr, *pntr);
......
  }
......
как Вы думаете, успеет отработать эта запись 4 байтов (по 8,5мс) до прихода следующего
переднего фронта(20мс)?
А что будет происходить если в функции EEPROM_write мы разрешили вложенные прерывания ?
Код
// ADC interrupt service routine
interrupt [ADC_INT] void adc_isr(void)
{
..........
i=(adc_data*2.56)/1024;
.........
u=(adc_data*2.56)/1024;               //сохраниение результата измерения напряжения                
.........
current=((1.2224-i)/2)/0.1;
........
Вы хотя бы примерно представляете сколько времени занимает 1 оперция деления
просто целочисленных 32бит/32бит ? А деление float ?

Ну и в остальных частях проги тоже много чего можно нарыть
- чтение кнопок без фильтрации
- 3 прерывания вместо 1-2 достаточных для такой проги
- все рассчеты только в прерываниях вместо основного цикла
....................

Начинайте с чего-нить попроще, потратите куда как меньше времени на освоение в целом (с) smile.gif
Go to the top of the page
 
+Quote Post
Motion
сообщение May 7 2008, 19:38
Сообщение #48


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 23-07-07
Из: Киев
Пользователь №: 29 297



Цитата
очень интересным является #asm("sei"); в конце функции который просто разрешает
нам вложенные прерывания

Когда я запрещал или разрешал прерывания, я подразумевал, что эти 2 команды разрешают/запрещают глобальное разрешение прерываний (то есть изменение флага I в регистре SREG). Посмотрел в книге - там команда sei, например, означает общее разрешение прерываний. Это ведь ассемблерные вставки. А вы говорите про разрешение/запрешение вложеных прерываний... Что это значит?


Цитата
как Вы думаете, успеет отработать эта запись 4 байтов (по 8,5мс) до прихода следующего
переднего фронта(20мс)?


Это уже не важно, что будет потом. Запись в ЕЕPROM будет происходить лишь при пропадании питания. Сейчас я записывал в EEPROM лишь чтобы узнать правильно ли считается мощность. То есть периодической записи в EEPROM происходить не будет.


Цитата
Вы хотя бы примерно представляете сколько времени занимает 1 оперция деления
просто целочисленных 32бит/32бит ? А деление float ?

Нет, а где можно почитать?


Цитата
А что будет происходить если в функции EEPROM_write мы разрешили вложенные прерывания ?

Получается вложеные прерывания будут разрешины, а общие запрещины? И тогда устройство не сможет нормально работать из-за общего запрета прерываний?


Цитата
чтение кнопок без фильтрации

А что за фильтрация? Вы имеете ввиду антидребезг? Или возможность ложного срабатывания в случае помехи?

Цитата
3 прерывания вместо 1-2 достаточных для такой проги

1 прерывание для синхронизации (INT0)
1 прерывание для таймера0 (для измерения значений)
1 прерывание для таймера1 (для отсчёта угла отпирания)

Кака же можно обойтись одним-двумя?


Цитата
все рассчеты только в прерываниях вместо основного цикла

Если вызвана подпрограмма обработки прерывания, она будет выполняться до конца или её в любой момент может прервать другое прерывание или только прерывание с более высоким приоритетом?


Цитата
Ваша основная проблема в том что Вы не можете правильно спроектировать прогу так
что бы все операции работали параллельно, поэтому я и предложил Вам написать тестовую
прогу с чтением/рассчетом данных с АЦП и параллельной записью в EEPROM,
Вам это просто необходимо для того чтобы понять основы проектирования прог в реалтайме,
когда много разных процессов должны работать одновременно(почти одновременно).

Да, наверное так и есть. Значит буду начинать с более простого(то, что вы предложили).

Но я так и не понял сути, что мне нужно сделать. Нужно паралельно мерять значения напряжения, их каким-то образом обрабатывать (так называемое скольжение) и паралельно со всем этим записывать результат в EEPROM?
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 7 2008, 20:30
Сообщение #49


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Уффф... бум отвечать по пунктам:
Цитата(Владимир_КПИ @ May 7 2008, 23:38) *
Когда я запрещал или разрешал прерывания, я подразумевал, что эти 2 команды разрешают/запрещают глобальное разрешение прерываний (то есть изменение флага I в регистре SREG). Посмотрел в книге - там команда sei, например, означает общее разрешение прерываний. Это ведь ассемблерные вставки. А вы говорите про разрешение/запрешение вложеных прерываний... Что это значит?
когда я говорил про 2 команды я имел в виду вот это:
EECR |= (1<<EEMWE);
EECR |= (1<<EEWE);

только эта спецпоследовательность должна выполняться при запрещенных прерываниях,
когда Вы в своей функции EEPROM_write в конце ставите #asm("sei"); Вы разрешаете ВСЕ прерывания...
Цитата
Это уже не важно, что будет потом. Запись в ЕЕPROM будет происходить лишь при пропадании питания. Сейчас я записывал в EEPROM лишь чтобы узнать правильно ли считается мощность. То есть периодической записи в EEPROM происходить не будет.
Про потом это конечно хорошо, но при таком коде Вы никогда не перейдете
к этой самой стадии "потом", Ваш код записи в EEPROM просто мешает фунициклировать правильно
всем прерываниям....
Ну и уже чисто мое ИМХО, это неправильно уповать только на то что Вы успеете записать
многобайтовую переменную в случае пропадания питания, должно быть 2 механизма записи,
1 это привязанное ко времени(типа раз в XXX) второе при пропадании питания, ну
и механизм который разруливает это при старте...
Цитата
Нет, а где можно почитать?
Можно не прочитать а посчитать/просимулировать.
Ваша проблема в том что Вы пытаетесь сразу все посчитать в float и сразу все поделить,
а это нужно делать в самый последний момент, те пока можем, считаем все в целых и
желательно без делений, перевод в float или деления только перед выдачей на экран или
сохранением, хотя если еще чуть подумать, для сохранения это тоже не нужно,
какая разница в каких единицах будет все храниться в EEPROM ?
Цитата
Получается вложеные прерывания будут разрешины, а общие запрещины? И тогда устройство не сможет нормально работать из-за общего запрета прерываний?
выше ответил, будут разрешены ВСЕ прерывания и вложенные в том числе,
и при рассчетах с float прямо в прерывании АЦП Вы явно не всегда будете успевать...

Цитата
А что за фильтрация? Вы имеете ввиду антидребезг? Или возможность ложного срабатывания в случае помехи?
Антидребезг конечно, фильтрация это просто общее название.
Цитата
1 прерывание для синхронизации (INT0)
1 прерывание для таймера0 (для измерения значений)
1 прерывание для таймера1 (для отсчёта угла отпирания)
Кака же можно обойтись одним-двумя?
Если вызвана подпрограмма обработки прерывания, она будет выполняться до конца или её в любой момент может прервать другое прерывание или только прерывание с более высоким приоритетом?
Да, наверное так и есть. Значит буду начинать с более простого(то, что вы предложили).

Ну как минимум 2 из этих задач можно совместить,
ну и еще, подумайте, может чего-нить из этого можно делать и в основной проге ?
про прерывания Вы неправильно поняли, Вы сами разрешаете им быть вложенными,
НО, если Вы им запретите быть вложенными при том софте который есть, станет тока хуже...

Цитата
Но я так и не понял сути, что мне нужно сделать. Нужно паралельно мерять значения напряжения, их каким-то образом обрабатывать (так называемое скольжение) и паралельно со всем этим записывать результат в EEPROM?
Скользящее среднее это очень простая штука, это просто сумма
последних N отсчетов какой-нить меняющейся величины(например показаний АЦП) поделенная на
количество отсчетов N. То есть при получении каждого нового отсчета, мы просто суммируем
последние N отсчетов и делим сумму на N. Нужно просто грамотно организовать хранение
отсчетов и иметь это скользящее среднее в любой момент времени.
Так же нужно раз в секунду записать текущее значение скользящего среднего в EEPROM при этом
не прерывая рассчет скользящего среднего...

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

P.S. про кольцевые буферы Вам уже намекнули, ну и делить не всегда необходимо(для хранения)...
Go to the top of the page
 
+Quote Post
_Pasha
сообщение May 8 2008, 04:24
Сообщение #50


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(singlskv @ May 8 2008, 00:30) *
То есть при получении каждого нового отсчета, мы просто суммируем
последние N отсчетов и делим сумму на N.
P.S. про кольцевые буферы Вам уже намекнули, ну и делить не всегда необходимо(для хранения)...


И каждый раз суммировать тоже не обязательно, достаточно при поступлении нового отсчета вычесть из результата скользящего среднего элемент, на который указывает указатель кольцевого буфера, затем записать в буфер новый отсчет и прибавить его к результату. А потом передвинуть указатель. В начальный момент времени у Вас все будет ==0, поэтому до заполнения буфера ничего эдакого делать не надо - все само устаканится.
Go to the top of the page
 
+Quote Post
Motion
сообщение May 10 2008, 06:51
Сообщение #51


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 23-07-07
Из: Киев
Пользователь №: 29 297



По поводу прерываний:

Так как функция записи в EEPROM вызывается из прерывания EXT_INT0, то на момент вызова функции EEPROM_write(...); флаг I будет сброшен. То есть глобально будут запрещены все прерывания. Тогда зачем их запрещать на 2 команды -
EECR |= (1<<EEMWE);
EECR |= (1<<EEWE);
???


Я так понял, что ошибка была в том, что я глобально разрешал прерывания внутри подпрограммы обработки прерываний INT0, чего не должно было быть. Все прерывания должны были быть разрешены (автоматически) только после завершения подпрограммы обработки INT0. Так?
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 10 2008, 18:30
Сообщение #52


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Владимир_КПИ @ May 10 2008, 10:51) *
Так как функция записи в EEPROM вызывается из прерывания EXT_INT0, то на момент вызова функции EEPROM_write(...); флаг I будет сброшен. То есть глобально будут запрещены все прерывания. Тогда зачем их запрещать на 2 команды -
EECR |= (1<<EEMWE);
EECR |= (1<<EEWE);
Для тех кто в танке, еще раз повторяю, нужно не запретить прерывания на эти
2 команды, нужно запомнить были ли запрещены/разрешены прерывания в момент когда
мы добрались до этих команд, если были запрещены так и оставить, если были разрешены,
запретить их только на эти 2 команды.
В Вашем конкретном случае, когда вся запись осуществляется только из прерываний,
запрещение/разрешение прерываний вобще не нужно.
Цитата
Я так понял, что ошибка была в том, что я глобально разрешал прерывания внутри подпрограммы обработки прерываний INT0, чего не должно было быть. Все прерывания должны были быть разрешены (автоматически) только после завершения подпрограммы обработки INT0. Так?
В первом приближении так, тока это Вам не поможет сделать Ваш код рабочим... sad.gif
У Вас принципиально неправильно спланированна программа,
я Вам уже советовал поупрожняться в этом деле, но похоже Вы решили править Ваш код,
ну чтож, пожелаем Вам удачи...
Go to the top of the page
 
+Quote Post
Motion
сообщение May 12 2008, 09:23
Сообщение #53


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 23-07-07
Из: Киев
Пользователь №: 29 297



Цитата
У Вас принципиально неправильно спланированна программа,
я Вам уже советовал поупрожняться в этом деле, но похоже Вы решили править Ваш код,
ну чтож, пожелаем Вам удачи


Нет, я сделаю как вы посоветовали. Просто пытаюсь понять свои ошибки, чтобы не допустить их в будущем.
Go to the top of the page
 
+Quote Post
Motion
сообщение May 12 2008, 14:42
Сообщение #54


Местный
***

Группа: Свой
Сообщений: 466
Регистрация: 23-07-07
Из: Киев
Пользователь №: 29 297



Есть уточняющие вопросы:

- скользящее среднее считать для моей схемы? При 100% мощности? Т.е. мерять "идеальную" синусоиду?
- с какой частотой?
- какое количество отсчётов?
- вы писали, что раз в секунду нужно писать скользящее среднее в EEPROM. Время равное 1 секунде можно считать по количеству внешних прерываний INT0 (периодов сетевого напряжения) или нужно использовать таймер, например?
- как организовать хранение последних N отсчётов? Т.е. этот самый кольцевой буфер. Понятно, что значения будут храниться где-то в ROM. Но где именно? В массиве, в памяти?
Go to the top of the page
 
+Quote Post
singlskv
сообщение May 12 2008, 17:17
Сообщение #55


дятел
*****

Группа: Свой
Сообщений: 1 681
Регистрация: 13-05-06
Из: Питер
Пользователь №: 17 065



Цитата(Владимир_КПИ @ May 12 2008, 18:42) *
Есть уточняющие вопросы:

- скользящее среднее считать для моей схемы? При 100% мощности? Т.е. мерять "идеальную" синусоиду?
- с какой частотой?
- какое количество отсчётов?
- вы писали, что раз в секунду нужно писать скользящее среднее в EEPROM. Время равное 1 секунде можно считать по количеству внешних прерываний INT0 (периодов сетевого напряжения) или нужно использовать таймер, например?
Считайте это пока просто абстрактной задачкой, к Вашим синусойдам это
пока отношения не имеет. Самое главное для Вас сейчас научиться планировать задачку,
и в частности сделать так чтобы несколько независимых функций работали "одновременно".
Иначе у Вас получается что функции которые должны работать в реалтайме (чтение показаний АЦП,
ловля перехода через 0, итд) постоянно прерываются функциями которые делаются
очень неспешно(запись в EEPROM, рассчет результатов в флоат, итд)

то есть я Вам предлагаю написать относительно простую задачку:
- опрос АЦП с какой-то частотой (лучше кстати сразу по нескольким каналам)
- рассчет среднего по каждому каналу(ну это типа просто для тренировки и понимания как нужно
хранить и делать предварительные вычисления побыстрому когда данных много)
- запись посcчитанных значений в EEPROM с некоторой переодичностью

вот когда Вы напишите этот учебный пример, мы его раскритикуем и после этого Вы
напишите правильно... smile.gif
у Вас просто будет готовый каркас к которому Вы уже просто будете прикручивать свою обработку.

Цитата
- как организовать хранение последних N отсчётов? Т.е. этот самый кольцевой буфер. Понятно, что значения будут храниться где-то в ROM. Но где именно? В массиве, в памяти?
кольцевой. не в ROM а в RAM. в массиве.

Ну а для уточнения задачки, ну пусть будет 2 делителя напряжения с переменными резисторами
в одном из плечей, частоту АЦП выберите сами, по максимуму но с запасом на обработку.
Go to the top of the page
 
+Quote Post
ibiza11
сообщение Jan 17 2009, 10:50
Сообщение #56


Участник
*

Группа: Участник
Сообщений: 54
Регистрация: 13-01-09
Пользователь №: 43 304



Цитата(Владимир_КПИ @ May 1 2008, 17:06) *
А можно подать постоянное напряжение 9В с батареек?

Дело в том, что это напряжение пойдёт на нагрузку. Сопротивление лампочки в холодном состоянии 26Ом. Почти к.з. Не взорвутся ли у меня, например, батарейки при включении?
ахахахахахахаха))))) cranky.gif
Go to the top of the page
 
+Quote Post

4 страниц V  « < 2 3 4
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 10:23
Рейтинг@Mail.ru


Страница сгенерированна за 0.01476 секунд с 7
ELECTRONIX ©2004-2016