Skip to content

Instantly share code, notes, and snippets.

@phec
Last active August 29, 2015 14:05
Show Gist options
  • Save phec/23cb3cfb27c955e182e6 to your computer and use it in GitHub Desktop.
Save phec/23cb3cfb27c955e182e6 to your computer and use it in GitHub Desktop.
Beehive Monitor
// 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
}
}
}
#!/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...")
# -*- 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()
@phec
Copy link
Author

phec commented Sep 2, 2014

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment