cicuta
Newbie level 3
Attiny13 generates 2 PWM-modulated sine waves 1..70Hz, shifted by +/-90deg, Fpwm=9375 Hz (4800000 / 256 / 2), RPM controlled by potentiometer, and not stabilized, amplitude changes from 25% at minimal RPM to 100% at maximal RPM. Start/Stop and Reverse controlled by 2 switches.
Cotroller:
Transistors VT2/VT4 and VT1/VT3 control sine 1/2 polarity.
Driver (1 full bridge):
SD pins connected to +5V.
Firmware written in AVR-GCC, controller runs at 4.8MHz, fuses: L=0x79, H=0xF9
.h
.c
Modeling in Proteus:
Controller PCB project in Kicad: View attachment motor_async_t13-01 ().zip
Driver PCB project: View attachment drv-bridge-ir2104x2-th-01 ().zip
Firmware: View attachment motor_async_t13-01 ().hex.zip
Assembled boards:
Cotroller:
Transistors VT2/VT4 and VT1/VT3 control sine 1/2 polarity.
Driver (1 full bridge):
SD pins connected to +5V.
Firmware written in AVR-GCC, controller runs at 4.8MHz, fuses: L=0x79, H=0xF9
.h
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 #ifndef MAIN_H_ #define MAIN_H_ #define F_CPU 4800000uL #define F_PWM (F_CPU / 256 / 8) #define RPM_MIN 60 #define RPM_MAX (4112+RPM_MIN) #define ADC_MAX 255 #define ADC_INC 1 #define PIN_IN_MAX 20 #define ADDR_ADC_INC 0x3FF #include <stdint.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> #include <util/delay.h> int main();
.c
Code C - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 #include "main.h" // 0..Pi/2 sine table const uint8_t sine[64] PROGMEM = { 0, 6, 13, 19, 25, 31, 37, 44, 50, 56, 62, 68, 74, 80, 86, 92, 98, 103, 109, 115, 120, 126, 131, 136, 142, 147, 152, 157, 162, 167, 171, 176, 180, 185, 189, 193, 197, 201, 205, 208, 212, 215, 219, 222, 225, 228, 231, 233, 236, 238, 240, 242, 244, 246, 247, 249, 250, 251, 252, 253, 254, 254, 255, 255 }; // division bits const uint8_t divs[16] PROGMEM = {4,4,4,4+8,4+8,4+8,2,2,2+8,2+4,2+4,2+4+8,2+4+8,1,1,1}; volatile register uint16_t acc asm("r2"); // phase accumulator volatile register uint16_t inc asm("r4"); // phase increment volatile register uint8_t rev asm("r6"); // reverse flag volatile register uint8_t div asm("r7"); // PWM amplitude division flags: 0=x1, 1=/2, 2=/4, 3=/8 volatile register uint8_t tmr asm("r8"); // event timer divisor volatile register uint8_t foff asm("r9"); // on/off flag volatile register uint8_t frev asm("r10"); // on/off flag volatile register uint8_t adc asm("r11"); // smoothed ADC volatile register uint8_t adc_inc asm("r12"); // ADC increment/decrement rate int main(){ // GPIO DDRB = (1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB4); // ADC ADMUX = (1<<ADLAR)|(1<<MUX1)|(1<<MUX0); ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADATE)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); ADCSRB = 0; // T0 TCCR0A = (1<<WGM00);//|(1<<WGM01); TCCR0B = (1<<CS00);//(1<<CS01) TIMSK0 = (1<<TOIE0); sei(); // PWM acc = inc = adc = 0; adc_inc = pgm_read_byte(ADDR_ADC_INC); if (adc_inc == 0xFF) adc_inc = ADC_INC; while(1){ if (!tmr){ tmr = 255; if (foff >= (PIN_IN_MAX/2)){ // OFF state if (adc){ if (adc >= adc_inc) adc -= adc_inc; else adc = 0; } } else { // ON state if (rev != (frev >= (PIN_IN_MAX/2))){ // reverse if (adc){ // slow down to 0 RPM if (adc >= adc_inc) adc -= adc_inc; else adc = 0; } else rev = !rev; } else { // slow RPM up/down if (adc < ADCH){ if (adc <= (ADC_MAX - adc_inc)) adc += adc_inc; else adc = ADC_MAX; } else if (adc > ADCH){ if (adc >= adc_inc) adc -= adc_inc; else adc = 0; } } // get current amplitude divisor div = pgm_read_byte(&divs[adc >> 4]); } // calculate current RPM uint16_t rpm = (((uint16_t)adc * ((RPM_MAX-RPM_MIN) >> 4)) >> 4) + RPM_MIN; // calculate phase increment inc = (!adc) ? 0 : rpm >> 3; } } return 0; } ISR(TIM0_OVF_vect){ if (tmr) tmr--; // decrement event timer if (inc == 0){ // phase increment == 0 ? PWMs OFF TCCR0A &= ~((1<<COM0A1)|(1<<COM0B1)); if (tmr == 0){ PORTB |= (1<<PB2); DDRB &= ~(1<<PB2); asm volatile ("nop \n nop \n"); if (!!(PINB & (1<<PB2))){ // read OFF pin if (foff <= (PIN_IN_MAX)) foff++; } else if (foff) foff--; DDRB |= (1<<PB2); } } else { // PWMs ON TCCR0A |= (1<<COM0A1)|(1<<COM0B1); // PWM A uint8_t phase = acc >> 8; // phase MSB: 0..255 if (phase & 0x80){ // set bridge polarity PORTB |= (1<<PB4); DDRB &= ~(1<<PB4); asm volatile ("nop \n nop \n"); if (!!(PINB & (1<<PB4))){ // read REV pin if (frev <= (PIN_IN_MAX)) frev++; } else if (frev) frev--; DDRB |= (1<<PB4); } else PORTB &= ~(1<<PB4); uint8_t index = phase & 0x7F; // index in sine table if (index > 63) index = (uint8_t)127 - index; // 90..180deg ? reverse index uint8_t ai = pgm_read_byte(&sine[index]), ao = 0; // undivided / divided amplitude if (div & 1) ao = ai; else { ai >>= 1; // division if (div & 2) ao += ai; ai >>= 1; if (div & 4) ao += ai; ai >>= 1; if (div & 8) ao += ai; } OCR0A = ao; // set PWM A regiter // PWM B phase += rev ? 192 : 64; // phase shifted by -/+90deg if (phase & 0x80){ // set bridge polarity PORTB |= (1<<PB2); DDRB &= ~(1<<PB2); asm volatile ("nop \n nop \n"); if (!!(PINB & (1<<PB2))){ // read OFF pin if (foff <= (PIN_IN_MAX)) foff++; } else if (foff) foff--; DDRB |= (1<<PB2); } else PORTB &= ~(1<<PB2); index = phase & 0x7F; // index in sine table if (index > 63) index = (uint8_t)127 - index; // 90..180deg ? reverse index ai = pgm_read_byte(&sine[index]), ao = 0; // undivided / divided amplitude if (div & 1) ao = ai; else { ai >>= 1; // division if (div & 2) ao += ai; ai >>= 1; if (div & 4) ao += ai; ai >>= 1; if (div & 8) ao += ai; } OCR0B = ao; // set PWM B register acc += inc; // next phase sample } }
Modeling in Proteus:
Controller PCB project in Kicad: View attachment motor_async_t13-01 ().zip
Driver PCB project: View attachment drv-bridge-ir2104x2-th-01 ().zip
Firmware: View attachment motor_async_t13-01 ().hex.zip
Assembled boards:
Last edited: