· 6 years ago · Apr 25, 2020, 12:48 AM
1# Write your code here :-)
2import board
3import busio
4import digitalio
5import time
6import random
7#import adafruit_am2320
8from analogio import AnalogIn
9import adafruit_dht
10
11led = digitalio.DigitalInOut(board.D13)
12led.direction = digitalio.Direction.OUTPUT
13
14
15#Lights to indicate whats going on without looking at the computer
16
17#Green will blink every second
18greenStatus = digitalio.DigitalInOut(board.D10)
19greenStatus.direction = digitalio.Direction.OUTPUT
20
21#Blue will hold while data is being sent
22blueStatus = digitalio.DigitalInOut(board.D11)
23blueStatus.direction = digitalio.Direction.OUTPUT
24
25#Red is when the system halts for whatever reason
26#either no WIFI or thingspeak responds that it didn't get the data
27redStatus = digitalio.DigitalInOut(board.D12)
28redStatus.direction = digitalio.Direction.OUTPUT
29
30greenStatus.value = 0
31blueStatus.value = 0
32redStatus.value = 0
33
34
35# Input for light level
36lightInput = AnalogIn(board.A0)
37
38
39
40
41
42#The dht sensor just needs to be plugged into the specific digital port with pull up resistor
43
44dht = adafruit_dht.DHT22(board.D6)
45
46
47
48#Defining the properties of the i/o pin, its defined as an input and it's pulled low
49
50
51#Wifi name and password
52ssid = "DutchoLinksys20725"
53pwd = "P1nn@cle"
54
55
56#API key to accsess thingspeak
57API_KEY = "Y5HYWBZQOHSJI38O"
58
59START_TIME = int(time.monotonic())
60#How often the feather should send data to thingspeak
61#WAIT_TIME should be in minutes
62WAIT_TIME = 5
63
64#How often in minutes should the feather read data from the environment
65MEASURE_TIME = 1
66
67
68
69globalIndex = 1
70
71#The dictionary structure that we will be using to store data and send it to thingspeak
72#The first element in the data list is the average of the other 5 values
73#the other 5 values are updated every MEASURE_TIME minutes
74#globalIndex determines which one its on
75fieldDict = {
76"Light": {
77 "field": 1,
78 "data": [0,0,0,0,0,0]
79 },
80#TempA would be used if an analog temp sensor was used
81"TempA": {
82 "field": 4,
83 "data": [0,0,0,0,0,0]
84 },
85"TempD": {
86 "field": 3,
87 "data": [0,0,0,0,0,0]
88 },
89"Humd": {
90 "field": 2,
91 "data": [0,0,0,0,0,0]
92 },
93#I don't use the occupancy sensor
94"Occ": {
95 "field": 5,
96 "data": [0,0,0,0,0,0]
97 }
98}
99
100
101#Sets up the uart signal with the approbriate baudrate
102uart = busio.UART(board.TX, board.RX, baudrate=115200)
103
104
105#list of ESP setup commands
106ESP_setup = ["AT","AT+RESTORE","AT+CWMODE=1",'AT+CWJAP="{}","{}"'.format(ssid,pwd),"AT+CIPMODE=0"]
107
108time.sleep(2)
109
110
111
112
113dataTest = True
114#Sets up the ESP
115blueStatus.value = 1
116for x in range(len(ESP_setup)):
117
118
119 str_to_write = ESP_setup[x] + "\r\n"
120 bytes_to_write = bytes(str_to_write, 'utf-8')
121 uart.write(bytes_to_write)
122
123 print("COMMAND: ", bytes_to_write)
124
125
126 time.sleep(.5)
127
128 data = uart.readline()
129 data = uart.read()
130 print("DATA: ", data)
131
132
133 #This next block of code is just to keep on trying to connect to the wifi since it wont send an immediate "OK"
134 #
135 #TODO: Have it test for a "FAIL" or something and then try and run the command again
136 #
137 if data is not None and ("AT+CWJAP" in ESP_setup[x]):
138 if("OK" in data):
139 dataTest = False
140 while (("AT+CWJAP" in ESP_setup[x]) and dataTest == True):
141 data = uart.read()
142 print("DATA: ", data)
143 if data is not None:
144 if("OK" in data):
145 break
146
147
148 #Just outputs the response from the ESP
149 if data is not None:
150 data_string_full = ''.join([chr(b) for b in data]) # Creates the string from the ESP's response
151 data_string = data_string_full.strip() # removes \r\n from end
152 print("RESPONSE: ", data_string)
153blueStatus.value = 0
154
155
156# Forms the GET command/message by putting in the approriate fields and data from fieldDict
157# No Input
158# Returns the fully formed GET command
159def formGETMsg():
160
161 #The basic message with the API key
162 baseMsg = "GET /update?api_key={}".format(API_KEY)
163
164 #Goes through the fieldDict and adds the appropiate field and data value to the GET message
165 for sensor in fieldDict:
166 baseMsg = baseMsg + ("&field{}={}".format(fieldDict[sensor]["field"],fieldDict[sensor]["data"][0]))
167
168 #Adds the thing at the end
169 baseMsg = baseMsg + " HTTP/1.1"
170 return baseMsg
171
172
173
174#Sends the data to Thingspeak using the values in fieldDict
175#No return right now, but I should eventually make it return whether or not it succeeded or not
176def sendDataBetter():
177 blueStatus.value = 1
178 print("starting to send")
179
180 #Calls the formGETMsg() function
181 getMsg = formGETMsg()
182 print("GET MESSAGE: ", getMsg)
183
184 #dataLen is the length in bytes of data that we are going to send, so thats the GET command the "host..." thing and 10 extra bytes for control characters
185 dataLen = len(bytes(getMsg, 'utf-8'))+len(bytes("Host: api.thingspeak.com", 'utf-8'))+10
186
187 #Like with the ESP_setup this is just a list of commands to send data to thingspeak
188 dataCMDS= ['AT+CIPSTART="TCP","api.thingspeak.com",80',"AT+CIPSEND={}".format(dataLen),getMsg,"Host: api.thingspeak.com","","AT+CIPCLOSE"]
189
190 #Goes through dataCMDS and sends each one to the ESP
191 #
192 #TODO: Have this also check the response from the ESP and make record whether or not the data was recieved by thingspeak, so look for a 200 msg in the Json that thingspeak responds with
193 #
194 for x in range(len(dataCMDS)):
195 str_to_write = dataCMDS[x] + "\r\n"
196 bytes_to_write = bytes(str_to_write, 'utf-8')
197 uart.write(bytes_to_write)
198 print("DATA: ",bytes_to_write)
199 data = uart.readline()
200 data = uart.read()
201 print("response?: ", data)
202 time.sleep(1) # Honestly just scared to push this too fast
203 print("sent")
204 blueStatus.value = 0
205
206
207
208#All these are are just get and set methods for retrieving data from each of the sensors and setting the data in fieldDict appropriatly
209#Is converted from Celsius
210def getSetTempD():
211 tempD_value = dht.temperature
212 fieldDict["TempD"]["data"][0] = (sum(fieldDict["TempD"]["data"])-fieldDict["TempD"]["data"][0])/5
213 return tempD_value
214 print("good")
215# return 1
216
217def getSetHumd():
218 humd_value = dht.humidity
219 fieldDict["Humd"]["data"][globalIndex] = humd_value
220 fieldDict["Humd"]["data"][0] = (sum(fieldDict["Humd"]["data"])-fieldDict["Humd"]["data"][0])/5
221 return humd_value
222# return 1
223def getSetOcc():
224
225 return 1
226
227#Analog to digital converter formula used in the getSetLight()
228def getVoltage(pin):
229 return(pin.value*3.3)/65536
230
231def getSetLight():
232 light_value = getVoltage(lightInput)
233 fieldDict["Light"]["data"][globalIndex] = light_value
234 fieldDict["Light"]["data"][0] = (sum(fieldDict["Light"]["data"])-fieldDict["Light"]["data"][0])/5
235 return light_value
236
237
238#Sets all data values in fieldDict
239def getSetAll():
240 getSetTempD()
241 getSetHumd()
242 getSetOcc()
243 getSetLight()
244 print("INDEX: ", globalIndex,"\nAll Got Sot", fieldDict)
245
246
247#The main function, will update the fieldDict every WAIT_TIME minutes and send that data to thingSpeak
248def mainFunction():
249 global gLedCoolDown
250 currentTime = time.monotonic()
251 #print((currentTime-START_TIME) % (WAIT_TIME*60))
252
253
254
255 gLedCoolDown -= 1
256 #toggles the green LED every 5000 loops
257 if(gLedCoolDown>0 and gLedCoolDown<=150):
258 greenStatus.value = 1
259
260 if(gLedCoolDown <= 0):
261 greenStatus.value = 0
262 gLedCoolDown = 1000
263
264
265
266 #Every minute
267 if((currentTime-START_TIME) % ((MEASURE_TIME*60))==0):
268 global globalIndex
269 getSetAll()
270 globalIndex += 1
271 if(globalIndex > 5):
272 globalIndex=1
273
274
275 #Once every cycle
276 if(((currentTime-START_TIME) % (WAIT_TIME*60)==0)):
277 #getSetAll()
278 sendDataBetter()
279
280
281
282gLedCoolDown = 1000
283
284
285#Main Loop
286while True:
287 mainFunction()