-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathATMEGA-Mosquito-Sensor-v1.ino
276 lines (230 loc) · 8.74 KB
/
ATMEGA-Mosquito-Sensor-v1.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
// ----------------------------------------------------
// ATMEGA based Mosquito listening device
// - Record WAV file on SD card
//. - Offline processing to identify presence and
//. type of mosquito
//
// Derived from:
// APC magazine - Arduino Masterclass
// Project #18 - Digital Audio Recorder v6.0
// ----------------------------------------------------
#include <SdFat.h>
#include "SPI.h"
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
SdFat sd;
SdFile rec;
const unsigned int darBufSize = 128;
const unsigned int totalBuf = darBufSize * 8;
const unsigned int bufSplit_1 = darBufSize;
const unsigned int bufSplit_2 = darBufSize * 2;
const unsigned int bufSplit_3 = darBufSize * 3;
const unsigned int bufSplit_4 = darBufSize * 4;
const unsigned int bufSplit_5 = darBufSize * 5;
const unsigned int bufSplit_6 = darBufSize * 6;
const unsigned int bufSplit_7 = darBufSize * 7;
const int chipSelect = 4;
unsigned long fileSize = 0L;
unsigned long waveChunk = 16;
unsigned int waveType = 1;
unsigned int numChannels = 1;
//------------ SET SAMPLE RATE HERE --------------------
unsigned long sampleRate = 44100;
//unsigned long sampleRate = 22050;
//------------ SET SAMPLE RATE HERE --------------------
unsigned long bytesPerSec = sampleRate;
unsigned int blockAlign = 1;
unsigned int bitsPerSample = 8;
unsigned long dataSize = 0L;
unsigned long recByteCount = 0L;
unsigned long recByteSaved = 0L;
const int btnStart = 6;
const int btnStop = 5;
const int ledStart = 13;
const int ledStop = 3;
//Increment filenum each time record key is pressed
int filenum=0;
int recPressed = 0;
int stopPressed = 0;
unsigned long oldTime = 0L;
unsigned long newTime = 0L;
byte buf00[darBufSize]; // buffer array 1
byte buf01[darBufSize]; // buffer array 2
byte buf02[darBufSize]; // buffer array 3
byte buf03[darBufSize]; // buffer array 4
byte buf04[darBufSize]; // buffer array 4
byte buf05[darBufSize]; // buffer array 4
byte buf06[darBufSize]; // buffer array 4
byte buf07[darBufSize]; // buffer array 4
byte byte1, byte2, byte3, byte4;
unsigned int bufByteCount;
byte bufWrite;
byte lastBuf = 7;
byte valOCR2A = 16000000/(8*sampleRate);
void setup() { // THIS RUNS ONCE
Serial.begin(9600);
Setup_timer2();
Setup_ADC();
pinMode(10, OUTPUT);
pinMode(ledStart, OUTPUT);
pinMode(ledStop, OUTPUT);
pinMode(btnStop, INPUT_PULLUP);
pinMode(btnStart, INPUT_PULLUP);
if (sd.begin(chipSelect, SPI_FULL_SPEED)) { // initialise card on SPI to 8MHz SPI bus speed
Serial.println("SD Card initialized successfully");
for (int dloop = 0; dloop < 4; dloop++) {
digitalWrite(ledStart,!digitalRead(ledStart));
delay(100);
}
} else { // if error, flash LED twice per second, until reset
Serial.println("SD Card initialization ERROR");
while(1) {
digitalWrite(ledStart,!digitalRead(ledStart));
digitalWrite(ledStop,!digitalRead(ledStop));
delay(500);
}
}
}
void loop() { // THIS RUNS LOTS!
if (digitalRead(btnStart) == LOW && recPressed == 0) {
Serial.println("++++++++ START RECORDING +++++++");
StartRec(); // launch StartRec method
}
if (digitalRead(btnStop) == LOW && recPressed == 1) {
Serial.println("********* STOP RECORDING*****");
StopRec(); // launch StopRec method
}
if (recPressed == 1) {
if (recByteCount % totalBuf > bufSplit_1 && lastBuf == 7) {
rec.write(buf00,darBufSize); lastBuf = 0; recByteSaved += darBufSize;
} else if (recByteCount % totalBuf > bufSplit_2 && lastBuf == 0) {
rec.write(buf01,darBufSize); lastBuf = 1; recByteSaved += darBufSize;
} else if (recByteCount % totalBuf > bufSplit_3 && lastBuf == 1) {
rec.write(buf02,darBufSize); lastBuf = 2; recByteSaved += darBufSize;
} else if (recByteCount % totalBuf > bufSplit_4 && lastBuf == 2) {
rec.write(buf03,darBufSize); lastBuf = 3; recByteSaved += darBufSize;
} else if (recByteCount % totalBuf > bufSplit_5 && lastBuf == 3) {
rec.write(buf04,darBufSize); lastBuf = 4; recByteSaved += darBufSize;
} else if (recByteCount % totalBuf > bufSplit_6 && lastBuf == 4) {
rec.write(buf05,darBufSize); lastBuf = 5; recByteSaved += darBufSize;
} else if (recByteCount % totalBuf > bufSplit_7 && lastBuf == 5) {
rec.write(buf06,darBufSize); lastBuf = 6; recByteSaved += darBufSize;
} else if (recByteCount % totalBuf < bufSplit_1 && lastBuf == 6) {
rec.write(buf07,darBufSize); lastBuf = 7; recByteSaved += darBufSize;
}
}
}
void StartRec() { // begin recording process
digitalWrite(ledStart,HIGH);
digitalWrite(ledStop,LOW);
recByteCount = 0;
bufByteCount = 0;
recByteSaved = 0;
bufWrite = 0;
recPressed = 1; // recording button has been pressed
stopPressed = 0;
writeWavHeader();
sbi (TIMSK2, OCIE2A); // enable timer interrupt, start grabbing audio
}
void StopRec() { // stop recording process, update WAV header, close file
cbi (TIMSK2, OCIE2A); // disable timer interrupt
writeOutHeader();
digitalWrite(ledStart,LOW); // turn off recording LED
digitalWrite(ledStop,HIGH); // light stop LED
recPressed = 0;
Serial.println("List of files:");
sd.ls(LS_R);
}
void writeOutHeader() { // update WAV header with final filesize/datasize
rec.seekSet(4);
byte1 = recByteSaved & 0xff;
byte2 = (recByteSaved >> 8) & 0xff;
byte3 = (recByteSaved >> 16) & 0xff;
byte4 = (recByteSaved >> 24) & 0xff;
rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4);
rec.seekSet(40);
rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4);
rec.close();
}
void writeWavHeader() { // write out original WAV header to file
String filename ;
recByteSaved = 0;
filenum++;
filename = String("rec") + String(filenum) + String(".wav");
rec.open(filename.c_str(), O_CREAT | O_TRUNC | O_RDWR);
Serial.println("Opened file:" + filename + " for recording");
rec.write("RIFF");
byte1 = fileSize & 0xff;
byte2 = (fileSize >> 8) & 0xff;
byte3 = (fileSize >> 16) & 0xff;
byte4 = (fileSize >> 24) & 0xff;
rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4);
rec.write("WAVE");
rec.write("fmt ");
byte1 = waveChunk & 0xff;
byte2 = (waveChunk >> 8) & 0xff;
byte3 = (waveChunk >> 16) & 0xff;
byte4 = (waveChunk >> 24) & 0xff;
rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4);
byte1 = waveType & 0xff;
byte2 = (waveType >> 8) & 0xff;
rec.write(byte1); rec.write(byte2);
byte1 = numChannels & 0xff;
byte2 = (numChannels >> 8) & 0xff;
rec.write(byte1); rec.write(byte2);
byte1 = sampleRate & 0xff;
byte2 = (sampleRate >> 8) & 0xff;
byte3 = (sampleRate >> 16) & 0xff;
byte4 = (sampleRate >> 24) & 0xff;
rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4);
byte1 = bytesPerSec & 0xff;
byte2 = (bytesPerSec >> 8) & 0xff;
byte3 = (bytesPerSec >> 16) & 0xff;
byte4 = (bytesPerSec >> 24) & 0xff;
rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4);
byte1 = blockAlign & 0xff;
byte2 = (blockAlign >> 8) & 0xff;
rec.write(byte1); rec.write(byte2);
byte1 = bitsPerSample & 0xff;
byte2 = (bitsPerSample >> 8) & 0xff;
rec.write(byte1); rec.write(byte2);
rec.write("data");
byte1 = dataSize & 0xff;
byte2 = (dataSize >> 8) & 0xff;
byte3 = (dataSize >> 16) & 0xff;
byte4 = (dataSize >> 24) & 0xff;
rec.write(byte1); rec.write(byte2); rec.write(byte3); rec.write(byte4);
}
void Setup_timer2() {
TCCR2B = _BV(CS21); // Timer2 Clock Prescaler to : 8
TCCR2A = _BV(WGM21); // Interupt frequency = 16MHz / (8 x 62 + 1) ~= 32000Hz
OCR2A = valOCR2A; // Compare Match register set to 62
}
void Setup_ADC() {
ADMUX = 0x65; // set ADC to read pin A5, ADLAR to 1 (left adjust)
cbi(ADCSRA,ADPS2); // set prescaler to 3 / ADC clock = 4MHz
sbi(ADCSRA,ADPS1);
sbi(ADCSRA,ADPS0);
}
ISR(TIMER2_COMPA_vect) {
sbi(ADCSRA, ADSC); // start ADC sample
while(bit_is_set(ADCSRA, ADSC)); // wait until ADSC bit goes low = new sample ready
recByteCount++; // increment sample counter
if (recByteCount % totalBuf < bufSplit_1) {
buf00[recByteCount % darBufSize] = ADCH;
} else if (recByteCount % totalBuf < bufSplit_2) {
buf01[recByteCount % darBufSize] = ADCH;
} else if (recByteCount % totalBuf < bufSplit_3) {
buf02[recByteCount % darBufSize] = ADCH;
} else if (recByteCount % totalBuf < bufSplit_4) {
buf03[recByteCount % darBufSize] = ADCH;
} else if (recByteCount % totalBuf < bufSplit_5) {
buf04[recByteCount % darBufSize] = ADCH;
} else if (recByteCount % totalBuf < bufSplit_6) {
buf05[recByteCount % darBufSize] = ADCH;
} else if (recByteCount % totalBuf < bufSplit_7) {
buf06[recByteCount % darBufSize] = ADCH;
} else {
buf07[recByteCount % darBufSize] = ADCH;
}
}