Close

It's Pie for Dinner

A project log for Intelligent Bat Detector

Bat species are auto detected 'in the wild' using machine learning with results transmitted to the cloud

Tegwyn☠TwmffatTegwyn☠Twmffat 02/18/2020 at 10:320 Comments

LoRa is not meant for big data. To get long range transmission with low power, the transmit time can be quite long, about a second in this case, and the TTN has a fair use policy of 30 seconds per day. For developers, this is a challenge and creating a simple bar chart as above is no easy feat. The data I wanted to transmit is represented in the table, top left, so obviously trying to transmit this in one go is a non starter. Instead, I transmitted one species at a time, presuming that normally we would not have more than 2 or 3 species being detected in one evening. This worked quite well except, as can be seen in the middle right, there are gaps in the data! This was solved by iterating through the species repeatedly and programming the channel to give precedence to the most recent reading for that species. After familiar with MatLab, this was actually quite fun and eventually I came up with quite a neat bit of code:

% Channel ID to read data from 
readChannelID = 744655; 
SpeciesIDFieldID = 3; 
AudioEventsFieldID = 4; 
   
% Channel Read API Key   
% If your channel is private, then enter the read API 
% Key between the '' below:   
readAPIKey = '';
   
% Fetch the last 10 points from the Bat Detector channel:
speciesID= thingSpeakRead(readChannelID,'Fields',SpeciesIDFieldID,'NumPoints',10,...
'ReadKey',readAPIKey); 

numAudioEvents = thingSpeakRead(readChannelID,'Fields',AudioEventsFieldID,...
'NumPoints',10,'ReadKey',readAPIKey);

A = [speciesID numAudioEvents]
[~,b] = unique(A(:,1),'last')
C = A(b,:)

% Extract the first column, species label:
D = C(:,1)

% Extract the second column, audio events:
E = C(:,2)

labels = string(D)
x = E

% This is where the mapping assignment occurs:
% May want to remove House keys or try and divide by 10 or something.
numbers_to_decode = {'0','17','26','32','35','71','92'};
names = {'','C.PIP','HOUSE.KEYS','NOCTULA','PLECOTUS','RHINO.HIPPO','S.PIP'};
M = containers.Map(numbers_to_decode,names)

k = keys(M) ;
val = values(M) ;

% Now get the species name from the numbers using the map:
for i = 1:length(labels)
     z{i}=M(labels{i})
end

% Trim the length of the audio events vector to fit that of species:
len_z = length(z);
len_x = length(x);
len_xy = (len_x - len_z);

% Trim x vector to match z:
x = x(len_xy +1 : end);

pie(x,z)

 This was typed into the 'visualisations' sections and tested by hitting the 'save and run' button. 

I can't stress how incredibly user friendly ThingSpeak is and they give quite a generous 3 million data points and 4 channels before it's necessary to buy a license.

Discussions