0407 ARM DAY5

이의혁·2023년 4월 9일
0

1. DC Moter PWM Control
PWM 제어 API를 활용방법
1-1 SYSTEM : 84MHZ
1-2 TIM3 CH1 PWM

분주  84000000/840
	-->  100,00HZ
    -->  100KHZ
	-주기 :  T = 1/f
    		=>1/100000 = 0.00001 sec = 10us
     
     10us * 100개 ->0.001초 -> 1ms
     
  • counter period 가 100 이면 1ms
    auto-reload perload 를 enable 하면 counter가 자동으로 0으로 초기화 됌

  • duty cycle을 60으로 설정
  • PortA6 에 DC Motor 연결 power켰을 때 초기화 작업
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1); //PA6: DC Motor PWM
  • 속도 증가
    버튼이 눌렸으면 LED를 TOGGLE함으로 써 버튼이 눌림을 인식하고
    현재 상태에 저장되어있는 pwm값을 pwm_value에 저장하고 +10을 함으로써 속도를 증가 시킨다
    그리고 duty cycle이 최대 100이므로 100을 넘게 되면 pwm_value 값을 100 으로 고정하고
    그 값을 다시 pwm에 저장을 한다.

	//Speed Inc
	if (get_button(BUTTON0_GPIO_Port, BUTTON0_Pin, BUTTON0)== BUTTON_PRESS) //BUTTON0 PRESS 상태}
	{
		HAL_GPIO_TogglePin(GPIOB, GPIO_Pin0); //Led Toogle
		pwm_value = __HAL_TIM_GET_COMPARE(&htim3, TIM_CHANNEL_1); //현재 설정된 PWM 값을 읽어오는 API함수
		pwm_value += 10 ; //speed 10 INC
		if(pwm_value > 100) pwm_value = 100;
		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwm_value); //pwm 값 설정 변경
		
	}
  • 속도 감소
    버튼이 눌렸으면 LED를 TOGGLE함으로 써 버튼이 눌림을 인식하고
    현재 상태에 저장되어있는 pwm값을 pwm_value에 저장하고 -10을 함으로써 속도를 감소시킨다.
    그리고 duty cycle을 최소 60으로 설정하였으므로 60보다 작게되면 pwm_value 값을 60으로 고정하고
    그 값을 다시 pwm에 저장을 한다.
if (get_button(BUTTON1_GPIO_Port, BUTTON1_Pin, BUTTON1)== BUTTON_PRESS) //BUTTON1 PRESS 상태}
	{
		HAL_GPIO_TogglePin(GPIOB, GPIO_Pin1); //Led Toogle
		pwm_value = __HAL_TIM_GET_COMPARE(&htim3, TIM_CHANNEL_1); //현재 설정된 PWM 값을 읽어오는 API함수
		pwm_value -= 10 ; //speed 10 INC
		if(pwm_value < 60) pwm_value = 60;
		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwm_value); //pwm 값 설정 변경

	}
  • start와 stop동작
//Start/Stop
	if (get_button(BUTTON2_GPIO_Port, BUTTON2_Pin, BUTTON2)== BUTTON_PRESS)	//BUTTON2 PRESS 상태}
	{
		HAL_GPIO_TogglePin(GPIOB, GPIO_Pin2); //Led Toogle
		if(!start_flag)
		{
			start_flag = 1;
			HAL_TIM_PWM_Start(&htim3, PWM_TIM_CHANNEL_1);
		}
		else
		{
			start_flag = 0;
			HAL_TIM_PWM_Stop(&htim3, PWM_TIM_CHANNEL_1);
		}
	}

2. I2CLCD 부착 & I2C protocol 분석
PB9 -> I2CLCD SDA
PB8 -> I2CLCD SCL


connectivity -> I2C1 -> MODE를 I2C로 하면 PA8,9가 활성이 됌


main.c에 구조체가 활성화 된다.

[STM32] FAN Control
아래와 같이 LCD에 출력 한다. (버튼 제어에 따른 PWM 변화 값을 출력)
UIHYEOK FAN
Speed:


uint16_t pwm_value = 0;
uint8_t start_flag = 0;
extern TIM_HandleTypeDef htim3;
//FAN control main funtion

void dcmotor_pwm_control(void)
{
	//Speed Inc
	if (get_button(BUTTON0_GPIO_Port, BUTTON0_Pin, BUTTON0)== BUTTON_PRESS) //BUTTON0 PRESS 상태}
	{
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_0); //Led Toogle
		pwm_value = __HAL_TIM_GET_COMPARE(&htim3, TIM_CHANNEL_1); //현재 설정된 PWM 값을 읽어오는 API함수
		pwm_value += 10 ; //speed 10 INC
		if(pwm_value > 100) pwm_value = 100;
		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwm_value); //pwm 값 설정 변경

	}
	//Speed dec
	if (get_button(BUTTON1_GPIO_Port, BUTTON1_Pin, BUTTON1)== BUTTON_PRESS) //BUTTON1 PRESS 상태}
	{
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_1); //Led Toogle
		pwm_value = __HAL_TIM_GET_COMPARE(&htim3, TIM_CHANNEL_1); //현재 설정된 PWM 값을 읽어오는 API함수
		pwm_value -= 10 ; //speed 10 INC
		if(pwm_value < 60) pwm_value = 60;
		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwm_value); //pwm 값 설정 변경

	}
	//Start/Stop
	if (get_button(BUTTON2_GPIO_Port, BUTTON2_Pin, BUTTON2)== BUTTON_PRESS)	//BUTTON2 PRESS 상태}
	{
		HAL_GPIO_TogglePin(GPIOB, GPIO_PIN_2); //Led Toogle
		if(!start_flag)
		{
			start_flag = 1;
			HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
			pwm_value = 60;

		}
		else
		{
			start_flag = 0;
			HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
			pwm_value = 0;

		}
	}
}
void i2c_lcd_main(void)
{
	char lcd_buff[20];

 	i2c_lcd_init();

	move_cursor(0,0);
	lcd_string("UIHYEOK FAN!");
	sprintf (lcd_buff, "Speed : %3d", pwm_value);
	move_cursor(1,0);
	lcd_string(lcd_buff);
	HAL_Delay(500);

}

[STM32]I2C protocol 분석
dataseet상에는 9번 clock일 때 ack신호발생
9번 째 신호때 마다 ack
unsigned char lcd_test[2] = { '4', 0};
문자열의 null을 나타내기 위해서 뒤에 0을 붙힘


st신호가 발생하게 되면 총 8비트의 SDA가 SCL의 falling edge 에 맞춰서 값이 출력이 된다
첫번째 8비트중에서 상위 7비트는 MASTER가 SLAVE에게 보내는 주소이고, lsb는 read/write bit를 의미한다.
현재 lsb가 0이므로 write가 동작하는 것을 의미한다. 그리고 slave가 신호를 받았다는 ACK신호가 올라가고
그후 MASTER가 SLAVE 에게 데이터를 보내준다 그리고 SLAVE가 데이터를 받았다는 ACK신호가 올라가고 동작이 끝이난다.
ACK신호는 CLK이 9번째 일 때 발생한다.
< 과제 : 전자레인지 >
Button0 : Up time설정
Button1: Down time설정
Button2: start/stop 버튼


void microwave_time_state()
{
	if (get_button(BUTTON0_GPIO_Port, BUTTON0_Pin, BUTTON0)== BUTTON_PRESS) //BUTTON0 PRESS 상태}
	{
		sec += 10;
	}
	else if (get_button(BUTTON1_GPIO_Port, BUTTON1_Pin, BUTTON1)== BUTTON_PRESS) //BUTTON0 PRESS 상태}
	{
		if(sec>= 10)
		{
			sec -= 10;
		}
		else
		{
			sec = 0;
		}
	}
	else if (get_button(BUTTON2_GPIO_Port, BUTTON2_Pin, BUTTON2)== BUTTON_PRESS) //BUTTON0 PRESS 상태}
	{
		if(!start_flag)

			{
				start_flag = 1;


			}
			else
			{
				start_flag = 0;
			}
	}
}
  • 버튼 0번을 누르게 되면 sec가 10씩 증가, 버튼 1번을 누르게 되면 sec가-10씩 감소 만약에 sec가 10 이상일 때 누르면 10씩 감소하고 만약 10보다 작은숫자에서 10초를 감소하는 버튼을 누르게 되면 바로 0으로 되어서 기기가 꺼지게 된다.
    2번 버튼을 누르게 되면 flag가 발생 하게 하는데 flag가 1이면 start신호 falg가 2이면 stop신호이다.
void microwave__time_excute()
{
	if(start_flag) //on
	{
		if(sec)
		{
			if(t11ms_ultrasonic >= 1000) //1초
			{
				t11ms_ultrasonic = 0;
				sec -= 1;
			}

			HAL_TIMEx_PWMN_Start(&htim3, TIM_CHANNEL_1);
			pwm_value = 80;
			__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwm_value); //pwm 값 설정 변경
		}
		else
		{
			HAL_TIMEx_PWMN_Start(&htim3, TIM_CHANNEL_1);
			pwm_value = 0;
			__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwm_value); //pwm 값 설정 변경
		}

	}
	else if(!start_flag) //stop
	{
		HAL_TIMEx_PWMN_Start(&htim3, TIM_CHANNEL_1);
		pwm_value = 0;
		__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_1,pwm_value); //pwm 값 설정 변경
	}
}
  • flag가 1이고 sec라는게 존재 할 때
           if(t11ms_ultrasonic >= 1000) //1초
    			{
    				t11ms_ultrasonic = 0;
    				sec -= 1;
    			}
           
    이 코드가 실행하게 되는데, 1초마다 sec가 1초씩 감소하게 하는 코드이다
    그리고 선풍기가 pwm_value 80값으로 돌아가게 하였고 만약 flag가 있지만 sec가 없을 때는 선풍기가 멈추게 설정 하였다
    flag가 0일 때에는 선풍기가 꺼지게 하였다.
       
  
