Недоступна генерация синуса выше 83 Гц (ATMega48)

Обсуждаем контроллеры компании Atmel.
Ответить
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение sheffline_85 »

Добрый день форумчане, написал код для Atmega 48 трехфазного частотника
Листинг

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

volatile char i; 
 
volatile unsigned char b_sin; // Индекс фазы B в таблице синуса
volatile unsigned char c_sin; // Индекс фазы C в таблице синуса
 
volatile unsigned char temp_a; // временное хранение значения фазы A
volatile unsigned char temp_b; // временное хранение значения фазы B
volatile unsigned char temp_c; // временное хранение значения фазы C
 
volatile unsigned int freq_inv=31250; // задает период прерывания
volatile unsigned int freq=83; // задает частоту
 
volatile unsigned char amp_sin = 255; // амплитуда синуса. 255 это максимум.   
 
#include <mega48.h>
#include <delay.h>
#include <stdio.h> 
#include <sin256.h> 
 
interrupt [EXT_INT0] void ext_int0_isr(void)
{
 
}
 
 
interrupt [EXT_INT1] void ext_int1_isr(void)
{
 
}
 
 
interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
 
ADCSRB = sin[i];
                   
temp_a=((unsigned int)amp_sin*(unsigned int)sin[i])>>8;
 
OCR0A = temp_a;
     
b_sin=i+85;
 
ADCSRB = sin[b_sin];
 
temp_b=((unsigned int)amp_sin*(unsigned int)sin[b_sin])>>8;
 
OCR0B = temp_b; 
 
c_sin=i+170;
 
ADCSRB = sin[c_sin];
 
temp_c=((unsigned int)amp_sin*(unsigned int)sin[c_sin])>>8;
 
OCR2A = temp_c;
 
i++;
if (i>255) i=0;
 
b_sin++;
if (b_sin>255) b_sin=0;
 
c_sin++;
if (c_sin>255) c_sin=0;
 
}
 
 
void main(void)
{
#pragma optsize-
CLKPR=0x80;
CLKPR=0x00;
#ifdef _OPTIMIZE_SIZE_
#pragma optsize+
#endif
 
PORTD=0x0C;
DDRD=0x00;
TCCR0A=0xA3;
TCCR0B=0x01;
TCNT0=0x00;
ASSR=0x00;
TCCR2A=0x83;
TCCR2B=0x01;
TCNT2=0x00;
 
 
DDRD|=(1<<5)|(1<<6); // PD5 PD6  выходы ШИМ Таймер0
DDRB|=(1<<3);        // PB3      выход  ШИМ Таймер2
 
 
OCR1AH = ((unsigned int)freq_inv/(unsigned int)freq)>>8;
OCR1AL = ((unsigned int)freq_inv/(unsigned int)freq);
 
OCR1BH=0x00;
OCR1BL=0x00;
 
TCCR1A = 0x00;
TCCR1B = 0x09;
EICRA=0x00;
EIMSK=0x00;
PCICR=0x00;
 
 
TIMSK0=0x00;
   
TIMSK1=0x02;
 
TIMSK2=0x00;
   
UCSR0A=0x00;
UCSR0B=0x08;
UCSR0C=0x06;
UBRR0H=0x00;
UBRR0L=0x0C;
 
ACSR=0x80;
ADCSRB=0x00;
 
// Global enable interrupts
#asm("sei")
 
while (1)
      {
 
      }
}


Я новичок, не пинайте сильно, что в данном коде не так?
Попытка выставить любую частоту выше 83 заканчивается одним и тем же, работой на частоте 50 Гц.
компилятор CodevisionAVR, проверяю в протеусе.

Код естественно будет доработан плюшками, но пока хоть разобраться с частотой, она регулируется только в диапазоне 0-83 Гц

Попытка производить вычисления в теле прерывания таймера 1 приводит вообще к околесице, к тому же самому только в 30 Гц.

в синусе 256 значений, для целого числа сдвига фаз.

потолком является величина 2-значная.
Регистр OCR1A как и таймер 1 16 битный.
Число 8000000/(256*freq) в любом случае меньше 2 байт.
Процедура деления выполняется нацело, т.е. без плавающей точки, т.е. те же 100 Гц будут в регистре OCR1A числом 138 или же OCR1AH=0x01 OCR1AL=0x38, при попытке прописать эти значения в лоб, то же самое происходит что при вычислении (естественно вычисление закоменчивается при этом).

Что за затык может быть такой искусственный?
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение ARV »

unsigned char i;

фазаА = sin[i];
фазаВ = sin[(i+85) & 0xFF];
фазаС = sin[(i+170) & 0xFF];
i++;

это и весь обработчик прерывания. не нужно 3 разных индекса, не нужно проверять индексы на переполнение... как-то так.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение sheffline_85 »

переписал код как вы посоветовали

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

interrupt [EXT_INT1] void ext_int1_isr(void)
{

}


interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
                 
OCR0A = ((unsigned int)amp_sin*(unsigned int)sin[i])>>8;
     
OCR0B = ((unsigned int)amp_sin*(unsigned int)sin[(i+85)&0xFF])>>8; 

OCR2A = ((unsigned int)amp_sin*(unsigned int)sin[(i+170)&0xFF])>>8; 

i++;

}


Диапазон расширился до 115 Гц, в принципе теперь мне его за глаза и за уши.
Я так понимаю данное ограничение вызвано размером ОЗУ МК?
т.е. если применить 128 атмегу с 4кБ ОЗУ то вполне себе влезет 460 Гц 256 точеченого синуса?
а с проверкой по переполнению это я да, перемудрил, сам выбрал режим очистки OCR0A/B и OCR2A по переполнению и зачем-то продублировал это в преывании, сожрав дополнительно процессорное время.
Последний раз редактировалось sheffline_85 Пт ноя 07, 2014 15:06:03, всего редактировалось 2 раза.
Аватара пользователя
mail_robot
Встал на лапы
Сообщения: 112
Зарегистрирован: Сб янв 05, 2013 07:03:09
Откуда: в #опе изумруды?

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение mail_robot »

