AS7ti6K

Расчет Оборотов. "глюки?" В Протеусе.

65 сообщений в этой теме

IMXO    1 347

А почему 8 мплаб? Он же старее... И протеус у меня 7,7 SP2.... Новое - не значит хорошее, но всеж, есть какие-то серьезные аргументы в пользу старых версий?

потому что 10-ка сделана на основе 8-ки + свои глюки... плюс 10-ки только в поддержке новых камней, для старых камней лучше пользовать 8.92, как собственно и хайтек 9.60 PL3 STD лучше 9.80 pro на основе последнего сделан ХС8 опять же польза последнего в только поддержке новых камней ....

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

Я тут вот еще что подумал, а не может это быть из-за входных данных?

Может это внутренний генератор (вирт прибор в протеусе) глючит?

используйте генератор CLOCK - использует минимальное кол-во ресурсов сима...

берите три пина и через них выводите переменную Freq в два регистра 74ls595

пины регистров и генератора отправляете в граф лог.анализатор , записываете нужное кол-во времени и смотрите меняется ли показание Freq и в какое время.....

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

По поводу версий ясно.

используйте генератор CLOCK - использует минимальное кол-во ресурсов сима...

берите три пина и через них выводите переменную Freq в два регистра 74ls595

пины регистров и генератора отправляете в граф лог.анализатор , записываете нужное кол-во времени и смотрите меняется ли показание Freq и в какое время.....

Буду пытаться разбираться в том, что Вы сказали.... К своему стыду, чувствую себя вообще деревянным в этом деле :(

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

И все таки я думаю, что протеус меня дурит, или компилятор.

Изменил код так, что считается 1 импульс и мерится без каких либо округлений.

в таком случае при частоте в 5 гц переменная TurnsTime в обработчике прерывания GPIF должна равнятся 200000 мкс ну или около того хотя-бы.

Но в протеусе она хоть убейся равна около 3333

И результаты в Freq и RPM при этом верные.

Что-то тут не то. Если 1000000 разделить на эти 3333 то получаются обороты в минуту при 5 герцах. Вроде сходится, но на 1 импульс должно быть 200000 мкс

Т.е. 1000000 / 200000 = 5 и вот эти 5 умножаем на 60 и получаем 300.

А как компилятор по другому считает, я не понимаю :)

Спасибо. Интересный подход. Но для меня, т.е. на моем уровне знаний, это пока усложнение и запутывание задачи...

Я тут в трех числах запутался....(

Изменено пользователем AS7ti6K

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
UTSource

Найдите миллионы труднодоступных

электронных компонентов

AS7ti6K    2

как заставить компилятора или оптимизатора делать то, что сказано, а не по своему?

if (TMR1IF) {

MksTurns += 65536;

>>>>TMR1IF = 0;

}

При 5 гц Программа останавливается на данной точке, но MksTurns остается быть равным 0.

Вообще ничего не понимаю.... Пишу одно, делается не понятно как, в результате вроде "всё верно", но есть ошибки или глюки, а где их искать не имею возможности из-за того, что не знаю как это делает компилятор с оптимизатором да с протеусом.... они сговорились против меня)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551

Но в протеусе она хоть убейся равна около 3333

И результаты в Freq и RPM при этом верные.

Протеус глючно отображает переменные unsigned long (он их показывает 2-х байтными), есть такой у него косяк. Причём signed long отображает нормально.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

Хм, да... Действительно. Поменял на long и всё стало отображаться правильно.

Единственное, TurnsTime при 5 гц получает значения примерно в районе 199950

но иногда прыгает выше 200000 и соответственно частота становится ниже.

С чем вообще связаны такие скачки значений при, вроде бы, одинаковых данных?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551

Скорее всего связано с разным временем выхода на обработку. +-50 тактов потери для подобного МК - мелочи. Не обращайте на это внимания.

Для более точных измерений нужно использовать чипы с аппаратными средствами запуска и останова таймера на время периода импульсов. Что-то типа захвата.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

Ясно, спасибо.

Вот сейчас исправил код исходя из всех полученных данных. С учетом 2 имп на оборот и считать по 3 оборота(6 импульсов).

Так же сделал MksTurns += 65536 - TMR1; потому как на момент выполнения этой строки в TMR1 не 0.

