This shows you the differences between two versions of the page.
| Next revision | Previous revision | ||
| et:examples:motor:dc:speed [2011/12/09 13:20] – tekitatud raivo.sell | et:examples:motor:dc:speed [2020/07/20 12:00] (current) – external edit 127.0.0.1 | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Mootori kiiruse juhtimine ====== | ||
| + | Näide, mis võimaldab nuppudest mootori 0 kiirust suurendada ja vähendada ja pöörlemissuunda muuta. Lisaks on main.c failis ka funktsioon, mis võimaldab kõigi DC nootorite kiiruseid muuta ja suunda vahetada: | ||
| + | |||
| + | |||
| + | <code c> | ||
| + | void dcmotor_drive(unsigned char index, signed char direction, unsigned char speed) | ||
| + | </ | ||
| + | |||
| + | |||
| + | Hetkel see ei ole mõeldud teegi mootorite osaga kasutamiseks, | ||
| + | |||
| + | Kõige üldisemalt saab viikude PWM-i juhtida compbuff[CHMAX] muutuja kaudu. Nii võite endale ise funktsioonid jne koostada. Siis saab kõiki | ||
| + | |||
| + | Kui kanalite arvu muudate, siis vaadake ka SoftPWM.c fail üle, kus tuleb üleliigsete kanalite haldamine kinni keerata: faili lõpus compare funktsioonid. | ||
| + | |||
| + | On oht, et selle SoftPWMi taimer0 kattub hw_delay funktsioonis kasutatuga. Lihtsalt teadmiseks. | ||
| + | Kui mujal projektis soovite kasutada, siis kindlasti peab failis, kus on dcmotor_drive funktsioon olema ka volatile unsigned char compbuff[CHMAX]; | ||
| + | |||
| + | Kõik failid allalaadimiseks siin: | ||
| + | * {{: | ||
| + | * {{: | ||
| + | * {{: | ||
| + | * {{: | ||
| + | |||
| + | |||
| + | |||
| + | <code c> | ||
| + | / | ||
| + | * | ||
| + | * | ||
| + | * - File : main.c | ||
| + | * | ||
| + | * | ||
| + | * - Supported devices : Atmega2561. | ||
| + | * | ||
| + | * | ||
| + | *****************************************************************************/ | ||
| + | |||
| + | #include < | ||
| + | #include " | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | #include < | ||
| + | |||
| + | |||
| + | // Global buffer. Defined SoftPWM.c | ||
| + | volatile unsigned char compbuff[CHMAX]; | ||
| + | |||
| + | pin led_red | ||
| + | pin led_yellow = PIN(C, 4); | ||
| + | pin led_green | ||
| + | |||
| + | pin button1 = PIN(C, 0); | ||
| + | pin button2 = PIN(C, 1); | ||
| + | pin button3 = PIN(C, 2); | ||
| + | |||
| + | |||
| + | // | ||
| + | // The program entry point. | ||
| + | // | ||
| + | int main(void) | ||
| + | { | ||
| + | unsigned char rxdata = 0; | ||
| + | signed char direction = -1; | ||
| + | |||
| + | |||
| + | // Seab LEDid töökorda | ||
| + | pin_setup_output(led_red); | ||
| + | pin_setup_output(led_yellow); | ||
| + | pin_setup_output(led_green); | ||
| + | |||
| + | // Seab nupud töökorda | ||
| + | pin_setup_input_with_pullup(button1); | ||
| + | pin_setup_input_with_pullup(button2); | ||
| + | pin_setup_input_with_pullup(button3); | ||
| + | |||
| + | // Lülitab LEDid välja | ||
| + | pin_set(led_green); | ||
| + | pin_set(led_yellow); | ||
| + | pin_set(led_red); | ||
| + | |||
| + | // Ekraani seadistamine | ||
| + | lcd_gfx_init(); | ||
| + | |||
| + | // LCD ekraani puhastamine | ||
| + | lcd_gfx_clear(); | ||
| + | |||
| + | lcd_gfx_backlight(true); | ||
| + | |||
| + | // Kursori (nähtamatu) ekraani keskele viimine | ||
| + | lcd_gfx_goto_char_xy(3, | ||
| + | |||
| + | // Teksti kuvamine | ||
| + | lcd_gfx_write_string(" | ||
| + | |||
| + | | ||
| + | InitSoftPWM(); | ||
| + | |||
| + | |||
| + | while(1) | ||
| + | { | ||
| + | | ||
| + | |||
| + | // Nupp S1 alla vajutatud | ||
| + | if(!pin_get_debounced_value(button1)) | ||
| + | { | ||
| + | // Kiiruse suurendamine | ||
| + | if(rxdata < 0xFF) | ||
| + | { | ||
| + | rxdata++; | ||
| + | } | ||
| + | pin_clear(led_green); | ||
| + | |||
| + | } | ||
| + | |||
| + | // Nupp S2 alla vajutatud | ||
| + | if(!pin_get_debounced_value(button2)) | ||
| + | { | ||
| + | // Kiiruse vähendamine | ||
| + | if(rxdata > 0x00) | ||
| + | { | ||
| + | rxdata--; | ||
| + | } | ||
| + | pin_clear(led_yellow); | ||
| + | |||
| + | } | ||
| + | |||
| + | // Nupp S3 alla vajutatud | ||
| + | if(!pin_get_debounced_value(button3)) | ||
| + | { | ||
| + | // | ||
| + | if(direction == 1) | ||
| + | { | ||
| + | direction = -1; | ||
| + | } | ||
| + | else | ||
| + | { | ||
| + | direction = 1; | ||
| + | } | ||
| + | |||
| + | } | ||
| + | |||
| + | pin_set(led_green); | ||
| + | pin_set(led_yellow); | ||
| + | |||
| + | //Mootori juhtimine | ||
| + | dcmotor_drive(0, | ||
| + | sw_delay_ms(5); | ||
| + | |||
| + | /* | ||
| + | dcmotor_drive(0, | ||
| + | sw_delay_ms(500); | ||
| + | dcmotor_drive(0, | ||
| + | sw_delay_ms(500); | ||
| + | */ | ||
| + | |||
| + | } | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Funktsioon mootori juhtimiseks. | ||
| + | // | ||
| + | void dcmotor_drive(unsigned char index, signed char direction, unsigned char speed) | ||
| + | { | ||
| + | switch (index) | ||
| + | { | ||
| + | case 0: | ||
| + | if(direction == 1) | ||
| + | { | ||
| + | compbuff[6] = 0x00; | ||
| + | compbuff[7] = speed; | ||
| + | } | ||
| + | if(direction == -1) | ||
| + | { | ||
| + | compbuff[7] = 0x00; | ||
| + | compbuff[6] = speed; | ||
| + | } | ||
| + | |||
| + | break; | ||
| + | |||
| + | |||
| + | case 1: //OK | ||
| + | |||
| + | if(direction == 1) | ||
| + | { | ||
| + | compbuff[0] = 0x00; | ||
| + | compbuff[1] = speed; | ||
| + | } | ||
| + | if(direction == -1) | ||
| + | { | ||
| + | compbuff[0] = speed; | ||
| + | compbuff[1] = 0x00; | ||
| + | } | ||
| + | |||
| + | break; | ||
| + | |||
| + | case 2: //OK | ||
| + | |||
| + | if(direction == 1) | ||
| + | { | ||
| + | compbuff[4] = 0x00; | ||
| + | compbuff[5] = speed; | ||
| + | } | ||
| + | if(direction == -1) | ||
| + | { | ||
| + | compbuff[5] = 0x00; | ||
| + | compbuff[4] = speed; | ||
| + | } | ||
| + | |||
| + | break; | ||
| + | |||
| + | case 3: //OK | ||
| + | |||
| + | if(direction == 1) | ||
| + | { | ||
| + | compbuff[2] = 0x00; | ||
| + | compbuff[3] = speed; | ||
| + | } | ||
| + | if(direction == -1) | ||
| + | { | ||
| + | compbuff[3] = 0x00; | ||
| + | compbuff[2] = speed; | ||
| + | } | ||
| + | |||
| + | break; | ||
| + | |||
| + | // | ||
| + | |||
| + | |||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | PWM generaator: | ||
| + | |||
| + | <code c> | ||
| + | // | ||
| + | // | ||
| + | // 10 Channel software PWM | ||
| + | // | ||
| + | // - AppNote | ||
| + | // | ||
| + | // Introduction | ||
| + | // This documents data structures, functions, variables, defines, enums, and | ||
| + | // typedefs in the software for application note AVR136. | ||
| + | // | ||
| + | // | ||
| + | // Channels are mapped to specific port pins in the SoftPWM.h file | ||
| + | // \section PWMinfo PWM frequency and crystal selection | ||
| + | // | ||
| + | // The PWM base frequency is the crystal frequency divided by 65536, e.g. for | ||
| + | // a 7.3728MHz crystal the PWM base frequency will be 112.5Hz. The standard | ||
| + | // STK500 3.6864MHz oscillator could be used as a clock source, but the PWM | ||
| + | // base frequency would be reduced which may result in unacceptable ripple. | ||
| + | // Jitter will be +/-1 clock cycle max, or +/-0.0015% of base frequency. | ||
| + | // | ||
| + | // This demonstration shows ten PWM channels, for GCC the ISR uses less than | ||
| + | // 50% of processing time during the softcount=0 interrupt. The principles | ||
| + | // shown should accomodate up to 24 channels on suitable AVR devices whilst | ||
| + | // maintaining PWM accuracy, ISR optimisation may improve this even further. | ||
| + | // | ||
| + | |||
| + | #include " | ||
| + | |||
| + | // global buffers | ||
| + | unsigned char compare[CHMAX]; | ||
| + | extern volatile unsigned char compbuff[CHMAX]; | ||
| + | |||
| + | // | ||
| + | // Init function. This function initialises the hardware | ||
| + | // | ||
| + | void InitSoftPWM(void) | ||
| + | { | ||
| + | unsigned char i, pwm; | ||
| + | |||
| + | CLKPR = (1 << CLKPCE); | ||
| + | CLKPR = 0; // set clock to maximum (= crystal) | ||
| + | |||
| + | __watchdog_reset(); | ||
| + | MCUSR &= ~(1 << WDRF); | ||
| + | WDTCSR |= (1<< | ||
| + | WDTCSR = 0x00; // disable watchdog timer | ||
| + | |||
| + | DDRD = PORTD_MASK; | ||
| + | DDRB = PORTB_MASK; | ||
| + | |||
| + | |||
| + | pwm = PWMDEFAULT; | ||
| + | |||
| + | |||
| + | for(i=0 ; i<CHMAX ; i++) // initialise all channels | ||
| + | { | ||
| + | compare[i] = pwm; // set default PWM values | ||
| + | compbuff[i] = pwm; // set default PWM values | ||
| + | } | ||
| + | |||
| + | |||
| + | TIFR0 = (1 << TOV0); | ||
| + | TIMSK0 = (1 << TOIE0); | ||
| + | TCCR0B = (1 << CS00); | ||
| + | |||
| + | sei(); | ||
| + | } | ||
| + | |||
| + | // | ||
| + | // Interrupt Service Routine | ||
| + | // | ||
| + | ISR (TIMER0_OVF_vect) | ||
| + | { | ||
| + | static unsigned char pinlevelB=PORTB_MASK, | ||
| + | static unsigned char softcount=0xFF; | ||
| + | |||
| + | PORTB = pinlevelB; | ||
| + | PORTD = pinlevelD; | ||
| + | |||
| + | |||
| + | if(++softcount == 0){ // increment modulo 256 counter and update | ||
| + | // the compare values only when counter = 0. | ||
| + | compare[0] = compbuff[0]; | ||
| + | compare[1] = compbuff[1]; | ||
| + | compare[2] = compbuff[2]; | ||
| + | compare[3] = compbuff[3]; | ||
| + | compare[4] = compbuff[4]; | ||
| + | compare[5] = compbuff[5]; | ||
| + | compare[6] = compbuff[6]; | ||
| + | compare[7] = compbuff[7]; | ||
| + | // | ||
| + | // | ||
| + | // last element should equal CHMAX - 1 | ||
| + | |||
| + | pinlevelB = PORTB_MASK; | ||
| + | pinlevelD = PORTD_MASK; | ||
| + | } | ||
| + | // clear port pin on compare match (executed on next interrupt) | ||
| + | if(compare[0] == softcount) CH0_CLEAR; | ||
| + | if(compare[1] == softcount) CH1_CLEAR; | ||
| + | if(compare[2] == softcount) CH2_CLEAR; | ||
| + | if(compare[3] == softcount) CH3_CLEAR; | ||
| + | if(compare[4] == softcount) CH4_CLEAR; | ||
| + | |||
| + | if(compare[5] == softcount) CH5_CLEAR; | ||
| + | if(compare[6] == softcount) CH6_CLEAR; | ||
| + | if(compare[7] == softcount) CH7_CLEAR; | ||
| + | // | ||
| + | // | ||
| + | |||
| + | |||
| + | } | ||
| + | </ | ||