본문 바로가기

Lobo's study room/아두이노

아두이노 우노와 부저모듈, lcd, 초음파 센서 다루기.

#port

신호가 들고 나는 길목.

GPIO : 범용입출력신호. HIGH/ LOW 출력

AFIO : A(Alternated)/기본 기능 이외의 추가적 기능

시리얼통신 : 장치끼리 연결시 접핀을 통해 연결

금:전성이 가장 높다. 제일 가느다라면서 길게 늘릴수 있는 물질!

 

#IC칩 패키징

 

#아두이노 우노

출처 : scipia

 

Digital Write 가능한 핀 : 0~13, A0~A5

Analog Write 가능한 핀 : ~(틸더) 표시가 있는 곳 : ~3, ~5, ~6, ~9, ~10, ~11

Analog Read 가능한 핀 : A0~A5

헤더핀 : USB 연결을 시리얼로!

 

#아두이노 우노 회로도

schematics.pdf
0.07MB

M8TXD8-RXD0

ADC0~5->PCO0~5

SDA(4)~SCL(5)

메모리번지 주소.

SDI->RESET,SCK->13BUILT IN, MISO, MOSI

 

#우리가 생각하는 디지털 신호와 실제 디지털 신호

 

우리가 생각하는 디지털 신호/이미지 출처 : 임베디드 스토리
실제 데이터 신호에서는 Bounce가 일어난다!/이미지 출처 : 임베디드 스토리

#듀티비

HIGH가 출력되는 시간. POSITIVE

#port2servo

map함수 이용해서 posVal 구하기

map함수

fromLow, fromHigh -> toLow, toHigh

0~1023의 변화를 0~180도로 변화시키기

pot2 servo 회로도

#include <Servo.h>

Servo srv;

int posVal = 90;
int potVal = 0;

void setup(){
srv.attach(9);
}

void loop(){
potVal = analogRead(A0);
//0~1023
//y=map(x,1,50,50,1);
posVal = map(potVal, 0, 1023, 0, 180);
//0~180
srv.write(posVal);
delay(50);
}

#pot2servo2

map함수 사용하지 않고 posVal 구하기

potVal:posVal = 1023 : 180

posval * 1023 = potVal * 180

posVal = potVal * 180 / 1023

map함수 아닐때는 형 지정해주기. long으로!

double을 굳이 쓸 필요없을때는 성능저하를 막기위해 굳이 쓰지 말기.

#include <Servo.h>

Servo srv;

long posVal = 90;
long potVal = 0;

void setup(){
srv.attach(9);
}

void loop(){
potVal = analogRead(A0);
//0 ~ 1023
//y = map(x, 1, 50, 50, 1);
//potVal : posVal = 1023 : 180
//posVal x 1023 = potVal x 180
//posVal = potVal * 180 / 1023
//posVal = map(potVal, 0, 1023, 0, 180);
posVal = potVal * 180 / 1023;
srv.write(posVal);
delay(50);
}

#부저모듈 회로도

#buzz1

tone함수와 notone함수 사용하여 부저의 울렸다 멈추는 주기 조절.

tone함수

notone함수

duration을 통해 delay 시간 조절

const int pinBuzz = 8;

int note[] = {262, 294, 330, 349, 392, 440, 494, 523};

void setup(){
int len = sizeof(note) / sizeof(int);
for(int i = 0; i < len; i++){
tone(pinBuzz, note[i]);
delay(400);
noTone(pinBuzz);
delay(200);
}
}

void loop(){
}

#buzz_serialPlayer

부저모듈이용하여 노래 연주하기

atoi():문자 스트링을 정수값으로 변환.

else을 사용하여 오타나 지정되지 않은 명령어 발생시 예외처리.

문자열제한이 걸려있어서 한번에 플레이가능한 음길이 제한이 있음...

const int buzz = 8;

const int note[] = {262, 294, 330, 349, 392, 440, 494, 523};
const char codes[] = "CDEFGABC"; // = {C,D,E,F,G,A,B,C};
const int tempo = 200;

void setup(){
	Serial.begin(9600);
    Serial.println(">> play music~ <<");
    }
    
void loop(){
	if(Serial.available() > 0){
    char ch = Serial.read();
    player(ch, tempo);
    }
}

void player(char ch, int tm){
if(ch >= '1' && ch <= '8')//if(ch >= 49 && ch<= 56)
{
Serial.print(codes[(ch-'0')-1]);//'1'-'0' = 49-48 =1
Serial.print(" ");
tone(buzz, notes[(ch-'0')-1]);
delay(tm);
}
else if(ch == '0')
{
delay(tm);
Serial.println();
}
else;

noTone(buzz);
}

툴-시리얼 모니터에 값을 입력하면 부저모듈에서 음이 연주된다!

-학교종
556655305533200556655305323100
-퐁당퐁당
12331356501233135650653653221235500
-징글벨
532155505321666064327770554231005321555053216660643255556542100
-비행기
32123330222355003212333302232100

#I2C 16×2 캐릭터 LCD

I2C 16×2 캐릭터 LCD는 한줄에 16자, 2줄 표시 가능한 LCD!

그래픽 LCD의 경우 직접 글자폰트를 만들어서 써야하지만 편리하게 라이브러리를 통해 편하게 구현할수 있다.

PCF8574 라이브러리 설치 방법은 다음과 같다.

*스케치-라이브러리 포함하기-라이브러리 관리

 

*liquidcrystal I2C 검색

void setCursor(int col, int row) // 여기서부터 텍스트 출력 가능

 

#lcd 회로도

#lcd_hello

 

lcd모니터에 hello, 1~60 출력

#include <LiquidCrystal_PCF8574.h>
#include <Wire.h>

LiquidCrystal_PCF8574 lcd(0x27);

int count = 0;

void setup()
{
int error;
Serial.begin(9600);
Serial.println("LCD...");
Serial.println("Dose: check for LCD");

Wire.begin();
Wire.beginTransmission(0x27);
error = Wire.endTransmission();
Serial.print("Error: ");
Serial.print(error);

if(error == 0){
	Serial.println(": LCD found.");
    lcd.begin(16, 2);
    }else{
    Serial.println(": LCD not found.");
    }
    lcd.setBacklight(255);
    lcd.home();
    lcd.clear();
    lcd.print("Hello LCD");
    }
    
void loop(){
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0,1);
lcd.print(count);
delay(500);
count = (count + 1) % 60;
}

 

#lcd_from_pot

-회로설계는 LCD회로+가변저항회로로 겹치는 핀은 사이드쪽을 이용해서 연결해줍니다!

 

가변저항값을 나타내는 adc값 모니터에 출력.

가변저항이 없을때도 나타나기는 하지만 무의미한 값 출력. 현재 전압이 어느정도인지! 나타냄.


*코드 업로드 후에는 리셋을 눌러주세요!

 

위 화면처럼 표시되어서 아두이노 코드나 회로설계가 잘못된줄 알았는데 리셋후 다시 값이 잘 출력되는것을 확인할수 있었습니다.

#include <LiquidCrystal_PCF8574.h>
#include <Wire.h>

LiquidCrystal_PCF8574 lcd(0x27); //set the LCD address to 0x27 for a 16 char and 2 line display 

const int pinPot = A0;
int count = 0;

void setup(){
int error;
Serial.begin(9600);
Serial.println("LCD...");
Serial.println("Dose : check for LCD");

Wire.begin();
Wire.beginTransmission(0x27);
error = wire.endTransmission();
Serial.print("Error: ");
Serial.print(error);

if(error == 0){
	Serial.println(": LCD found.");
    lcd.begin(16, 2);
    }else{
    Serial.println(" LCD not found.");
    }//if
    lcd.setBacklight(255);
    lcd.home();
    lcd.clear();
    //lcd.cursor();
    lcd.print("Hello LCD");
    lcd.setCursor(0, 1);
    lcd.print("adc = ");
    }//setup()
    
void loop(){
lcd.setCursor(6, 1);
lcd.print(" ");
lcd.setCursor(6, 1);
lcd.print(analogRead(pinPot));
delay(500);
//count = (count + 1) % 60;
}

#lcd_from_pot_n_2servo

회로도 : LCD와 가변저항 그리고 서보모터 대로 꽂아주시면 됩니다!

 

여기서 퀴즈! 19v 2.1A의 호환품으로 적당한것은?

단 우리가 택할 수 있는 것은?

1.19v 5.0A

2.19v 2.0A

답은 1입니다!<-드래그

 

공급받는 전기는 부족한데 많은 전기를 꺼낼갈때 화재등 문제가 발생합니다!

그래서 전열기 등에서 화재가 자주 납니다.

 

이 코드는 lcd와 서보모터를 동시에 돌아가게하는 코드로

실제 코드 작동시 작동은 하지만 너무 lcd가 평소보다 더 깜빡이는 현상을 볼 수 있습니다.

 

#include <LiquidCrystal_PCF8574.h>
#include <Wire.h>
#include <Servo.h>
//set the LCD address to 0x27 for a 16 chars and 2 line display
LiquidCrystal_PCF8574 lcd(0x27);
Servo myservo;

