Вы находитесь на странице: 1из 9

29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.

ru

Топики Блоги Люди Форум Магазин Конкурс Справочная Войти или Зарегистрироваться

Сообщество EasyElectronics.ru

Все Коллективные Персональные TOP

Хорошие Плохие Поиск

Генерация синуса 50 Гц на AVR


Блог им. antonluba

Я недавно в форуме чисто теоретически поднимал • Бесплатная среда разработки плат


вопрос о бесперебойнике с чистым синусом. • Видео экскурсия по нашей фабрике
• Всего $2 За 10 печатных плат!
А тут еще стабилизатор сгорел, от которого котел • Всего $7 за трафарет для пасты!
газовый запитан был, да с такими спецэффектами
сгорел, что до сих пор запах горелой изоляции в
кухне. Слава Богу, УЗО отработало, проводка
выдержала, в общем, обошлось.

Так что теория постепенно начала превращаться в


практику, но пока (на уровне идеи) с использованием железного
трансформатора от сгоревшего UPS, коих у меня накопилось уже много.

UPD: Добавил пару картинок

Вообще-то идей по поводу бесперебойника у меня много, начиная с


непрерывного преобразования 12->220 и заканчивая синхронизацией с
сетью и переключением байпасса на симисторах при переходе через ноль.
Но первым этапом будет генерация синуса.

Использовать будем Timer1 микроконтроллера ATMega168. Подойдет и


ATTiny2313, у него такой же таймер1.
Прямой эфир
Имеющийся у меня трансформатор (как и большинство дешевых UPS) имеет
Комментарии Публикации
отвод от средней точки низковольтной обмотки. Поэтому нужно сделать
генерацию раздельных полуволн с двух выходов сравнения таймера.
Aneg → EmBitz + PinBoard II без
использования ST Link'а. 6 → Pinboard
Кроме того, для синхронизации с сетью нужно предусмотреть подстройку
частоты, для чего максимальное значение таймера будем задавать в Planer → WT32 или Bluetooth гарнитура
это просто! 44 → Связь железа с компьютером.
регистре ICR1. На первом этапе это будет #define. Когда дойдет дело до
синхронизации с сетью, изменение этого значения в соответствии с __bl__ → Передача данных в устройство
импульсами синхронизации позволит создать некое подобие ФАПЧ, через COM-порт 7 → LabView

синхронизирующей периоды сети и UPS, чтобы избежать импульсов при antohami → Beremiz - свободная среда
переключении. программирования ПЛК. Часть 1 67 → PLC

Papandopala → Ассемблерные вставки в


Для обеспечения диапазона подстройки частоты вниз, максимальное AVR-GCC 51 → AVR
значение заполнения ШИМ не доходит до значения регистра ICR1. Запас я
dremov → Lukey 702 - Подключаем HAKKO
взял 10%, хотя, думаю, можно его и уменьшить.
A1321 111 → Инструмент

Для облегчения задачи я сделал простую табличку расчета параметров Vga → Фоторезист + ЛУТ = ... 34 →
Технологии
таймера и таблицы синуса под нужные параметры. Кстати, ее легко
адаптировать под другие задачи. kos → Модуль Zigbee UART DL-20 33 →
Деталька

Таблицу синуса я использовал для простоты, но, пользуясь информацией из sdv_cyborg → MCUCapture - утилита для
интернета, можно генерировать вполне приемлемый синус на лету. Я захвата данных из массива в памяти
проверил, результат получается очень близкий. Или подготовить таблицу микроконтроллера 3 → Софт для электронщика

