Controle de Velocidade de dois motores DC usando AVR

Olá, neste trabalho demonstra-se o funcionamento de dois motores DC usando o Kit Atmega128.

Atmega128-M128

Será fundamental para o desenvolvimento do carro autónomo que se tem vindo a falar nos anteriores artigos.

Neste artigo apenas consta uma pequena demonstração, usando o Proteus com 2 motores DC e um servomotor incluindo sonar.

Para que este artigo não seja estático, vou deixar uma pequena demonstração com video do funcionamento.

Como não podia deixar de ser deixo também um pouco do Código beta, cujo desenvolvimento está em curso e será actualizado conjuntamente com o artigo.

Mantenham-se atentos –> AQUI

 

main beta
/*
 *Control_Motor_DC.c
 *20/10/2017
 *Author: Norlinux
 *http://www.microelectronic.pt
 *https://www.facebook.com/MundoDosMicrocontroladores/
 *http://maquina.96.lt
 *Released under GPLv3.
 *Please refer to LICENSE file for licensing information.
 *which can be found at http://www.gnu.org/licenses/gpl.txt
 */


#include <avr/io.h>
#include <avr/interrupt.h>
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#define F_CPU 8000000UL
#include <util/delay.h>
#include "lcd/lcd_lib.h"
#include "Functions.h"
volatile unsigned char vucUp = 0;
volatile uint32_t uiTimerCounter = 0;
volatile unsigned char vucStartSonar = 0;
volatile long vlResult = 0;

uint16_t uiValorMax=0, uiValor[3]={};
uint16_t uiValorEsq=0, uiValorDir=0, uiValor0=0;

Servo Servo9g={0,0}; // Inicio da Estrutura


// Macros
#define Frente 1
#define Traz -1
#define Motors_Port PORTA
#define Motors_DDR DDRA
#define Motor_Dir_F 0
#define Motor_Dir_T 1
#define Motor_Esq_F 2
#define Motor_Esq_T 3
#define PER_DDR DDRA
#define PER_Port PORTA
#define Led 4
#define buzz 5
#define sinal_Neg_Pos(val) (val&0x8000)>>15 //// retorna 1 se val negativo; 0 se val positivo
#define set_bit(adress,sign,bit) (adress|=((sign&0x01)<<bit)) //Coloca a um o Bitx do Portx em função do sinal que retorna(PORTx,sig,SPxx)
#define clr_bit(adress,bit) (adress&=~(1<<bit)) // Coloca a zero o Bitx do Portx (PORTx,Pxx)
#define signal_bit(port, sigbit1, sigbit0, sig) port &= (0xFE<<sigbit1); port &= (0xFE<<sigbit0);port |= ((sig&0x01)<<sigbit1);port |= ((~sig&0x01)<<sigbit0);
#define Direcao_Motor_Dir(port, in1, in2, sinal)  clr_bit(port,in1); clr_bit(port,in2); set_bit(port,sinal,in1);set_bit(port,~sinal,in2);
#define Direcao_Motor_Esq(port, in3, in4, sinal)  clr_bit(port,in3); clr_bit(port,in4); set_bit(port,sinal,in3);set_bit(port,~sinal,in4);
#define OCR1_Valor(val) (0.226*val)
//#define Toggle_Led() (PER_Port^=(1<<Led))
//#define Liga_buzz() (PER_Port|=(1<<buzz))
//#define Desliga_buzz() (PER_Port&=~(1<<buzz))  
typedef struct motores {
	int Set_P_dir;
	int Set_P_esq;
	int valor_actual_dir;
	int valor_actual_esq;
	int8_t sentido_dir;
	int8_t sentido_esq;
} motor_dc;

motor_dc motor={0,0,0,0,0,0};
volatile uint16_t conta = 0;
volatile uint32_t timerCounter = 0;
volatile unsigned char up = 0,running = 0;
volatile long result = 0;

void HW_Init_motor()
{	
	//---------------------Motor init code -------------------------
	Motors_DDR |= (1<<Motor_Dir_F) | (1<<Motor_Dir_T) | (1<<Motor_Esq_F) | (1<<Motor_Esq_T);
	//---------------------Perifericos -----------------------------
	//PER_DDR |= (1<<Led) | (1<<buzz);
	//---------------------Timer PWM Code---------------------------
	TCCR1A|= (1<<COM1A1) | (1<<COM1B1) | (1<<WGM10);	 // configurar Timer1 PWM, Phase Correct, 8-bit ( 255 )
	TCCR1B |= (1<<CS10);											// No prescaling
	//--------------------Timer Sonar Code--------------------------
	// setup 8 bit timer & enable interrupts, timer increments to 255 and interrupts on overflow
	TCCR0 = (0<<CS02)|(0<<CS01)|(1<<CS00); // select internal clock with no prescaling
	TCNT0 = 0; // reset counter to zero
	TIMSK = 1<<TOIE0; // enable timer interrupt
	//--------------------------Interrupcoes----------------
	EICRA|=(0<<ISC11)|(1<<ISC10);				// Flanco ascendente
	EIMSK|=(1<<INT1);							//Int1
	//------------------------------------------------------
}


void motor_control_dir(motor_dc *motor)
{
	// coloca o motor em movimento
	if (motor->valor_actual_dir == 0) {
		Direcao_Motor_Dir(Motors_Port, Motor_Dir_F, Motor_Dir_T, sinal_Neg_Pos(motor->Set_P_dir));
		//signal_bit(Motors_Port,Motor_Dir_F,Motor_Dir_T,sinal_Neg_Pos(motor->sentido_dir));
	}
		  // diminui a velocidade do motor
		  if (motor->valor_actual_dir > motor->Set_P_dir) {
			  motor->valor_actual_dir--;
			  OCR1A = abs(motor->valor_actual_dir);
		  }

		  // aumenta a velocidade do motor
		  if (motor->valor_actual_dir < motor->Set_P_dir) {
			  motor->valor_actual_dir++;
			  OCR1A = abs(motor->valor_actual_dir);
		  }
}
void motor_control_esq(motor_dc *motor)
{
	// coloca o motor em movimento
	if (motor->valor_actual_esq == 0) {
		Direcao_Motor_Esq(Motors_Port, Motor_Esq_F, Motor_Esq_T, sinal_Neg_Pos(motor->Set_P_esq));
		//signal_bit(Motors_Port,Motor_Esq_F,Motor_Esq_T,sinal_Neg_Pos(motor->sentido_esq));
	}
	// diminui a velocidade do motor
	if (motor->valor_actual_esq > motor->Set_P_esq) {
		motor->valor_actual_esq--;
		OCR1B = abs(motor->valor_actual_esq);
	}

	// aumenta a velocidade do motor
	if (motor->valor_actual_esq < motor->Set_P_esq) {
		motor->valor_actual_esq++;
		OCR1B = abs(motor->valor_actual_esq);
	}
}

// timer overflow interrupt, each time when timer value passes 255 value
SIGNAL(TIMER0_OVF_vect)
{

	if (vucUp) {	// voltage rise was detected previously
		uiTimerCounter++; // count the number of overflows
		// dont wait too long for the sonar end response, stop if time for measuring the distance exceeded limits
		uint32_t ticks = uiTimerCounter * 256 + TCNT0;
		uint32_t max_ticks = (uint32_t)MAX_RESP_TIME_MS * INSTR_PER_MS; // this could be replaced with a value instead of multiplying
		if (ticks > max_ticks) {
			// timeout
			vucUp = 0;	 	 // stop counting timer values
			vucStartSonar = 0; // ultrasound scan done
			vlResult = -1; // show that measurement failed with a timeout (could return max distance here if needed)
		}
	}
}
SIGNAL(INT1_vect)
{
	if (vucStartSonar) { //accept interrupts only when sonar was started
		if (vucUp == 0) { // voltage rise, start time measurement
			vucUp = 1;
			uiTimerCounter = 0;
			TCNT0 = 0; // reset timer counter
			} else {
			// voltage drop, stop time measurement
			vucUp = 0;
			// convert from time to distance(millimeters): d = [ time_s * 340m/s ] / 2 = time_us/58
			vlResult = (uiTimerCounter * 256 + TCNT0) / (58 * INSTR_PER_US);
			vucStartSonar = 0;
		}
	}
}


void SendTrigger() {

	TRIGGER_PIN_SET_BAIXO(Trigger_Port,TRIG);
	_delay_us(1);
	TRIGGER_PIN_SET_ALTO(Trigger_Port,TRIG);
	vucStartSonar = 1; // sonar launched
	_delay_us(10);
	TRIGGER_PIN_SET_BAIXO(Trigger_Port,TRIG);
	_delay_us(1);
}
void ServerMotor(Servo *Servo9g)
{
	
	ServoPosicao = Menos90Graus;
	Wait()
	if (vucStartSonar == 0) SendTrigger();
	uiValorEsq = vlResult;
	ServoPosicao=Mais90Graus
	Wait()
	if (vucStartSonar == 0) SendTrigger();
	uiValorDir=vlResult;
	if (uiValorEsq<uiValorDir)
	{uiValorMax=uiValorDir; motor.sentido_dir=Frente; motor.sentido_esq=Frente;Servo9g->Posicao=Pos_Dir;}
	else
	{uiValorMax=uiValorEsq; motor.sentido_dir=Traz; motor.sentido_esq=Traz;Servo9g->Posicao=Pos_Esq;}
	ServoPosicao = ZeroGraus;
}
int main(void)
{
    HW_Init_motor();
	HW_Init_servo();
	LCDinit();
	sei();
	 char cBuffer[16]={};
	while(1)
    {
		if (vucStartSonar == 0) SendTrigger();
		_delay_ms(10);
		
		sprintf(cBuffer,"Distancia = %03.0f",OCR1_Valor(vlResult));
		LCDprintXY(cBuffer,0,0);
		if (vlResult> 0 && vlResult <100)
		{
			INIT_TIMER3; ServerMotor(&Servo9g); 
			motor.Set_P_dir=(-trunc(OCR1_Valor(vlResult)));
			motor.Set_P_esq=(-trunc(OCR1_Valor(vlResult)));
		}
		else if (vlResult> 110 && vlResult <400)
		{
			STOP_TIMER3;
			motor.Set_P_dir=trunc(OCR1_Valor(vlResult));
			motor.Set_P_esq=trunc(OCR1_Valor(vlResult));
		}
		else if (vlResult> 410 && vlResult <1000)
		{
			motor.Set_P_dir=trunc(OCR1_Valor(vlResult));
			motor.Set_P_esq=trunc(OCR1_Valor(vlResult));
		}
		else
		{
			motor.Set_P_dir=(-254);
			motor.Set_P_esq=(-254);
		}
		motor_control_dir(&motor);
		motor_control_esq(&motor);
		}
}

Esquema do Projecto:

2Motors DC

Deixe uma resposta

Your email address will not be published.

www.000webhost.com