ШИМ на Attiny13 управляемый напряжением или аналоговым сигналом

Дело было вечером — делать было нечего, ай думаю забацаю ШИМ который будет управляться сигналом с АЦП.Для создания сего чуда будем использовать Attiny13 — у меня их куча завалялась. Юзать будем апартный ШИМ. Причём один выход назначим инвертированный, а другой прямой. Ещё подключим кнопку для того чтобы менять частоту таймера ну и тем самым несущую  частоту ШИМ.

Вот такая модель вышла в Proteus

pwm

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

pwm13

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

Пред-делитель  = 1.pwm 1

Пред-делитель  = 2.pwm 2

Пред-делитель  = 3.pwm 3

Пред-делитель  = 4.pwm 4

Пред-делитель  = 5.pwm 5

Применений много — от регулятора мощности до регулятора света или напряжения.

Исходный код программы:

#include <tiny13.h>
#include <delay.h>
#define ADC_VREF_TYPE 0x00
  unsigned int pwm = 0;
  float pwm_f=0;
  unsigned char pwm_val = 0;   
  eeprom unsigned char trc[2];
// Read the AD conversion result
unsigned int read_adc(unsigned char adc_input)
{
ADMUX=adc_input | (ADC_VREF_TYPE & 0xff);
// Delay needed for the stabilization of the ADC input voltage
delay_us(10);
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCW;
}

void main(void)
{
// 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=Out Func0=Out 
// State5=T State4=T State3=T State2=T State1=0 State0=0 
PORTB=0x00;
DDRB=0x03;
PORTB.4=1;
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: Timer 0 Stopped
// Mode: Phase correct PWM top=0xFF
// OC0B output: Non-Inverted PWM
// OC0A output: инвертрованое значение
TCCR0A=0xB1;
TCCR0B=0x03;
TCNT0=0x00;
OCR0A=0x00;
OCR0B=0x00;

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

// ADC initialization
// ADC Clock frequency: 76,563 kHz
// ADC Bandgap Voltage Reference: Off
// ADC Auto Trigger Source: ADC Stopped
// Digital input buffers on ADC0: On, ADC1: On, ADC2: On, ADC3: On
DIDR0&=0x03;
DIDR0|=0x00;
ADMUX=ADC_VREF_TYPE & 0xff;
ADCSRA=0x87;
 if(PINB.4==0){delay_ms(10);while(!PINB.4){;}; TCCR0B=3; trc[0] = 0;} //если зажали кнопку при включении
 //то сбрасываем сохранения 
 if(trc[0]==1){TCCR0B = trc[1];} //проверяем сохранённое значение
 else{trc[1]=3; TCCR0B = trc[1];} //востанавливаем
while (1)
 { 
 pwm = (int)read_adc(1); //считываем значение АЦП
 pwm_f =(int) pwm/4; //делим его на 4 и берём только целую часть
 pwm_val=(char)pwm_f; //преобразование типов
 OCR0A = (char) pwm_val; //записываем значение в регистр А
 OCR0B = (char) pwm_val; //записываем значение в регистр В
 delay_ms(1);
 
 if(PINB.4==0){delay_ms(10);while(!PINB.4){;}; TCCR0B++; trc[1] = TCCR0B; trc[0]=1;} //изменяем частоту ШИМ
 if(TCCR0B>=6){TCCR0B=1;}
 }
}

07.04.17 FUSE


Скачать проект ШИМ на Attiny13 управляемый напряжением или аналоговым сигналом Скачали 2467 раз

ШИМ на Attiny13 управляемый напряжением или аналоговым сигналом: 42 комментария

  1. Добрый день. Объясните пожалуйста для чего в этой части кода
    adc = (int)read_adc(1); //считываем значение АЦП
    adc_f =(int) adc/4; //делим его на 4 и берём только целую часть

    Вы делите считанное значение на 4?

  2. Подскажите пожалуйста, не могу разобрать ошибку:

    adc = (int)read_adc(1); //считываем значение АЦП
    adc_f =(int) adc/4; //делим его на 4 и берём только целую часть
    adc_in=(char)adc_f; //преобразование типов

    if (adc_in>=0 && 18 && 20 && <=23) Error:invalid expression
    {OCR2=14;}
    ……..

    Когда писал так же под тини13 — не было никаких ошибок

    1. Так нельзя делать

      if (adc_in>=0 && 18 && 20 && < =23)

      нельзя!
      Если надо сравнить то:

      if (adc_in>=0 && adc_in< =23)
      или if (adc_in==0||adc_in==18||adc_in==20||adc_in==23)
      

      ну и все в таком духе, смотря что нужно...
      Сам компилятор вам подсказует что у вас ошибка в выражении.
      ____________________________________________________________
      Чтобы корректно вставить код используйте теги: КОД

      1. Спасибо за помощь. Вот так было написано:

        adc = (int)read_adc(1); //считываем значение АЦП
        adc_f =(int) adc/4; //делим его на 4 и берём только целую часть
        adc_in=(char)adc_f; //преобразование типов

          1. Для Atmega8. В моем случає памяти Attiny13 мало…
            Я просто не могу понять, в чем ошибка кода. В первом сравнении убрал && оставил просто adc<18 и компилятор не ругается….
            Спасибо

  3. Добрый день. Подскажите, как изменить или добавить код для включения — отключения шим кнопкой? Как выключателем, нажата — есть ШИМ на выходе, отпущена — на выходах вместо ШИМ — 0. Спасибо.

    1. Шимом управляют регистры:
      TCCR0A=0xB1;
      TCCR0B=0x03;
      Соответственно если сделать так:
      TCCR0A=0x00;
      TCCR0B=0x00;
      Шим формироваться не будет — только выход шыма надо дополнительно после этого в ноль сбросить.
      Вот и все, далее думаю разберётесь.

      1. Благодарю. Как дополнительно в ноль сбросить не понял (в ноль само собой сбрасывается), но кнопка заработала так, как я хотел. Как-то так:
        if(PINB.5==0)
        {
        TCCR0A=0x00;
        }
        if(PINB.5==1)
        {
        TCCR0A=0xB1;
        }
        Кстати, поясните, как в ноль сбрасывать? Где-то что-то я не понимаю.

  4. Добрый день.
    Подкажите, в программировании не селен, но есть необходимость подкорректировать данный проект изменения в следуюющем:
    1. Убрать кнопку.
    2. Оставить несущую частоту только 23кГц
    Буду признателен. Спасибо.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *