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

 
 
4 страниц V  < 1 2 3 4 >  
Closed TopicStart new topic
> MSP430 - вопросы от чайника, генератор опорного напряжения
Daria
сообщение Jun 14 2008, 21:39
Сообщение #31


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Jun 12 2008, 23:18) *
1. если вы хотите задействовать аппаратные возможности таймера по формированию импульсов, то сразу же используйте и аппаратную возможность синхронизации запуска АЦП. Обратите внимание, что вместо того, чтобы программно "дергать" битом ASC12SC можно аппаратно управлять запуском преобразования от сигналов TA1 или TB0, TB1. Т.е. как я и предлагал ранее - формировать времянку с помощью выходного сигнала TA1 и им же управлять запуском АЦП.

Спасибо, постараюсь разобраться smile.gif
Цитата(rezident @ Jun 12 2008, 23:18) *
2. Насчет шумов АЦП и осреднения. Время сэмплирования и преобразования нужно выбирать, исходя в т.ч. из соображений сопротивления источника сигнала. Вы не слишком ли малое время сэмплирования выбрали? Поскольку у вас количество каналов измерения значительно меньше, чем количество каналов АЦП, то усреднение можно сделать полуаппаратно. Запускаете АЦП в режиме последовательности каналов которые сконфигурированы на один и тот же вход АЦП. А затем простым вычислением среднего арифметического значения нескольких значений ADC12MEMx усредняете.

А я вот примерно так и собиралась сделать smile.gif даже и не знаю, как по-другому biggrin.gif спасибо еще раз.
Господа, товарищи, и все же
Помогите разобраться с переопределением типов!!!
int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело? Объясните, пожалуйста!
заранее спасибо.
Go to the top of the page
 
+Quote Post
Dog Pawlowa
сообщение Jun 15 2008, 09:37
Сообщение #32


Гуру
******

Группа: Свой
Сообщений: 2 702
Регистрация: 14-07-06
Пользователь №: 18 823



Цитата(Daria @ Jun 15 2008, 00:39) *
Помогите разобраться с переопределением типов!!!
int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело?

Я думаю, что дело в том, что x никогда не бывает больше 2y-1.
Я предпочитаю работать с целочисленной арифметикой, но при этом нужно держать в памяти диапазоны возможных значений аргументов. Впрочем, как Вы используете float, тоже нужно smile.gif


--------------------
Уходя, оставьте свет...
Go to the top of the page
 
+Quote Post
rezident
сообщение Jun 15 2008, 20:37
Сообщение #33


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Jun 15 2008, 03:39) *
Помогите разобраться с переопределением типов!!!
int x,y; переопределяю (float) (х), возвращаю return (int)(x/y), так как пока хочу работать с целыми, и принимающая программка сделана под них. Но отношение получается либо 0, либо 1. В чем тут дело? Объясните, пожалуйста!
Это не переопределение, а приведение типа. Чтобы операция деления производилась с числами именно типа float нужно приведение типов сделать непосредственно в выражении
Код
return ((int)((float)x/(float)y))
причем int и второй float можно не указывать, т.к. в операции деления приведение типа к более "высокому" будет сделано автоматически. И результат операции будет приведен к типу int автоматически в соответствии с типом результата, возвращаемым функцией. Но для наглядности можно написать так, как я указал.
Второй способ - использовать временные (локальные) переменные требуемого типа. Большого расхода памяти это не вызовет, т.к. компилятор оптимизирует сам обращение к таким переменным.
Код
float fTmp;
if (y!=0)         //проверка исключения "деление на нуль"
{ fTmp=(float)x;  //приведение типа для наглядности
  fTmp/=(float)y; //опять же здесь приведение типа только для наглядности
}
else
  fTmp=0;        //вынужденная обработка возникшего исключения
return((int)fTmp);
Go to the top of the page
 
+Quote Post
Daria
сообщение Jun 16 2008, 20:24
Сообщение #34


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Большое спасибо, rezident, теперь все получилосьsmile.gif))
Go to the top of the page
 
+Quote Post
rezident
сообщение Jun 16 2008, 20:30
Сообщение #35


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Я рад вашим успехам smile.gif
Кстати, если вам требуется округление, то можно (до преобразования в int) при вычислениях с float прибавлять число 0.5f.
Go to the top of the page
 
+Quote Post
VAI
сообщение Jun 17 2008, 03:32
Сообщение #36


Профессионал
*****

Группа: Модераторы
Сообщений: 1 120
Регистрация: 17-06-04
Пользователь №: 37



Цитата
прибавлять число 0.5f.

если число положительное, и вычитать 0.5, если число отрицательное.
Примерно, в общем виде, где-то так:
Код
/* --- round() -------------------------------------------------------------------------------------------- **
*  На выходе получаем округлённый float-результат
*  value    - что округлять
*  accuracy - с какой точностью округлять (например 2. или 0.03 или 0.1 и т.д.)
* -------------------------------------------------------------------------------------------------------- */
float round( float value, float accuracy )
{
  return( ((long)( value / accuracy + ( value < (float)0. ? (float)-0.5 : (float)0.5 ))) * accuracy );
}


--------------------
Если зайца бить, его можно и спички научить зажигать
Сколько дурака не бей - умнее не будет. Зато опытнее
Go to the top of the page
 
+Quote Post
Daria
сообщение Jun 17 2008, 19:48
Сообщение #37


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Jun 17 2008, 00:30) *
Я рад вашим успехам smile.gif

Зря иронизируете, я медленно(очень медленно), но верно расту biggrin.gif
Цитата(rezident @ Jun 17 2008, 00:30) *
Кстати, если вам требуется округление, то можно (до преобразования в int) при вычислениях с float прибавлять число 0.5f.

Спасибо за совет - пригодится smile.gif



Цитата(VAI @ Jun 17 2008, 07:32) *
если число положительное, и вычитать 0.5, если число отрицательное.
Примерно, в общем виде, где-то так...

Спасибо, VAI.
Go to the top of the page
 
+Quote Post
rezident
сообщение Jun 18 2008, 16:28
Сообщение #38


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Jun 18 2008, 01:48) *
Зря иронизируете, я медленно(очень медленно), но верно расту biggrin.gif
Никакой иронии! Это чистосердечно. Смайлик неподходящий выбрал. Вот такие надо было. a14.gif
Go to the top of the page
 
