Skip to content
Snippets Groups Projects
Commit d8836209 authored by David Preiss's avatar David Preiss
Browse files

Update 5 files

- /inputDevices_2_gauss.ino
- /inputDevices_3_filters.ino
- /inputDevices_4_linearization.ino
- /Input Devices 2022.pdf
- /README.md
parent 877742a3
Branches
No related tags found
No related merge requests found
File added
# Input Devices Recitation
This recitation aims to introduce the basics of working with inputs on Arduino embeded devices. Slides are hosted [here](https://gitlab.cba.mit.edu/classes/863.22/site/-/blob/master/doc/input_devices/Input%20Devices%202022.pdf).
### Example Code
1) [inputDevices_1_basic.ino](https://gitlab.cba.mit.edu/classes/863.22/site/-/blob/master/doc/input_devices/inputDevices_1_basic.ino) is a simple sketch introducing analogRead().
2) [inputDevices_2_gauss.ino](https://gitlab.cba.mit.edu/classes/863.22/site/-/blob/master/doc/input_devices/inputDevices_1_basic.ino) adds a tare, ADC resolution, and conversion to Gauss.
3) [inputDevices_3_filters.ino](https://gitlab.cba.mit.edu/classes/863.22/site/-/blob/master/doc/input_devices/inputDevices_1_basic.ino) shows various filtering approaches, including batch averaging, moving averaging, and low pass filters.
4) [inputDevices_4_linearization.ino](https://gitlab.cba.mit.edu/classes/863.22/site/-/blob/master/doc/input_devices/inputDevices_1_basic.ino) shows a simple lookup table implementation with linearization.
// Variables
const int sensorPin = 27;
float reading = 0;
float tare = 0; // initializing our tare
const int ADC_res = 10; // desired ADC resolution
const float sens = 0.005; // V/G, taken from datasheet
const float conversion_factor = 3.3/(pow(2,ADC_res))/sens; // [V/ADC] / [V/G] gives us Gauss/ADC
void setup() {
Serial.begin(115200);
analogReadResolution(ADC_res); // Here we can set the number of bits used by our ADC
tare = analogRead(sensorPin); // Take one reading to use as our tare value
}
void loop() {
float reading = (analogRead(sensorPin) - tare)*conversion_factor; // now we will subtract by our tare, and multiply by our conversion factor
Serial.print(reading);
Serial.println(" Gauss");
delay(10);
}
// Variables
const int sensorPin = 27;
float reading = 0;
float tare = 0;
// Variables for Averaging
const int totalSamples = 10;
int index_avg = 0;
int value = 0;
float sum = 0;
int readings[totalSamples]; // create an empty array of size totalSamples
// Variables for Low Pass
float filteredOutputPrevious = 0;
const float RC = 0.159;
const float dT = 0.01; // time in seconds
const float C1 = dT/(RC+dT); // coefficient 1
const float C2 = RC/(RC+dT); // coefficient 2
void setup() {
Serial.begin(115200); // initialize serial communication with computer:
analogReadResolution(10); // Here we can set the number of bits used by our ADC
// Now for our tare, we can use our low pass filter several times to get more accuracy
filteredOutputPrevious = analogRead(sensorPin); // First let's initialize the previous value with a single new reading
for (int i = 0; i < 10; i++) { // Next let's repeat the measurement a few times to make sure we are getting a nice filtered output
tare = lowPassRead();
}
}
void loop() {
float reading = analogRead(sensorPin) - tare;
Serial.print(reading);
Serial.print(", ");
float filtered_reading = batchAverageRead() - tare; // Batch average reading
//float filtered_reading = movingAverageRead() - tare; // Moving average read
//float filtered_reading = lowPassRead() - tare; // Low pass read
Serial.println(filtered_reading); // send our reading over USB to the computer
delay(dT*1000); // delay between reads in miliseconds (necessary for low pass)
}
// Batch Averaged sensor reading ----------------------------------------------------
float batchAverageRead(){
sum = 0;
for (int i = 0; i < totalSamples; i++){
sum = sum + analogRead(sensorPin); // sum totalSamples readings
delay(dT*1000); // wait for every reading! This is bad :(
}
return sum / totalSamples;
}
// Moving Average sensor reading ----------------------------------------------------
float movingAverageRead(){
sum = sum - readings[index_avg]; // Remove the oldest entry from the sum
value = analogRead(sensorPin); // Read the next sensor value
readings[index_avg] = value; // Add the newest reading to the window
sum = sum + value; // Add the newest reading to the sum
index_avg = (index_avg+1)%totalSamples; // Increment the index, and wrap to 0 if it exceeds the window size
return sum/(float(totalSamples)); // Divide the sum of the window by the window size for the result
}
// Low Pass Filter sensor reading -------------------------------------------------
float lowPassRead(){
float filteredOutput = analogRead(sensorPin)*(C1) + filteredOutputPrevious*(C2); // All we need to do here is to measure once and do some fast multiplication with our coefficients! This is great :)
filteredOutputPrevious = filteredOutput; // And store our output for next time
return filteredOutput;
}
// Variables
const int sensorPin = 27;
float reading = 0;
float tare = 0;
// Variables for Low Pass
float filteredOutputPrevious = 0;
const float RC = 0.159;
const float dT = 0.01; // time in seconds
const float C1 = dT/(RC+dT); // coefficient 1
const float C2 = RC/(RC+dT); // coefficient 2
// Variables for linearization
const int interp_samples = 10;
float interp_inputs[interp_samples] = {296, 200.3, 139.5, 100.8, 75, 57, 44.05, 35, 28, 23}; // Raw ADC readings
float interp_outputs[interp_samples] = {0, 2, 4, 6, 8, 10, 12, 14, 16, 18}; // Associated linear distances
void setup() {
Serial.begin(115200); // Initialize serial communication with computer:
// Now for our tare, we can use our low pass filter several times to get more accuracy
filteredOutputPrevious = analogRead(sensorPin); // First let's initialize the previous value with a single new reading
for (int i = 0; i < 10; i++) { // Next let's repeat the measurement a few times to make sure we are getting a nice filtered output
tare = lowPassRead();
}
}
void loop() {
float filtered_reading = lowPassRead() - tare; // we will always subtract the tare from our readings
linearized(filtered_reading); // send our reading over USB to the computer
delay(dT*1000); // delay between reads in miliseconds
}
// Low Pass Filter sensor reading -------------------------------------------------
float lowPassRead(){
float filteredOutput = analogRead(sensorPin)*(C1) + filteredOutputPrevious*(C2);
filteredOutputPrevious = filteredOutput;
return filteredOutput;
}
// Linearization ------------------------------------------------------------------
float linearized(float reading){
float linear_output = reading; // Print our raw output for reference first
Serial.print("Raw reading: ");
Serial.print(reading);
if (reading <= interp_inputs[0] && reading >= interp_inputs[interp_samples-1]){ // If we are reading within the interpolation lookup range
for (int i = 0; i <= interp_samples; i++){
if (reading > interp_inputs[i]){ // Find our exact location by iterating through the table and checking each time
float scaling_factor = abs((reading - interp_inputs[i]) / (interp_inputs[i] - interp_inputs[i-1])); // Calculate our percentage between two interpolation points
linear_output = (interp_outputs[i-1] - interp_outputs[i])*scaling_factor + interp_outputs[i]; // Apply that scaling factor to the associated conversion points
Serial.print(" Linearized reading: ");
Serial.print(linear_output);
Serial.println(" mm");
break;
}
}
}
else {
Serial.println(" Outside of interpolation range");
}
return linear_output;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment