I've just bought the following photodiode (here) and I am trying to make a simple Arduino circuit/code so that the photodiode is able to record an LED blinking at an arbitrary refresh rate (frequency).
I have an Arduino Uno driving the sensor, and a Raspberry Pi driving the LED at a given frequency.
I would like some help as my knowledge in signal processing is minimal, and I would appreciate any feedback or tips on whether what I am doing is correct or not.
Here is the Arduino code:
CODE UPDATED!!
//#include <TimerOne.h>
#include <Arduino.h>
const unsigned long ONESEC = 1000000; // microseconds
const int size = 600;
int sensorValue[size];
int dly = 1000000 / size; // delay so to fill N samples during 1 complete second (1,000,000 microseconds)
int maxValue = 0;
int minValue = 1000000;
double Alpha = 0.1; // [0.0 - 1.0] weight parameter
double filteredValue = 0.0;
double prevValue = 0.0;
double avgsum = 0.0;
int total = 0;
int avgtotal = 0;
const int s = 10;
int rounds = size / s;
int tmparr[s];
const int btnPin = 7;
const int sensorPin = A0; // sensor pin
void setup() {
Serial.begin(57600);
// init tmparr
for(int i=0;i<s;i++){
tmparr[i] = 0;
}
}
void waitForButton(int btnPin){
Serial.println("Waiting...");
while(digitalRead(btnPin) != 1){
continue;
}
Serial.println("Button has been pressed!");
}
void loop() { // code that loops forever
int i = 0;
unsigned long curTime = micros();
unsigned long prevTime, startTime;
prevTime = curTime;
startTime = curTime;
while(curTime - startTime <= ONESEC){ // sofar the time between the current and the start time is less than 1 second, keep recording data
if(curTime - prevTime < dly){ // sofar the current and the previous time stamp has a differene of less than N seconds, do not record anything
curTime = micros();
continue;
}
sensorValue[i++] = analogRead(sensorPin);
if(i > size){
break;
}
prevTime = curTime;
curTime = micros();
}
///////////////////////
///////////////////////
// Data processing ////
///////////////////////
///////////////////////
// filter the signal and find maximum/minimum and avg
for(int i=0;i<size;i++){
int v = sensorValue[i];
filteredValue = (v * Alpha) + (prevValue * (1-Alpha)); // exponential filtering
sensorValue[i] = filteredValue; // re-writing the sensor data !! RAW DATA ARE BEING OVERWRITTEN !!
avgsum = avgsum + filteredValue;
prevValue = filteredValue;
if(maxValue < filteredValue){
maxValue = filteredValue;
}
if(minValue > filteredValue){
minValue = filteredValue;
}
}
avgsum = avgsum / size;
// plotting and segregating the signal
int peaks = 0;
int prevState = -1;
for(int i=0;i<rounds;i++){
for(int j=0;j<s;j++){
int v = sensorValue[(i*s)+j];
total = total - tmparr[j];
total = total + v;
avgtotal = total / s;
tmparr[j] = v;
Serial.print(avgtotal); // new filtered value
Serial.print(",");
Serial.print(avgsum);
Serial.print(",");
Serial.println(v); // filtered value
if(avgtotal > avgsum + (avgsum*0.01)){
// Serial.println(1);
if(prevState != 1){
peaks++;
prevState = 1;
}
}
else{
// Serial.println(0);
prevState = 0;
}
}
}
Serial.print("peaks:");
Serial.println(peaks);
}
So far I am getting somewhere close I guess. Down are some of the recorded measurements. Filtering the signal, I suspect, is not optimal to make clear distinction between peaks and trough in the signal. Also I am not sure if the shape of the signal is proper representation of the actual input signal given that the filtering influence that in a way or another based on the used parameters.
Any tips for what I should do and how I should proceed to make it more reliable and accurate?
Update 1:
Here is the Pi code:
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
from time import sleep # Import the sleep function from the time module
GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
GPIO.setup(8, GPIO.OUT, initial=GPIO.LOW) # Set pin 8 to be an output pin and set initial value to low (off)
freq = 5.0 # Hz
cycle = 1.0/freq
hcycle = cycle / 2.0
while True: # Run forever
GPIO.output(8, GPIO.HIGH) # Turn on
sleep(hcycle) # Sleep for N second
GPIO.output(8, GPIO.LOW) # Turn off
sleep(hcycle)
Update 2:
After updating the code, for very low frequencies I get kinda nicely shaped-signal
Things start to get messier with high frequency (not that high) at 30 Hz for instance, where trying to segregate the signal based on the total average line does not result in informative value for how many peaks and troughs there are, for several peaks can be under the lines and several troughs can be above the line. Output reads 25 peaks here.
so I am starting to think that the filtering technique I am using maybe is not the best. Any suggestions?