본문 바로가기
프로세싱+아두이노+안드로이드

아두이노 차량에 스피드 센서 사용 방법

by YJHTPII 2022. 5. 13.
반응형

https://m.blog.naver.com/dev4unet/221209677083

 

[버섯] 아두이노 차량에 스피드 센서 사용 방법 - Arduino Robot Car with Speed Sensors - Using Arduino Interrupts

버섯돌이의 정보 공유 Arduino Robot Car with Speed Sensors - Using Arduino Interrupts - 해외 ...

blog.naver.com

 

 

 

 

 

버섯돌이의 정보 공유
Arduino Robot Car with Speed Sensors - Using Arduino Interrupts - 해외 영상
 
Created Date: 2018.02.16
Modified Date: 2018.02.16
revision 1.0
 
 
키워드 : 아두이노, Arduino, DIY, Tutorial, Robot Car, Speed Sensors, Arduino Interrupts
 
들어가며..
안녕하세요 버섯돌이 유재성입니다.

포스팅 후에도 틈틈이 내용을 다듬다 보니 수정이 잦네요.^^

원문 수정 시 공유한 곳의 글 들도 함께 수정하려고 노력합니다만 수정이 쉽지 않습니다.^^;;;

작성한지 오래된 글은 가급적 블로그의 원본 글 이나 알리마스터(링크) 카페에 등록된 글을 함께 참고하시기 바랍니다.

 

아두이노의 인터럽트를 이용한 스피드 센서 사용법에 대한 꽤 상세한 해외 강좌입니다.

 

 

ㅎㅎㅎ.. 비슷한 강좌도 쓰려고 관련 부품들을 구매한 지도 어느덧 몇 년이 훨씬 지나갔네요^^;;

본업을 손 놓고 이쪽을 자주 접할 때에는 그러려니 했었지만...

그동안 손 놓았던 본업의 기초를 다시 쌓느라고 비수면으로 너무 바쁘게 보냈더니 

이제는 이쪽 분야는 Hello World도 기억이 안 나는 관계로 시간 될 때 기초부터 정독해야겠네요^^

 

Arduino Robot Car with Speed Sensors - Using Arduino Interrupts

 

1만 원 이하로 구매 가능한 차량 KIT를 이용합니다.

부품 구성을 보면 모터에 연결하는 인코더(검은색 동그라미)가 있지만 전자 부품은 포함되어 있지 않은 제품입니다.

 

그래서 인코더를 이용하시려면 H206 같은 광 인터럽트 센서나 기타 다른 센서 부품이 필요합니다.

 

하지만 H206 만으로는 오차가 있어서 보정을 위한 Comparator를 함께 사용해야 합니다.

 

 

비교기는 두 개의 입력과 1개의 출력을 갖는 장치로서

하나의 입력은 기준 전압이고 다른 하나의 입력은 포토트랜지스터의 출력을 연결합니다.

 

열쇠는 기준 전압으로서 포토 트랜지스터의 입력이 기준 전압보다 낮 으면 비교기의 디지털 출력은 로우로 유지되고

입력이 기준 전압과 동일하거나 초과하면 출력은 높아지게 됩니다.

 

 

 

센서는 이런 형태로 장착하면 됩니다.

 

 

아두이노와 L298N 모터 드라이버를 비롯하여 스피드 센서를 연결합니다.



아두이노 모델에 따라 디지털 인터럽트 핀 번호가 다릅니다.





간단한 센서 테스트를 위한 결선도입니다.

 

 

실제로는 이런 형태가 되겠지요?

 

 

테스트 코드이며 시리얼 모니터에 RPM이 출력됩니다.

/*
Optical Sensor Two Motor Demonstration
DualMotorSpeedDemo.ino
Demonstrates use of Hardware Interrupts
to measure speed from two motors
 
DroneBot Workshop 2017
*/
 
// Include the TimerOne Library from Paul Stoffregen
#include "TimerOne.h"
 
// Constants for Interrupt Pins
// Change values if not using Arduino Uno
 