void microwave_lcd()
{
	char lcd_buff[20];
	lcd_sec = sec % 60;
	lcd_min	= sec / 60 %60;

	 	i2c_lcd_init();

		move_cursor(0,0);
		lcd_string("LEE MICROWAVE");
		sprintf (lcd_buff, "Timer %02d : %02d",lcd_min,lcd_sec );
		move_cursor(1,0);
		lcd_string(lcd_buff);
		HAL_Delay(500);

}
  • lcd_sec,min은 lcd에 표현 되어지는 sec와 min을 나타내는 것이다.

동작영상


다른방식의 과제

int microwave_on = 0;
void HAL_SYSTICK_Callback(void) // INTERRUPT 발생 시 CALL하는 함수,SYSTICK 기본으로 제공되어있는 TICK ->1ms
{
	if(microwave_on)
	{
		t1ms_counter++;
	}

	//t11ms_ultrasonic++;
}
  • systick은 사용자의 편의를 위해 기본적으로 1ms로 설정되어있는 함수이다 microwave라는 변수가 참이 될 때에만 t1ms_counter가 1씩 증가하게 된다.
    void lcddisp_time()
    {
    	if(t1ms_counter > 1000)
    	{
    		count --;
    		t1ms_counter = 0;
    	}
    	sec = count % 60;
    	min = (count /60) % 60;
    }
  • t1ms_counter가 1000보다 커지게 되면 1ms가 된다
    그러면 count를 1개씩 감소하게 하고, t1ms_counter를 초기화 해준다 그러면 1초가 지날때마다 count가 1씩 감소하게된다.
    그리고 sec와 min은 lcd에 출력하게 하는 초와 분이다.

    void i2c_lcd()
    {
    	char buff[20];
    
    	move_cursor(0,0);
    	lcd_string("MICROWAVE");
    	move_cursor(1,0);
    	sprintf(buff, "TIEMR %02d:%02d", min, sec);   //num값 바로 그대로 출력
    	lcd_string(buff);
    }
  • 이렇게 나타내면 lcd에 출력이된다.

    void microwave()
    {
    	if (get_button(BUTTON0_GPIO_Port, BUTTON0_Pin, BUTTON0)== BUTTON_PRESS) //BUTTON0 PRESS 상태}
    	{
    		count += 10;
    	}
    	else if (get_button(BUTTON1_GPIO_Port, BUTTON1_Pin, BUTTON1)== BUTTON_PRESS) //BUTTON1 PRESS 상태}
    	{
    		if(count >= 10)
    		{
    			count -= 10;
    		}
    		else
    		{
    			count = 0;
    		}
    	}
    	else if (get_button(BUTTON2_GPIO_Port, BUTTON2_Pin, BUTTON2)== BUTTON_PRESS) //BUTTON2 PRESS 상태}
    	{
    		if(!microwave_on)
    		{
    			microwave_on = 1;
    			HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
    		}
    		else if(microwave_on)
    		{
    			microwave_on = 0;
    			HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
    		}
    	}
    	if(!count)
    	{
    		microwave_on = 0;
    		HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
    
    	}
    }
  • 버튼 0번을 누르면 count가 10씩 증가하게 되고
    버튼 1번을 누르면 count가 10씩 감소하게된다.
    만약 count가 10보다 클 때 버튼 1번을 누르면 10씩 감소되지만 10보다 낮은 값에서 버튼 1번을 누르면 0으로 고정하게 하였다.
    맨 처음 microwave_on이 0인 상태이고, 버튼 2번을 눌렀을 시 microwave_on을 1로 주게 되고 그러면 맨 위에 있는 systic함수가 실행되게 된다 그러면 1초마다 count가 1씩 감소하는 것이 실행되고
    HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
    이 함수로 인하여 모터가 start가 된다.
    그리고 다시 버튼 2번을 누르게 되면 microwave_on이 0이 되어서 systick함수가 멈추게 되고'
    HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
    이 함수로 인하여 모터가 stop이 된다.

그리고 카운터가 0이 됐을 시 모터가 멈추게 하는 코드를 만들었다.
이렇게 만든 코드로 실행을 하게 되면 위에있는 영상과 똑같이 나오게 된다.

profile
코딩왕이 되는 길

0개의 댓글