Forked from Pleasegivemeamango/lightstimulus_arduino.cpp
Created
December 5, 2024 19:07
-
-
Save janhohenheim/ebce545a8d9fb877612e63ddf00efc2b to your computer and use it in GitHub Desktop.
Use Welford's online algorithm
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <ArduinoGraphics.h> | |
| #include <Arduino_MKRRGB.h> | |
| #include <Stream.h> | |
| #define let auto const | |
| using namespace std; | |
| const double CALIBRATION_SECONDS = 1.0; | |
| const double STANDARD_DEVIATION_ABOVE_NOISE_MEAN = 3.0; | |
| bool calibration_done = false; | |
| double activation_threshold = 0.0; | |
| double noise_mean = 0.0; | |
| double noise_sse = 0.0; | |
| size_t noise_readout_count = 0; | |
| void setup() { | |
| MATRIX.begin(); | |
| // set the brightness, supported values are 0 - 255 | |
| MATRIX.brightness(48); | |
| Serial.begin(115200); // open the serial port | |
| Serial1.begin(115201); // open the serial port | |
| while (!Serial) { | |
| ; // wait for serial monitor to open. | |
| } | |
| Serial.println("Starting calibration..."); | |
| } | |
| void loop() { | |
| /// incoming serial byte | |
| let inByte = Serial1.read(); | |
| let input_voltage = readAnalogVoltage(A0); | |
| Serial.print(input_voltage); | |
| // Calibration follows [Welford's online algorithm](https://en.m.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm) | |
| if (millis() < CALIBRATION_SECONDS * 1000.0) { | |
| noise_readout_count++; | |
| let delta = input_voltage - noise_mean; | |
| noise_mean += delta / noise_readout_count; | |
| let delta2 = input_voltage - noise_mean; | |
| noise_sse += delta * delta2; | |
| return; | |
| } | |
| if (!calibration_done) { | |
| let noise_sd = sqrt(noise_sse / (noise_readout_count - 1)); | |
| activation_threshold = noise_mean + STANDARD_DEVIATION_ABOVE_NOISE_MEAN * noise_sd; | |
| Serial.println("Calibration done!"); | |
| Serial.print("Mean noise: "); | |
| Serial.print(noise_mean); | |
| Serial.println( "V"); | |
| Serial.print("Noise standard deviation: "); | |
| Serial.print(noise_sd); | |
| Serial.println(" V"); | |
| Serial.print("Using "); | |
| Serial.print(activation_threshold); | |
| Serial.print(" V as a threshold. ( = "); | |
| Serial.print(noise_mean); | |
| Serial.print(" V + "); | |
| Serial.print(STANDARD_DEVIATION_ABOVE_NOISE_MEAN); | |
| Serial.print(" * "); | |
| Serial.print(noise_sd); | |
| Serial.println(" V)"); | |
| Serial.println("(5.0 V is the max allowed input voltage)"); | |
| calibration_done = true; | |
| } | |
| if (input_voltage > activation_threshold){ | |
| MATRIX.beginDraw(); | |
| MATRIX.fill(22, 22, 22); | |
| MATRIX.rect(0, 0, MATRIX.width(), MATRIX.height()); | |
| MATRIX.endDraw(); | |
| delay(10); | |
| } | |
| else { | |
| MATRIX.beginDraw(); | |
| MATRIX.fill(0, 0, 0); | |
| MATRIX.rect(0, 0, MATRIX.width(), MATRIX.height()); | |
| MATRIX.endDraw(); | |
| delay(10); | |
| } | |
| } | |
| float readAnalogVoltage(uint8_t pin) { | |
| return analogRead(A0) * 5.0 / 1023.0; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment