Страница 1 из 1

Динамическая индикация на ATTiny13

Добавлено: Пн сен 29, 2014 19:59:11
Gisteresis
Мяяяяу!
Бьюсь значит вот с каким шайтаном.
Сделал милливольтиметр на ATTiny13A. Частота 9.4МГц. Хочу вывести на 4значный семисегментный индикатор. Вывод динамический по прерыванию таймера, работает прекрасно. В прерывании АЦП происходит преобразование условных единиц АЦП в число и разбивка на декады, чтобы их потом выводило прерывание таймера. Все рабоает. Проверял выводом регистра АЦП. Выводит значение от 0 до 1023.

Первый вопрос.
Настроил преобразование АЦП на минимум, 73.438кГц. Значения на дисплее дергаются. Как сделать еще меньше? Например 2..3 преобразования в секунду.

Второй вопрос.
Преобразование кода сделал так

Код: Выделить всё

iVolts = 5*adc_data[0]-(24*adc_data[0]/1024)*5;
cDigit[0][0] = ~cSeg[((iVolts/1000)%10)];
cDigit[1][0] = ~cSeg[((iVolts/100 )%10)];
cDigit[2][0] = ~cSeg[((iVolts/10  )%10)];
cDigit[3][0] = ~cSeg[((iVolts/1   )%10)];
Понимаю, что изобрел протез. Как сделать нормально?
Если я просто делаю так

Код: Выделить всё

iVolts = 5000*adc_data[0]/1024
то преобразование упирается в 16ти битовое умножение. Операция 5000*adc_data[0] требует больше чем 16 бит.
Есть ли какой то аналог функции MulDiv?
Как это нормально сделать на ATTiny?

Расшифровывать эту писанину думаю не нужно?
cDigit[0][0] - это массив на 4 декады для того чтобы потом прерывание таймера брало оттуда и выводило.
cSeg - это массив с кодами семисегментного индикатора.

Просьба отослать к существующей ветке, если такая есть.

Re: Динамическая индикация на ATTiny13

Добавлено: Пн сен 29, 2014 20:32:39
ARV
во-первых: извиняюсь, вы применили какие-то схемные решения для подключения 7-сегментного 4-разрядного индикатора к МК с 6-ю доступными ножками? или ошибка и МК у вас другого типа?

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

Re: Динамическая индикация на ATTiny13

Добавлено: Пн сен 29, 2014 20:51:31
shads
Gisteresis писал(а):Первый вопрос.
Настроил преобразование АЦП на минимум, 73.438кГц. Значения на дисплее дергаются. Как сделать еще меньше? Например 2..3 преобразования в секунду.
Сделать усреднение... или просто поставь между обновлениями буфера дисплея _delay_ms (300);
(естественно - при этом динамическая обработка дисплея должна быть реализована в прерывании...)
Gisteresis писал(а):Второй вопрос.
Как сделать нормально?
Просто приведи любое из значений к 32-м разрядам...
Например так: iVolts = (uint32_t)5000*adc_data[0]/1024;
или так: iVolts = 5000UL*adc_data[0]/1024;
или так: iVolts = 5000*(uint32_t)adc_data[0]/1024

Re: Динамическая индикация на ATTiny13

Добавлено: Пн сен 29, 2014 21:03:40
vdavid
shads писал(а): или так: iVolts = 5000*(uint8_t)adc_data[0]/1024
Ну только не так :) .

Re: Динамическая индикация на ATTiny13

Добавлено: Пн сен 29, 2014 21:05:11
shads
vdavid писал(а):
shads писал(а): или так: iVolts = 5000*(uint8_t)adc_data[0]/1024
Ну только не так :) .
Хе... по привычке написал... естественно - (uint32_t)... поправлю :)...

Re: Динамическая индикация на ATTiny13

Добавлено: Пн сен 29, 2014 21:21:56
oleg110592
расчет можно подсократить, 4 разряд думаю не нужен - разрешение 1мВ вряд ли нормально получится

Код: Выделить всё

//V=(ADC*VAREF)/1024     
//V=ADC*500/1024 
//V=ADC*125/256       
Voltage = (unsigned int)(((unsigned long)read_adc(3)*125)>>8);
binary to bcd:

Код: Выделить всё

