2024.6.25 수업날
오늘은 어제 배웠던 HC-SR04(Ultrasonic) 초음파 센서를 가지고 INT, ICP 형식으로 코드를 작성하고
EZ moter r300으로 선풍기를 만드는 프로젝트를 진행하였다.
< Ultrasonic_int >
어제 배웠던 Ultrasonic 초음파 센서를 INT 형식으로 소스코드를 작성한다.
결과는 똑같지만, 소스코드의 내용에는 차이가 있다.
/*
* def.h
*
* Created: 2024-06-25 오전 9:20:11
* Author: USER
*/
#ifndef DEF_H_
#define DEF_H_
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#endif /* DEF_H_ */
먼저, def.h라는 헤더파일이 추가되었다.
이는 #define, #include와 같이 모든 파일의 서두에 공통적으로 들어가는 부분을 def.h 헤더파일에 하나로 묶어 정리한 것이다.
때문에 이 아래로의 헤더파일에는 def.h 헤더파일을 불러오기 위해 #include "def.h" 라고 추가로 적어야한다.
/*
* uart0.c
*
* Created: 2024-06-11 오후 2:11:35
* Author: USER
*/
#define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
void UART0_Init()
{
UBRR0H = 0x00; // 9~11 bit
UBRR0L = 207; // 9600bps 설정
UCSR0A = (1<<U2X0); // 2배속 설정
// 비동기 모드, 8비트, 패리티비트 없음, 스톱비트 1개
// UCSR0C = 0x06; // 초기값으로 대체 0000 0110
UCSR0B |= (1<<RXEN0); // 수신가능
UCSR0B |= (1<<TXEN0); // 송신가능
UCSR0B |= (1<<RXCIE0); // 수신 인터럽트 인에이블
}
void UART0_Transmit(char data)
{
while(!(UCSR0A & (1<<UDRE0))); // 송신 가능 하냐?(대기중), UDR이 비어 있는지? //비슷한 구문이 ctc쯤에 있을것이다
UDR0 = data;
}
unsigned UART0_Recevie()
{
while(!(UCSR0A & (1<<RXC0))); // 수신 대기중
return UDR0;
}
/*
* uart0.h
*
* Created: 2024-06-11 오후 2:11:59
* Author: USER
*/
#ifndef UART0_H_
#define UART0_H_
#include "def.h"
void UART0_Init();
void UART0_Transmit(char data);
unsigned UART0_Recevie();
#endif /* UART0_H_ */
/*
* ultrasonic.c
*
* Created: 2024-06-25 오전 9:17:45
* Author: USER
*/
#include "ultrasonic.h"
// 전역변수 선언
volatile uint16_t startCount;
volatile uint16_t endCount;
volatile uint16_t US_TCNT;
void ultraInit()
{
TRIGGER_DDR |= (1<<TRIGGER_PIN); // 트리거핀 출력 설정
ECHO_DDR &= ~(1<<ECHO_PIN); // 에코핀 입력 설정
EICRA |= (1<<ISC31) | (1<<ISC30); // Rising Edge 인터럽트
EIMSK |= (1<<INT3); // INT3 인터럽트 활성화
TCCR1B |= (1<<CS11) | (1<<CS10); // Timer1 의 64분주
//TCCR1B |= (1<<CS21) | (1<<CS10); // Timer1 의 1024분주
}
void ultraTrigger()
{
TCNT1 = 0;
TRIGGER_PORT &= ~(1<<TRIGGER_PIN);
_delay_us(1);
TRIGGER_PORT |= (1<<TRIGGER_PIN);
_delay_us(10);
TRIGGER_PORT &= ~(1<<TRIGGER_PIN);
}
ISR(INT3_vect) //이거는 헤더파일에 복붙하지 않아도 됨, 내장되어있는거임, 인터럽트 서비스 루틴
{
if(ECHO_PORT & (1<<ECHO_PIN)) // echo핀이 Rising 이라면~
{
startCount = TCNT1; // 현재 카운트값을 startCount에 대입
EICRA &= ~(1<<ISC30);
EICRA |= (1<<ISC31); // falling edge
//printf("startCount : %d\n", startCount);
}
else
{
endCount = TCNT1; //falling edge 에서의 count
if(endCount >= startCount)
{
US_TCNT = endCount - startCount;
}
if(endCount < startCount)
{
US_TCNT = (0xffff - startCount) + endCount;
}
US_TCNT = endCount - startCount;
EICRA |= (1<<ISC31) | (1<<ISC30); // Rising Edge 인터럽트
//printf("endCount : %d\n", endCount);
}
}
uint16_t ultraDistance()
{
// 64분주로 했을 때
uint16_t distance = (uint16_t)(US_TCNT * 0.000004 * 34000)/2; // 4us(0.000004), 340m-->34000cm
// 1024분주로 했을 때
//uint16_t distance = (uint16_t)(US_TCNT * 0.000064 * 34000)/2; // 340m-->34000cm
return distance;
}
Ultrasonic_Int를 실행하기 위해서는 ultrasonic.c 파일이 필요하다.
Int는 ISR 함수를 사용한다. ISR는 인터럽트 서비스 루틴의 약자이다.
또한 ultraDostace에 64분주로 설정했을 때의 계산식도 추가로 작성한다.
/*
* ultrasonic.h
*
* Created: 2024-06-25 오전 9:17:57
* Author: USER
*/
#ifndef ULTRASONIC_H_
#define ULTRASONIC_H_
#include "def.h"
#define TRIGGER_DDR DDRD
#define ECHO_DDR DDRD
#define TRIGGER_PORT PORTD // 출력
#define ECHO_PORT PIND //입력
#define TRIGGER_PIN 2
#define ECHO_PIN 3
void ultraInit(); //초기화
void ultraTrigger(); // 트리거 올려줌
uint16_t ultraDistance(); // 16진수로 거리 보내줌
#endif /* ULTRASONIC_H_ */
/*
* I2C.c
*
* Created: 2024-06-24 오전 9:39:19
* Author: USER
*/
#include "I2C.h"
void I2C_Init()
{
I2C_DDR |= (1<<I2C_SCL) | (1<<I2C_SDA); // 출력 설정
TWBR = 72; // 100KHz
// TWBR = 32; // 200KHz
// TWBR = 12; // 400KHz
}
void I2C_Start()
{
TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN);
while(!(TWCR & (1<<TWINT)));
}
void I2C_Stop()
{
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}
void I2C_TxData(uint8_t data)
{
TWDR = data; //데이터를 받으면 8비트 레지스터에 집어넣음
TWCR = (1<<TWINT) | (1<<TWEN);
while(!(TWCR & (1<<TWINT))); // 전송 완료 대기
}
void I2C_TxByte(uint8_t devAddrRW, uint8_t data)
{
I2C_Start();
I2C_TxData(devAddrRW);
I2C_TxData(data);
I2C_Stop();
}
/*
* I2C.h
*
* Created: 2024-06-24 오전 9:39:30
* Author: USER
*/
#ifndef I2C_H_
#define I2C_H_
#include "def.h"
// 데이터 시트 보고 정해진 포트 위치를 지정해준것임
#define I2C_DDR DDRD
#define I2C_SCL PORTD0
#define I2C_SDA PORTD1
void I2C_Init();
void I2C_Start();
void I2C_Stop();
void I2C_TxData(uint8_t data);
void I2C_TxByte(uint8_t devAddrRW, uint8_t data);
#endif /* I2C_H_ */
/*
* I2C_LCD.c
*
* Created: 2024-06-24 오전 9:40:07
* Author: USER
*/
#include "I2C_LCD.h"
uint8_t I2C_LCD_Data;
void LCD_Data4Bit(uint8_t data) // 4bit
{
I2C_LCD_Data = (I2C_LCD_Data & 0x0f) | (data & 0xf0); // 상위4비트
LCD_EnablePin();
I2C_LCD_Data = (I2C_LCD_Data & 0x0f) | ((data & 0x0f) << 4); //하위4비트
LCD_EnablePin();
}
void LCD_EnablePin()
{
I2C_LCD_Data &= ~(1<<LCD_E); // E Low 설정
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
I2C_LCD_Data |= (1<<LCD_E); // E High 설정
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
I2C_LCD_Data &= ~(1<<LCD_E); // E Low 설정
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
_delay_us(1800);
}
void LCD_WriteCommand(uint8_t commandData)
{
I2C_LCD_Data &= ~(1<<LCD_RS);
I2C_LCD_Data &= ~(1<<LCD_RW);
LCD_Data4Bit(commandData);
}
void LCD_WriteData(uint8_t charData)
{
I2C_LCD_Data |= (1<<LCD_RS);
I2C_LCD_Data &= ~(1<<LCD_RW);
LCD_Data4Bit(charData);
}
void LCD_BackLightOn()
{
I2C_LCD_Data |= (1<<LCD_BACKLIGHT);
I2C_TxByte(LCD_DEV_ADDR, I2C_LCD_Data);
}
void LCD_GotoXY(uint8_t row, uint8_t col)
{
col %= 16;
row %= 2;
uint8_t address = (0x40 * row) + col;
uint8_t command = 0x80 + address;
LCD_WriteCommand(command);
}
void LCD_WriteString(char *string)
{
for (uint8_t i = 0; string[i]; i++)
{
LCD_WriteData(string[i]);
}
}
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string)
{
LCD_GotoXY(row, col);
LCD_WriteString(string);
}
void LCD_Init()
{
I2C_Init();
_delay_ms(20);
LCD_WriteCommand(0x03);
_delay_ms(10);
LCD_WriteCommand(0x03);
_delay_ms(1);
LCD_WriteCommand(0x03);
LCD_WriteCommand(0x02);
LCD_WriteCommand(COMMAND_4BIT_MODE);
LCD_WriteCommand(COMMAND_DISPLAY_OFF);
LCD_WriteCommand(COMMAND_DISPLAY_CLEAR);
LCD_WriteCommand(COMMAND_ENTRY_MODE);
LCD_WriteCommand(COMMAND_DISPLAY_ON);
LCD_BackLightOn();
}
/*
* I2C_LCD.h
*
* Created: 2024-06-24 오전 9:40:21
* Author: USER
*/
#ifndef I2C_LCD_H_
#define I2C_LCD_H_
#include "def.h"
#include "I2C.h"
#define LCD_RS 0
#define LCD_RW 1
#define LCD_E 2
#define LCD_BACKLIGHT 3
#define LCD_DEV_ADDR (0x27<<1) // 주소는 0x27, <<은 W를 유지하기 위해
// lcd4bit.h에서 복사해온 코드
#define COMMAND_DISPLAY_CLEAR 0x01 // Clear all display
#define COMMAND_DISPLAY_ON 0x0C // 화면 ON, 커서 OFF, 커서 점멸 OFF
#define COMMAND_DISPLAY_OFF 0x08 // 화면 OFF, 커서 OFF, 커서 점멸 OFF
#define COMMAND_ENTRY_MODE 0x06
#define COMMAND_4BIT_MODE 0x28 // 4비트, 화면 2행, 5X8 Font-->8비트
void LCD_Data4Bit(uint8_t data); // 4bit
void LCD_EnablePin();
void LCD_WriteCommand(uint8_t commandData);
void LCD_WriteData(uint8_t charData);
void LCD_BackLightOn(); //이거는 추가한거임
void LCD_GotoXY(uint8_t row, uint8_t col);
void LCD_WriteString(char *string);
void LCD_WriteStringXY(uint8_t row, uint8_t col, char *string);
void LCD_Init();
#endif /* I2C_LCD_H_ */
/*
* Ultrasonic_INT.c
*
* Created: 2024-06-25 오전 9:10:07
* Author : USER
*/
#include "def.h" // 총집편 설정 파일
#include "I2C_LCD.h"
#include "uart0.h"
#include "ultrasonic.h"
FILE OUTPUT = FDEV_SETUP_STREAM(UART0_Transmit, NULL, _FDEV_SETUP_WRITE);
int main(void)
{
uint16_t distance;
UART0_Init();
ultraInit();
stdout = &OUTPUT;
sei();
while (1)
{
ultraTrigger();
_delay_ms(50); // 인터럽트 시간 확보
distance = ultraDistance();
printf("Distance : %d cm\r\n", distance);
_delay_ms(1000);
}
}
위의 소스코드를 실행하고 comportmaster를 실행하면 아래와 같이 나타난다.
마찬가지로 152~156cm는 초음파 센서가 꽂혀있는 브레드보드를 천장과 수평으로 세웠을 때,
초음파센서와 강의실 천장까지의 거리를 나타낸다.
< Ultrasonic_INT7 >
이번에는 초음파 센서의 echo 핀 위치를 바꾼 후 소스코드를 작성해본다.
아래는 ATmega128a의 데이터 시트인데, INT7이 위치하는 PE7번을 사용할 것이다.
이번에는 Ultrasonic_INT의 소스코드 중에서
def.h, uart0.c, uart.h, I2C.c, I2C.h, I2C_LCD.h, I2C_LCD.c, main.c 파일을 복사+붙여넣기 한 후
ultrasonic.c, ultrasonic.h의 파일을 수정하여 작성한다.
Ultrasonic.c, Ultrasonic.h 소스코드
/*
* ultrasonic.c
*
* Created: 2024-06-25 오전 9:17:45
* Author: USER
*/
#include "ultrasonic.h"
// 전역변수 선언
volatile uint16_t startCount;
volatile uint16_t endCount;
volatile uint16_t US_TCNT;
volatile uint8_t risingEdge = 1;
void ultraInit()
{
TRIGGER_DDR |= (1<<TRIGGER_PIN); // 트리거핀 출력 설정
ECHO_DDR &= ~(1<<ECHO_PIN); // 에코핀 입력 설정
EICRB |= (1<<ISC70);
// EICRA |= (1<<ISC31) | (1<<ISC30); // Rising Edge 인터럽트
EIMSK |= (1<<INT7); // INT7 인터럽트 활성화
TCCR1B |= (1<<CS11) | (1<<CS10); // Timer1 의 64분주
//TCCR1B |= (1<<CS21) | (1<<CS10); // Timer1 의 1024분주
}
void ultraTrigger()
{
TCNT1 = 0;
TRIGGER_PORT &= ~(1<<TRIGGER_PIN);
_delay_us(1);
TRIGGER_PORT |= (1<<TRIGGER_PIN);
_delay_us(10);
TRIGGER_PORT &= ~(1<<TRIGGER_PIN);
}
// 7번이 인터럽트 걸렸을 때
ISR(INT7_vect) //이거는 헤더파일에 복붙하지 않아도 됨, 내장되어있는거임, 인터럽트 서비스 루틴
{
if(risingEdge)
{
startCount = TCNT1;
risingEdge = 0;
}
else
{
endCount = TCNT1;
risingEdge = 1;
}
}
uint16_t ultraDistance()
{
uint16_t pulseWidth = endCount - startCount;
uint32_t timeUs = pulseWidth * 4;
uint16_t distance = (timeUs * 34)/2000;
return distance;
//US_TCNT = endCount - startCount;
// 64분주로 했을 때
//uint16_t distance = (uint16_t)(US_TCNT * 0.000004 * 34000)/2; // 4us(0.000004), 340m-->34000cm
//return distance;
// 1024분주로 했을 때
//uint16_t distance = (uint16_t)(US_TCNT * 0.000064 * 34000)/2; // 340m-->34000cm
이번에는 INT7에서의 결과를 살펴보는 것이기 때문에 ISR(INT7_vect) 로 수정하고 그 아래의 내용도 위의 소스코드처럼 변경해야 한다.
또한, Ultrasonic.c.의 UltraDistance에서
아래의 사진과 같이 윗 부분의 주석을 풀어 실행시켜보고, 아래 부분의 주석을 풀어 실행시킨 다음
ComportMaster의 결과가 같은지 확인해야한다.
/*
* ultrasonic.h
*
* Created: 2024-06-25 오전 9:17:57
* Author: USER
*/
#ifndef ULTRASONIC_H_
#define ULTRASONIC_H_
#include "def.h"
#define TRIGGER_DDR DDRD
#define ECHO_DDR DDRE
#define TRIGGER_PORT PORTD // 출력
#define ECHO_PORT PINE //입력
#define TRIGGER_PIN 2
#define ECHO_PIN 7
void ultraInit(); //초기화
void ultraTrigger(); // 트리거 올려줌
uint16_t ultraDistance(); // 16진수로 거리 보내줌
#endif /* ULTRASONIC_H_ */
ATmega 128a 데이터 시트에서 본 것처럼
INT7은 PE7번 이기 때문에 ECHO_DDR를 DDRE로, Echo 핀을 7번으로 수정하였다.
아래는 Ultrasonic_INT7의 ComportMaster의 결과이다.
< Ultrasonic_ICP >
ICP란 Input Capture 라는 의미로,
상승 에지(rising edge) 또는 하강 에지(falling edge)가 발견되면 이 때의 TCNT 값이 ICR 레지스터에 기록된다.
즉, TCNT 값이 capture 되어 ICR에 기록되는 것이다.
edge 발견 시점에 인터럽트를 발생시킬 수 있어서 입력 신호의 시간, duty_cycle, 주파수 측정 등에 사용할 수 있다.
이번에도 Ultrasonic_ICP 소스코드를 작성할 때 Ultrasonic_INT7 소스코드에서
ultrasonic.h, def.h, uart0.c, uart.h, I2C.c, I2C.h, I2C_LCD.h, I2C_LCD.c, main.c 파일을 복사+붙여넣기 한 후
ultrasonic.c 파일을 수정하여 작성한다.
ultrasonic.h의 파일을 수정하지 않는 이유는
아래의 ATmega 128a 데이터시트에서 ICP3이 PE7번으로 동일하기 때문이다.
Ultrasonic.c 소스코드 수정
/*
* ultrasonic.c
*
* Created: 2024-06-25 오전 9:17:45
* Author: USER
*/
#include "ultrasonic.h"
// 전역변수 선언
volatile uint16_t startCount;
volatile uint16_t endCount;
//volatile uint16_t US_TCNT;
volatile uint8_t risingEdge = 1;
void ultraInit()
{
TRIGGER_DDR |= (1<<TRIGGER_PIN); // 트리거핀 출력 설정
ECHO_DDR &= ~(1<<ECHO_PIN); // 에코핀 입력 설정
// Timer Input Capture, 64분주 , 추가한 부분
TCCR3B |= (1<<ICES3) | (1<<CS31) | (1<<CS30);
ETIMSK |= (1<<TICIE3); //Input Catpure Enable
}
void ultraTrigger()
{
TCNT1 = 0;
TRIGGER_PORT &= ~(1<<TRIGGER_PIN);
_delay_us(1);
TRIGGER_PORT |= (1<<TRIGGER_PIN);
_delay_us(10);
TRIGGER_PORT &= ~(1<<TRIGGER_PIN);
}
// 7번이 인터럽트 걸렸을 때
ISR(TIMER3_CAPT_vect) //이거는 헤더파일에 복붙하지 않아도 됨, 내장되어있는거임, 인터럽트 서비스 루틴
{
// 추가한 부분
if(risingEdge)
{
startCount = ICR3; // 요게 ICR3L, ICR3H 2개인데..
TCCR3B &= ~(1<<ICES3); // 하강엣지로 변경
risingEdge = 0;
}
else
{
endCount = ICR3;
TCCR3B |= (1<<ICES3); // 상승엣지
risingEdge = 1;
}
}
uint16_t ultraDistance()
{
uint16_t pulseWidth = endCount - startCount;
uint32_t timeUs = pulseWidth * 4;
uint16_t distance = (timeUs * 34)/2000;
return distance;
//US_TCNT = endCount - startCount;
// 64분주로 했을 때
//uint16_t distance = (uint16_t)(US_TCNT * 0.000004 * 34000)/2; // 4us(0.000004), 340m-->34000cm
//return distance;
// 1024분주로 했을 때
//uint16_t distance = (uint16_t)(US_TCNT * 0.000064 * 34000)/2; // 340m-->34000cm
}
ICP를 사용하기 때문에 ultraInit 에서 데이터시트를 보고 관련된 레지스터로 수정하였고,
ISR(TIMER3_CAPT_vect)에서 상승 에지(rising edge) 또는 하강 에지(falling edge)가 나타나도록 수정하였다.
< EZ MOTOR R300 >
이번에는 EZ MOTOR R300을 사용하여 Uart, FASTPWM의 소스코드 내용을 가지고
ComportMaster에서 출력된 숫자나 문자에 따라 50% 출력, 75% 출력, 100% 출력, 0% 출력이 나타나는 프로젝트를 만들어본다.
Fan_making 소스코드(다른분의 코드를 기반으로 수정한 코드입니다. 감사합니다)
/*
* FAN_making.c
*
* Created: 2024-06-25 오후 2:07:35
* Author : USER
*/
#define F_CPU 16000000UL // CPU 클럭 주파수를 16MHz로 설정
#include <avr/io.h> // AVR 매크로 및 레지스터 정의
#include <util/delay.h> // _delay_ms() 함수를 사용하기 위한 헤더 파일
void UART0_Init() // UART 통신 초기화 함수
{
// 비동기, 8비트, 패리티 비트 없음, 스톱 비트 1개 설정
UBRR0H = 0x00; // 송수신 속도 설정 레지스터 High byte 초기화 (9-11 bit)
UBRR0L = 207; // 송수신 속도 설정 레지스터 Low byte 설정 (9600bps)
UCSR0A = (1<<U2X0); // 2배속 모드 설정 (속도 향상)
UCSR0B |= (1<<RXEN0); // 수신 가능 설정
UCSR0B |= (1<<TXEN0); // 송신 가능 설정
}
void UART0_Transmit(char data) // UART로 문자 전송 함수
{
while(!(UCSR0A & (1<<UDRE0))); // 데이터 레지스터가 비어있는지 확인하여 대기
UDR0 = data; // 데이터 레지스터에 데이터 쓰기
}
unsigned UART0_Receive() // UART로부터 문자 수신 함수
{
while(!(UCSR0A & (1<<RXC0))); // 데이터 수신 대기
return UDR0; // 수신된 데이터 반환
}
void fan_Init() // 선풍기 제어 핀 초기화 함수
{
DDRB |= (1 << DDB5); // PB5 핀을 출력으로 설정 (OC1A 핀)
}
void set_PWM_duty_cycle(uint16_t duty_cycle) // PWM 듀티 사이클 설정 함수
{
OCR1A = duty_cycle; // PWM의 듀티 사이클 설정
}
void PWM_Init() // PWM 초기화 함수
{
// 빠른 PWM 모드, 비반전 모드 설정
TCCR1A = (1 << COM1A1) | (1 << WGM11);
// 분주비 64 설정
TCCR1B = (1 << WGM13) | (1 << WGM12) | (1 << CS11) | (1 << CS10);
// TOP 값 설정 (ICR1 = 2499)
ICR1 = 2499;
}
int main(void)
{
UART0_Init(); // UART 초기화
fan_Init(); // 선풍기 제어 핀 초기화
PWM_Init(); // PWM 초기화
while (1) // 무한 루프
{
char command = UART0_Receive(); // UART로부터 명령 문자 수신
// 수신된 명령에 따라 선풍기 제어
switch (command)
{
case '0': // 0: 선풍기 끄기
set_PWM_duty_cycle(0); // 듀티 사이클 0 설정
UART0_Transmit('0');
break;
case '1': // 1: 선풍기 LOW 속도
set_PWM_duty_cycle(625); // 듀티 사이클 25% 설정
UART0_Transmit('1');
break;
case '2': // 2: 선풍기 MEDIUM 속도
set_PWM_duty_cycle(1250); // 듀티 사이클 50% 설정
UART0_Transmit('2');
break;
case '3': // 3: 선풍기 HIGH 속도
set_PWM_duty_cycle(1875); // 듀티 사이클 75% 설정
UART0_Transmit('3');
break;
case '4': // 4: 선풍기 최대 속도
set_PWM_duty_cycle(2498); // 듀티 사이클 100% 설정
UART0_Transmit('4');
break;
default:
break; // 잘못된 명령인 경우 아무 작업도 하지 않음
}
}
}
위의 소스코드에서 EZ MOTOR R300을 ATmega 128a와 연결할 때
PB5번을 출력으로 설정하여 EZ MOTOR R300과 같이 동봉된 한 케이블에는 PB5번에, 다른 케이블에는 gnd에 연결해야한다.
EZ MOTOR R300과 같이 동봉된 케이블의 극성은 없지만, 실리콘 팬이 돌아가는 방향이 반대가 된다.
Fan_Init, PWM_Init을 FastPWM의 소스코드를 기반으로 추가작성하였다.
또한, Fan_making 소스코드에 ComportMaster의 Recv 부분에 숫자로 표시되도록 소스코드를 작성하였다.
아래는 Fan_making 소스코드의 ComportMaster 결과이다.
Ultrasonic(int, ICP), EZ motor R300 끝!
'Harman 세미콘 아카데미 > Atmega128a' 카테고리의 다른 글
2024.7.16 [ATmega128a]10 - 다기능 선풍기 만들기 팀프로젝트 (0) | 2024.07.16 |
---|---|
2024.6.24 [ATmega128a]⑧ - I2C 통신, ULTRASONIC(HC-SR04) (0) | 2024.06.24 |
[ATmega 128a]⑦ - UART 통신 (0) | 2024.06.18 |
[ATmega 128a]⑥ - LCD 8bit, LCD 8bit counter, LCD 4bit (0) | 2024.06.18 |
[ATmega 128a]⑤ - CTC, NOMAL, FastPWM, PWM16BIT, dalay 함수 (0) | 2024.06.18 |