Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* Pretende-se controlar a velocidade de um motor DC utilizando PWM. Os interruptores SW1, SW2, SW3 e SW4 permitem definir as velocidades de rotação do motor com os valores 0%, 40%, 70% e 100% da velocidade nominal. SW5 e SW6 definem o sentido de rotação.
- Qualquer alteração de velocidade/sentido deve ser implementada utilizando uma rampa de aceleração/desaceleração com uma taxa fixa de 1 unidade (OCR) / 10ms.
- Sugestão:
- Utilizar o TC0, programado em modo CTC, para obter uma temporização base de 5ms.
- Utilizar o TC2, programado em modo PWM (Fast PWM ou Phase Correct PWM), para gerar o sinal de PWM na saída OC2 (PB7). A frequência deste sinal de PWM deve ser de, aproximadamente, 500Hz. O sentido de rotação será definido através das saídas Dir0 (PB4) e Dir1 (PB5). */
- #include <avr/io.h>
- #include <avr/interrupt.h>
- #include <stdlib.h>
- #include <math.h>
- // IN1 -> 6
- // EN -> 8
- // IN2 -> 5
- // GND -> 8
- // VCC -> 7
- // definicoes
- #define Done 1
- #define NotDone 0
- #define clock_freq 16000000
- #define prescaler 1024
- // macros
- #define pwm_value(val) (255 * val) / 100
- #define timer_value(val) val / 5
- #define ocr_value(val) ((val * pow(10, -3) * clock_freq) / prescaler) -1
- // retorna 1 se val negativo; 0 se val positivo
- #define signal(val) (val&0x8000)>>15
- // 0xFE: 11111110: 11111110<<5 -> 355555520
- // bitwise AND (&): flags = flags & MASK -> flags &= MASK;
- // <<: shitft left: a<<b: desloca os bits de "a", "b" passos para a esquerda (cada passo significa "multiplicar por dois")
- // bitwise OR (|): flags = flags | MASK -> flags |= MASK;
- // bitwise NOT (~): inverte os bits
- #define signal_bit(port, sigbit1, sigbit0, sig) \
- port &= (0xFE<<sigbit1);\
- port &= (0xFE<<sigbit0);\
- port |= ((sig&0x01)<<sigbit1);\
- port |= ((~sig&0x01)<<sigbit0);
- typedef struct motor {
- int setpoint;
- int actual_point;
- } motor_t;
- void Inic(motor_t *motor);
- void pwm(motor_t *motor);
- unsigned char cnt = timer_value(20);
- unsigned char pwm_update = Done;
- int main() {
- motor_t motor;
- Inic(&motor);
- // switch da direccao e switch da velocidade em simultâneo
- while(1) {
- switch (PINA & 0x0F) {
- case 0x0E:
- motor.setpoint = pwm_value(0);
- break;
- case 0x0D:
- if ((PINA & 0x10) == 0)
- motor.setpoint = pwm_value(-40); // -102
- else
- motor.setpoint = pwm_value(40); // 102
- break;
- case 0x0B:
- if ((PINA & 0x10) == 0)
- motor.setpoint = pwm_value(-70); // -178
- else
- motor.setpoint = pwm_value(70); // 178
- break;
- case 0x07:
- if ((PINA & 0x10) == 0)
- motor.setpoint = pwm_value(-100); // -255
- else
- motor.setpoint = pwm_value(100); // 255
- break;
- }
- if (pwm_update == NotDone) {
- pwm(&motor);
- }
- }
- return 0;
- }
- // inic
- void Inic(motor_t *motor) {
- // switch
- DDRA = 0x00; // 0b00000000;
- PORTA = 0xC0; // 0b11000000;
- // motor
- DDRB = 0xB0; // 0b10110000;
- PORTB = 0x10; // 0b00010000;
- // timer 0
- OCR0 = ocr_value(5);
- TCCR0 = 0x0F;
- cnt = timer_value(10);
- // PWM
- OCR2 = 0;
- TCCR2 = 0x64; // 0b01100100;
- // interr
- TIMSK = TIMSK|0x2; // == TIMSK |= 0x2
- SREG = SREG | 0x80;
- // inic da estrutura
- motor->setpoint = 0;
- motor->actual_point = 0;
- }
- // interrupcao
- ISR(TIMER0_COMP_vect) {
- cnt--;
- if (cnt == 0) {
- cnt = timer_value(10);
- pwm_update = NotDone;
- }
- }
- // pwm: chamada a cada 10ms
- void pwm(motor_t *motor) {
- // coloca o motor em movimento
- // coloca o motor no sentido correcto
- if (motor->actual_point == 0) {
- // signal pos -> output: 16
- // signal neg -> output: 32
- signal_bit(PORTB, 5, 4, signal(motor->setpoint));
- }
- // se motor mais rapido que o pretendido
- if (motor->actual_point > motor->setpoint) {
- motor->actual_point--;
- OCR2 = abs(motor->actual_point);
- }
- // se motor mais lento que o pretendido
- if (motor->actual_point < motor->setpoint) {
- motor->actual_point++;
- OCR2 = abs(motor->actual_point);
- }
- pwm_update = Done;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement