현재 10월 말, 11월 초에 있을 자작전기차 대회를 위해 전기자동차를 제작하는 중입니다.
사실 본의아니게 들어온 자동차 동아리이지만...(캔위성 대회 준비하면서 장소 빌려쓰다가...) 속도계랑 온도계를 만들게 되었습니다.
대략적인 모습은 이렇습니다. 좌측의 노란색 7-세그먼트가 각각 속도와 바퀴의 RPM을 표시해줍니다. 가운데에 위치한 빨간 7-세그먼트는 모터와 모터컨트롤러의 온도계를 표시합니다.
현 사진의 상태는 K-type Thermocouple이 연결되어있지 않아 Erro신호를 보내도록 설계하였습니다.
밤에보면 이런모습입니다. 사실 속도계를 만드는 과정은 다음과 같습니다.
준비물 : 2x 아두이노 프로 미니 (5V) , IR 장애물 탐지 모듈, 4x 7-Segments, 2x MAX6675, 정신력
대략적인 회로도는 다음과 같이 그렸습니다. 휠 근처에 부착한 적외선 인지 센서로 바퀴의 회전수를 읽어서 두개의 4-digit 7-세그먼트에 띄워줍니다.
적외선 인지센서가 부착된 모습은 다음과 같습니다.
위는 모터의 온도계에 직결될 K-Type ThermoCouple의 데이터값을 읽을 Max6675 모듈을 장착한 모습입니다.
제작하는 모습은 다음과 같습니다.
초반에 실제로 작동하는지 테스트해보고... 바로 제작 들어갑니다.
대략적인 계기판 위치 잡아주고
완성되었습니다.
온도도 잘뜨고... 대성공인줄 알았으나 오른쪽 디스플레이가 불량이어서 교체한게 첫번째 사진입니다.
속도계의 코드는 아래와 같아요
#include <Arduino.h>
#include <TM1637Display.h>
#include <TimerOne.h>
const byte CLK1 = 2; // define CLK pin (any digital pin)
const byte DIO1 = 3; // define DIO pin (any digital pin)
const byte CLK2 = 11; // define CLK pin (any digital pin)
const byte DIO2 = 12; // define DIO pin (any digital pin)
const int IRSensorPin = 7;
const float Diameter = 0.20;
const uint8_t SEG_DONE[] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
SEG_C | SEG_E | SEG_G, // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E
};
const uint8_t SEG_ERR[] = {
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_E | SEG_G, // R
SEG_E | SEG_G, // R
};
TM1637Display display1(CLK1, DIO1);// define dispaly 1 object
TM1637Display display2(CLK2, DIO2);// define dispaly 2 object
uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 }; // all segments clear
// Note: This program was used at one time with a reed relay, for a bicycle cadence counter,
// but it works all right with the input from the IR sensor.
// If I need to reuse it, all variables are still in place.
int inputState; // the current state from the input pin
int lastInputState = LOW; // the previous InputState from the input pin
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 5; // the debounce time; increase if the output flickers
long time;
long endTime;
long startTime;
int lin_vel;
int RPM = 0;
float lnTime = 0;
void setup() {
pinMode(IRSensorPin, INPUT);
display1.setBrightness(0x0f);// set brightness of dispaly 1
display2.setBrightness(0x0f);// set brightness of dispaly 2
Serial.begin(9600);
display1.setSegments(SEG_DONE);
display2.setSegments(SEG_DONE);
endTime = 0;
Timer1.initialize(1000000); // Set the timer to 60 rpm, 1,000,000 microseconds (1 second)
Timer1.attachInterrupt(timerIsr); // Attach the service routine here
}
void loop() {
time = millis();
int currentSwitchState = digitalRead(IRSensorPin);
if (currentSwitchState != lastInputState) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
if (currentSwitchState != inputState) {
inputState = currentSwitchState;
if (inputState == LOW) {
calculateRPM();
}
else {
}
}
}
lastInputState = currentSwitchState;
}
// ---------------------------------------------------------------
void calculateRPM() {
startTime = lastDebounceTime;
lnTime = startTime - endTime;
RPM = 60000 / (startTime - endTime);
endTime = startTime;
}
void timerIsr()
{
// Print RPM every second
// RPM based on timer
Serial.println("---------------");
time = millis() / 1000;
Serial.print(time);
Serial.print(" RPM: ");
Serial.println(RPM);
lin_vel = (Diameter) * RPM * ((2 * PI) / 60) * 3.6;
int lin_vel_16 = lin_vel;
Serial.print(" Linear_Speed: ");
Serial.println(lin_vel);
display1.showNumberDec(RPM);
display2.showNumberDec(lin_vel_16);
delay(10);
RPM = 0;
}
속도계는 1ms동안 얼마나 센서의 High, Low값의 전환이 있었는지를 기준으로 RPM을 측정하고 RPM을 속도로 변환시켰습니다.
하나의 아두이노로 두개의 디스플레이를 쓰기위해서 많은 정보를 찾아보았습니다. 다음은 온도계의 코드입니다.
#include <Arduino.h>
#include <TM1637Display.h>
#include <MAX6675.h>
int CS1 = 4; // CS pin on MAX6675
int SO1 = 5; // SO pin of MAX6675
int sCK1 = 6; // SCK pin of MAX6675
int CS2 = 8;
int SO2 = 9;
int sCK2 = 10;
int units = 1; // Units to readout temp (0 = raw, 1 = ˚C, 2 = ˚F)
float motor_temperature = 0.0; // Temperature output variable
float controller_temperature = 0.0;
const byte CLK1 = 2; // define CLK pin (any digital pin)
const byte DIO1 = 3; // define DIO pin (any digital pin)
const byte CLK2 = 11; // define CLK pin (any digital pin)
const byte DIO2 = 12; // define DIO pin (any digital pin)
const uint8_t SEG_DONE[] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, // O
SEG_C | SEG_E | SEG_G, // n
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G // E
};
const uint8_t SEG_ERR[] = {
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_E | SEG_G, // R
SEG_E | SEG_G, // R
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F // O
};
TM1637Display display1(CLK1, DIO1);// define dispaly 1 object
TM1637Display display2(CLK2, DIO2);// define dispaly 1 object #
uint8_t data[] = { 0x0, 0x0, 0x0, 0x0 }; // all segments clear
// Initialize the MAX6675 Library for our chip
MAX6675 temp1(CS1,SO1,sCK1,units);
MAX6675 temp2(CS2,SO2,sCK2,units);
// MAX6675 Library already sets pin modes for MAX6675 chip!
void setup() {
display1.setBrightness(0x0f);// set brightness of dispaly 1
display2.setBrightness(0x0f);// set brightness of dispaly 2
Serial.begin(9600);
Serial.println("Init");
display1.setSegments(SEG_DONE);
display2.setSegments(SEG_DONE);
delay(1000);
}
void loop() {
// Read the temp from the MAX6675
motor_temperature = temp1.read_temp();
int temperature_16_motor = motor_temperature;
controller_temperature = temp2.read_temp();
int temperature_16_controller = controller_temperature;
if(motor_temperature < 0 || controller_temperature < 0) {
// If there is an error with the TC, temperature will be < 0
Serial.print("Temperature Error on CS");
Serial.println( motor_temperature );
Serial.print("Controller Temperature Error");
Serial.println( controller_temperature);
display1.setSegments(SEG_ERR);
display2.setSegments(SEG_ERR);
delay(1000);
} else if (motor_temperature < 0)
{
Serial.print("Motor Current Temperature ERR");
Serial.println( motor_temperature );
Serial.print("Controller Current Temperature : ");
Serial.println( controller_temperature);
display1.setSegments(SEG_ERR);
display2.showNumberDec(temperature_16_controller,true,4,0);
}
else if (controller_temperature < 0)
{
Serial.print("Motor Current Temperature :");
Serial.println( motor_temperature );
Serial.print("Controller Current Temperature ERR ");
Serial.println( controller_temperature);
display1.showNumberDec(temperature_16_motor,true,4,0);
display2.setSegments(SEG_ERR);
}
else
{
Serial.print("Motor Current Temperature :");
Serial.println( motor_temperature );
Serial.print("Controller Current Temperature : ");
Serial.println( controller_temperature);
display1.showNumberDec(temperature_16_motor,true,4,0);
display2.showNumberDec(temperature_16_controller,true,4,0);
}
}
어때요 참 쉽죠? 오늘은 여기까지입니다. 추가 질문이 있으시다면 문의주세요.
다음은 미뤄두었던 인공지능 혹은 전공과목 공부를 포스팅하겠습니다.
'Embedded > Arduino' 카테고리의 다른 글
Low Pass Filter을 적용한 서미스터(Thermistor) 아두이노 블루투스 온도계 (0) | 2020.09.04 |
---|