Простой ШИМ на ATTiny13.Регулируем всё

Потребовалось регулировать температуру маленького  12-ти вольтового паяльника Baku 938 мощностью 8 Вт , но в интернете попадались схемы ШИМ на дискретных элементах, например, схемы на таймере 555, к561ла7, к561лн2, на мультивибраторе из транзисторов.

ШИМ или PWM — процесс управления мощностью, подводимой к нагрузке, путём изменения скважности импульсов, при постоянной частоте. 

Собрав несколько из них, ни одна меня не устроила, у них был слишком крутой спад\подъем сопротивления при вращении ручки переменного резистора — от 2 кОм сразу подскакивало к 7 кОм, и следовательно, при этом, к примеру, подключенный для теста на исток полевого транзистора, компьютерный вентилятор со скорости 20 процентов сразу поднимал обороты до 90-100 процентов. В общем, чтобы пользоваться схемой, пришлось бы вращать потенциометр с прецизионной точностью и\или с замером сопротивления при вращении.

Однако, нашлась схема, собранная на ATTiny13, в которой используется цифровая ШИМ . Посмотреть статью о ней можно на странице  cxem.net/master/61.php

Сначала я отнесся к ней скептически, но зря, потому что схема минимальна по обвязке, по сравнению с дискретными схемами найденными ранее. Микросхема маленькая и дешевая, изготавливается в корпусах SOIC,DIP, QFN, MLF, ножек всего 8, как и у таймера NE\LM555.

ШИМ на ней получается точным и легко регулируется.

 

Смотрите также статьи по теме:

Как прошить микроконтроллер ATmega, AVR

Эмуляция AVR в Proteus, микроконтроллеры в Proteus

Как написать код для AVR, программирование микроконтроллеров Atmel AVR на Си

 

Наглядная схема (принципиальную схему смотрите по ссылке выше на сайте-источнике).

 

Описание чипа Atmel (Microchip) ATTiny13A 

ATTiny13A — это 8 битный AVR микроконтроллер с программируемой Flash памятью внутрисистемно, размером 1 КБ.

Распиновка (pinout) микроконтроллера ATTiny13A 

 

В чем отличие ATTiny13 от ATTiny13A ?

Tiny13A — это более новый и улучшенный микроконтроллер от Atmel.

Ранее выпускались два варианта Тини13 — с обычным (ATTiny13, работает от 2.7 вольт) и пониженным (ATTiny13V, работает от 1.8 вольт) питанием.

При этом первый вариант работает на частоте до 20 Мгц, второй — до 10Мгц.

С выходом Тини13А убрали разделение мк по питанию, Тини13А работает и от 1.8 вольт (в этом режиме, при пониженном низковольтном питании его невозможно заставить работать на высокой частоте).

 

Примечание по сборке схемы

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

Светодиоды лучше брать с тусклым свечением, разные яркие цвета могут раздражать, особенно ярко светится синий светодиод. Яркость можно снизить применив в цепи питания светодиодов резисторы, например, до 2 кОм.

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

Также можно обойтись и без линейного стабилизатора напряжения LM7805 (КРЕН5), если схема питается напряжением в 5 вольт, и регулируемая нагрузка работает от такого же напряжения, а не от 12 вольт.

Для стабильности напряжения можно добавить керамические конденсаторы (на наглядной схеме выделены квадратом салатового цвета) — 0,33 микроФарад (334) на вход 7805, и 0,1 микрофарад (104) на выходе 7805.

Используемая нагружаемая мощность будет ограничена полевым (MOSFET) транзистором.

 

Прошивка

Почитав комментарии на оригинальной странице, увидел несколько комментариев об ошибке — надо вначале держать кнопку 30 секунд, чтобы ШИМ запустился, что конечно же ну очень долго.

Так как исходники прилагались — решил исправить ошибку и добавить индикацию работы светодиодами нагляднее. Исходники, к моему сожалению оказались на BascomAVR.

Пришлось его скачать и открыть исходник в нем. Исправив ошибку с ожиданием в 30 секунд — решил проверить и залить прошивку. Но прошивка не захотела литься, подумав что это ошибка компилятора BascomAVR, было решено написать свой код для ATTiny13 на Си в Atmel Studio 7, конечно с сохранением оригинальной схемотехники, чтобы было можно только лишь залить прошивку и ничего не переделывать на печатке.

Написал тестовый код в Atmel Studio, скомпилировал прошивку, заливаю в attiny13 – опять ошибка:

mismatch 0x000000

Ошибка оказалась не в средах разработки, а в программе для прошивки мк, конкретно в моем случае в  eXtreme Burner AVR, для того, чтобы исправить данную ошибку необходимо открыть файл

C:\Program Files\eXtreme Burner – AVR\Data\chips.xml

Найти ATTiny13 и между тегами 64 Вместо 64 написать 32 – после этого ATTiny13 начал шиться без проблем.

Спустя несколько дней программа была написана.

 

Что изменено и добавлено в прошивку:
Не нужно удерживать кнопку на протяжении 30 секунд
+ Добавлено 8 значений ШИМ вместо 7
+ Добавлена индикация включения.
+ Сделана наглядная индикация режима ШИМ .
+ Добавлено автосохранение значения ШИМ (по умолчанию выключено)

Индикация включения — при включении очень быстро и с реверсом перельются все три светодиода.

Переключение режимов осуществляется нажатием на кнопку, действует циклически.

 

Файлы прошивки находятся в конце статьи.

 

При возникновении дополнительных вопросов по работе с кодами для микроконтроллеров , вам может помочь статья:

Как написать код для AVR, программирование микроконтроллеров Atmel AVR на Си

 

 

Пояснения по работе устройства с новой прошивкой

Режимы работы:
0 — Все светодиоды выключены, Значение ШИМ — 0 (0%)
1 — Моргает светодиод 1, ШИМ — 32 (12%)
2 — Моргает светодиод 2, ШИМ — 64 (25%)
3 — Моргает светодиод 3, ШИМ — 96 (37.6%)
4 — Все светодиоды переливаются, ШИМ — 128 (50%)
5 — Горит светодиод 1, ШИМ — 160 (62.7%)
6 — Горит светодиод 2, ШИМ — 192 (75.2%)
7 — Горит светодиод 3, ШИМ — 224 (87.8%)
8 — Все светодиоды моргают, ШИМ — 255 (100%)

ШИМ — 0 (0%) — питание на «регулируемом устройстве» отсутствует, например, паяльник не греется.

ШИМ — 255 (100%) — полная мощность работы «регулируемого устройства».

 

Для включения автосохранения значения ШИМ необходимо удержать кнопку в течении 3-х секунд, для отключения — осуществить тоже самое.

При этом при включении автосохранения на 1,5 секунды загорится светодиод 1.
При отключении — на 1,5 секунды загорится светодиод 3.Удерживать кнопку можно в любом режиме, но лучше это делать в режиме 0- так будет нагляднее.

Не стоит забывать, что при включенном автосохранении каждый раз, при нажатии на кнопку записываются данные в EEPROM, ресурс записи EEPROM в Atmel AVR — 100 000.

 

Программирование ATTiny13 микроконтроллера

  1. Для заливки прошивки в ATTiny потребуется: USB ASP Программатор микроконтроллеров ATmega AVR.
  2. Программа eXtreme Burner AVR.

Необходимо поставить фьюз на работу от внутреннего тактового генератора на 9,6 Мгц

Т.к. я пользуюсь eXtreme Burner AVR то во вкладке Fuse\Bits записываю такие байты вместо выставления галок(в других программах-прошивальщиках галки):

Младший байт(Low Byte\Fuse) – 7A

Старший байт (High Byte\Fuse) – EB

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

homes-smart.ru/fusecalc/?prog=avrstudio&part=ATtiny13A

Слева вверху, где написано Байты конфигурации вводим  – 7A в окошечко LOW

и EB в окошечко HIGH – получаем указание на то, где следует поставить галки.

 

Собранное в корпус устройство ШИМ с вынесенной кнопкой:

(Принципиальная схема и печатная плата имеется на приведенном выше сайте.)

Плата ШИМ, упакованная в корпус от другого устройства и подключенный к ней паяльник.

 

.

Файлы прошивки в формате HEX:

Оригинальная, скомпилированная из приведенных ниже исходников:

SolderPWM

 

Прошивка с более высокой частотой (Не тестировалась на реальной схеме!):

PWM_HF

 

Прошивка по просьбе одного из пользователей нашего сайта, частота ШИМ — около 2,3 килоГерц:

SolderPWM_v1_1_1

В данной прошивке всего три режима

0 — Выключено

1 — ШИМ 80%, светится светодиод 1

2 — ШИМ 90%, светится светодиод 1,2

3 — ШИМ 100%(Постоянное питание), светится светодиод 1, 2 и 3

 

Исходник с подробными комментариями также прилагается, можно изменить под свои нужды:

/*
/*
 * SolderPWM.c
 *
 * Created: 05.11.2017 23:33:14
 * Author LampCORE.ru: 
 */ 
 
 
#define F_CPU 9600000UL //частота процессора 9,6 Мгц
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <avr/eeprom.h>
 
//макросы для включения, выключения светодиодов
//низкий уровень - на ножке 0 вольт, высокий уровень - на ножке 5 вольт
#define LED1_OFF PORTB &= ~(1<<PB4); //Низкий уровень ножки PB4 
#define LED2_OFF PORTB &= ~(1<<PB3); //Низкий уровень ножки PB3
#define LED3_OFF PORTB &= ~(1<<PB2); //Низкий уровень ножки PB2
 
#define LED1_ON PORTB |= (1<<PB4);  //Высокий уровень ножки PB4
#define LED2_ON PORTB |= (1<<PB3);  //Высокий уровень ножки PB3
#define LED3_ON PORTB |= (1<<PB2); //Высокий уровень ножки PB2
//Указатели для EEPROM
uint8_t autosave_p EEMEM; uint8_t level_p EEMEM;
//Переменная для выбора режима ШИМ
uint8_t level=0;
//volatile - чтобы компилятор не трогал эти переменные и не оптимизировал
//Счетчики в прерывании
//для мигания 
volatile uint8_t count=0;
//для переливания 3х светодиодов
volatile uint8_t count2=0;
//счетчик удержания кнопки 
volatile uint8_t i=0;
//переменная для события был_клик
volatile uint8_t wasclick=0;
//36 переполнений (36 раз происходит событие TCNT0>255 ) = 1 секунда
// Прерывание по совпадению счетчика таймера с OCR0A
// 9 600 000 Гц/Предделитель 1024 / 1000 = 9 375 Гц в секунду/255=36 прерываний 
//в секунду
ISR (TIM0_COMPA_vect)
{
 
//инкремент счетчиков, две переменные, чтобы режимы 
//светодиодов мигания и переливания не зависили друг от друга
count++;
//если больше пол секунды
if(count>18){count=0;}
 
	count2++;
	//если больше секунды
	if(count2>36){count2=0;}
 
}
 
 
//функция отключить все светодиоды
void off_all_led()
{
	LED1_OFF;LED2_OFF;LED3_OFF;
}
 
 
 
 
int main(void) {
 
// Настраиваем порты ввода/вывода	
DDRB |= 1<<PB4;//Ножка PB4 как выход
DDRB |= 1<<PB3;//Ножка PB3 как выход
DDRB |= 1<<PB2;//Ножка PB2 как выход
 
 
DDRB |= 0<<PB1;//Ножка PB1 как вход(кнопка)
PORTB |= (1 << PB1);//Включаем подтягивающий Pull-UP резистор для ножки 
//PB1(вход-кнопка)(высокий уровень(+5Вольт))
 
 
DDRB   |= (1 << PB0);    //Ножка PB0 как выход(ШИМ)
TCCR0A = (1 << COM0A1) | (1 << WGM00);  //выбор ШИМ  с фазовой коррекцией
TCCR0B = 0x05; //Предделитель - 1024 и старт таймера
TCNT0 = 0;     // Сброс счетчика прерываний(0-255)
OCR0A=0;       //Выбор Значения ШИМ
 
 TIMSK0=0x04;//Разрешить выполнение прерываний по совпадению в OCR0A	 		
 sei();// Разрешить глобальные прерывания
 
 
	//Индикация включения, быстрое переливание светодиодов с инвертированием
	LED3_ON;
	_delay_ms(45);
	LED3_OFF;
 
	LED2_ON;
	_delay_ms(45);
	LED2_OFF;
 
	LED1_ON;
	_delay_ms(45);
	LED1_OFF;
 
	LED2_ON;
	_delay_ms(45);
	LED2_OFF;
 
	LED3_ON;
	_delay_ms(45);
	LED3_OFF;
 
 
	//переменная для хранения значения автосохранения включено\выключено
		uint8_t autosave;
		//считать значение автосохранения с EEPROM по адресу в &autosave_p
		autosave=eeprom_read_byte(&autosave_p);
 
 
	//если сохранение включено то режим ШИМ равен значению из EEPROM 
	if (autosave==1)
	{
		level=eeprom_read_byte(&level_p);
		//Проследовать сразу на метку handler_button, где 
		//сразу инициируется режим, считанные из EEPROM
		goto handler_button;
	}
 
 
 
 
	//Бесконечный цикл
	while(1)
	 {
 
 
 
 //Если на PB1 низкий уровень(если кнопка нажата)
 if( ! (PINB & (1 << PB1))) { 
//Событие был_клик произошло 
wasclick=1;
//инкремент счетчика нажатия кнопки до i=255
if (i!=255){ _delay_ms(83); i++; //если прошло 3 и более секунд 
if (i>=36)
	{
		//События был_клик НЕ было
		wasclick=0;
 
				//если автосохранение включено - отключить, записать
// это в EEPROM
		if (autosave==1)
		{
			eeprom_write_byte(&autosave_p,0);
			autosave=0;
		}
		//если автосохранение выключено - включить, записать в EEPROM
		else
		{
			eeprom_write_byte(&autosave_p,1);
		autosave=1;
		}
 
 
		//если автосохранение включено включить светодиод 1 на 1,5 секунды
		if (autosave==1)
		{	
			LED1_ON;
			_delay_ms(1500);
			LED1_OFF;
			//перейти сразу к обработке переменной level
			goto handler_button;
		}	
 
		else
		//иначе, если автосохранение выключено включить светодиод 3 на
//1,5 секунды
		{
	      LED3_ON
	      _delay_ms(1500);
	      LED3_OFF;
		  //перейти сразу к обработке переменной level
		  goto handler_button;
 
		}
 
 
 
	i=0;//сброс счетчика после долгого нажатия	
 
	 //перейти сразу к обработке переменной level
	goto handler_button;
 
	}//i>=36
 
 
 }//i!=255
 
 
 
}//! (PINB & (1 << PB1))
 
 
 
// Выполнять только, если кнопка отпущена т.е. выполняется, только, если wasclick=1
//(событие был_клик произошло)
if  ( (PINB & (1 << PB1))&&wasclick==1) { //события был_клик не было wasclick=0;
_delay_ms(83); 
//Точные числа перескакивают, в узкий диапазон попасть трудно, поэтому от 2х до 12,
// 2*83+83=249 миллисекунд
//если кнопка была нажата (+83миллисекунды пауза внутри условия) 83*2 миллисекунд
if (i>=2&&i<=12) 
{ 
// повысить режим
level++; 
//если режим превышает 7 сделать режим 0
if(level>8){level=0;}
 
			   //если включено автосохранение записать в EEPROM значение
// режима
			   	if (autosave==1)
			   	{
				   	eeprom_write_byte(&level_p,level);
			   	}
 
 
		   //метка обработки переменной level(режимов)
		handler_button:   	   	
	   	switch(level)
	   	{
			   //каждому значению level - свое значение ШИМ и режим 
//светодиодов
		   	case 0:OCR0A=0;off_all_led();break;
		   	case 1:OCR0A=32 ;off_all_led(); break;
		   	case 2:OCR0A=64;off_all_led()  ;break;
		   	case 3:OCR0A=96;off_all_led()   ;break;
 
 
		   //Если быстро нажать кнопку count2 не сбросится и какой-либо
                  // светодиод будет гореть
		  //некоторое время вместо того, чтобы погаснуть - переливания не
                  // будет
		  //принудительно сбросим count2
		   	case 4:OCR0A=128;off_all_led();count2=0;break;
 
		   	case 5:OCR0A=160;off_all_led() ;
		   	LED1_ON;
		   	break;
 
		   	case 6:OCR0A=192;off_all_led()   ;
		   	LED1_ON;LED2_ON;
		   	break;
 
		   	case 7:OCR0A=224;off_all_led() ;
		   	LED1_ON;LED2_ON;LED3_ON;
		   	break;
 
 
		   	case 8:OCR0A=255;off_all_led();break;
 
 
	   	}//switch
 
	i=0;//сброс счетчика кнопки
   }//i>=2
 
 
 
 
}//release отпущено
 
 
 
 
	//Мерцания светодиодов		
	//Каждому значению ШИМ - свой режим светодиодов
	 switch(level)
	 {
	 case 0:;break;
	 case 1:	
        //count прибавляется на 9 за пол секунды
       if(count>=0&&count<9){LED1_ON;} if(count>9&&count<=18){LED1_OFF;} ;
        break; 
 
case 2: 
//
if(count>=0&&count<9){LED2_ON;} 
if(count>9&&count<=18){LED2_OFF;} ;
break; 
case 3: 
// 
if(count>=0&&count<9){LED3_ON;} if(count>9&&count<=18){LED3_OFF;} ;
break; 
case 4: 
//переливания, свой счетчик count2
if(count2>=0&&count2<6)
{LED3_OFF;LED2_OFF;LED1_ON} if(count2>6&&count2<=12){LED1_OFF;} 
if(count2>=12&&count2<18){LED1_OFF;LED3_OFF;LED2_ON} 
if(count2>18&&count2<=24){LED2_OFF;} 
if(count2>=24&&count2<30){LED2_OFF;LED1_OFF;LED3_ON} 
if(count2>30&&count2<=36){LED3_OFF;} ;break; 
case 5: ;break; 
case 6:;break; 
case 7:;break; 
case 8: if(count>=0&&count<9){LED1_ON;LED2_ON;LED3_ON;}
if(count>9&&count<=18){LED1_OFF;LED2_OFF;LED3_OFF;}
	;break;
 
	 }
 
 
 
	 }//while
 
 
}//main