при старте контроллера. К сожалению, для достижения необходимой Technicum505SU → Корректируем время
точности этот метод требует умножения чисел с несколькими цифрами после на счётчике СОЭ-55 МЗЭП 23 → Блог им. toxin65
запятой или каких-то трюков, поэтому я пока от него отказался.
anakost → Delphi. Определение
разрешения видеофайлов форматов AVI и MKV
Таблица содержит только четверть периода синуса, остальное повторяется в прямым парсингом без использования кодеков.
разном порядке, ну, вы поняли. Часть II. 1 → Алгоритмы и программные
решения
Количество импульсов ШИМ на период синуса фиксированное, оно

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 1/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru
расчитывается из исходных данных в таблице. kalobyte-ya → USB для AVR. Часть 2. HID
Class на V-USB 363 → Связь железа с
компьютером.
/*
* PWM_Mega168.c 011119xx → Управление светодиодной
лентой на WS2812B с STM32F10x 254 → STM32
*
* Created: 08.03.2015 19:03:07 Vga → Две схемы таймера для
* Author: antonluba вентилятора ванной комнаты. 16 → Блог им.
Technicum505SU
*/
trengtor → Макетирование на Veroboard
#include <avr/io.h> stripboard и на простых stripboard 105 →
Технологии
#include <avr/interrupt.h>
Vga → DDS синтезатор AD9833 83 → Блог
#define PULSE_PER_QUADRANT 88 им. grand1987

#define TOP_ 456 Vga → Delphi. Определение разрешения


видеофайла формата MP4 прямым парсингом
const uint16_t sinus[PULSE_PER_QUADRANT] = без использования кодеков. 20 → Алгоритмы и
программные решения
{
0 , Technicum505SU → Школьный
7 , осциллограф Н3017, паспорт. 9 → Инструмент

15 , UR5SIX → Очередная "blue pill" на RISC-V


22 , контроллере 8 → Блог им. perry_moshkin
29 ,
hudoykl → Руководство по
36 , проектированию устройств с операционными
44 , усилителями. Впервые на русском языке! 17 →
51 , Компэл - Журнал "Новости Электроники"

58 , Весь эфир | RSS


65 ,
73 ,
80 ,
1-Wire Altera arduino ARM Assembler
87 ,
94 , Atmel AVR C++ compel DIY enc28j60
101 , ethernet FPGA gcc I2C IAR KEIL
108 , LaunchPad LCD led linux LPCXpresso
115 ,
MSP430 nxp PCB PIC pinboard2 RTOS
122 ,
129 , STM32 STM8 STM8L TI UART
136 , USB алгоритм ассемблер АЦП
143 , библиотека блок питания вопрос
150 , деталька дисплей идея инструмент
157 ,
конкурс конкурс2 ЛУТ
163 ,
170 ,
микроконтроллеры начинающим
обзор Отладочная плата паяльник
177 ,
183 , печатная плата плата ПЛИС поделки
190 , покупки программатор
196 , программирование светодиод софт
202 , схема схемотехника Технологии
209 ,
умный дом фоторезист халява хрень
215 ,
Часы юмор
221 ,
227 ,
233 ,
239 , Блоги
245 ,
251 , Топ

257 ,
262 , AVR 38.98
268 , STM8 37.92
273 ,
279 , Мусоровоз 29.53

284 , STM32 28.46


289 ,
Связь железа с компьютером. 24.04
294 ,
299 , Деталька 23.24
304 ,
Схемотехника 18.15
309 ,
314 , Умный дом 17.75
319 ,
MSP430 17.13
323 ,
327 , LPC1xxx 14.79
332 , Все блоги

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 2/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru
336 ,
340 ,
344 ,
348 ,
352 ,
355 ,
359 ,
362 ,
366 ,
369 ,
372 ,
375 ,
378 ,
381 ,
383 ,
386 ,
388 ,
390 ,
393 ,
395 ,
396 ,
398 ,
400 ,
401 ,
403 ,
404 ,
405 ,
406 ,
407 ,
407 ,
408 ,
409 ,
409 ,
409

};

uint8_t quadrant;
uint8_t pulse_counter;
uint8_t sin_index;

ISR(TIMER1_OVF_vect)
{
switch (quadrant)
{
case 1:
OCR1A = sinus[pulse_counter];
pulse_counter++;
if (pulse_counter==PULSE_PER_QUADRANT-1)
{
quadrant = 2;
}
break;
case 2:
OCR1A = sinus[pulse_counter];
pulse_counter--;
if (pulse_counter == 0)
{
quadrant = 3;
OCR1A = 0;
}
break;
case 3:
OCR1B = sinus[pulse_counter];
pulse_counter++;
if (pulse_counter==PULSE_PER_QUADRANT-1)
{
quadrant = 4;
}
break;
case 4:

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 3/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru
OCR1B = sinus[pulse_counter];
pulse_counter--;
if (pulse_counter== 0)
{
quadrant = 1;
OCR1B = 0;
}
break;
}
}

int main(void)
{
pulse_counter = 0;
quadrant = 1;

// ports init
PORTB = 0;
DDRB = (1 << PB1)|(1 << PB2);

// timer init
TCCR1A = (1 << COM1A1)|(0 << COM1A0)|(1<< COM1B1)|(0 << COM1B0)|
TCCR1B = (1 << WGM13)|(0 << WGM12)|(0 << CS12)|(0 << CS11)|(1 <<
ICR1 = TOP_;
TIMSK1 = (1 << TOIE1);

OCR1A = 0;
OCR1B = 0;

//global init
sei();

while(1)
{
//TODO:: Please write your application code
}
}

Схема в протеусе выглядит так:

Сигнал на осциллографе протеуса:

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 4/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru

Параметры трансформатора, конечно, с потолка, только для получения


формы сигнала на выходе. Работает и просто с RC-цепочками на выходах
МК.

Вот еще картинки:

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 5/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru

Здесь синусоида отстает немного, так как фильтрацию сделал на


индуктивностях.

Модель для протеуса цепляю к статье.

Продолжение здесь

AVR, PWM, Timer, генератор сигналов

+5 09 марта 2015, 21:00 antonluba 3


Файлы в топике: ATMega168_model.zip , Расчет таймера.xls.zip , ATMega168_model_RCfilter.zip

Комментарии (22)
RSS свернуть / развернуть

Подобного рода осциллограммы в Proteus проще и лучше делать в «Graph Mode», для 0
смешанных сигналов лучше использовать Mixed graph. Кроме увеличения скорости
анализа, можно будет легко масштабировать, использовать курсоры. Осциллограф в
Proteus работает медленно, да и кривовато.

kvm
09 марта 2015, 23:35

Я бы порекомендовал использовать, что нибудь на ARM (например STM32), в которых 0


возможности таймеров значительно расширены.

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 6/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru

__bl__
09 марта 2015, 23:37

Синус-то из таблицы можно один раз вычислять в начале обработчика, и значение 0


положить во временную переменную. И оттуда брать, тогда не надо будет 4 раза
индексы считать.

Anatol80
10 марта 2015, 00:49

При условии, что оперативной памяти достаточно 0

__bl__
10 марта 2015, 01:18 ↑

Индекс вообще считается автоматически, один раз за прерывание, а в зависимости 0


от четверти меняется направление счета и выход, на который подается сигнал.

antonluba
10 марта 2015, 10:39 ↑

Про автоматически это интересно, конечно)) Но Вы листинг все же взгляните 0


что там в начале каждого case. Не начинается ли каждый case с высчисление
адреса по индексу массива? Возможно, узнаете много нового про компилятор.
Удачи!

Anatol80
10 марта 2015, 12:41 ↑

Автоматически имел в виду в прерывании, один раз. На каждом 0


следующем прерывании новое значение. Что вы предлагаете, не понимаю?

antonluba
10 марта 2015, 12:46 ↑

Что ж там не понять? Откройте листинг с ассемблерными 0


инструкциями. Посмотрите начало каждого case. Что там делается? Не
вычисляется ли в КАЖДЫЙ раз по индексу адрес загружаемого
данного? Видимо, вычисляется)) Это штук 7 ASM-инстукций, если не
больше. От этого можно избавиться, если при входе в обработчик
ОДИН раз взять из памяти значение и НЕ ВЫЧИСЛЯТЬ его адреса в
каждом case.

Anatol80
10 марта 2015, 13:07 ↑

В смысле, делать инкремент и декремент указателя, а не индекса? 0

antonluba
10 марта 2015, 13:35 ↑

Каждый раз при вызове прерывание отрабатывает одно из 0


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

Меня больше смущает, что переменные


uint8_t quadrant;
uint8_t pulse_counter;

не объявлены как volatile (потенциально оптимизатор может


поломать код)

e_mc2
10 марта 2015, 13:44 ↑

Меня больше смущает, что переменные 0

