Skip to content
TUWLAB.com
모든 게시물에 대하여 '링크'
방식의 퍼가기만 허용합니다.
한양대학교 전자통신컴퓨터공학부
바라미
  • 87
  • 2573459
DNS Powered by DNSEver.com
AVR

[온도조절 인두기] 5. 소프트웨어 제작

Posted 2014. 01. 21 Updated 2017. 06. 02 Views 13015 Replies 0
Atachment
첨부

오랜 시간 중단되었던 온도조절 인두기 프로젝트를 다시 꺼낸건 3학년 2학기가 끝나고 겨울방학이 시작한 12월 말이었습니다.

다시 시작할때는 이제 코딩만 하면 된다는 생각에 큰 부담은 없었습니다.
- 단지, 방학이 시작함과 동시에 몰아닥친 귀차니즘이 가장 큰 적이 되었죠..


하드웨어를 제어하는 펌웨어를 만들 때는, 주변 장치를 제어하는 드라이버 역할을 하는 장치 제어 모듈들을 따로 만들어서 검증한 다음, main에서 이들을 통합하는 순서로 진행하면 디버깅 없이 깔끔하게 작성할 수 있습니다.

소프트웨어 제작과정에서 예상대로 딱히 큰 어려움은 없었습니다..
- 귀차니즘때문에 하루면 코딩할거 며칠씩 붙잡고 있었던 현상만 제외하면 말이죠.


AVR에 C++ 객체지향 프로그래밍을 적용한 첫 프로젝트였던 만큼, 모듈화와 재사용성을 고려하여 프로그램을 작성하였습니다. 각 모듈별로 추후 다방면으로 응용이 가능한 요소들을 추가하기도 했습니다.



▲ 제어 소프트웨어 구조


- Button : 온도조절 버튼 2개를 제어하는 모듈. 단순 클릭만 감지하는 것이 아니라, 계속 누르고 있을 경우 지속적으로 이벤트를 발생시키는 Key Repeat 감지 기능도 지원합니다.

- Buzzer : 부저를 켜고 끄는 모듈. 뒤에서 설명할 Note Player에서 내부적으로 이 모듈을 활용합니다.

- Config : EEPROM을 제어하여 환경설정을 저장하거나 읽어오는 모듈. 마지막 설정 온도를 기억하고, 부저로부터 발생하는 소리를 켜고 끄는 기능을 지원합니다.

- Display : 4자리 숫자판(FND)을 제어하는 모듈. C언어의 printf와 같은 인터페이스를 제공하고, 숫자 뿐만 아니라 알파벳의 일부와 특수문자도 표시할 수 있습니다.

- Heater : 히터에 공급되는 24V를 외부 제어로 단속하고, 히터의 현재 온도를 지속적으로 계산하여 지정된 Event Listener로 반환합니다.

- Light : 기판 하단에 부착된 두 개의 상태표시등(청, 적)을 제어합니다.

- NotePlayer : 악보를 입력받아서 Buzzer 모듈을 통해 재생하는 모듈. 지금 생각해도 사실 이 모듈이 구지 온도조절 인두기에 구현될 필요는 없습니다. 단지 재미와 추후 재사용성을 위해 구현해 보았습니다. Timer를 활용여 구현하였기 때문에 Main routine을 Blocking하지 않고 마치 음악 재생 쓰레드가 새로 생성된 것과 유사하게 동작합니다.


다음은 모든 모듈들을 통합하여 인두기를 구동하는 Main Routine의 원본 소스코드입니다.

#define F_CPU 8000000UL
#define __DELAY_BACKWARD_COMPATIBLE__

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <util/delay.h>

#include "include/Display.cpp"
#include "include/Light.cpp"
#include "include/Buzzer.cpp"
#include "include/NotePlayer.cpp"
#include "include/Button.cpp"
#include "include/Config.cpp"
#include "include/Heater.cpp"

#define TEMPERATURE_IDLE 455

static unsigned char melodyTemperatureIncrease[][3] = 
{
	{4, NP_SYB_C, NP_DUR_32},
	{4, NP_SYB_E, NP_DUR_32}
};

static unsigned char melodyTemperatureDecrease[][3] =
{
	{4, NP_SYB_E, NP_DUR_32},
	{4, NP_SYB_C, NP_DUR_32}
};

static unsigned char melodyHeaterOff[][3] =
{
	{5, NP_SYB_C, NP_DUR_32},
	{4, NP_SYB_G, NP_DUR_32},
	{4, NP_SYB_E, NP_DUR_32},
	{4, NP_SYB_C, NP_DUR_32}
};

static unsigned char melodyBoot[][3] = 
{
	{4, NP_SYB_E, NP_DUR_16},
	{4, NP_SYB_Eb, NP_DUR_16},
	{4, NP_SYB_E, NP_DUR_16},
	{4, NP_SYB_Eb, NP_DUR_16},
	{4, NP_SYB_E, NP_DUR_16},
	{4, NP_SYB_B, NP_DUR_16},
	{4, NP_SYB_D, NP_DUR_16},
	{4, NP_SYB_C, NP_DUR_16},
	{4, NP_SYB_A, NP_DUR_8}
};

bool gFlagSoundEnable;
unsigned int gTemperature;

void * operator new(size_t size)	{ return malloc(size); }
void * operator new[](size_t size)	{ return malloc(size); }
void operator delete(void * ptr)	{ free(ptr); }
void operator delete[](void * ptr)	{ free(ptr); }
	
void ControlHeater();
void DisplayTemperature();
void StartIncreaseTemperature();
void IncreaseTemperature();
void StartDecreaseTemperature();
void DecreaseTemperature();
void SaveTemperature();
/************************** Caution ************************
Set compiler optimization option to 'Optimize Most(-O3)'.
Otherwise, EEPROM write procedure will not operate properly.
************************************************************/

#include "AdjustableSolderingIron.hpp"

void ControlHeater()
{
	unsigned int currentTemperature = hHeater->GetTemperature();

	if (gTemperature == TEMPERATURE_IDLE)
	{
		hHeater->Off();
		
		hLight->Off(LIGHT_RED);
		
		if (currentTemperature > 64)
			hLight->On(LIGHT_BLUE);
		else
			hLight->Off(LIGHT_BLUE);
	}
	else
	{
		hLight->Off(LIGHT_BLUE);
		
		if (currentTemperature <= gTemperature - 5)
		{
			hHeater->On();
			hLight->On(LIGHT_RED);
		}
		else if (currentTemperature >= gTemperature + 10)
		{
			hHeater->Off();
			hLight->Off(LIGHT_RED);
		}
	}
}

void DisplayTemperature()
{
	if (gTemperature == TEMPERATURE_IDLE)
		hDisplay->Printf(" 0FF");
	else
		hDisplay->Printf("%3u.c", gTemperature);
}

void StartIncreaseTemperature()
{
	IncreaseTemperature();

	if (gFlagSoundEnable)
	{
		if (gTemperature != TEMPERATURE_IDLE)
			hNotePlayer->SetNote(melodyTemperatureIncrease, 2, 0.5);
		else
			hNotePlayer->SetNote(melodyHeaterOff, 4, 0.5);
		
		hNotePlayer->Play();
	}
}

void IncreaseTemperature()
{
	if (gTemperature == TEMPERATURE_IDLE)
		gTemperature = 200;
	else if (gTemperature + 25 <= 450)
		gTemperature += 25;
	else
		gTemperature = TEMPERATURE_IDLE;

	DisplayTemperature();
}

void StartDecreaseTemperature()
{
	DecreaseTemperature();

	if (gFlagSoundEnable)
	{
		if (gTemperature != TEMPERATURE_IDLE)
			hNotePlayer->SetNote(melodyTemperatureDecrease, 2, 0.5);
		else
			hNotePlayer->SetNote(melodyHeaterOff, 4, 0.5);
		
		hNotePlayer->Play();
	}
}

void DecreaseTemperature()
{
	if (gTemperature == TEMPERATURE_IDLE)
		gTemperature = 450;
	else if (gTemperature - 25 >= 200)
		gTemperature -= 25;
	else
		gTemperature = TEMPERATURE_IDLE;

	DisplayTemperature();
}

void SaveTemperature()
{
	hConfig->SetLastTemperature(gTemperature);
}

