BASIC4MCU | 질문게시판 | 블루투스 자동/수동을 하려고 하는데... 도와주세요 ㅠㅠ
페이지 정보
작성자 도와주세요q 작성일2020-11-26 21:45 조회158,052회 댓글12건본문
#include <Adafruit_NeoPixel.h>
#include <SoftwareSerial.h>
#include <Stepper.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <DHT.h>
#define DHTPIN 7 // 온습도 7번핀 사용
#define DHTTYPE DHT11 // DHT 11 모델사용
#define BT_RXD 4
#define BT_TXD 5
#define PIN 12 // 제어 신호핀
#define NUMPIXELS 6 // 제어하고 싶은 LED 개수
#define BRIGHTNESS 180
SoftwareSerial bluetooth(BT_RXD, BT_TXD); // 블루투스 설정 BTSerial(Tx, Rx)
LiquidCrystal_I2C lcd(0x27,16,2);
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
int WIN1 = 2; //토양습도 모터
int WIN2 = 3;
int a = 1;
int b = 0;
int c = 0;
DHT dht(DHTPIN, DHTTYPE);
const int stepsPerRevolution = 64;
Stepper stepper(stepsPerRevolution, 8, 10, 9, 11);
void setup()
{
stepper.setSpeed(220); // 속도 설정
lcd.init();
Serial.begin(9600);
dht.begin();
pinMode(WIN1,OUTPUT); // 빗방울모터 2개핀 출력
pinMode(WIN2,OUTPUT);
pinMode(A0,INPUT); // 토양습도 값 입력으로
bluetooth.begin(9600);
pixels.begin();
}
void loop()
{
float h = dht.readHumidity(); // 습도 측정
float t = dht.readTemperature(); // 섭씨 온도 측정
int ground = analogRead(A1); // A1 아날로그 값 ground에 저장
int Raindrops = analogRead(A0); // A0 아날로그 값 raindrops에 저장
int light = analogRead(A2); // A2 아날로그 값 raindrops에 저장
lcd.backlight();
lcd.display();
lcd.print("TEMP: ");
lcd.print(t,1);
lcd.print(" C");
lcd.setCursor(0,1);
lcd.print("HUMI: ");
lcd.print(h,1);
lcd.print(" %");
Serial.print("습도: ");
Serial.print(h);
Serial.print(" 온도: ");
Serial.print(t);
Serial.println();
Serial.print("토양습도 : "); // 확인하려고 만든 코드
Serial.println(ground);
Serial.print("빗방울 감지 : ");
Serial.println(Raindrops);
Serial.print("조도센서 값 : ");
Serial.println(light);
bluetooth.print("습도: ");
bluetooth.print(h);
bluetooth.println(" %");
bluetooth.print("온도: ");
bluetooth.print(t);
bluetooth.println(" C");
//자동
if(Raindrops>300 && t>26){ // 만약에 빗방울감지되지않고 온도가 27도 보다 높으면 문이 열림
if(a==1){
a++;
stepper.step(map(180,0,360,0,2037));
delay(100);
}
}
else{ // 비가감지되거나 온도가 26도 이하면 문이닫힘
if(a>1){
a=1;
stepper.step(map(-180,0,-360,0,-2037));
delay(100);
}
}
if(light>300){
pixels.setPixelColor(0, pixels.Color(255,0,0));
pixels.setPixelColor(1, pixels.Color(0,255,0));
pixels.setPixelColor(2, pixels.Color(0,0,255));
pixels.setPixelColor(3, pixels.Color(0,255,0));
pixels.setPixelColor(4, pixels.Color(255,0,0));
pixels.setPixelColor(5, pixels.Color(0,255,0));
pixels.show();
}
else {
pixels.setPixelColor(0, pixels.Color(0,0,0));
pixels.setPixelColor(1, pixels.Color(0,0,0));
pixels.setPixelColor(2, pixels.Color(0,0,0));
pixels.setPixelColor(3, pixels.Color(0,0,0));
pixels.setPixelColor(4, pixels.Color(0,0,0));
pixels.setPixelColor(5, pixels.Color(0,0,0));
pixels.show();
}
if(ground>400 && c == 0)// 토양습도 값이 400이상(토양이 건조한상태)이면 모터 작동 그 외에는 멈춤
{
digitalWrite(WIN1,HIGH); // 모터작동
digitalWrite(WIN2,LOW);
}
else
{
digitalWrite(WIN1,LOW); // 모터정지
digitalWrite(WIN2,LOW);
}
// 수동모드
while(bluetooth.available() > 0){ //블루투스 수신하면 while문 시작
b = bluetooth.read(); // 블루투스값 b에 저장
Serial.print(b);
if(b == 1) { // b의 값이 1이면
digitalWrite(WIN1,HIGH); // 모터작동
digitalWrite(WIN2,LOW);
Serial.print(b);
}
else if(b == 2) {
digitalWrite(WIN1,LOW); // 모터정지
digitalWrite(WIN2,LOW);
Serial.print(b);
}
else if(b == 3) {
pixels.setPixelColor(0, pixels.Color(255,0,0)); // led on
pixels.setPixelColor(1, pixels.Color(0,255,0));
pixels.setPixelColor(2, pixels.Color(0,0,255));
pixels.setPixelColor(3, pixels.Color(0,255,0));
pixels.setPixelColor(4, pixels.Color(255,0,0));
pixels.setPixelColor(5, pixels.Color(0,255,0));
pixels.show();
Serial.print(b);
}
else if(b == 4) {
pixels.setPixelColor(0, pixels.Color(0,0,0)); // led off
pixels.setPixelColor(1, pixels.Color(0,0,0));
pixels.setPixelColor(2, pixels.Color(0,0,0));
pixels.setPixelColor(3, pixels.Color(0,0,0));
pixels.setPixelColor(4, pixels.Color(0,0,0));
pixels.setPixelColor(5, pixels.Color(0,0,0));
pixels.show();
Serial.print(b);
}
else if(b == 5) // 반복문 나가기
break;
}
Serial.print(b);
delay(2000);
lcd.clear();
}
수동부분에서 while문 쓰고 각각 if문 마지막 부분에 b = bluetooth.read(); 를 써도 계속 while문을 빠져나가고 루프가 돌아 수동모드로 제어를 지속할수가없어요 ㅠㅠ 도와주세요...
댓글 12
조회수 158,052master님의 댓글
master 작성일
// 수동모드
주석을 달아놓으면 수동모드가 될까요?
c언어 명령어를 사용하세요
도와주세요q님의 댓글
도와주세요q 작성일
// 수동모드는 구분하기 편하려고 적은거구요..
앱인벤터에서 블루투스 값 받으면 그거 이용해서 수동모드로 제어하려고합니다. while문을 쓰고 각 if문 마다 b = bluetooth.read(); 를 쓰면 계속 while문을 빠져나가구요. 안쓰면 while문에 갇혀서 동작을 안하네요... 어떤 방법을 써야할지 알고싶어서 질문드렸습니다.
master님의 댓글
master 작성일
void loop() {
if(b==0){ // b가 0이면 자동모드입니다. // 추가
기존코드
} // 추가
// 수동모드
기존코드
else if(b == 5)b=0; // else if(b == 5)break; // 반복문 나가기 // 자동모드로 변경
}
Serial.print(b); delay(2000); lcd.clear(); // 이 코드 중 필요없는 라인은 삭제하세요
}
도와주세요q님의 댓글
도와주세요q 작성일말씀하신대로 일단 수정했습니다! 하지만 수동모드에서 계속 while문에 갇히거나 while문을 완전히 나가서 루프가 계속 새로 도는 문제가 해결이 안됩니다 선생님... 대체 뭐가 문제일까요 수동모드 if문 마다 b = bluetooth.read(); 썼는데 대체 왜 while문을 벗어나는건지 알수가 없습니다... ㅠㅠ
master님의 댓글
master 작성일
if문 마다 b = bluetooth.read(); 를 사용하면 안됩니다.
소프트웨어 시리얼은 available() 체크없이 read()를 하면 데이터가 올 때까지 기다리지 않고 0xFf를 리턴합니다.
master님의 댓글
master 작성일첨부 소스 중에서 루프문에 갇힐만한 코드는 존재하지 않습니다.
도와주세요q님의 댓글
도와주세요q 작성일
while문 대신
if(bluetooth.available())
b = bluetooth.read(); {
이것안에 if문 b=0부터 5를 넣어 보았는데 그래도 제가 delay 시간을 넣은만큼 잠시 작동하고 루프가 처음으로 돌아갑니다 ㅠㅠ
도와주세요q님의 댓글
도와주세요q 작성일
if(b == 1) { // b의 값이 1이면
digitalWrite(WIN1,HIGH); // 모터작동
digitalWrite(WIN2,LOW);
이대로만 if 문을 쓰면 while에서 나오질 않아 고민하다가 if문에 if available,read 을 써보았는데 아예 while문에서 빠져나가 전체 루프가 다시돌게 돌았습니다. 전체 루프가 다시 돌면 마지막 딜레이 이후에 자동모드가 되니... 그래서 혹시나 하고 read문만 써보았는데 이래서 안되는거였네요! 답변감사합니다!
그럼 혹시 수동모드에서 어떻게 if문을 고쳐야 제가 원하는 때에 while문을 빠져나와 다시 루프를 돌게할수있을까요????
master님의 댓글
master 작성일
while(bluetooth.available() > 0){ //블루투스 수신하면 while문 시작
b = bluetooth.read(); // 블루투스값 b에 저장
이하 코드 생략
와일문은 자동이든 수동이든 항상 체크해야 합니다.
//
저 코드 위에 있는 코드는 자동모드(b==0)일 때만 실행 해야하죠
도와주세요q님의 댓글
도와주세요q 작성일
답변감사합니다.
while(bluetooth.available()>0){ //블루투스 수신하면 while문 시작
b = bluetooth.read(); // 블루투스값 b에 저장
if(b == 1) { // b의 값이 1이면
digitalWrite(WIN1,HIGH); // 모터작동
digitalWrite(WIN2,LOW);
Serial.print(b);
}
else if(b == 2) {
digitalWrite(WIN1,LOW); // 모터정지
digitalWrite(WIN2,LOW);
}
else if(b == 3) {
pixels.setPixelColor(0, pixels.Color(255,0,0)); // led on
pixels.setPixelColor(1, pixels.Color(0,255,0));
pixels.setPixelColor(2, pixels.Color(0,0,255));
pixels.setPixelColor(3, pixels.Color(0,255,0));
pixels.setPixelColor(4, pixels.Color(255,0,0));
pixels.setPixelColor(5, pixels.Color(0,255,0));
pixels.show();
}
else if(b == 4) {
pixels.setPixelColor(0, pixels.Color(0,0,0)); // led off
pixels.setPixelColor(1, pixels.Color(0,0,0));
pixels.setPixelColor(2, pixels.Color(0,0,0));
pixels.setPixelColor(3, pixels.Color(0,0,0));
pixels.setPixelColor(4, pixels.Color(0,0,0));
pixels.setPixelColor(5, pixels.Color(0,0,0));
pixels.show();
}
else if(b == 5) // 다시 자동
b=0;
}
말씀하신대로 이렇게 짜보았습니다. 블루투스로 값을 넣었을 때 여전히 while문을 빠져나가 버립니다... 5를 넣었을 때만 while문을 빠져나가야 하는데 1,2,3,4를 넣어도 잠시 작동할뿐 다시 loof문 처음부터 자동으로 동작합니다. 어떻게 해야 while문 안에서 계속 작동하다가 b에 5를 넣었을 때 위의 자동모드로 동작하게 할 수 있을까요? while문을 한번동작후 계속반복되지않고 블루투스 값이 다시 0이 되어 자동으로 계속 동작하는 것 같습니다.
master님의 댓글
master 작성일
if(b == '1') {
else if(b == '2'){
else if(b == '3'){
보통 시리얼모니터 등으로 입력할 때는 정수가 아닌 문자형의 값을 체크해야 합니다.
도와주세요q님의 댓글
도와주세요q 작성일
정말 감사합니다 ㅠㅠ 해결했어요! 오늘 이걸로 대체 몇시간을 고민한건지... 허허 정말 감사합니다!
왜 문자형의 값을 체크해야 하는지 공부해봐야겠어요!