uint8_t quadrant;
uint8_t pulse_counter;

не объявлены как volatile (потенциально оптимизатор


может поломать код)
we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 7/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru
Спасибо за подсказку, когда буду отлаживать, проверю

antonluba
10 марта 2015, 13:50 ↑

Спасибо за подсказку, когда буду отлаживать, +1


проверю
Я бы рекомендовал в подобных случаях всегда явно
делать запрет оптимизации (через volatile или барьер
компиляции), не надеясь на отладку. Дело в том, что
оптимизатор – вещь тонкая, в таком виде (предположим)
он оставит инициализацию этих переменных в коде,
потом вы немного код перепишите – он эту
инициализацию уберет. Или Вы перейдете на другую
версию AVRGCC, в которой оптимизатор будет более
«умным»…

e_mc2
10 марта 2015, 16:33 ↑

Ну, ИАР не делает одно обращение никогда. Он в лучшем 0


случае (при макс. оптимизации) в начале каждого case
сделает call на общую подпрограмму извлечения слова из
массива. А это — лишние такты внутри обработчика.
Некультурно))

Anatol80
10 марта 2015, 14:07 ↑

переменная 0
const uint16_t sinus[PULSE_PER_QUADRANT]

будет храниться в памяти RAM.


Нужно отчетливо понимать, что мы имеем дело с гарвардской архитектурой. Это значит,
что область ОЗУ и область программ имеют свою адресацию. Поскольку компилятор не
обладает искусственным интеллектом, ему требуется подсказать, что читать нужно из
другой области памяти.
нужно использовать функции чтения из памяти pgmspace.h
а вначале ставить макрос PROGMEM.
Здесь на этом же сайте уже писалось об этом. Почитайте.

Mihail
10 марта 2015, 10:24

переменная 0
const uint16_t sinus[PULSE_PER_QUADRANT]
будет храниться в памяти RAM
Да, это я знаю, спасибо. Но для проверки идеи, тем более на модели, не стал
усложнять.

antonluba
10 марта 2015, 10:38 ↑

по схеме: Конечно, одно из самых больших преимуществ данной схемы — простота, 0


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

Mihail
10 марта 2015, 10:37

Транзисторы будут сильно греться 0

Поясню: это только иллюстрация идеи, не дальше чем моделирование.

В прототипе будут другой контроллер, другие драйверы, другие транзисторы,


другие резисторы, защитные диоды, обратные диоды в затворе, блокировочные
конденсаторы, накопительные конденсаторы, предохранители, другой
трансформатор, провода потолще :-)))…

antonluba
10 марта 2015, 10:46 ↑

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 8/9
29.02.2020 Генерация синуса 50 Гц на AVR / Блог им. antonluba / Сообщество EasyElectronics.ru

-1
значит соответственно и другая программа. А что мы обсуждаем тогда вообще?
Сама идея синуса на МК тоже не нова.

Mihail
10 марта 2015, 11:24 ↑

значит соответственно и другая программа 0

Программа будет дополняться другими функциями: синхронизация с


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

Для меня новое в этой программе — возможность подстройки частоты в


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

antonluba
10 марта 2015, 11:40 ↑

А честный синус сейчас мало где нужен вообще. 0


Например, если БП сделан по схеме Диодный мост->конденсатор->ШИМ, то ему меандр
(е ащё лучше — постоянка) — самое то.
Чистый синус нужен для повышения КПД низкочастотных трансформаторов и
двигателей. Однако, низкочастотные трансформаторы это странно, а двигатели надо
пускать через частотники, а там

Диодный мост->конденсатор->ШИМ
dekar
10 марта 2015, 12:08

Двигатели много где есть. В котлах часто трансформаторы используются. И при 0


питании от UPS c «модифицированной синусоидой» котел у меня противно зудел.

antonluba
10 марта 2015, 12:41 ↑

для движков (подозреваю, трёхфазных) советую MC3PHAC. 0

scaldov
14 марта 2015, 15:22 ↑

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.

Design by — Студия XeoArt © Powered by LiveStreet CMS

we.easyelectronics.ru/antonluba/generaciya-sinusa-50-gc-na-avr.html 9/9