+Quote Post
Daria
сообщение Jun 22 2008, 15:37
Сообщение #39


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Здравствуйте, и снова вопросы smile.gif много, много вопросов smile.gif
1.!! Сначала по поводу усреднения отсчетов для уменьшения шума -
предлагали использовать бит MSC в регистре ADC12CTL0. Правильно ли я понимаю, что тогда значения выборок будут постоянно(до сброса бита ENC) записываться в регистры ADC12MEMx, и получить усредненное значение можно считывая значения из разных регистров ADC12MEMx и деля на их количество? Но у меня 16 каналов АЦП, задействовано в дальнейшем будет 5. Т.е. я могу использовать для усреднения только три значения из регистров ADC12MEMx - маловато будет... sad.gif
ну, или я все же не понимаю, поясните тогда принцип использования бита MSC.
Делаю усреднение пока так(знаю, что криво, но)
int filter(int r[10])// среднее арифметическое 10 значений
{
int s, t;
s = 0;
for(t = 0 ; t < 10 ; t++)
s+=r[t];
return s/10;
}
...
ADC12CTL0 = ADC12ON + REFON + SHT0_8;// настройка АЦП
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1+ SHS_1;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;
index = 0;
...
И, собственно
if (TACCTL0 & CCIFG)// если таймер переключился
{

if (P1OUT & BIT5)// и, если вывод все еще в единице,т.е. еще идет длинный импулсьс
{

ADC12CTL0 |= ENC;
Vr[0][index] = ADC12MEM3; // записываем в массив значения из ADC12MEMх
Vr[1][index] = ADC12MEM4;
ADC12CTL0 &= ENC;

index++;
if (index >= 10)// когда значений в массиве 10
{
index = 0;
offset[0] = (Vs[0] - filter(Vr[0]))/2; // Вычисление смещений уровня сигнала
offset[1] = (Vs[1] - filter(Vr[1]))/2;

Vx = filter(Vr[0]) - offset[0]; //вычисление координат вектора маг.индукции
Vy = filter(Vr[1]) - offset[1];

azimut = calculation (Vx,Vy); //вычисление азимута

}


send_int(azimut);

} send_int(azimut) - вычисленный азимут посылается на СOM. Описание send_int было выше в теме, да и не в ней суть, на вычисления тоже можно не обращать внимания smile.gif
ВОПРОС! -
2.!! В данном случае вычисляю азимут 10 раз, а посылаю только один. т.е. 10 раз посылается одно и то же значение. Если переношу строчку send_int(azimut); под строку
azimut = calculation (Vx,Vy); - т.е. сразу после вычисления и отправляю, то программа не работает sad.gif На СOM ничего не приходит! 07.gif Поясните, пожалуйста, если будет время разобраться - ПОЧЕМУ?!
3.!! Вопрос не по теме MSP430, уж извините, но вдруг кто-нибудь знает - Когда считываю уровень сигнала с датчика, он самопроизвольно "плывет", плата лежит неподвижно, а уровень за минуту убегает довольно прилично, при вычислении азимута получается, что в минуту градусов +/- 5 07.gif С чем это может быть связано? Датчик, напоминаю, HMC1002 biggrin.gif Вопрос в основном к Курту, если он заглянет. Да, Kurt, отправила Вам письмо - загляните в ящик - там еще куча вопросов по компасу конкретно biggrin.gif Ну, Вы сами обещали помочь biggrin.gif
Ну вот, пока все - помогите, кто может чем сможет biggrin.gif Не ругайте за безграмотность и всех
с победой сбороной России biggrin.gif yeah.gif
Go to the top of the page
 
+Quote Post
rezident
сообщение Jun 22 2008, 18:38
Сообщение #40


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(Daria @ Jun 22 2008, 21:37) *
ну, или я все же не понимаю, поясните тогда принцип использования бита MSC.
Бит MSC не имеет прямого отношения к усреднению. Он лишь позволяет автоматически запускать таймер сэмплирования (Sample Timer) после каждого преобразования (если выбран режим последовательности каналов). На блок-схеме из User's Guide хорошо видно, что устройство выборки-хранения (Sample-and-Hold или УВХ в отечественной терминологии), подключенное к входному 16-и канальному мультиплексору управляется сигналом SAMPCON. Лог.1. SAMPCON включает режим выборки, в котором конденсатор УВХ заряжается до напряжения входного сигнала, подключенного к выбранному входу мультиплексора, а лог.0 отключает УВХ от мультиплексора и запускает преобразование. Длительность лог.1 задается таймером сэмплирования, либо внешним сигналом в обход таймера сэмплирования. Сам таймер сэмплирования запускается по фронту сигнала SHI, который формируется либо программно от ADC12SC, либо одним из трех внешних сигналов от модулей таймера A или таймера B. Так вот установка бита MSC позволяет не ждать фронта сигнала SHI для запуска каждого последующего преобразования, а формировать его аппаратно по окончании предыдущего преобразования. Но это все работает только, если выбран режим управления от Sample Timer и режим последовательности каналов.
Цитата(Daria @ Jun 22 2008, 21:37) *
Делаю усреднение пока так(знаю, что криво, но)
int filter(int r[10])// среднее арифметическое 10 значений
{
int s, t;
s = 0;
for(t = 0 ; t < 10 ; t++)
s+=r[t];
return s/10;
}
Ну некоторая "кривизна" присутствует только при передаче аргумента функции. Передавать следует указатель на массив отсчетов и возможно еще и длину этого массива.
Код
int filter(int *ptr, int size)
{ int s=0, t;
  for(t=0; t<size; t++)
  s+=*ptr;
  ptr++;
  if (size>0)  //проверим на исключение "деление на нуль"
    return (s/size);
  else
    return 0;
}

Вызов функции будет такой
Код
x=filter(r, 10);

или
Код
x=filter(&r[0], 10);

Передавать второй аргумент имеет смысл потому, что если вы неправильно неудачно выбрали времена, то у вас будет заполнен не весь буфер. Т.е. за выбранное время будет меньше 10 преобразований. См. ниже про эту потенциальную ошибку.
Цитата(Daria @ Jun 22 2008, 21:37) *
...
ADC12CTL0 = ADC12ON + REFON + SHT0_8;// настройка АЦП
ADC12CTL1 = CSTARTADD0 + CSTARTADD1 + ADC12SSEL_1+ CONSEQ_1+ SHS_1;
ADC12MCTL3 = INCH_3;
ADC12MCTL4 = INCH_4 + EOS;
index = 0;
...
Еще раз обращаю внимание, что во избежание ошибок при формировании слова из отдельных битов следует пользоваться побитовым ИЛИ '|', а не оператором сложения '+'.
Цитата(Daria @ Jun 22 2008, 21:37) *
И, собственно

if (P1OUT & BIT5)// и, если вывод все еще в единице,т.е. еще идет длинный импулсьс
{
Здесь возможно имеется потенциальная алгоритмическая ошибка. Проверять нужно не только до начала преобразования, но и после окончания преобразования. И если после окончания преобразования бит сменил свое состояние, то результат последнего преобразования нужно отбрасывать. Следовательно у вас может быть не 10 отсчетов, а меньше. Поэтому выше я предложил передавать в функцию фильтрации еще и реальную длину буфера отсчетов.
Цитата(Daria @ Jun 22 2008, 21:37) *
2.!! В данном случае вычисляю азимут 10 раз, а посылаю только один. т.е. 10 раз посылается одно и то же значение. Если переношу строчку send_int(azimut); под строку
azimut = calculation (Vx,Vy); - т.е. сразу после вычисления и отправляю, то программа не работает sad.gif На СOM ничего не приходит! 07.gif Поясните, пожалуйста, если будет время разобраться - ПОЧЕМУ?!
Затрудняюсь сходу дать однозначный ответ, но думаю, что причиной является факт, что получение значения измерения и передача его через UART это процессы вообще-то асинхронные, но вы их пытаетесь принудительно синхронизировать без использования буферов. Вы используете передачу по опросу бита готовности, а не по прерыванию. А каждая передача "тормозит" измерения на время передачи двух символов. Поэтому за тот же самый интервал времени (который у вас фиксированный и определяется таймером) вы получаете меньше отсчетов, чем предполагаемое вами количество (10). Следовательно условие if (index >= 10) не выполняется, результата azimut вы не получаете, и передача через UART тоже не идет. Для решения этой проблемы рекомендую использовать передачу по прерываниям и формировать для передачи свой собственный буфер, линейный или циклический.

По 3-му вопросу ответить не могу. Я не "копенгаген", да и с подобными датчиками я не работал laughing.gif
Эскизы прикрепленных изображений
Прикрепленное изображение
 
Go to the top of the page
 
+Quote Post
Daria
сообщение Jun 24 2008, 19:17
Сообщение #41


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Здравствуйте снова.
Rezident, спасибо за подробный разбор, но вот я начала после Ваших комментов разбираться и окончательно зависла 07.gif biggrin.gif
Во-первых, после того, как фильтр сделала по Вашему совету - с делением не на 10, а на index. числа начали получаться жуткими и бессмысленными, вразнобой и без всякой связи с поворотом платы - как это можно объяснить? 07.gif
Во-вторых, я, наивная, полагала, что преобразование АЦП запускается сейчас синхронно с переключением таймера, я ведь вроде не битом ADC12SC "дергаю", а ставлю бит SHS_1 в ADC12CTL1 - т.е использую выход таймера А1... или нет? Проверка if (P1OUT & BIT5) идет не перед стартом преобразования, а перед тем, как записывать новый элемент в массив, т.е. как раз то, о чем Вы говорите... так мне казалось smile.gif
В третьих, тут вроде все советовали как раз использовать как можно меньше прерываний, лучше вообще без них, вот и стараюсь без них smile.gif
и вообще - Вы обещали рассказать, как в данном случае не программно дергать P1OUT, а использовать выход таймера - как это можно сделать, ведь изменение состояния вывода должно произойти только через 918 переключений таймера 05.gif
И все-таки вопрос - почему send_int(azimut) нельзя перенести в то место, в которое хочется smile.gif ? Если бы условие if (index >= 10) никогда не выполнялось, то и вычисление никогда не происходило бы, а что-то таки вычисляется. Без фильтра работает smile.gif только сильно скачет, что не есть хорошо.
Вот такие непонятки smile.gif
будет время, ответьте, пожалуйста.

Сообщение отредактировал Daria - Jun 24 2008, 19:19
Go to the top of the page
 
+Quote Post
rezident
сообщение Jun 24 2008, 20:13
Сообщение #42


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Daria, давайте все исходники (весь проект). Варианты возможных нюансов в многоветвистое дерево вырастают, а телепатия что-то тяжело нынче идет smile.gif
Я бы вам посоветовал отладить работу АЦП не с датчиком, а с постоянными напряжениями для начала. Вы еще не до конца разобрались с синхронной работой ADC12 и TimerA и вообще с функционированием ADC12.
Go to the top of the page
 
+Quote Post
Daria
сообщение Jun 25 2008, 18:18
Сообщение #43


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(rezident @ Jun 25 2008, 00:13) *
Я бы вам посоветовал отладить работу АЦП не с датчиком, а с постоянными напряжениями для начала.

да пробовала smile.gif Вроде нормально идет. Правда, пробовала без всяких усреднений...
Цитата(rezident @ Jun 25 2008, 00:13) *
Вы еще не до конца разобрались с синхронной работой ADC12 и TimerA и вообще с
функционированием ADC12.

Эт точно biggrin.gif да и с USART похоже тоже. Видимо все дело в том, как я отправляю число. Функция send_int получилась кривоватая. Вот подскажите, как просто и хорошо отправить целое число, 12бит, чтобы занять как можно меньше времени и получить как можно меньше ошибок при приеме? Пробовала без флажка 0xFF, означающего конец посылки, но при "слеплении" получаются ошибки.
вы говорили, что нужно как-то по прерываниям работать, как? smile.gif Да, вот что странно, когда я разрешаю прерывания по передаче, вообще перестает работать.
А проект пока маленький совсем, прикладываю текст.
Не ругайтесь на "+", я потом обязательно исправлю, все как-то недосуг smile.gif
Вообще спасибо за поддержкуsmile.gif

Сообщение отредактировал Daria - Jun 25 2008, 18:25
Прикрепленные файлы
Прикрепленный файл  1.txt ( 6.62 килобайт ) Кол-во скачиваний: 108
 
Go to the top of the page
 
+Quote Post
NoName
сообщение Jun 26 2008, 14:11
Сообщение #44


Участник
*

Группа: Участник
Сообщений: 36
Регистрация: 4-03-05
Из: Киев
Пользователь №: 3 078



Цитата(Daria @ Jun 25 2008, 21:18) *
Функция send_int получилась кривоватая. Вот подскажите, как просто и хорошо отправить целое число, 12бит, чтобы занять как можно меньше времени и получить как можно меньше ошибок при приеме?


Имеет смысл сразу организовать протокол обмена.
Пример:
адрес получателя 1 или 2 байта
идентификатор пакета 2 байта - соответвует идентификатору запроса.
длина данных пакета 1 или 2байт
данные []
адрес отправителя 1 или 2 байта
СRC 2 байт

истина прописная, протокол то все равно прийдется организовывать )))
либо воспользоватся общепринятыи протоколом для Вашей конторы ...
Go to the top of the page
 
+Quote Post
Daria
сообщение Jun 26 2008, 18:44
Сообщение #45


Местный
***

Группа: Участник
Сообщений: 229
Регистрация: 24-02-08
Пользователь №: 35 345



Цитата(NoName @ Jun 26 2008, 18:11) *
Имеет смысл сразу организовать протокол обмена.
либо воспользоватся общепринятыи протоколом для Вашей конторы ...

Спасибо. Общепринятого протокола нет - контора большая, кто обменивается, тот между собой обычно и договариваетсяsmile.gif А пока как-нибудь. А имеет смысл писать такой протокол ради того, чтобы просто постоянно отправлять число от 0 до 360 на COM- и больше ничего?
Да, rezident, бог с ним. с усреднением - все равно особенно не поможет, нужно делать норамльный цифровой фильтр. А я до него еще не доросла smile.gif Чутка попозже. Пока вот вопрос - записываю число во flash, использую режим записи по словам. т.е. int число пишется легко и без проблем. А как записать float - надо уже режим поблоковой записи? Или нет?

Сообщение отредактировал Daria - Jun 26 2008, 18:50
Go to the top of the page
 
+Quote Post

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

 


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


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