Stap 7: De Code
Deze code wordt gelezen wanneer de magneet passeert de sensor en houdt een lopend gemiddelde van de tijd tussen pedaal passeert. Deze gegevens worden gebruikt voor het berekenen van de rotaties per minuut.
Als u wilt output naar de LED's, het maakt gebruik van een functie voor het berekenen van de helderheid van de LED gebaseerd op de rpm-waarde. Dit creëert een gladde vervagende effect tussen de LEDs als de waarden veranderen.
De beste manier om te lezen van de sensor zou zijn geweest met interrupts, maar ik liep in een probleem waar de waarden van de sensor waren niet hoog genoeg te registreren met de Arduino als digitale signalen. Zodoende had mij voor het gebruik van de analoge sensor-waardes.
Dit is niet de meest elegante code, maar het werkt en is momenteel vergrendeld in een doos op mijn fiets, dus ik ben posting deze zo is. Suggesties en wijzigingen zijn welkom.
#define ARRAY_SIZE 3 //The number of values to keep in the running average #define TIMEOUT 1500 //Max time without input before turning off LEDs #define FADE_INCREMENT .1 //Controls the fading speed--adjust with trial and error #define LED_CONSTANT -20 //Used in the brightness fading equation //RPM targets for each LED: #define RED_1_TARGET 45 #define YELLOW_1_TARGET 68 #define GREEN_TARGET 90 #define YELLOW_2_TARGET 113 #define RED_2_TARGET 135 /**PORT SETUP**/ const int magnetSensor = A7; //Change this for your arduino const int red1 = 12; const int yellow1 = 10; const int green = 9; const int yellow2 = 5; const int red2 = 4; const int ledPin = 11; bool magnetOn = false; bool prevMagOn = false; bool primed = false; bool arrayEmpty = false; float times[ARRAY_SIZE]; //array to hold values for the running average float startTime = millis(); int rpm = 0; bool pedaling = false; int targetR1; int targetY1; int targetG; int targetR2; int targetY2; float r1; float y1; float g; float y2; float r2; //add a new value to the array, moving the rest back one space and removing the oldest void updateTimes(float newValue) { for(int i = 0; i < ARRAY_SIZE-1; i++) { times[i] = times[i+1]; } times[ARRAY_SIZE-1] = newValue; } //returns an average of the values in the array int avgArray(float values[]) { int total = 0; int counted = ARRAY_SIZE; for(int i = 0; i < ARRAY_SIZE; i++) { total = total + values[i]; if(values[i] == 0) counted--; } return(total/counted); } //for debugging void printValues() { for(int i = 0; i < ARRAY_SIZE - 1; i++) { Serial.print(times[i]); Serial.print(", "); } Serial.println(times[ARRAY_SIZE -1]); } //clear the array void clearTimes() { for(int i = 0; i < ARRAY_SIZE; i++) times[i] = 0; } //check if the array is full void checkFullArray() { arrayEmpty = true; for(int i = 0; i < ARRAY_SIZE; i++) { if(times[i] != 0) arrayEmpty = false; } } //use a function to calculate the brightness of a given led based on a target int calculateLED(int target) { if (rpm <= 0) return 0; return int(LED_CONSTANT*abs(target-rpm)+255); } void setup() { pinMode(red1, OUTPUT); pinMode(yellow1, OUTPUT); pinMode(green, OUTPUT); pinMode(yellow2, OUTPUT); pinMode(red2, OUTPUT); Serial.begin(9600); } void loop() { //Read from the hall effect sensor (using analog values, unfortunately) int magnetState = analogRead(magnetSensor); Serial.println(magnetState); if(magnetState > 60) { magnetOn = false; } else { magnetOn = true; } if(!magnetOn && prevMagOn) { primed = true; } //timeout if(millis()-startTime > TIMEOUT) { clearTimes(); pedaling = false; } if(magnetOn && !prevMagOn && primed) { //if magnet passes sensor once float currentTime = millis(); float changeTime = (currentTime - startTime); //record the time since the last pedal startTime = millis(); if(pedaling) //if there has been pedaling since the last timeout updateTimes(changeTime); //add the time to the running average array primed = false; pedaling = true; } //mostly for debugging, this blinks the built-in LED whenever the magnet passes the sensor if(magnetOn) digitalWrite(ledPin, HIGH); else digitalWrite(ledPin, LOW); prevMagOn = magnetOn; checkFullArray(); float gap = avgArray(times); if(arrayEmpty) { rpm = 0; } else rpm = 60000/gap; //turn millisecond gap value into rpm //light the lowest red LED when the first pedal stroke is recorded, since there isn't enough data to calculate rpm if(pedaling && rpm == 0) rpm = 40; /******LED OUTPUT*****/ //calculate values targetR1 = calculateLED(RED_1_TARGET); targetY1 = calculateLED(YELLOW_1_TARGET); targetG = calculateLED(GREEN_TARGET); targetY2 = calculateLED(YELLOW_2_TARGET); targetR2 = calculateLED(RED_2_TARGET); //Normalize negative values to zero (these should really be in an array...) if(targetR1 < 0) targetR1 = 0; if(targetY1 < 0) targetY1 = 0; if(targetG < 0) targetG = 0; if(targetY2 < 0) targetY2 = 0; if(targetR2 < 0) targetR2 = 0; //fade to value if (r1 < targetR1) r1 += FADE_INCREMENT; if (r1 > targetR1) r1 -= FADE_INCREMENT; if (y1 < targetY1) y1 += FADE_INCREMENT; if (y1 > targetY1) y1 -= FADE_INCREMENT; if (g < targetG) g += FADE_INCREMENT; if (g > targetG) g -= FADE_INCREMENT; if (y2 < targetY2) y2 += FADE_INCREMENT; if (y2 > targetY2) y2 -= FADE_INCREMENT; if (r2 < targetR2) r2 += FADE_INCREMENT; if (r2 > targetR2) r2 -= FADE_INCREMENT; //output to LEDs analogWrite(red1, r1); analogWrite(yellow1, y1); analogWrite(green, g); analogWrite(yellow2, y2); analogWrite(red2, r2); }