прока проц будет считать синус, я успею глотнуть пива и покурить сходить.

Любой выпускник ясельной группы детского садика г. Мухосранска знает, что сперва надо заготовить таблицу уже посчитаных синусов, потом собрать их в массив с индексами соответствующими углам, радианам или еще там чему, а потом в коде просто дергать уже готовый синус из таблицы.

ваш кэп
Нужно делать то, что нужно. А то что не нужно, делать не нужно (с) Винни Пух
Аватара пользователя
ARV
Ум, честь и совесть. И скромность.
Сообщения: 18544
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск
Контактная информация:

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение ARV »

где вы увидели связь объема ОЗУ с частотой генерации синуса?!

синус у вас генерируется прерываниями? предположим, каждое прерывание берется новая выборка синуса, т.е. максимальная частота синуса у вас будет равна частота_прерываний*256, т.е. частота синуса завсит только от частоты прерываний.

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

Мой уютный бложик... заходите!
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение sheffline_85 »

Ну так она заготовлена и объявлено место ее хранения в начале кода
#include <mega48.h>
#include <delay.h>
#include <stdio.h>
#include <sin256.h>


Или вы предлагаете на каждое значение амплитуды отдельную таблицу бахать? :shock:
Проц не считает синус, он берет готовые значения из таблицы, пихает их в регистр сравнения с кратным частоте синуса периодом катается по таблице.
Единственное сто проц считает это амплитуду данного синуса и его частоту, последнее сделано для лианеризации, чтобы можно было плавно разгонять или кратно по кнопке менять частоту.

Синус проц не считает в данном коде.
Аватара пользователя
mail_robot
Встал на лапы
Сообщения: 112
Зарегистрирован: Сб янв 05, 2013 07:03:09
Откуда: в #опе изумруды?

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение mail_robot »

аааа, ну ладна :tea:
Нужно делать то, что нужно. А то что не нужно, делать не нужно (с) Винни Пух
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение sheffline_85 »

ARV
понял вас, спасибо, т.е. нужно максимально оптимизировать процессы внутри прерывания?
единственное что я вижу целесообразным это вынесение расчета амплитуды за пределы прерывания, куда ее лучше пихнуть в бесконечный цикл или в майн?
Проверил ограничив код вашим первоначальным вариантом, потолком стала частота 200 Гц

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

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{
                 
OCR0A = sin[i];
     
OCR0B = sin[(i+85)&0xFF]; 

OCR2A = sin[(i+170)&0xFF]; 

i++;

}


я так понял чтобы поднятся выше придется уже резать таблицу с 256 до 128/64/32 значений?
sheffline_85
Нашел транзистор. Понюхал.
Сообщения: 176
Зарегистрирован: Ср дек 08, 2010 11:05:59
Откуда: Ростов-на-Дону
Контактная информация:

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение sheffline_85 »

попробовал делать обсчет амплитуды вне тела прерывания получается чехарда с кучей шума на вершинах.
Видимо все же придется оставить как есть, на месте, а для желающих получить 400 гц привод посоветовать высокочастотные Атмеги.
uk8amk
Поставщик валерьянки для Кота
Сообщения: 2222
Зарегистрирован: Вт ноя 27, 2007 11:32:06
Откуда: Tashkent

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение uk8amk »

Для этого делают пинг-понг буфер. Пока первый обсчитывается, воспроизводится второй. Потом они меняются местами. Никакого шума и чехарды.

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

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение Kavka »

Что-то думается, что volatile там не нужен.
Спойлер

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

interrupt [TIM1_COMPA] void timer1_compa_isr(void)
{

static unsigned char i=0;
                 
OCR0A = sin[i];
     
OCR0B = sin[(i+85)&0xFF];

OCR2A = sin[(i+170)&0xFF];

i++;

}
Когда уже ничего не помогает - прочтите, наконец, инструкцию.
Лучший оптимизатор находится у вас между ушей. (Майкл Абраш, программист Quake и QuakeII)
Избыток информации ведёт к оскудению души - Леонтьев А. (сказано в 1965 г.)
Аватара пользователя
COKPOWEHEU
Говорящий с текстолитом
Сообщения: 1525
Зарегистрирован: Чт июн 10, 2010 20:11:19

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение COKPOWEHEU »

Можно добавить множитель частоты

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

volatile freq_mult=1;
...
static unsigned char i=0;
i+=freq_mult;
Да, будет пропуск какого-то количества значений, но при 256 значениях в таблице будет не слишком заметно.
vdavid
Мучитель микросхем
Сообщения: 410
Зарегистрирован: Чт ноя 13, 2008 16:33:42

Re: Недоступна генерация синуса выше 83 Гц (ATMega48)

Сообщение vdavid »

sheffline_85 Асинхронная загрузка OCRx на частотах близких к частоте ШИМ приводит к полному безобразию. Загружайте в прерывании переполнения таймера ШИМ. Это раз. Максимальная частота синуса на 256 точках может быть 20 000 000/256/256=305 Гц. Для дальнейшего повышения частоты уменьшаем число точек. Ну, и, наконец, для нормального формирования сигналов для управления мостом все равно нужно переходить на Phase correct PWM. При этом частота (или число точек синусоиды) еще уменьшится вдвое Посмотрите на апликейшены Атмел. Там все просто и доходчиво.
Ответить

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