[아두이노] Inter-Task Communication

HEEJOON MOON·2022년 6월 6일
0

ITC in FreeRTOS

KEYPAD를 이용한 모터 제어

  • 왼쪽 회전, 정지, 오른쪽 회전 3개의 키에 의해 모터 동작
  • Keypad ISR과 Motor Task간 큐를 이용하여 데이터 전달

< ITC1.c >

#include <FreeRTOS_AVR.h>

// 모터, 키패트 핀 정의
const int MT_P = 10;
const int MT_N = 9;
const int LeftKey = 2; // 0번 인터럽트 사용
const int StopKey = 3; // 1번 인터럽트 사용
const int RightKey = 21; // 2번 인터럽트 사용

// Task간 데이터 전달을 위해 전역으로 큐를 선언
QueueHandle_t xQueue;

// 키패트 ISR -> Queue로 데이터를 전달
void LeftKeyControl(){
	uint16_t sendValue = 1;
    xQueueSendFromISR(xQueue, &sendValue, 0);
}

void RightKeyControl(){
	uint16_t sendValue = 2;
    xQueueSendFromISR(xQueue, &sendValue, 0);
}

void RightKeyControl(){
	uint16_t sendValue = 3;
    xQueueSendFromISR(xQueue, &sendValue, 0);
}

void MotorTask(void *arg){
	uint16_t receiveValue = 0;
    
    while(1){
    	// Queue로부터 데이터 수신을 대기
        if(xQueueReceive(xQueue, &receiveValue, 0)){
        	// Left state
            if(receiveValue==1){
            	digitalWrite(MT_P, LOW);
                digitalWrite(MT_N, HIGH);
            }
            // Stop state
            if(receiveValue==2){
            	digitalWrite(MT_P, LOW);
                digitalWrite(MT_N, LOW);
            }
            // Right state
            if(receiveValue==3){
            	digitalWrite(MT_P, HIGH);
                digitalWrite(MT_N, LOW);
            }
        }
    }
}

void setup(){
	pinMode(MT_P, OUTPUT);
    pinMode(MT_N, OUTPUT);
    
    pinMode(LeftKey, INPUT);
    pinMode(StopKey, INPUT);
    pinMode(RightKey, INPUT);
    
    // 인터럽트 설정
 	attachInterrupt(0, LeftKeyControl, RISING); // Left키패드 입력은 Rising 조건일때 0번 인터럽트   
    attachInterrupt(1, StopKeyControl, RISING);
    attachInterrupt(1, RightKeyControl, RISING);
    
    // ITC를 위한 큐 생성
    xQueue = xQueueCreate(3, sizeof(uint16_t)); // 버퍼의 아이템수가 3인 큐 생성 
    
    if(xQueue!=NULL){ // 큐가 생성된 경우 Motor Task를 생성하고 스케쥴링 실행
    	xTaskCreate(MotorTask, NULL, 200, NULL, 1, NULL);
		vTaskStartScheduler();
    }
}

void loop(){}

KEYPAD를 이용한 모터 속도 제어

  • 왼쪽 or 오른쪽 회전은 25% 회전
  • 버튼 2개를 추가하여 속도를 제어
  • 한 번 누를때마다 50 -> 75 -> 100 -> 50으로 속도 제어

< ITC2.c >

#include<FreeRTOS_AVR.h>

const int MT_P =10;
const int MT_N =9;

const int LeftKey =2; // 0번 인터럽트
const int StopKey =3; // 1번 인터럽트
const int RightKey =21; // 2번 인터럽트
const int LeftSpeedKey =20; // 3번 인터럽트
const int RightSpeedKey =19; // 4번 인터럽트

// 255기준 Duty-cycle 정의 
const int val[4] = {127, 190, 255, 190};

// ITC을 위한 전역 큐
QueueHandle_t xQueue;

int count1, count2 = 0;

// 키패트 ISR -> Queue로 데이터를 전달
void LeftKeyControl(){
	uint16_t sendValue = 1;
    xQueueSendFromISR(xQueue, &sendValue, 0);
}

void StopKeyControl(){
	uint16_t sendValue = 2;
    xQueueSendFromISR(xQueue, &sendValue, 0);
}

void RightKeyControl(){
	uint16_t sendValue = 3;
    xQueueSendFromISR(xQueue, &sendValue, 0);
}

void LeftKeySpeedControl(){
  uint16_t sendValue =4;
  xQueueSendFromISR(xQueue, &sendValue, 0);
}

void RightKeySpeedControl(){
  uint16_t sendValue =5;
  xQueueSendFromISR(xQueue, &sendValue, 0);
}

void MotorTask(){
	uint16_t recievevalue = 0;
    
    while(1){
    
    	if(xQueueReceive(xQueue, &receiveValue, 0)){
              // Rotate Left
              if(receiveValue==1){
                analogWrite(MT_P, 0);
                analogWrite(MT_N, 64);
               }
              // STOP
              else if(receiveValue==2){
                analogWrite(MT_P, 0);
                analogWrite(MT_N, 0);
              }
              // Rotate Right
              else if(receiveValue==3){
                analogWrite(MT_P, 0);
                analogWrite(MT_N, 64);
               }
             // Left Rotation Speed up
             else if(receiveValue==4){
                analogWrite(MT_P, 0);
                analogWrite(MT_N, val[count1]);
      			count1 = (count1+1) % 4;
               }
             // Right Rotation Speed up
             else if(receiveValue==5){
                analogWrite(MT_P, val[count2]);
                analogWrite(MT_N, 0);
      			count2 = (count2+1) % 4;
               }
        }
    }
}

void setup() {
  // Set pin Mode
  pinMode(MT_P, OUTPUT);
  pinMode(MT_N, OUTPUT);

  pinMode(LeftKey, INPUT);
  pinMode(StopKey, INPUT);
  pinMode(RightKey, INPUT);
  pinMode(LeftSpeedKey, INPUT);
  pinMode(RightSpeedKey, INPUT);
	
  // 인터럽트 추가
  attachInterrupt(0, LeftKeyControl, RISING);
  attachInterrupt(1, StopKeyControl, RISING);
  attachInterrupt(2, RightKeyControl, RISING);
  attachInterrupt(3, LeftKeySpeedControl, RISING);
  attachInterrupt(4, RightKeySpeedControl, RISING);
  
  // 큐 생성
  xQueue = xQueueCreate(5, sizeof(uint16_t));
  
  if(xQueue !=NULL) {
    xTaskCreate(MotorTask, NULL, 200, NULL, 1, NULL);
    vTaskStartScheduler();
  }
}

void loop(){}
profile
Robotics, 3D-Vision, Deep-Learning에 관심이 있습니다

0개의 댓글