You were right all along. I was already dizzy after a few days of testing variants. Apologies.
Setting as INPUT respects the dampened sinus shape, but quality is horrible.
Reading with INPUT A1.
Now I have the opposite effect, before readings were 0, now 1023. I tried pluging my CD power supply in the AREF, set to 3.44V, but when I connect the anode to GND, it shows 4.9V (Not sure why.).
Then the difference was scope's resistor vs Arduino's resistor.
So I guess the problem now became:
- How to increase resistance on Arduino's pin to prevent altering the reading.
- Hot to set the correct ranges so I read something from 0-1023 and not only 1023?
(I'm tempted to accept your answer and create a new one with the above?)
I though I was helping you by removing extra code.
later will upload all of it, not in that laptop ATM.
I expect my current implementation to pick up frequencies from 2kHz to 44KHz, tested with fn generator, but facing this issue with natural responses.
Complete code:
#define PinD7 B00000001
#define PinD6 B00000010
#define PinD5 B00000100
#define PinD4 B00001000
#define PinD3 B00010000
#define PinD2 B00100000
#define PinD1 B01000000
#define PinD0 B10000000
byte Dpins[8] = {PinD0, PinD1, PinD2, PinD3, PinD4, PinD5, PinD6, PinD7};
#define healthPin 22
// How many peaks to sample for frequency estimation.
#define PEAKS 5
#define BUFFER_SIZE 1000
int resultBuff[BUFFER_SIZE] = {};
// Classes to move o a library
class SampleRate {
public:
// Duration in microS
unsigned long duration;
int samples;
// Should be in samples per microS
double sampleFrequency;
// Should be in microS
double sampleDuration;
SampleRate (unsigned long duration, int samples)
: duration(duration)
, samples(samples)
, sampleFrequency((double) samples / duration)
, sampleDuration((double) duration / samples) {};
};
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(healthPin, OUTPUT);
Serial.begin (115200);
pinMode(A1, INPUT);
Serial.println ();
ADCSRA &= ~(bit (ADPS0) | bit (ADPS1) | bit (ADPS2)); // clear prescaler bits
// uncomment as required
ADCSRA |= bit (ADPS0); // 2
// ADCSRA |= bit (ADPS1); // 4
// ADCSRA |= bit (ADPS0) | bit (ADPS1); // 8
// ADCSRA |= bit (ADPS2); // 16
// ADCSRA |= bit (ADPS0) | bit (ADPS2); // 32
// ADCSRA |= bit (ADPS1) | bit (ADPS2); // 64
// ADCSRA |= bit (ADPS0) | bit (ADPS1) | bit (ADPS2); // 128
}
bool done = false;
// the loop function runs over and over again forever
void loop() {
// port toggle test, max rate
// while (true) {
// //delayMicroseconds(3);
// // Freq 2.667Mhz
// // duty cycle: 70% (because of the loop delay it's not 50%)
//// PORTA &= !B00000001; // Off
//// PORTA |= B00000001; // On sets Arduino pin 22 (Digital)
PORTA = B00000001; // On
//delay(300);
//PORTA = B00000000; // Off
//delayMicroseconds(1);
// }
if (! done) {
unsigned long startTime = micros ();
// Fast AnalogRead test
SampleRate sr1 = readSignal(800, true);
done = true;
float freq = findNaturalFreq(sr1);
unsigned long duration = micros () - startTime;
Serial.print("Natural Freq: ");
Serial.println(freq, 8);
Serial.print("Samples: ");
Serial.println(sr1.samples);
// delay(10);
Serial.println();
Serial.print("E2E sampling duration: ");
Serial.println(duration, 8);
}
delay(1);
PORTA = B00000000; // Off
delay(1);
// digitalWrite(healthPin, LOW);
//delayMicroseconds(60);
}
/**
*
* Avg slope of last four data points positive is considered SlopeUp,
* Anything else is considered slopeDown, as a catch all for noise.
*/
bool isSlopeDown(int currentIdx, SampleRate sr) {
// skips immediate to avoid noise
return ! (((float) (resultBuff[currentIdx] - resultBuff[currentIdx - 1]
+ resultBuff[currentIdx - 1] - resultBuff[currentIdx - 2]
+ resultBuff[currentIdx - 2] - resultBuff[currentIdx - 3]
+ resultBuff[currentIdx - 3] - resultBuff[currentIdx - 4]) / 4) > 0);
}
/**
* find index of 1st two peaks in result buffer.
*/
int * findPeaks(SampleRate sr) {
static int peaks[PEAKS] = {0, 0, 0, 0, 0};
int runningPeak = 0;
int runningPeakValue = 0;
bool foundPeak = false;
for (int i = 3; i < sr.samples - 3; i++) {
// wait till we are slope up
if(isSlopeDown(i, sr)) {
if (foundPeak) {
foundPeak = false;
if (runningPeak < 5) {
runningPeak += 1;
runningPeakValue = 0;
} else {
break;
}
}
continue;
}
// Now we are riding signal up. keeping highest seen value.
Serial.print("SlopeUp!: ");
Serial.println(i);
if (runningPeakValue <= resultBuff[i]) {
peaks[runningPeak] = i;
runningPeakValue = resultBuff[i];
foundPeak = true;
}
}
Serial.print("Peaks: ");
for (int i = 0; i < PEAKS; i++) {
Serial.print(peaks[i]);
Serial.print(" : ");
}
Serial.println();
return peaks;
}
/**
* Finds st two peaks and computes frequency in peaks/microSeconds
* turned into Hz
*/
double findNaturalFreq(SampleRate sr) {
int *peaks = findPeaks(sr);
int deltas[PEAKS - 1] = {};
for (int i = 1 ; i < PEAKS; i++) {
int prev = *(peaks + (i - 1));
int current = *(peaks + i);
deltas[i-1] = current - prev;
}
Serial.print("Deltas: ");
for (int i = 0; i < PEAKS - 1; i++) {
Serial.print(deltas[i]);
Serial.print(" : ");
}
Serial.println();
// remove noise, tollrance: 3 datapoints difference between deltas
int suspect1 = -1;
int suspect2 = -1;
int tolerance = 3;
int removed = 0;
float acumDeltas = 0;
for (int i = 0 ; i < PEAKS - 2; i++) {
acumDeltas += deltas[i];
int deltaDelta = deltas[i] - deltas[i + 1];
if (abs(deltaDelta) > tolerance) {
if (suspect1 > -1) {
int deltaSuspect = deltas[suspect1] - deltas[i + 1];
int guilty = abs(deltaSuspect) > tolerance ? suspect1 : suspect2;
suspect1 = -1;
suspect2 = -1;
removed++;
acumDeltas -= deltas[guilty];
deltas[guilty] = -1;
} else {
if (i == PEAKS - 2) {
deltas[i + 1] = -1;
removed++;
}
suspect1 = i;
suspect2 = i + 1;
}
}
}
acumDeltas += (deltas[PEAKS - 2] > -1 ) ? deltas[PEAKS - 2] : 0;
float avgDeltas = acumDeltas / ( PEAKS - 1 - removed);
Serial.print("Deltas wothout noise: ");
for (int i = 0; i < PEAKS - 1; i++) {
Serial.print(deltas[i]);
Serial.print(" : ");
}
Serial.println();
Serial.print("AVG Deltas: ");
Serial.println(avgDeltas);
Serial.print("PEAKS - 1 - removed: ");
Serial.println(PEAKS - 1 - removed);
float period = avgDeltas * sr.sampleDuration;
Serial.print("period: ");
Serial.println(period, 4);
return ((float) 1000000 / period);
}
/**
* With 1000 datapoints I can describe at this sample rates:
* 500 Hz wave, 1.5 cycles. (good enouh to find max values)
* 20KHz Is the max freq I Can describe accurately.
* 30KHz Is the max freq I Can describe accurately with noInterrupts() on.
* 40KHz Still can see a signall, about 8 datapoints peak to peak with noInterrupts() on.
* Good to find max valtage in range.
*/
int cycle = 0;
SampleRate readSignal(int samples, bool isVerbose) {
if (samples > BUFFER_SIZE) {
// silently limiting samples to max
samples = BUFFER_SIZE;
}
// Warm-up
for (int i = 0; i < 200; i++) {
resultBuff[i] = analogRead (A1);
}
unsigned long startTime = micros ();
for (int i = 0; i < samples; i++) {
resultBuff[i] = analogRead (A1);
}
unsigned long duration = micros () - startTime;
SampleRate sr = SampleRate(duration, samples);
if (isVerbose && (cycle % 10) == 0) {
for (int i = 0; i < samples; i++) {
Serial.println(resultBuff[i]);
}
Serial.print("Duration: ");
Serial.println(duration);
Serial.print("sample freq samples/MicroSeconds: ");
Serial.println(sr.sampleFrequency);
Serial.print("samples: ");
Serial.println(sr.samples);
Serial.print("sampleDuration: ");
Serial.println(sr.sampleDuration, 6);
Serial.println();
cycle = 0;
}
cycle++;
return sr;
}
Notes:
Why do you expect the oscillations visible in pic. 1?
I expect any oscillation that results from a random LC circuit. after a pulse. As that'd be it's natural response. later I plan to hit it with pulses at that Fq. to get a higher voltage as a response.
In your pic it seems A1 is plugged into the row next to your resistor...
I put it like that in an attempt to lave less voltage on A1, (for safety?)
What kind of time constant do you expect from your LC circuit?
I don't want any constant, but my code to find the natural freq within 2KHz-44KHz.