void setup(){
myservo.attach(pinSrv);

int error;
Serial.begin(9600);
Serial.println("LCD...");
Serial.println("Dose : check for LCD");

Wire.begin();
Wire.beginTransmission(0x27);
error = Wire.endTransmission();
Serial.print("Error: ");
Serial.print(error);

if(error == 0){
Serial.println(": LCD found.");
lcd.begin(16, 2); //initialize the lcd
}else{
Serial.println(": LCD not found.");
}
lcd.setBacklight(255);
lcd.home();
lcd.clear();
lcd.print("Hello LCD");
lcd.setCursor(0, 1);
lcd.print("pos = ");
}
//1023->180, 1023 / 180 = 5.6833333 
void loop(){
int pos = analogRead(pinPot) / 6;
myservo.write(pos);
delay(50);
lcd.setCursor(6, 1);
lcd.print("   ");
lcd.setCursor(6, 1);
lcd.print(pos);
delay(500);
}

#초음파 센서 회로도

#초음파센서

초음파 반사파가 도착하면 HIGH로 변하고 다시 LOW로 돌아가는 시간.

즉, 왕복시간을 통해 왕복거리를 구할 수 있습니다.

연직방향 : 거리가 가장 짧게 나오는 구간!

측정가능거리는 4cm~4m 입니다.

 

# HC-SR04_Simple

라이브러리 설치.HC-SR04 by Dirk Sarodnick

HC-SR04 by Dirk Sarodnick을 설치해줍니다.

음속 : 340m/s

340m/1sec = 340,000mm / 1,000,000ms

return된 값. 왕복시간 echo time.

거리?*2*distance(mm)/echo-time(ms)

340,000(mm)/1,000,000(ms) = 2 * distance(mm)/echo_time(ms)

2000000*d = 340,000 * echo_time

distance = 340000 * echo_time/2000000

distance = 17 * echo_time / 100;

m 밀리

M 마이크로

N 나노

p 피코

 

# HC-SR04

trig:신호를 집어넣어야 해서 아두이노보드로 부터 출력을 받을수있는 핀에 꽂아주기(출력)

echo:반사파 수신시 high->low로 떨어집니다. 아두이노보드로 입력을 주는 핀에 꽂아주기(입력)

출처 : thumb down

 

pinTrig = 4;
pinEcho = 5;

void setup(){
pinMode(pinTrig, OUTPUT);
pinMode(pinEcho, INPUT);
Serial.begin(9600);
Serial.println("mesure distance with HC-SR04");
}

void loop(){
trig();//transmit trigger pulse
unsigned long echo_time = get_echoTime();
if(echo_time != 0){
/*
340(m) / 1(sec) = 2 * distance(mm) / echo_time(us)
340,000(mm) / 1,000,000(us) = 2 * distance(mm) / echo_time(us)
2,000,000 * distance = 340,000 * echo_time
distance = 340,000 * echo_time / 2,000,000
=17 * echo_time / 100
*/
unsigned int distance = 17 * echo_time / 100;
Serial.print("distance = ");
Serial.println(distance);
}else Serial.println("out of range!");
delay(200);
}

void trig(void){
digitalWrite(pinTrig, HIGH);
delayMicroseconds(10);
digitalWrite(pinTrig, LOW);
}

unsigned long get_echoTime(void){
unsigned long echoTime = 0;
while(digitalRead(pinEcho) == LOW);
unsigned long startTime = micros();
while(digitalRead(pinEcho) == HIGH);
ehcoTime = micros() - startTime;
//17 * 240 / 100 = 40.8(mm), 17 * 23000 / 100 =3910(mm)
if(echoTime >= 240 && echoTime <= 23000)
return echoTime;
else
return 0;
}

 

# HC-SR04_distance_meter

시리얼모니터에 1을 입력하면 현재 시점의 거리를 측정해서 시리얼모니터에 결과값을 출력해보자!

const int pinTrig = 4;
const int pinEcho = 5;

void setup(){
pinMode(pinTrig, OUTPUT);
pinMode(pinEcho, INPUT);
Serial.begin(9600);
Serial.println("measure distance with HC-SR04");
}

void loop(){
if(Serial.available() > 0){
	char ch = Serial.read();
    
    if(ch == '1'){
    	int dist = get_dist();
        if(dist != 0){
        	Serial.print("distance = ");
            Serial.println(dist);
            }
            else
            Serial.println("out of range!");
            }
            else;
            }
            }
            
void trig(void){
digitalWrite(pinTrig, HIGH);
delayMicroseconds(10);
digitalWrite(pinTrig, LOW);
}

unsigned long get_echoTime(void){
unsigned long echoTime = 0;
while(digitalRead(pinEcho) == LOW);
unsigned long startTime = micros();
while(digitalRead(pinEcho) == HIGH);
echoTime = micros() - startTime;
/*
17 * 240 / 100 =40.8(mm), 17 * 23000 / 100 = 3910(mm)
*/
if(echoTime >= 240 && echoTime <= 23000)
return echoTime;
else
return 0;
}

int get_dist(void){
trig(); /*transmit trigger pulse*/
unsigned long echo_time = get_echoTime();
if(echo_time != 0){
/*
340(m) / 1(sec) = 2 * distance(mm) / echo_time(us)
340,000(mm) / 1,000,000(us) = 2 * distance(mm) / echo_time(us)
2,000,000 * distance = 340,000 * echo_time
distance = 340,000 * echo_time / 2,000,000
= 17 * echo_time / 100
*/
unsigned long distance = 17 * echo_time / 100;
return distance;
}
else
return 0;

 

# HC-SR04_distance_meter_2

버튼을 누르면 현재 거리를 측정해 LCD모니터에 거리표현되게 만든 거리 측정기 코드!

init.lcd->lcd initialliztion

print_dist->lcd에 프린터하기 위한 함수

cm를 주려고 mm를 10으로 나눠서 표현.

유효거리 밖에서는 ERROR 표시 유효거리 내에서는 0.000

dist != 0일때 거리 측정, dist = 0일때 ERROR 표시

#include <LiquidCrystal_PCF8574.h>
#include <Wire.h>
/*set the LCD address to 0x27 for a 16 chars and 2 line display */
LiquidCrystal_PCF8574 lcd(0x27);

const int pinSW = 2;
const int pinTrig = 4;
const int pinEcho = 5;

const int bounce_time = 160;

void setup(){
pinMode(pinSW, INPUT_PULLUP);
pinMode(pinTrig, OUTPUT);
pinMode(pinEcho, INPUT);

Serial.begin(9600);
Serial.println("measure distance with HC-SR04");

int error;
Wire.begin();
Wire.beginTransmission(0x27);
error = Wire.endTransmission();

if(error == 0){
Serial.println(": LCD found.");
lcd.begin(16, 2);
}else
Serial.println(": LCD not found.");
init_lcd();
}

void loop(){
if(digitalRead(pinSW) != HIGH){
delay(bounce_time);

if(digitalRead(pinSW) != HIGH){
int dist = get_dist();

if(dist != 0){
	print_dist(dist);
    }
    else{
    print_error();
    }
    }
    }
    }
    
 void trig(void){
 digitalWrite(pinTrig, HIGH);
 delayMicroseconds(10);
 digitalWrite(pinTrig, LOW);
 }
 
 unsigned long get_echoTime(void){
 unsigned long echoTime = 0;
 while(digitalRead(pinEcho) == LOW);
 unsigned long startTime = micors();
 while(digitalRead(pinEcho) == HIGH);
 ehcoTime = micros() - startTime;
 /*
 17 * 240 / 100 = 40.8(mm), 17 * 23000 / 100 = 3910(mm)
 */
 if(echoTime >= 240 && echoTime <= 23000)
 	return echotime;
 else
 	return 0;
}

int get_dist(void){
trig(); /* transmit trigger pulse */
unsigned long echo_time = get_echoTime();
if(echo_time != 0){
/*
340(m) / 1(sec) = 2 * distance(mm) / echo_time(us)
340,000(mm) / 1,000,000(us) = 2 * distance(mm) / echo_time(us)
2,000,000 * distance = 340,000 * echo_time
distance = 340,000 * echo_time / 2,000,000
= 17 * echo_time / 100
*/
unsigned long distance = 17 * echo_time / 100;
return distance;
}
else
	return 0;
    }
    
void init_lcd(void){
lcd.setBacklight(255);
lcd.home();
lcd.clear();
lcd.print("<Distance Meter>");
lcd.setCursor(0, 1);
/*         0123456789012345 */
lcd.print("dist =       (m)");
}

void print_dist(int mm){
lcd.setCursor(7,1);
/*
0123456789012345
dist = 3.912(m)
*/
lcd.print("     ");
lcd.sestCursor(7, 1);
lcd.print(mm / 1000);
lcd.print(".");
lcd.print(mm % 1000 % 1000);
lcd.print(" (m)");
}

void print_error(void){
lcd.setCursor(7,1);
/*
0123456789012345
dist = ERROR (m)
*/
lcd.print("     ");
lcd.setCursor(7,1);
lcd.print("ERROR");
}