const byte MOTOR1 = 2;  // Motor 1 Interrupt Pin - INT 0
const byte MOTOR2 = 3;  // Motor 2 Interrupt Pin - INT 1
 
// Integers for pulse counters
unsigned int counter1 = 0;
unsigned int counter2 = 0;
 
// Float for number of slots in encoder disk
float diskslots = 20;  // Change to match value of encoder disk
 
// Interrupt Service Routines
 
// Motor 1 pulse count ISR
void ISR_count1()  
{
  counter1++;  // increment Motor 1 counter value
}
 
// Motor 2 pulse count ISR
void ISR_count2()  
{
  counter2++;  // increment Motor 2 counter value
}
 
// TimerOne ISR
void ISR_timerone()
{
  Timer1.detachInterrupt();  // Stop the timer
  Serial.print("Motor Speed 1: ");
  float rotation1 = (counter1 / diskslots) * 60.00;  // calculate RPM for Motor 1
  Serial.print(rotation1);  
  Serial.print(" RPM - ");
  counter1 = 0;  //  reset counter to zero
  Serial.print("Motor Speed 2: ");
  float rotation2 = (counter2 / diskslots) * 60.00;  // calculate RPM for Motor 2
  Serial.print(rotation2);  
  Serial.println(" RPM");
  counter2 = 0;  //  reset counter to zero
  Timer1.attachInterrupt( ISR_timerone );  // Enable the timer
}
 
void setup()
{
  Serial.begin(9600);
  
  Timer1.initialize(1000000); // set timer for 1sec
  attachInterrupt(digitalPinToInterrupt (MOTOR1), ISR_count1, RISING);  // Increase counter 1 when speed sensor pin goes High
  attachInterrupt(digitalPinToInterrupt (MOTOR2), ISR_count2, RISING);  // Increase counter 2 when speed sensor pin goes High
  Timer1.attachInterrupt( ISR_timerone ); // Enable the timer
}
 
void loop()
{
  // Nothing in the loop!
  // You can place code here
}

 

 

최종 차량의 소스입니다.

 /*  
  Robot Car with Speed Sensor Demonstration
  RobotCarSpeedSensorDemo.ino
  Demonstrates use of Hardware Interrupts
  to control motors on Robot Car
  
  DroneBot Workshop 2017
*/
 
// Constants for Interrupt Pins
// Change values if not using Arduino Uno
 
const byte MOTOR_A = 3;  // Motor 2 Interrupt Pin - INT 1 - Right Motor
const byte MOTOR_B = 2;  // Motor 1 Interrupt Pin - INT 0 - Left Motor
 
// Constant for steps in disk
const float stepcount = 20.00;  // 20 Slots in disk, change if different
 
// Constant for wheel diameter
const float wheeldiameter = 66.10; // Wheel diameter in millimeters, change if different
 
// Integers for pulse counters
volatile int counter_A = 0;
volatile int counter_B = 0;
 
 
// Motor A
 
int enA = 10;
int in1 = 9;
int in2 = 8;
 
// Motor B
 
int enB = 5;
int in3 = 7;
int in4 = 6;
 
// Interrupt Service Routines
 
// Motor A pulse count ISR
void ISR_countA()  
{
  counter_A++;  // increment Motor A counter value
}
 
// Motor B pulse count ISR
void ISR_countB()  
{
  counter_B++;  // increment Motor B counter value
}
 
// Function to convert from centimeters to steps
int CMtoSteps(float cm) {
 
  int result;  // Final calculation result
  float circumference = (wheeldiameter * 3.14) / 10; // Calculate wheel circumference in cm
  float cm_step = circumference / stepcount;  // CM per Step
  
  float f_result = cm / cm_step;  // Calculate result as a float
  result = (int) f_result; // Convert to an integer (note this is NOT rounded)
  
  return result;  // End and return result
 
}
 