Выставил 50 гц. Нажал и зажал пошаговое выполнение.... сидел наверное минут 10. Все было четко. Ячейки привьюс валуе у Freq и RPM так и остались пустые.

Но решил попробовать на другой частоте. Поставил 24 и где-то через минуту во freq мелькнул 0 а потом еще через пару минут в RPM мелькнуло значение 208 при должных 720. Остановил. И заново запустил..... и снова словил теже цифры примерно в теже периоды времени. И еще раз - и снова с начало 0 в Freq при этом RPM как и положено 720, а затем 208 в RPM

+- 50 мкс - это понятно но тут получается:

720/60=12 об/сек = 83333,33 мск/об

и

208/60 = 3,47 об/сек = 288461,5 мск/об

разница в 205128 мск. Довольно не мало)

Откуда такие точности(0 и 208) при неточностях МК???

Или это снова протеус шалит а я опять панику поднимаю?) Спасибо!

И да, я вернул тип unsigned long, и просто в протеусе не обращаю на это внимание. Т.е. "внутренне" он считает правильно же? Неправильно только отображает..

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551
Т.е. "внутренне" он считает правильно же? Неправильно только отображает..
Да, так и есть, проблема только с отображением.

Сейчас заметил у Вас в алгоритме "косячок". В основном цикле Вы проверяете TurnsTime на отлисие от нуля и исходя из этого считаете, что период закончен и нужно подсчитывать обороты. Это неправильно, т.к. эта переменная у Вас всегда будет отличная от нуля и обороты у вас считаются постоянно (условие всегда срабатывает). Необходимо завести переменную-флаг, устанавливать его в прерывании по импульсу (когда окончено преобразование периода), проверять его в основном цикле, там же сбрасывать и подсчитывать обороты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 347

Алекс проверка не для этого, это блокировка деления на 0....

протез не видит long int

наложил структуру

12f675_tax.rar

  • Одобряю 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551
Алекс проверка не для этого, это блокировка деления на 0....
Ага, точно.

Ну значит в любом случае нужно добавлять флаг, по которому производить "общение" обработчик прерываний <-> основной цикл. Т.к. перед подсчётом оборотов нужно убедиться в том, что период окончен и в переменной лежит правильное и последнее значение таймера.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 347

помоему это лишние тк смена идет в прерывании и в основном коде не меняется или нет?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551

Возможно, в данном случае и лишнее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

Исправил.... точнее добавил проверку готовности данных. Вроде бы заработало. Alex как всегда на высоте!

Пришлось немного изменить CalcRPM ибо при высоких оборотах из-за кратности 10 происходил вылет за пределы типов.

TAH5_2.zip

Но как всегда..... тестирую пока :)

Вот только пару вопросов:

Как все таки правильнее

if (TMR1IF) { // Таймер переполнился
  MksTurns += 65536 - TMR1; // Считаем микросекунды
  TMR1IF = 0; // Сбрасываем флаг таймера
}

или

if (TMR1IF) { // Таймер переполнился
  TMR1IF = 0; // Сбрасываем флаг таймера
  MksTurns += 65536 - TMR1; // Считаем микросекунды
}

Флаг сбрасывать вначале или в конце обработки прерывания?

Вот GPIF нужно обязательно в конце, а как остальные, например TMR1IF?

Вот тут:

} else {
  ReadyData = 0; // Данные НЕ готовы
  CntImpl++; //прибавить счетчик импульсов
}

Сброс ReadyData делать как выше, т.е.:

ReadyData = 0;

или

if (ReadyData)  ReadyData = 0;

Или всеж компилятор сам так сделает?

Спасибо!

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551
Флаг сбрасывать вначале или в конце обработки прерывания?
Без разницы. По крайней мере в Вашем случае...

Вот тут:

} else {
ReadyData = 0; // Данные НЕ готовы
CntImpl++; //прибавить счетчик импульсов
}

Сброс ReadyData делать как выше, т.е.:

ReadyData = 0;

или

if (ReadyData) ReadyData = 0;

А какой смысл от условия, если в любом случае идёт очистка переменной ? :)

	 } else {
		 ReadyData = 0;		 // Данные НЕ готовы
		 CntImpl++;			 //прибавить счетчик импульсов
	 }

Тут сброс ReadyData не нужен, его нужно сбрасывать в основном цикле, когда прошла проверка на его установку. Иначе есть вероятность пропустить импульс (условие в основном цикле), если основной цикл случайно затянется, мало ли что Вы туда ещё потом добавите.

Т.е. проверили, сбросили, выполнили вычисления.

while (1) {
 if (ReadyData){
	 ReadyData=0;
	 RPM = CalcRPM();	 //Если данные готовы, посчитать RPM
}
}

Мало того, его можно не только пропустить, но и условие, опять же, будет постоянно выполнятся, т.к. Вы флаг не сбрасываете.

Это как флаг прерывания - сброс после его проверки. Не сбросил - прерывания тупо зациклятся...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

} else {
if (ReadyData) ReadyData = 0;
CntImpl++;
}

А какой смысл от условия, если в любом случае идёт очистка переменной ? :)

Ну я имел в виду что пока идут CntImpl++; что быстрее выполнится, повторное(многократное) ReadyData = 0; или столько же if (ReadyData)

Изменено пользователем AS7ti6K

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551

Ну я имел в виду что пока идут CntImpl++; что быстрее выполнится, повторное(многократное) ReadyData = 0; или столько же if (ReadyData)

Очистка переменной будет происходить быстрее, чем проверка её на ноль. Так что условие лишнее.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
IMXO    1 347

MksTurns += 65536 - TMR1; // Считаем микросекунды

по моему это глупость....

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

по моему это глупость....

Возможно..... Я точных математических расчетов не делал, но после того как сделал этот вычет, то RPM перестали занижаться на 1 из-за того, что TurnsTime становился чуть выше нужного....

...в данном случае отнимается 18 мкс на одно переполнение.... При низких оборотах накапливалось наверное...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

Можно несколько вопросов по Вашему коду?

volatile struct vremia
{
unsigned int tamerL;
unsigned int tamerH;
} TurnsTimes @0x041;
volatile unsigned long int TurnsTime @0x041;

Это отличается от volatile unsigned long TurnsTime;

? Т.е. вместо структуры использовать long переменную

или это собс-но вся фишка кода?

Просто коды почти похожи. Но Ваш, вроде как, стабильнее, хотя при высоких частотах, по моему "убегает вверх" (значение Freq становится больше, чем входная частота)

Хотя сейчас еще раз сравнил Ваш и "свой" код в протеусе. Примерно одинаково... на частоте 250-260 гц начинают "убегать вверх".

Я пока с моими ничтожными знаниями плохо ориентируюсь в таких вещах как "<<", ">>"

Но я примерно понял то, что в MksTurns у Вас количество переполнений таймера.

Потом это каким-то "волшебным" образом укладывается в Вашу структуру.

И там оказываются нужные микросекуны.

Что-то наподобие мне полгода назад Alex делал пример. Там похожий метод, но вместо структуры использовалась long переменная.

Все из-за тех же хитрых способах связанных с << я и не взял за основу его код, а зря. Нужно разбираться.

Изменено пользователем AS7ti6K

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551

Ещё совет - разберитесь с указателями. Через них легко укладывать значения маленьких переменных в большую.

А << и >> - это обычные сдвиги влево и вправо.

ЗЫ: по поводу "глупости". Действительно, при переполнении таймера не нужно учитывать его пересчёт при выходе на обработку (естественно, это в Вашем случае). Время выхода на обработку нужно учитывать только при прерывании от приходящего импульса, но на этом чипе это сделать невозможно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
AS7ti6K    2

Убрал... ничего не изменилось. Значит мне показалось с занижением)

Спасибо.

А сдвиги и указатели, конечно нужно изучать... Буду стараться и надеюсь на Вашу посильную помощь :)

Через них легко укладывать значения маленьких переменных в большую.

Т.е. это как сделал в примере IMXO? ..

.volatile struct vremia

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Alex    551
Т.е. это как сделал в примере IMXO? ..
Нет, в его примере использованы сдвиги, а не указатели.

volatile struct - это немного не то )

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте аккаунт или войдите в него для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать аккаунт

Зарегистрируйтесь для получения аккаунта. Это просто!

Зарегистрировать аккаунт

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас