Как сгенерировать сигнал ШИМ, который изменяется не менее чем в 20 раз в диапазоне 0-5 В, используя микроконтроллер Atmeaga32 avr?

Я делаю проект фотоэлектрического (PV) регистратора данных, в качестве нагрузки можно использовать силовой полевой МОП-транзистор (IRFZ34N). Поэтому я хочу изменить напряжение затвора с помощью ШИМ-сигнала (диапазон 0-5 В) MCU, и мне нужно не менее 20 различных точек. поэтому я запутался при написании кода «C» для генерации ШИМ-сигнала. как 1. какой должен быть период времени PWM? 2. Как я могу варьировать рабочий цикл ШИМ на разных этапах? и так далее..

И, пожалуйста, помогите мне, если что-то еще, что я должен сделать, чтобы сделать мой проект успешным. Я был бы очень благодарен, если бы кто-то помог мне с ответом.

Ответы (2)

Вы можете сделать это в программном обеспечении и отслеживать все необходимые тайминги самостоятельно, но большинство микроконтроллеров имеют аппаратное обеспечение, которое может генерировать автономную ШИМ после того, как вы его инициализируете. Основными вещами являются таймер/счетчик и регистр сравнения выходных данных (OCR):

введите описание изображения здесь

Счетчик непрерывно увеличивается, представленный наклоном, и сравнивается с OCR. Выход PWM становится низким, когда счетчик превышает OCR, и снова становится высоким, когда он сбрасывается. Требуемое разрешение 5 % (20 шагов) не является проблемой; 16-битный таймер может генерировать ШИМ с разрешением лучше 0,002 %, и даже 8-битный таймер может генерировать разрешение 0,4 %.

Все, что вам нужно сделать, это запрограммировать новое значение в OCR. Чем меньше значение, тем меньше ширина импульса. Следующая анимация взята с этого сайта :

введите описание изображения здесь

Дальнейшее чтение
Использование высокоскоростного ШИМ AVR, примечания по применению Atmel.
Техническое описание ATMega32 описано на стр. 69 и далее. как использовать Timer0 для работы PWM.

Движущиеся картинки в Интернете? Это считается как минимум 10 000 красивых голосов.
@Kortuk - надеюсь, 10 000 за кадр! :-) Я слышал, что есть совершенно новое изобретение, с помощью которого можно делать еще более быстрые движущиеся картинки, кажется, это называют кинематографией или что-то в этом роде. Я не знаю, будет ли звук, возможно, в будущем. ;-)

Если предположить, что в вашем микроконтроллере есть модуль ШИМ, то все довольно просто. Вам нужно прочитать таблицу данных и соответствующим образом настроить свой модуль, а затем загрузить соответствующие значения в регистр рабочего цикла (обычно «сравнение»). Вот грубый пример: вы устанавливаете таймер для желаемой (фиксированной) частоты ШИМ, затем изменяете регистр, чтобы изменить время включения/выключения в этот период.
Скажем, у вас есть 10-битный модуль ШИМ. 10 бит = 2^10 = 1024. То есть для 50% рабочего цикла нужно загрузить в регистр 512, для 25% 256 и т.д. (конкретная работа вашего ШИМ модуля может немного отличаться)
Затем вы добавляете низкий проходной фильтр (обычно достаточно простого RC-фильтра) перед ШИМ для усреднения ШИМ и создания переменного напряжения постоянного тока:

ШИМ-фильтр

Радиоуправляемый фильтр

Для фильтра вам нужно убедиться, что частота ШИМ сильно ослаблена, оставив более низкие частоты - поскольку вы говорите, что вам нужен только постоянный ток, то подойдет что-то вроде R = 10k C = 0,1 мкФ. Это создаст отсечку 1/(2pi * 10k * 0,1 мкФ) = 159 Гц. Выберите частоту ШИМ значительно выше этой (например, 10 кГц).

Я заметил тег AVR - я не использую AVR (поэтому я не могу лично ручаться за приведенную ниже информацию), но я погуглил и нашел пару довольно хороших руководств:
Руководство по ШИМ Aquaticus
AVR Freaks Руководство по
ШИМ Пример синусоидальной волны ШИМ

Если вы не хотите использовать модуль ШИМ (или вам нужен ШИМ на определенном контакте), вот некоторый «мягкий» код ШИМ:

 // The following two ISRs are doing "poor man's PWM" 
//  but this allows it to be on a pin of my choice 
ISR(TIMER0_COMP_vect) { 
        // clear the output pin on OCR0 match 
   PORTC &= ~(1<<PC0); 
} 
ISR(TIMER0_OVF_vect) { 
        // set the output pin at timer overflow 
   PORTC |= (1<<PC0); 
} 

int main(void) { 

   // going to use PORTC.0 to PWM the contrast voltage 
   DDRC = (1<<DDC0); 
   TIMSK |= ((1<<OCIE0) | (1<<TOIE0)); // use both interrupts
   OCR0 = 10; // 10 out of 256 means very short on period (low voltage) 
   TCCR0 = (1<<CS00); // timer on - nice high PWM frequency 

   // Might later consider PWMing the backlight voltage too 
   // so it would also be adjustable ... 
   sei();