// Function to Move Forward
void MoveForward(int steps, int mspeed)
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
  
   // Set Motor A forward
   digitalWrite(in1, HIGH);
   digitalWrite(in2, LOW);
 
   // Set Motor B forward
   digitalWrite(in3, HIGH);
   digitalWrite(in4, LOW);
  
   // Go forward until step value is reached
   while (steps > counter_A && steps > counter_B) {
  
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
   }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero
 
}
 
// Function to Move in Reverse
void MoveReverse(int steps, int mspeed)
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
  
   // Set Motor A reverse
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
 
  // Set Motor B reverse
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  
   // Go in reverse until step value is reached
   while (steps > counter_A && steps > counter_B) {
  
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
    }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero
 
}
 
// Function to Spin Right
void SpinRight(int steps, int mspeed)
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
  
   // Set Motor A reverse
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
 
  // Set Motor B forward
  digitalWrite(in3, HIGH);
  digitalWrite(in4, LOW);
  
   // Go until step value is reached
   while (steps > counter_A && steps > counter_B) {
  
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
   }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero
 
}
 
// Function to Spin Left
void SpinLeft(int steps, int mspeed)
{
   counter_A = 0;  //  reset counter A to zero
   counter_B = 0;  //  reset counter B to zero
  
   // Set Motor A forward
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
 
  // Set Motor B reverse
  digitalWrite(in3, LOW);
  digitalWrite(in4, HIGH);
  
   // Go until step value is reached
   while (steps > counter_A && steps > counter_B) {
  
    if (steps > counter_A) {
    analogWrite(enA, mspeed);
    } else {
    analogWrite(enA, 0);
    }
    if (steps > counter_B) {
    analogWrite(enB, mspeed);
    } else {
    analogWrite(enB, 0);
    }
  }
    
  // Stop when done
  analogWrite(enA, 0);
  analogWrite(enB, 0);
  counter_A = 0;  //  reset counter A to zero
  counter_B = 0;  //  reset counter B to zero
 
}
 
void setup()
{
  // Attach the Interrupts to their ISR's
  attachInterrupt(digitalPinToInterrupt (MOTOR_A), ISR_countA, RISING);  // Increase counter A when speed sensor pin goes High
  attachInterrupt(digitalPinToInterrupt (MOTOR_B), ISR_countB, RISING);  // Increase counter B when speed sensor pin goes High
  
  // Test Motor Movement  - Experiment with your own sequences here  
  
  MoveForward(CMtoSteps(50), 255);  // Forward half a metre at 255 speed
  delay(1000);  // Wait one second
  MoveReverse(10, 255);  // Reverse 10 steps at 255 speed
  delay(1000);  // Wait one second
  MoveForward(10, 150);  // Forward 10 steps at 150 speed
  delay(1000);  // Wait one second
  MoveReverse(CMtoSteps(25.4), 200);  // Reverse 25.4 cm at 200 speed
  delay(1000);  // Wait one second
  SpinRight(20, 255);  // Spin right 20 steps at 255 speed
  delay(1000);  // Wait one second
  SpinLeft(60, 175);  // Spin left 60 steps at 175 speed
  delay(1000);  // Wait one second
  MoveForward(1, 255);  // Forward 1 step at 255 speed
  
  
}
 
 
void loop()
{
  // Put whatever you want here!
 
  
}

 

보다 자세한 내용은 원본 영상을 참고하시기 바랍니다.

출처 : https://youtu.be/oQQpAACa3ac

 

 

아래 블로그에 조립을 비롯하여 아두이노 코드 등 설명이 꽤 자세히 나와 있으니 가급적 참고하시기 바랍니다.

Build a Robot Car with Speed Sensors

https://dronebotworkshop.com/robot-car-with-speed-sensors/ 

 

 

참고 자료..

얼핏 봤을 때 대부분은 예전에 포스팅했었던 부품과 강좌들 같으니 별도로 찾지는 않겠습니다.

예전에 포스팅했었던 2륜이나 4륜 차량 KIT 정보와 센서 정보 및 부품 구매 글들을 참고하시면 도움이 되리라 봅니다.

 

반응형

댓글