Помогите ужать програаму, немного не влезает в ATTiny13

Обсуждаем контроллеры компании Atmel.
Ответить
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Kavka писал(а):Сколько по памяти получилось?
Получился предел мечтаний. 397слов сейчас. (Для вас конечно нет, но я в начале просто хотел чтобы прога залезла в кристалл)

Частота обновления дисплея выставлена таймером, минимум чтобы глаз не замечал мерцания. Тут все в порядке.
А вот отсчет прыгает то на следующее значение, то на предыдущее. Причем очень часто. Условно так: 4579, 4586, 4586, 4579, 4586... и последние 2 декады замыливаются. Если предпоследнюю еще можно различить, то последнюю нет.
Конденсаторы стоят 100пик
Вообще схема почти вот такая:
http://piccy.info/view3/7056674/27fe185 ... de5b/1200/
Только без стабилизатора тока, и вольтметр сделан делителем, тоже с конденсатором.

Сейчас стоит просто потенциометр 10к, который делит 5В и подается прямо на ноги, минуя делитель и усилитель. Конденсаторы на ногах стоят.

ПС: Нннда... я удивлялся как математические операции делают на ПК, там например транспонимарование матриц при помощи SSE... тут походу покруче замес :music:
Реклама
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Gisteresis
100 пик - это конечно круто :) . Поставьте лучше 100 нан. И R1 сильно уменьшить бы неплохо.
А под мельтишением я подразумевал именно слишком частую смену значений. Частота динамической индикации здесь ни при чем.
Реклама
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

vdavid писал(а):И R1 сильно уменьшить бы неплохо.
На днях прочитал про то, что сопротивление перед АЦП должно быть меньше 10к. 7.5к хватит?
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Зависит от частоты выборок. Чем больше частота - тем меньше должно быть сопротивление, чтобы успевал зарядиться внутренний конденсатор АЦП (его емкость порядка 13-14 пФ + сопротивление открытого ключа АЦП при выборке ~1 кОм + сопротивление Вашего резистора). А там уже считайте по формуле 1/RC и берите с запасом. ;)
Fucking static initialization order fiasco
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

R=(1/FC)-1000
Частота выбрана минимальная 75кГц
(1/75000*14*10^-12)-1000 = 951381 Ом
Почти 1 мегом, верно ли я считаю?
Пикофарад это 1*10^-12 фарад.
Реклама
Опытный кот
Аватара пользователя
Сообщения: 882
Зарегистрирован: Ср фев 22, 2012 01:25:21

Сообщение shads »

А как должна инфа отображаться на дисплее?
Если измерение тока и напряжения, то я так понимаю должно быть 2 четырех разрядных дисплея, на одном напруга на другом ток... но на схеме почему то один дисплей, хотя место есть для второго...
И значение должно быть с одним знаком после точки?
Реклама
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

верно ли я считаю?
Не совсем. Выборка происходит в первый такт из 13 тактов преобразования. ;) Т.е. реальное максимальное значение резистора будет в 13 раз меньше, т.е. не более 73 кОм для данной частоты выборок, чтобы не было искажений сигнала. Но лучше брать раза в два меньше - с запасом.
Fucking static initialization order fiasco
Контактная информация:
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Pink-Pank писал(а):Зависит от частоты выборок.
Вообще-то зависит от того, что и как мы измеряем. Это же не осциллограф и для усреднения результата мы делаем 256 выборок. Конденсатор служит для тех же целей, поэтому 1/RC может быть того же порядка, что и период всех выборок для усреднения. Я бы ничего не считал, а поставил 10 (можно 7.5) кОм и 0.1 мкФ.
Да и тактов преобразования здесь вовсе не 13. Плюс зачем-то задержка в 10 мкс перед запуском нового преобразования.
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

shads, извиняюсь за то что привел не совсем верную схему. Но я ниже пояснял что она доработана до вольтметра и амперметра, соответсвенно все как вы говорите 4 декады на вольты, 4 декады на амперы.
shads писал(а):И значение должно быть с одним знаком после точки?
Нее, так как я дисплей уже сделал, для вольт будет 2 знака после точки, а для ампер 3. Пофиг что там в конечных декадах будет шлак.
vdavid писал(а):Плюс зачем-то задержка в 10 мкс перед запуском нового преобразования.
Это генератор кода лепит и комментит что типа это стабилизирует результат преобразования...
По сути можно удалять.

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

// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
Опытный кот
Аватара пользователя
Сообщения: 721
Зарегистрирован: Ср июн 11, 2014 09:43:13
Откуда: США

Сообщение Pink-Pank »

Да и тактов преобразования здесь вовсе не 13..
Чтобы не ошибиться - проще отталкиваться от частоты тактирования АЦП. ) Тогда никакие такты считать не надо. и речь щла именно о максимальном номинале резистора. Если поставить слишком большой - конденсатор не будет успевать заряжаться/разряжаться - результат будет неверным.
Вообще, Атмеловцы рекомендуют в ДШ ставить резисторы не более 10 кОм, но они, видимо, отталкиваются от максимально возможной частоты тактирования АЦП + запас какой-то. Я в реальности ставил 200 кОм и понижал частоту примерно до 35 кГц - и все хорошо работало.
Fucking static initialization order fiasco
Контактная информация:
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Pink-Pank писал(а): Чтобы не ошибиться - проще отталкиваться от частоты тактирования АЦП.
Так именно их родимых будет 13 только в режиме free running. Здесь же мы имеем ручной запуск, так что уже точно не менее 14.5, плюс время выполнения кода в прерывании плюс 10 мкс. Еще раз про тау RC. Поскольку мы измеряем только для визуализации, то обновлять информацию чаще 3 раз в секунду не следует точно. Посему логично измерять именно среднее значение между последовательными обновлениями. Исходя из этого конденсатор и в 1 мкф при 10 кОм не испортит картину.
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Gisteresis писал(а):Получился предел мечтаний. 397слов сейчас.
Это ФЛЭШ. А в ОЗУ сколько занято?
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Kavka, В последнем варианте с 32-х битной арифметикой :) под стек осталось 47 байт. Хватит с головой.
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

В общем все работает. Всем огромное спасибо.
Обнаружил ошибку в плате. Питание ОУ не разведено :facepalm:
СпойлерИзображение

Изображение
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Gisteresis Так какой вариант прошивки, работает-то? Показания не сильно скачут? Мою последнюю пробовали?
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

Во, уже всё закончилось :)
Я пару заходов сделал на причёсывание кода и не только.
Получилась пара вариантов под gcc. Может кому пригодиться. Сразу скажу, что особо не старался, ибо проверять не на чем. Соответственно, могут быть ошибки. Но компилируется.

Добавил на следующий день:
Думаю, что накапливать в сумму для усреднения будет лучше сами "сырые" значения АЦП и масштабировать их единожды...
Вложения
av_metr_tiny13(v2).c
(3.66 КБ) 326 скачиваний
av_metr_tiny13(v1).c
(3.69 КБ) 339 скачиваний
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Друг Кота
Аватара пользователя
Сообщения: 4732
Зарегистрирован: Ср сен 18, 2013 10:08:26
Откуда: Санкт-Петербург

Сообщение Gisteresis »

Не ну можно и до идеала довести :)

Работает вот такой
Спойлер

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

#include <tiny13a.h>
#include <delay.h>

// Declare your global variables here

inline void wr_reg(char cData)
{
    char temp = cData;
    char i=0;
    for(i=0; i<8; i++)
    {
        PORTB.0 = (temp & 0x80);
        #asm("nop");
        PORTB.2 = 1;
        #asm("nop");        
        PORTB.2 = 0;
        temp = temp << 1;
    }
}

inline void latch_reg()
{
    #asm("nop");
    PORTB.1 = 1;
    #asm("nop");         
    PORTB.1 = 0;
}

flash char cSeg[]={
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111  // 9
};

char cDec = 0;
volatile char cDigit[8];
interrupt [TIM0_COMPA] void timer0_compa_isr(void)
{
    wr_reg(1<<cDec);
    wr_reg(cDigit[cDec]);
    //wr_reg(0b00000000);
    latch_reg();
    cDec += 1;
    if( cDec > 7 )
        cDec = 0; 
        
    TCNT0 = 0;
}

void toDigits(unsigned char i, unsigned long* ulSum) {
    unsigned char j;
    j=4;
    *ulSum=(5000UL*(*ulSum))/(256UL*1024);
    while (j>0) {
        j--;
        cDigit[i+j] = ~cSeg[*ulSum%10];
        *ulSum /=10;
    } 
    *ulSum = 0;
}

#define FIRST_ADC_INPUT 2
#define LAST_ADC_INPUT 3
#define ADC_VREF_TYPE 0x00

unsigned long ulVoltsSum = 0;
char sCounterVSum = 0;

unsigned long ulAmpersSum = 0;
char sCounterASum = 0;

// ADC interrupt service routine
// with auto input scanning
interrupt [ADC_INT] void adc_isr(void)
{
static unsigned char input_index=0;
// Read the AD conversion result
//// Select next ADC input
if (++input_index > LAST_ADC_INPUT)
   input_index=FIRST_ADC_INPUT;
ADMUX=ADC_VREF_TYPE +input_index;

if( input_index == 2 )
{
    ulVoltsSum += ADCW;
    sCounterVSum++;
    if( !sCounterVSum )
    {
        toDigits(0,&ulVoltsSum);
        cDigit[1] &= ~0b10000000;                       
        sCounterVSum = 0;        
    } 
}
if( input_index == 3 )
{   
    ulAmpersSum += ADCW;
    sCounterASum++;
    if( !sCounterASum )
    {
        toDigits(4,&ulAmpersSum);
        cDigit[4] &= ~0b10000000;
        sCounterASum = 0;        
    }
}
                 
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
}

