Last active
August 29, 2015 14:05
-
-
Save phec/23cb3cfb27c955e182e6 to your computer and use it in GitHub Desktop.
Beehive Monitor
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// beehive monitor | |
// v1.4 Spark code = include application.h for local compile | |
// help yourself | |
// don't blame me | |
// don't get stung | |
// other version for chip antenna narwal/112/5211 | |
// this version for black uFL/105/5208 | |
// have added delay to aud measurement to get 500uS per sample | |
// the first 50 odd frequency measurements seem to be anomalous - power settling or something - so take 50 measurements before saving | |
// add test for long wait and "toggle "reset" if stuck in loop (enter and leave deep sleep) | |
// slow sample rate - now see low frequency optical variation so switch off LED during optical read! | |
// 11/7 further slow optical sample rate from 345 to 500uS = 470 delay + sums | |
#include "application.h" | |
#include <math.h> | |
//pin definitions | |
const int led = D0; | |
int therm[6]; //two thermistor for demonstration expandable to 6 | |
const int micPin = A7; | |
const int optPin = A1; | |
uint16_t dynamicData[256]; //we are very short of memory so reuse this for optical and audio | |
int packetSize; | |
char UDPin[16]; | |
UDP udp; | |
int i; | |
// | |
int v[6]; //thermistor ADC readings | |
const float Rinf = 0.072; //thermistor constants for 57k thermistor | |
const float B = 4190.0; | |
const float Rup = 47000.0; //pullup resistor value | |
float t[6]; //temperature measurement | |
unsigned long startT, t1, t2; | |
char output[60]; //for spark variable | |
void setup() { | |
startT = millis(); | |
therm[0] = A0; | |
therm[1] = A2; | |
therm[2] = A3; | |
therm[3] = A4; | |
therm[4] = A5; | |
therm[5] = A6; | |
Spark.variable("temperature", &output, STRING); | |
pinMode(led, OUTPUT); | |
udp.begin(5208); | |
} | |
void loop() { | |
if (millis()-startT > 30*60*1000){ //if Spark has been awake for more than 1/2 hr send to sleep for 30 secs to reset | |
Spark.sleep(SLEEP_MODE_DEEP, 30); | |
} | |
if (udp.parsePacket()>1){ | |
digitalWrite(led, HIGH); // Turn ON the LED to show packet received | |
udp.read(UDPin,16); | |
if(UDPin[0]=='s'){ // If sn received, sleep for n mins | |
i = UDPin[1] - '0'; | |
if (i>0 && i<10){ | |
i*=600; //add a 00 for longer sleeps when debugged 600 = 10 mins times i | |
Spark.sleep(SLEEP_MODE_DEEP, i); | |
} | |
} | |
if(UDPin[0]=='d'){ // If d received, send monitoring data | |
udp.beginPacket(udp.remoteIP(), udp.remotePort()); | |
if (UDPin[1]=='t'){ | |
//update temperatures | |
for (i = 0; i<6;i++){ | |
v[i] = analogRead(therm[i]); | |
t[i] = B / log(Rup * v[i]/(4096 - v[i])/Rinf) - 273; | |
} | |
sprintf(output,"%d, %d, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f",v[0],WiFi.RSSI(),t[1],t[2],t[3],t[4],t[5],t[0]); | |
//sprintf(output,"%d, %d, %d, %d, %d, %d",v[0],v[1],v[2],v[3],v[4],v[5]); | |
udp.write((unsigned char*)&output,sizeof(output)); | |
} | |
else if (UDPin[1]=='a'){ | |
//update sound | |
for (i=-50;i<256;i++){ | |
//if (i == 0) t1 = millis(); //use this line to tune delay to get 500uS per sample | |
if (i >= 0) dynamicData[i]=analogRead(micPin); | |
else analogRead(micPin); //dummy read | |
delayMicroseconds(470); | |
} | |
//use the following two lines to tune delay to get 500uS per sample | |
//t2 = millis(); | |
//dynamicData[0] = t2-t1+2047; | |
udp.write((unsigned char*)&dynamicData[0],sizeof(dynamicData)); | |
} | |
else if (UDPin[1]=='o'){ | |
RGB.control(true); | |
RGB.brightness(0); | |
for (i= -50;i<256;i++){ | |
if (i >= 0) dynamicData[i]=analogRead(optPin); | |
else analogRead(optPin); //dummy read | |
delayMicroseconds(1470); | |
} | |
udp.write((unsigned char*)&dynamicData[0],sizeof(dynamicData)); | |
RGB.control(false); | |
} | |
udp.endPacket(); | |
digitalWrite(led, LOW); // Turn OFF the LED | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
# Beehive monitor v1.4BlackuFL | |
# host 192.168.105 | |
# socket 5208 | |
#save 16 spectra to average noise | |
#make time format excel compatible | |
#save raw and fft data in separate daily files v1.31 | |
#save sample averages | |
#save backups as csv | |
#filter out spikes in raw data | |
#split into separate functions | |
#print repeat no in raw file to track down extra writes | |
## | |
import socket # Import socket module | |
import time | |
import struct | |
import numpy | |
import sys | |
from math import log10 | |
import shutil | |
host = "192.168.1.105" # use name of server uFL (BlackuFL) | |
port = 5208 # Reserve a port for your service. | |
i=0 | |
datalen = 256 | |
print('v1.4BlackuFL') | |
p1 = '/media/IDEdrv/BeeMonitor/' | |
p2 = '/media/HD-EU2pi/BeeMonitor/' | |
def copyFile(name): | |
d = time.strftime("_%d_%m_%y")+ '.txt' | |
c = time.strftime("_%d_%m_%y")+ '.csv' | |
try: | |
shutil.copyfile(p1+name+d, p2+name+c) | |
except: | |
return -1 | |
return 0 | |
# try to open a connection to Spark | |
# if successful return the socket otherwise return 0 | |
def getSocket(): | |
s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #Create a socket object | |
sys.stdout.write('+') | |
sys.stdout.flush() | |
s.settimeout(3) | |
try: | |
s.connect((host, port)) | |
return s | |
except socket.error: | |
return 0 | |
def getOneMicSet(s): | |
dataOK = False | |
while not dataOK: | |
s.sendall(b'da\0 ') # da = send audio data | |
r = s.recv(2048) | |
if r == 0: # if r is 0 then the sender has closed for good | |
print('socket disconnected') | |
#read audio data packed in a buffer | |
micData1=struct.unpack('256h',r) | |
micData = numpy.array([x-2048 for x in micData1]) | |
stats = (micData.max() - micData.min())/micData.std() | |
#check data received OK | |
if len(micData) != datalen: | |
print('bad audio data') | |
dataOK = False | |
elif stats > 7: | |
print('spiky data '+ str(stats)) | |
dataOK = False | |
else: | |
dataOK = True | |
print('good data '+ str(stats)) | |
return micData | |
def getOneOptSet(s): | |
dataOK = False | |
while not dataOK: | |
s.sendall(b'do\0 ') # do = send optical data | |
r = s.recv(2048) | |
if r == 0: # if r is 0 then the sender has closed for good | |
print('socket disconnected') | |
#read optical data packed in a buffer | |
optData1=struct.unpack('256h',r) | |
optData = numpy.array([x-2047 for x in optData1]) | |
stats = (optData.max() - optData.min())/optData.std() | |
if len(optData) != datalen: | |
print('bad optical data') | |
dataOK = False | |
elif stats > 7: | |
print('spiky data '+ str(stats)) | |
dataOK = False | |
else: | |
dataOK = True | |
print('good data '+ str(stats)) | |
return optData | |
def getAudioData(s, w): | |
try: | |
with open("beeDataAudRaw"+time.strftime("_%d_%m_%y")+".txt","a") as raw, \ | |
open("beeDataAudFFT"+time.strftime("_%d_%m_%y")+".txt","a") as frq, \ | |
open("beeDataAudLinFFT"+time.strftime("_%d_%m_%y")+".txt","a") as lin: | |
micAvg = 0.0 | |
micCount = 0 #move above with open ?? | |
for repeat in range(0,16): | |
micData = getOneMicSet(s) | |
for x in micData: | |
raw.write('%d, ' % x) | |
raw.write(str(len(micData)) + ','+str(repeat) + '\n') | |
print(time.ctime()+' saved audio data') | |
print(str(repeat)+'----------------------') | |
freq = numpy.abs(numpy.fft.rfft(micData*w,256)) | |
for x in freq: | |
lin.write('%.4f, ' % x) | |
lin.write(time.strftime("%d/%m/%y %H:%M:%S")+' '+str(len(freq))+'\n') | |
dB = numpy.log10(freq) | |
for x in dB: | |
frq.write('%.4f, ' % x) | |
frq.write(time.strftime("%d/%m/%y %H:%M:%S")+' '+str(len(freq))+'\n') | |
micCount +=1 | |
if micCount == 1: | |
micAvg = freq | |
else: | |
micAvg += freq | |
micAvg /= micCount | |
with open('beeDataAudAvg.txt','a') as avg, \ | |
open('beeDataAudLinAvg.txt','a') as lin: | |
for x in micAvg: | |
lin.write('%.4f, ' % x) | |
if x>0: | |
avg.write('%.4f, ' % log10(x)) | |
else: | |
avg.write('-1000.0') | |
avg.write(time.strftime("%d/%m/%y %H:%M:%S")+'\n') | |
lin.write(time.strftime("%d/%m/%y %H:%M:%S")+'\n') | |
print('audio average saved') | |
except: | |
#print('error in getAudioData',sys.exc_info()[0]) | |
raise | |
def getOpticalData(s, w): | |
try: | |
optAvg = 0 | |
optCount = 0 | |
with open("beeDataOptRaw"+time.strftime("_%d_%m_%y")+".txt","a") as raw, \ | |
open("beeDataOptFFT"+time.strftime("_%d_%m_%y")+".txt","a") as frq, \ | |
open("beeDataOptLinFFT"+time.strftime("_%d_%m_%y")+".txt","a") as lin: | |
for repeat in range(0,16): | |
optData = getOneOptSet(s) | |
for x in optData: | |
raw.write('%d, ' % x) | |
raw.write(str(len(optData)) + ',' + str(repeat) + '\n') | |
print(time.ctime()+ ' saved optical data') | |
print(str(repeat)+'----------------------') | |
freq = numpy.abs(numpy.fft.rfft(optData*w,256)) | |
for x in freq: | |
lin.write('%.4f, ' % x) | |
lin.write(time.strftime("%d/%m/%y %H:%M:%S")+' '+str(len(freq))+'\n') | |
dB = numpy.log10(freq) | |
for x in dB: | |
frq.write('%.4f, ' % x) | |
frq.write(time.strftime("%d/%m/%y %H:%M:%S")+' '+str(len(freq))+'\n') | |
optCount += 1 | |
if optCount == 3: #ignore first two readings | |
optAvg = freq | |
elif optCount > 3: | |
optAvg += freq | |
optAvg /= (optCount - 2) | |
with open('beeDataOptAvg.txt','a') as avg, \ | |
open('beeDataOptLinAvg.txt','a') as linAv: | |
for x in optAvg: | |
linAv.write('%.4f, ' % x) | |
if x>0: | |
avg.write('%.4f, ' % log10(x)) | |
else: | |
avg.write('-1000.0') | |
avg.write(time.strftime("%d/%m/%y %H:%M:%S")+'\n') | |
linAv.write(time.strftime("%d/%m/%y %H:%M:%S")+'\n') | |
print('opt average saved '+str(optCount)) | |
except: | |
print('error in getOpticalData') | |
raise | |
def getTemperatureData(s): | |
s.sendall(b'dt\0 ') # dt = send thermal data | |
r='not read anything' | |
try: #check for data | |
r = s.recv(2048) | |
if r == 0: # if r is 0 then the sender has closed for good | |
print('socket disconnected') | |
#read string with temperature data | |
try: | |
text = r.decode("utf-8",'ignore') | |
except: | |
text = "Can't decode" | |
vals = [] | |
T = [0.0,0.0,0.0,0.0,0.0,0.0] | |
vals = text.split(',') | |
RSSI = vals[1] | |
for i in range(0,6): | |
T[i] = float(vals[i+2].strip('\0')) | |
with open("beeDataTherm.txt","a") as myfile: | |
for Tm in T: | |
myfile.write('%.1f, ' % Tm) | |
print(RSSI,T, len(T)) | |
myfile.write(time.strftime("%d/%m/%y %H:%M:%S")+'\n') | |
except: | |
print('error in getTemperatureData') | |
raise | |
def backupFiles(): | |
try: | |
shutil.copyfile(p1+'beeDataTherm.txt', p2+'beeDataTherm.csv') | |
shutil.copyfile(p1+'beeDataAudAvg.txt', p2+'beeDataAudAvg.csv') | |
shutil.copyfile(p1+'beeDataOptAvg.txt', p2+'beeDataOptAvg.csv') | |
shutil.copyfile(p1+'beeDataAudLinAvg.txt', p2+'beeDataAudLinAvg.csv') | |
shutil.copyfile(p1+'beeDataOptLinAvg.txt', p2+'beeDataOptLinAvg.csv') | |
copyFile('beeDataOptRaw') | |
copyFile('beeDataOptFFT') | |
copyFile('beeDataOptLinFFT') | |
copyFile('beeDataAudRaw') | |
copyFile('beeDataAudFFT') | |
copyFile('beeDataAudLinFFT') | |
except: | |
print('cant write to HD-EU2') | |
############################################## | |
w = numpy.hamming(datalen) | |
while True: | |
s = getSocket() | |
if not isinstance(s, socket.socket): | |
break | |
try: | |
getAudioData(s, w) | |
getOpticalData(s, w) | |
getTemperatureData(s) | |
backupFiles() | |
s.sendall(b's6\0 ') # s = sleep n is time in 10s of min | |
except socket.timeout: | |
time.sleep(10) | |
s.close() | |
print ("Finished...") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
""" | |
Created on Sun Jun 08 16:45:49 2014 | |
@author: Media | |
""" | |
import numpy as np | |
import matplotlib.pyplot as plt | |
from matplotlib.dates import strpdate2num | |
from mpl_toolkits.mplot3d import Axes3D | |
beeAud = np.loadtxt('/media/HD-EU2pi/BeeMonitor/beeDataAudFFT_28_08_14.csv',delimiter=',', | |
converters = {129:strpdate2num(' %d/%m/%y %H:%M:%S')}, | |
usecols = (range(100))) | |
im = plt.imshow(beeAud[:,:].T, vmin = 1, vmax = 4) | |
plt.contour(beeAud[:,:].T,(np.arange(0.0,4.0,0.333)), colors='black' ) | |
plt.colorbar(im, orientation='horizontal', shrink=0.8) | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This software is primitive and probably not fit for any purpose but you are welcome to use it and comment on the spark.io forum.