void Bin2bcd(unsigned int Value)
{
  unsigned char n=0;
  while (Value >= 100)
  {
    Value -= 100;
    n++;
  }
  Led0 = seg7[n];
  n = 0;
  while (Value >= 10)
  {
    Value -= 10;
    n++;
  }
  Led1 = seg7[n];
  Led2 = seg7[Value];
}
СпойлерИзображение

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:05:03
Gisteresis
ARV писал(а):какие-то схемные решения для подключения 7-сегментного 4-разрядного индикатора
Извиняюсь что не написал, но вроде это и ненужно было. Эта часть работает хорошо. Стоят 2 регистра 595х в первый пишется код цифры, второй зажигает нужную декаду через транзистор. В прерывании таймера зажигается одна декада, следующее прерывание зажигает следующую декаду. И так по кругу прерывание обновляет декады. Тут собственно проблем нет.
ARV писал(а):преобразование значения АЦП в выводимые символы не надо делать в прерывании!
Те в главном цикле ждать завершения прерывания?
А чем плохо если я это сделаю сразу в прерывании АЦП? Там код небольшой.
shads писал(а):Сделать усреднение...
Да, начал догадываться до этого. Спасибо.
shads писал(а):Просто приведи любое из значений к 32-м разрядам...
А вот просто привести к 32битам не получается. Вначале компилер говорит что РАМ не хватает. Ну ладно, расширил. Потом он говорит что это действие невозможно так как в ATTiny13 MUL 16ти битный. Там хоть к long long приводи, он все равно результат отрежет значением 65535. Вот в том то и вопрос был. Как с этим ограничением преобразовать данные с АЦП в миливольты и разбить на декады. Я поэтому и вспомнил MULDIV но не знаю какой ее аналог есть в CV. Код искал, пока безрезультатно.
oleg110592 писал(а):расчет можно подсократить, 4 разряд думаю не нужен - разрешение 1мВ вряд ли нормально получится
Ну оно собственно и не получается, там скорее шум какой то. Вопрос был скорее по математике преобразования.
Насчет подсократить подумаю, хорошее решение, сам не догадался.
....

Код: Выделить всё

read_adc(3)*125
Эта операция не пройдет. Максимальное значение АЦП 1024 его максимум можно умножить на 64, получится максимум 65536.

Всем спасибо за подсказки.

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:07:29
Dr. Alex
Gisteresis писал(а):... Частота 9.4МГц...
КАК???? :shock: Частота Тини13 9.6!!!!!

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:13:28
Gisteresis
Dr. Alex писал(а):Частота Тини13 9.6!!!!!
Да, 9.6мГц, вы правы.

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:18:43
oleg110592
приведение типов - (unsigned long)read_adc(3) теперь можно умножать на 125

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:23:27
Gisteresis
В ATTiny13 сама операция умножения 16ти битная. Привести к 32м битам можно, но само умножение не получается. Все, что выше 16го бита отрезается. Фирштейн. Тоесть максимальное число, которым может манипулировать тини 65535.
АЦП = 1024
1024*125=128000 что больше 65535.

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:26:50
oleg110592
все нормально работает (картинку приводил), причем тут тини - компилятор сделает всю работу

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:33:01
Gisteresis
Попробую ваш код вечером.
Но у меня уже было написано 5000*adc_data[0], и тут мне компилятор заявлял что команда MUL 16 битная, повторяю уже 4й раз. То есть числа подаем 32х битные, но в 16битные регистры с отрезанием всего лишнего. И результат выходит 16ти битный.
Оно собирается в исполняемый файл и после прошивки я вижу что работает только 2 последних разряда и там шлак. Что собственно и ожидалось от такого умножения.

ПС: Чтобы не устраивать пустой холивар, ждем до вечера. Опробую, скажу результат.

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 08:39:45
oleg110592
уже было написано 5000*adc_data[0]
если так, как выше товарищ shads говорил:

Код: Выделить всё

unsigned long V; 
V=5000UL*(unsigned long)adc_data[0];
компилятор не заявлял бы
Изображение

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 15:33:46
ARV
Gisteresis писал(а):
ARV писал(а):преобразование значения АЦП в выводимые символы не надо делать в прерывании!
Те в главном цикле ждать завершения прерывания?А чем плохо если я это сделаю сразу в прерывании АЦП? Там код небольшой.
не надо ничего ждать. если вам так ужасно хочется, молотите прерываниями АЦП, и в обработчике прерываний помещайте результат в переменную, которую затем в главном цикле по мере необходимости обсчитывайте и выводите изредка. только учтите, что для работы с 2-байтной переменной нужно обеспечить атомарность доступа, т.е. как минимум делайте так:

Код: Выделить всё

volatile int result_adc; // сюда в прерывании помещается результат

int main(void){
   // где-то в главном цикле делаете так
   int tmp;
   cli(); // запрет прерываний
   tmp = result_adc;
   sei(); // разрешение прерываний
   // дальше обрабатываете переменную tmp
}
только все это бессмысленно. я бы делал именно так, как вы сказали мне в ответ: в главном цикле ждал бы окончания преобразования и дальше его обрабатывал бы...

Re: Динамическая индикация на ATTiny13

Добавлено: Вт сен 30, 2014 17:18:12
slavokhire5
Dr. Alex писал(а):
Gisteresis писал(а):... Частота 9.4МГц...
КАК???? :shock: Частота Тини13 9.6!!!!!
В тини13 можно калибровать частоту =) так что 9.4 от внутреннего сделать не проблема

Re: Динамическая индикация на ATTiny13

Добавлено: Ср окт 01, 2014 08:03:00
Gisteresis
Модификатор UL решил проблему. Остальные множители не пришлось приводить к этому типу.

Код: Выделить всё

V=5000UL*adc_data[0]/1024;
Сделал усреднение. В общем все заработало как надо. Даже пытается что то вроде 4го разряда показывать, очень грубо.
Всем спасибо.