void main(void)
{
// Declare your local variables here

// Crystal Oscillator division factor: 1
/*#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif*/

// Input/Output Ports initialization
// Port B initialization
// Func5=In Func4=In Func3=In Func2=In Func1=In Func0=Out 
// State5=T State4=T State3=T State2=T State1=T State0=0 
//PORTB=0x00;
DDRB=0x07;

// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 9400,000 kHz
// Mode: Normal top=0xFF
// OC0A output: Clear on compare match
// OC0B output: Disconnected
//TCCR0A=0x00;
TCCR0B=0x05;
//TCNT0=0x00;
OCR0A=0x10;
//OCR0B=0x00;

// External Interrupt(s) initialization
// INT0: Off
// Interrupt on any change on pins PCINT0-5: Off
//GIMSK=0x00;
//MCUCR=0x00;

// Timer/Counter 0 Interrupt(s) initialization
TIMSK0=0x04;

// Analog Comparator initialization
// Analog Comparator: Off
ACSR=0x80;
//ADCSRB=0x00;
//DIDR0=0x00;

// ADC initialization
// ADC Clock frequency: 73,438 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: Off, ADC1: Off, ADC2: On, ADC3: On
DIDR0&=0x03;
DIDR0|=0x24;
ADMUX=FIRST_ADC_INPUT | (ADC_VREF_TYPE & 0xff);
ADCSRA=0xCF;

#asm("sei")

   while(1)
   {
   }
}
Отличия:
Изменил ноги вывода в регистры под свою плату.
Добавил десятичные точки
Сделал быстрее таймер. Дисплей мерцал. Старое значение таймера было выбрано для 4х1 дисплея.
Ну и усреднения 256 отстчетов. Значения меняются примерно 3..4 раза в секунду если дергается. Но в основном это только последний разряд, остальные разряды вполне комфортно читабельны.
Регулировка пока не понял. Но похоже немного нелинейна. Настраиваю на максимальном значении (29В и ток по потенциометру который делит 5В до 0.5В имитируя шунт 0.1Ом) Точно сказать немогу, но пока такое ощущение что в пределах 100мВ погрешность. Прецизионным конечно не назовешь, но в блок питания пойдет. Учитывая что разрешение в 10бит, реально 8, больше и недадут. Ток тоже скурпулезно не мерял, но тоже уплывает порядка 100..200мА. Так как стоит ОУ lm358 меряет не от нуля. И еще небыло отдельного питания для ОУ, подключил его к 5В, выход упирался в 3.6В (тоесть ток показывал 3600мА на дисплее).
Выходной резистор так и не сменил пока, он так 100к и стоял, и все похоже работает. Конденсаторы тоже пока 100пик. В ближайщее время поменяю на рекомендованные вами.
Общие впечатления от поделки хорошие. С продающимися встраиваемыми цифровыми вольтметрами и амперметрами не сравнивал.
Подозреваю в оставшееся место памяти даже влезет и ваттметр или небольшая программа регулятора... Мне нужен был АмперВольтМетр я им ограничиваюсь.

Неудобство использования в том что ОУ требует питания больше 5В. В связи с этим нужно или на самой плате размещать 5ти вольтовый стабилизатор или еще как.
Кто как делает? Обязательно нужен собственный стабилизатор?

Как вы советуете к питанию прикрутить дроссель для фильтрации? Все схемы которые нахожу для более жирных МК, у которых есть Aref. Насколько это вообще актуально?

Kavka, ваш код попозже посмотрю. Может что скрестить можно.
Мудрый кот
Аватара пользователя
Сообщения: 1810
Зарегистрирован: Чт июн 10, 2010 08:55:35
Откуда: Сибирские Афины

Сообщение Kavka »

В общем то же самое.
Пару моментов.

Вот это

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

if( cDec > 7 )
cDec = 0; 
заменяется на вот это

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

cDec &= 7
Мелочь, но избавляет от ветвления.

И об усреднении отсчётов АЦП.
1023 * 256 = 261888 в unsigned int не влезает, то есть 32 битное целое. Как есть.
26188 * 5000 = 1309440000 тоже 32 битное целое. Как есть.
26188 * 5000 / (256 * 1024) = 5000 прекрасно умещается в unsigned int

Таким образом вот тут

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

// unsigned long* ulSum

*ulSum=(5000UL*(*ulSum))/(256UL*1024);
результат вычисления выражения можно сохранить в переменной меньшей длинны. Что далее уменьшит сложность вычисления модуля и деления.
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Сообщение vdavid »

Kavka писал(а): результат вычисления выражения можно сохранить в переменной меньшей длинны. Что далее уменьшит сложность вычисления модуля и деления.
Ага, только увеличится как использование флеша, так и оперативки :( .
Электрический кот
Аватара пользователя
Сообщения: 1031
Зарегистрирован: Чт июн 20, 2013 00:00:58
Откуда: москва, м.Сходненская

Сообщение Mishany »

с вычислениями сталкивался с проблемой невлазания в int, использование uint_32 заметно загружает мк вычислениями, и еще заметил одну особенность в вычислениях если в процессе вычислений (все переменные int) по формуле два множителя дают >65535 то результат вычислений получается неправильный. толи у меня глюки были толи я чего не понимаю. в итоге считал отдельно тысячи и отдельно сотни x/1000 и x%1000
Ответить

Вернуться в «AVR»