int main(void)
{
	// Wait for power to be stable
	_delay_ms(10);
	
	// Change sound flag if button is pushed when booting
	if (hButton->GetButtonState(BUTTON_0) == BUTTON_STATE_DOWN)
	{
		gFlagSoundEnable = true;
		hConfig->SetSoundFlag(true);
	}
	else if (hButton->GetButtonState(BUTTON_1) == BUTTON_STATE_DOWN)
	{
		gFlagSoundEnable = false;
		hConfig->SetSoundFlag(false);
	}
	else
	{
		gFlagSoundEnable = hConfig->GetSoundFlag();
	}
	
	// Load last temperature
	gTemperature = hConfig->GetLastTemperature();
	
	// Validate temperature correctness (200 ~ 450 Celsius, Step = 25, 455 = IDLE)
	if (gTemperature != TEMPERATURE_IDLE && (gTemperature < 200 || gTemperature > 450 || (gTemperature % 25 != 0)))
	{
		gTemperature = 350;
		hConfig->SetLastTemperature(gTemperature);
	}
	
	// Booting Completed
	sei();

	if (gFlagSoundEnable)
	{
		hNotePlayer->SetNote(melodyBoot, 9, 0.3);
		hNotePlayer->Play();
	}

	DisplayTemperature();
	
	hHeater->SetEventListener(HEATER_EVENT_TEMPERATURE_CHANGED, ControlHeater);

	hButton->SetEventListener(BUTTON_0, BUTTON_EVENT_KEYDOWN, StartIncreaseTemperature);
	hButton->SetEventListener(BUTTON_0, BUTTON_EVENT_KEYPRESS, IncreaseTemperature);
	hButton->SetEventListener(BUTTON_0, BUTTON_EVENT_KEYUP, SaveTemperature);
	
	hButton->SetEventListener(BUTTON_1, BUTTON_EVENT_KEYDOWN, StartDecreaseTemperature);
	hButton->SetEventListener(BUTTON_1, BUTTON_EVENT_KEYPRESS, DecreaseTemperature);
	hButton->SetEventListener(BUTTON_1, BUTTON_EVENT_KEYUP, SaveTemperature);

	while (1);
}


프로젝트 설정에서 컴파일러 옵션 중 최적화(Optimization)를 -O3 로 설정해야 정상적으로 빌드됩니다. 최적화 하지 않으면 프로그램이 8KByte를  초과하고, 최적화 옵션을 낮게 설정하면 EEPROM Write가 정상적으로 이루어지지 않습니다.
(컴파일 옵션과 EEPROM Write의 연관성과 문제점은 추후 다른 포스트에서 다루도록 하겠습니다.)



▲ ADC Result - 히터 온도 변환 테이블 데이터 측정


사진을 보면 알 수 있지만, 작업하는 장소가 바뀐것을 알 수 있습니다. 그만큼 그 사이 엄청난 시간간극이... 이곳은 익산 제 방 테이블이 아닌 학교 기숙사입니다.


그렇게 소프트웨어 작성도 모두 끝나고, 칩에 굽는데도 성공했습니다. 그러나, 이것이 끝이 아니었습니다...
근본적인 문제가 해결되지 않은 하드웨어상의 문제점이 다시 고개를 든 것입니다... Hㅏ..


- 다음 글에 계속 -


서비스 선택
이용중인 SNS 버튼을 클릭하여 로그인 해주세요.
SNS 계정을 통해 로그인하면 회원가입 없이 댓글을 남길 수 있습니다.
댓글
?
Powered by SocialXE

List of Articles
번호 분류 제목 글쓴이 최근 수정일 조회 수
32 AVR [전자동 커튼] 최종 자료 정리 및 추후 개선사항 file TUW 2017.06.02 7669
31 AVR [전자동 커튼] 최종 설치 및 정비 과정 file TUW 2017.06.02 6631
30 AVR [전자동 커튼] 제어장치 회로도 및 부품 목록 file TUW 2017.06.02 7558
29 AVR [전자동 커튼] 제어보드 펌웨어 핵심구문 TUW 2014.04.20 6155
28 AVR [전자동 커튼] 제어보드 완성 사진 file TUW 2017.06.02 7150
27 AVR [전자동 커튼] 완성 & 동작 시연 동영상 9 file TUW 2017.06.02 8032
26 AVR [전자동 커튼] 기획서 TUW 2014.04.20 7682
25 AVR [전자동 커튼] 2차 설치, 또 다시 발견된 문제점 file TUW 2017.06.02 5897
24 AVR [전자동 커튼] 2차 설치 과정 file TUW 2017.06.02 6931
23 AVR [전자동 커튼] 1차 설치, 그 이후 문제점들과 내일 작업할 사항 TUW 2014.04.20 6237
22 AVR [전자동 커튼] 1차 설치 과정 file TUW 2017.06.02 6355
21 AVR [온도조절 인두기] 6. 마지막 디버깅 - LM2575 오버슈트(Overshoot) 현상 file TUW 2021.12.28 14795
» AVR [온도조절 인두기] 5. 소프트웨어 제작 file TUW 2017.06.02 13015
19 AVR [온도조절 인두기] 4. 문제점 발견 - ADC 입력에 저항분압 회로를 사용할 경우 문제점 file TUW 2017.06.02 15638
18 AVR [온도조절 인두기] 3. 하드웨어 디버깅 file TUW 2017.06.02 13596
17 AVR [온도조절 인두기] 2. 하드웨어 제작 file TUW 2017.06.02 12821
목록
Board Pagination Prev 1 2 Next
/ 2

Powered by Xpress Engine / Designed by Sketchbook

sketchbook5, 스케치북5

sketchbook5, 스케치북5