# SmartFarm
# Input : temperature, light, CO2
# Output : Blind/window( servo motor) , Fan, Led
# temperatur : 30도 이상이면 window opened/ 26도 이하이면 window close
# : dht 라이브러리 사용
# light : 어두운 상태 40000 이하 / 밝은 상태 60,000 이상
# : ADC 입력
# CO2 : 실내 400ppm / 실외 900ppm / 입김 4000ppm (센서 입력값/10 -> ppm)
# : ADC 입력 (0~3.3v를 0~65535 으로 분할 )
# auto / manual Mode SW 운용
# window opened/close switch 운용
# LED On/Off switch 운용
# FAN On/Off switch 운용
# DHT11
# DHT 11의 SIG 핀 하나를 가지고 양 방향 통신을 하는 Single Wire Two Way 통신 프로토콜을 사용 / 라이브러리 사용
# 전압으로 정보를 얻는게 아니고, Single-bus data format 사용 한 Serial Interface 통신 방식 (입출력 같이 사용)
# Pico 보드에서 starting signal을 보내면 DHT11에서 대응 정보를 제공하는 방식으로 data에 연결된 pinMode는 OUTPUT이 된다.
# sig 신호값 출력의 안정성을 위해 5K pull-up 저항을 사용하거나 이 저항이 장착된 모듈을 사용 할 수 있다.
# 단선 직렬 통신(단선 양방향)은 master가 slave를 호출하면 slave가 응답하는 방식인데, 다른 장치가 사용되는 동안은
# pull-up 으로 High 상태를 유지해야 한다.
# 센서의 전압 변동인 아날로그 신호는 디지털 형식으로 ADC 사용 안 하고 그냥 디지털 핀에 연결할 수 있다.
# MQ135-CO2 센서 (IR 센서 그림으로 대체)
# 센서 내부 열선이 가열된 상태에서 대기 중 불순물이 금속막에 달라 붙으면 저항값이 낮아져 생기는 전압 출력 감지
# Vcc / GND / NC / AO
# 프로그램 작동 시 blynk switch를 default 값으로 설정하기
# gauge 업데이트
# 모든 LED 표시는 보드에서 확인 신호 받아 적용하기
# auth = "nc33HXE33ZPozY05daTFlUFolj85AknG"
# ssid = 'KT_GiGA_10AD'
# password = '9cbf3xb977'
# auth = " "
# # auth = "R0-WaEsABBTA3q6Y1mkYGQ8lueo94JZ4"
# ssid = " "
# password = " "
# BlynkLib : Blynk 회사가 아닌 다른 community에서 배포한 라이브러리/ 최신 버젼이고 많은 프로젝트에서 사용되고 있다.
# blynklib : Blynk 회사에서 배포한 라이브러리/ 오래된 버전으로 별로 사용 안 되고 있는 듯...
# import network, time
# from machine import Pin, PWM, ADC
# import dht # micropython 내장 라이브러리 사용
# import neopixel # micropython 내장 라이브러리 사용
# import BlynkLib
# from BlynkerTimer import BlynkTimer # ???????????????????????????????
# auto_mode = 0
# pin_auto_led = 8
# pin_dht = 22 # DHT11 대신 DHT22로 표현하고 있음.
# pin_window = 1
# pin_fan = 4 # NPN Transistor TIP120의 Base에 연결
# # Fan에서 나온 GND 선이 Collector에 연결되어, Base 신호에 의해 연결되면
# # Emitter를 통해 GND에 연결된다.
# # Collector에 연결된 Fan의 Ground로 향하는 신호가 Base 신호가 있으면 Emitter를 통해 빠져 나가면서 Fan이 작동됨
# # OR_gate를 TIP120 대신 표현 / Buzzer는 Fan 대신 표현
# pin_light = 26 # ADC0 / 조도 센서 입력값 / not-gate를 조도 센서로 표현
# # 조도 센서 연결 : ADC reference 3.3V 사용(ADC_VREF)/ 10Kohm 저항 사용하여 AGND로 연결
# pin_co2 = 27 # ADC1 평상 시 실측 9000(실외 400 ppm, 0.04% / 실내 800ppm), 입김 4000ppm , 실측 40,000 정도
# # 특별한 보정 없이 입력값/10 ppm 정도로 하면 되는건가???????????
# pin_neo = 15 # led strip의 DI 연결 핀
# led=Pin('LED', Pin.OUT) # 'LED' : built-in LED
# led.on()
# auto_led = Pin(pin_auto_led,Pin.OUT )
# temp_sensor = dht.DHT11(Pin(pin_dht))
# window = PWM(Pin(pin_window))
# window.freq(50)
# fan = Pin(pin_fan, Pin.OUT)
# led_num = 15 # led strip에서 관리하는 led 갯수
# brightness = 0.2 # 0.0 ~ 1.0 범위
# ledstrip = neopixel.NeoPixel(Pin(pin_neo), led_num)
# # ADC_Vref - photoresistor - 10k ohm - AGND로 연결
# # 3.3V out에 연결하면... 비슷 비슷함 (Vref 전원이 noise가 작다 함)
# photoresistor = ADC(pin_light) # 2000:덮혀 있을 때 / 60000:실내 형광등 / 64800 :핸드폰 플래시
# co2 = ADC(pin_co2)
# close = 500000
# full_opened = 2300000
# opened = (close + full_opened)//2
# window.duty_ns(close)
from machine import Pin
import time, network, random
import BlynkLib
# from BlynkTimer import BlynkTimer
import dht
dhts=dht.DHT22(Pin((22)));
#AP : SSID and PASS --> WOKWi default parameters
# WIFI_SSID = 'CJ_Smart farm-5G'
# WIFI_PASS = '1234567890'
#wifi 연결
WIFI_SSID = ' ' # 시뮬레이션 환경에서는 가상의 값 투입
WIFI_PASS = ' ' # 시뮬레이션 환경에서는 가상의 값 투입
wifi = network.WLAN(network.STA_IF)
if not wifi.isconnected():
print("Connecting to WiFi...")
wifi.active(True)
wifi.connect( WIFI_SSID, WIFI_PASS)
while not wifi.isconnected():
print(".", end="_")
time.sleep(1)
print('\nWifi connected, IP:', wifi.ifconfig()[0])
# wifi = network.WLAN(network.STA_IF)
# wifi.active(True)
# wifi.connect(ssid, password)
# print("Connecting to WiFi...")
# while not wifi.isconnected():
# print(".", end="_")
# time.sleep(1)
# print('\nWifi connected, IP:', wifi.ifconfig()[0])
# Action as Wifi Station Mode (Client)
# wifi = network.WLAN(network.STA_IF)
# if not wifi.isconnected():
# print("Connecting to WiFi...")
# wifi.active(True)
# wifi.connect(ssid, password)
# while not wifi.isconnected():
# wifi.connect(ssid, password)
# print(".", end="_")
# time.sleep(1)
# print('\nWifi connected, IP:', wifi.ifconfig()[0])
# # wifi 연결
# wlan = network.WLAN(network.STA_IF)
# wlan.active(True)
# wlan.connect(ssid, password)
# cnt = 0
# # connection이 성공 될 때까지 재 시도...connect() 함수 한 번 call로 성공 안되는 경우가 많다.
# while wlan.isconnected() == False:
# print('waiting for connection...')
# time.sleep(1)
# cnt += 1
# if cnt <= 5:
# wlan.connect(ssid, password)
# cnt = 0
# ip = wlan.ifconfig()[0]
# print(ip)
# # # Blynk에 연결
# blynk = BlynkLib.Blynk(auth)
# # timer = BlynkTimer() # BlynkTimer에 맞춰 사용자 함수를 주기적으로 실행 시키기 위함
# @blynk.on('connected') # 데코레이터
# def blynk_connected():
# print('Pico W is connected to Blynk')
# @blynk.on("V10") # virtual pin 번호를 문자열 형태로 표기 /
# def autoMode(value): #V0 state가 변할 때 마다 실행/ 함수 이름은 아무 의미 없다!!!!!!!
# global auto_mode # value는 V0의 값이다.
# if int(value[0]) == 1: # value는 ['1']/['0']처럼 문자열로 주어지니 int()처리 필요함!
# auto_mode = 1
# time.sleep(0.5)
# print('Auto Mode')
# else:
# auto_mode = 0
# time.sleep(0.5)
# print('Manual Mode')
# # # Blynk App의 switch 같은 것을 통해 virtual pin의 state에 변화가 생기면 실행됨
# @blynk.on("V4") # virtual pin 번호를 문자열 형태로 표기 /
# def window_func(value): #V0 state가 변할 때 마다 실행/ 함수 이름은 아무 의미 없다!!!!!!!
# # value는 V0의 값이다.
# # print(value)
# if auto_mode == 0:
# if int(value[0]) == 1: # value는 ['1']/['0']처럼 문자열로 주어지니 int()처리 필요함!
# window.duty_ns(opened)
# print('Window opened')
# else:
# window.duty_ns(close)
# print('Window Close')
# else:
# print('widow state', value)
# blynk.virtual_write(4, 0 if int(value[0])==1 else 1)
# # auto mode일 때는 코드에 의해 write된 값이 반영되고 한다.
# # 강제로 버튼을 눌러도 누른대로 바뀌지 않도록 방지!
# @blynk.on("V6") # virtual pin 번호를 문자열 형태로 표기 /
# def led_func(value): #V0 state가 변할 때 마다 실행/ 함수 이름은 아무 의미 없다!!!!!!!
# # value는 V0의 값이다.
# if auto_mode == 0:
# if int(value[0]) == 1: # value는 ['1']/['0']처럼 문자열로 주어지니 int()처리 필요함!
# ledstrip.fill((0,255,0))
# ledstrip.write()
# print('LED ON')
# else:
# ledstrip.fill((0,0,0))
# ledstrip.write()
# print('LED OFF')
# else:
# blynk.virtual_write(6, 0 if int(value[0])==1 else 1)
# # auto mode일 때는 코드에 의해 write된 값이 반영되고 한다.
# # 강제로 버튼을 눌러도 누른대로 바뀌지 않도록 방지!
# @blynk.on("V8") # virtual pin 번호를 문자열 형태로 표기 /
# def fan_func(value): #V0 state가 변할 때 마다 실행/ 함수 이름은 아무 의미 없다!!!!!!!
# # value는 V0의 값이다.
# if auto_mode == 0:
# if int(value[0]) == 1: # value는 ['1']/['0']처럼 문자열로 주어지니 int()처리 필요함!
# fan.value(1)
# print('FAN ON')
# else:
# fan.value(0)
# print('FAN OFF')
# else:
# blynk.virtual_write(8, 0 if int(value[0])==1 else 1)
# # auto mode일 때는 코드에 의해 write된 값이 반영되고 한다.
# # 강제로 버튼을 눌러도 누른대로 바뀌지 않도록 방지!
# # def reading_light():
# # light_value = photoresistor.read_u16()
# # blynk.virtual_write(2, light_value)
# # print(light_value)
# # if light_value < 40000:
# # ledstrip.fill((0,255,0))
# # ledstrip.write()
# # blynk.virtual_write(6, 1)
# # if light_value > 50000:
# # ledstrip.fill((0,0,0))
# # ledstrip.write()
# # blynk.virtual_write(6, 0)
# # timer.set_interval(2, reading_light)
# blynk.virtual_write(10,0) # autoMode switch to Manual
# blynk.virtual_write(4,0) # window switch to close
# blynk.virtual_write(6,0) # led switch to off
# blynk.virtual_write(8,0) # fan switch to off
# while True:
# blynk.run()
# temp_sensor.measure()
# temp_value = temp_sensor.temperature()
# blynk.virtual_write(1, temp_value)
# print(temp_value, 'degrees')
# light_value = photoresistor.read_u16()
# blynk.virtual_write(2, light_value)
# print(light_value)
# co2_value = co2.read_u16()/10
# blynk.virtual_write(3,co2_value)
# print(co2_value, 'ppm')
# if auto_mode == 1:
# auto_led.on()
# # blynk.virtual_write(10,1) # auto_mode는 항상 버튼 눌려지는 대로 동작되는 것이므로 따로 write 할 필요는 없다.
# if temp_value > 31:
# window.duty_ns(opened)
# blynk.virtual_write(4,1)
# if temp_value < 26:
# window.duty_ns(close)
# blynk.virtual_write(4, 0)
# if light_value < 3000:
# ledstrip.fill((0,255,0))
# ledstrip.write()
# blynk.virtual_write(6, 1)
# if light_value > 50000:
# ledstrip.fill((0,0,0))
# ledstrip.write()
# blynk.virtual_write(6, 0)
# if co2_value > 900:
# fan.on()
# blynk.virtual_write(8,1)
# if co2_value < 830:
# fan.off()
# blynk.virtual_write(8, 0)
# else:
# auto_led.off()
# time.sleep(2) # 센서 입력을 위한 delay 필요하다.
''' Blynk
- @blynk.on('V1') : Blynk APP에서 직접 button을 터치하여 상태가 변하면 자동 실행
: blynk.virtual_write()에 의해 상태가 바뀔 때는 실행되지 않느다.
: 하부에 실행할 함수 작성 (함수 이름은 아무렇게나... 어차피 따로 call 되는 경우 없는 듯 하다)
: 매개변수의 값은 ['1']처럼 리스트로 문자열 값 형태임에 유의할 것!
- blynk.virtual_write(pin, 1) : button의 상태를 변경 할 수 있다./ 장치와 APP의 상태를 syncing 할 수 있다.
: gauge widget에 연결되어 있으면, 장치로부터 입력 받은 값을 표시하게 된다.
- Notification : 코드로 구현하지 않고, blynk site에서 구현할 수 있다.
: template -> Automations -> Type of Automation : Switch or Range Control with step (1) / Condition Enable
: Console의 Automations -> Create Automation -> Device State -> Template에서 automation 걸어 둔 Datestream 선택
- type of automation에 따라 상이한 옵션 나타남 - 알맞게 선택하면 됨
'''