Added interrupt-driven non-blocking ADC read. First step in increasing loop frequencies
This commit is contained in:
1
AdditiveControlCode/ADC.cpp
Symbolic link
1
AdditiveControlCode/ADC.cpp
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../lib/ADC.cpp
|
||||||
1
AdditiveControlCode/ADC.hpp
Symbolic link
1
AdditiveControlCode/ADC.hpp
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../lib/ADC.hpp
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "IndSensorMap.hpp"
|
#include "IndSensorMap.hpp"
|
||||||
#include "Controller.hpp"
|
#include "Controller.hpp"
|
||||||
|
#include "ADC.hpp"
|
||||||
|
|
||||||
// K, Ki, Kd Constants
|
// K, Ki, Kd Constants
|
||||||
Constants repelling = {1000, 0, 10000};
|
Constants repelling = {1000, 0, 10000};
|
||||||
@@ -24,6 +25,9 @@ float slewRateLimit = 10000.0; // max PWM change per control cycle (determined b
|
|||||||
// Might be useful for things like jitter or lag.
|
// Might be useful for things like jitter or lag.
|
||||||
#define sampling_rate 1000 // Hz
|
#define sampling_rate 1000 // Hz
|
||||||
|
|
||||||
|
// EMA filter alpha value (all sensors use same alpha)
|
||||||
|
#define alphaVal 0.3f
|
||||||
|
|
||||||
// ABOVE THIS LINE IS TUNING VALUES ONLY, BELOW IS ACTUAL CODE.
|
// ABOVE THIS LINE IS TUNING VALUES ONLY, BELOW IS ACTUAL CODE.
|
||||||
|
|
||||||
unsigned long tprior;
|
unsigned long tprior;
|
||||||
@@ -45,6 +49,12 @@ int ON = 0;
|
|||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
setupADC();
|
||||||
|
|
||||||
|
indL.alpha = alphaVal;
|
||||||
|
indR.alpha = alphaVal;
|
||||||
|
indF.alpha = alphaVal;
|
||||||
|
indB.alpha = alphaVal;
|
||||||
|
|
||||||
tprior = micros();
|
tprior = micros();
|
||||||
|
|
||||||
|
|||||||
1
PseudoSensorControl/ADC.cpp
Symbolic link
1
PseudoSensorControl/ADC.cpp
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../lib/ADC.cpp
|
||||||
1
PseudoSensorControl/ADC.hpp
Symbolic link
1
PseudoSensorControl/ADC.hpp
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../lib/ADC.hpp
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "IndSensorMap.hpp"
|
#include "IndSensorMap.hpp"
|
||||||
#include "PseudoSensorControl.hpp"
|
#include "PseudoSensorControl.hpp"
|
||||||
|
#include "ADC.hpp"
|
||||||
|
|
||||||
float refs[4] = {12.9,12.3,12.6,12};
|
float refs[4] = {12.9,12.3,12.6,12};
|
||||||
|
|
||||||
@@ -36,6 +37,8 @@ int ON = 0;
|
|||||||
void setup() {
|
void setup() {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
setupADC();
|
||||||
|
|
||||||
indL.alpha = alphaVal;
|
indL.alpha = alphaVal;
|
||||||
indR.alpha = alphaVal;
|
indR.alpha = alphaVal;
|
||||||
indF.alpha = alphaVal;
|
indF.alpha = alphaVal;
|
||||||
|
|||||||
46
lib/ADC.cpp
Normal file
46
lib/ADC.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "ADC.hpp"
|
||||||
|
|
||||||
|
#define NUM_PINS 4
|
||||||
|
|
||||||
|
const uint8_t adc_pins[] = {0, 1, 4, 5}; // A0, A1, A4, A5
|
||||||
|
|
||||||
|
volatile uint16_t adc_results[NUM_PINS];
|
||||||
|
volatile uint8_t current_channel_index = 0;
|
||||||
|
|
||||||
|
void setupADC() {
|
||||||
|
// 1. Set Reference to AVCC (5V)
|
||||||
|
// REFS0 = 1, REFS1 = 0
|
||||||
|
ADMUX = (1 << REFS0);
|
||||||
|
|
||||||
|
// 2. Set ADC Prescaler to 128 (16MHz / 128 = 125KHz)
|
||||||
|
// Good balance of speed and accuracy.
|
||||||
|
// Bits: ADPS2, ADPS1, ADPS0
|
||||||
|
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
|
||||||
|
|
||||||
|
// 3. Enable ADC and Enable ADC Interrupt
|
||||||
|
ADCSRA |= (1 << ADEN) | (1 << ADIE);
|
||||||
|
|
||||||
|
// 4. Set initial channel to the first pin in our list
|
||||||
|
ADMUX = (ADMUX & 0xF0) | (adc_pins[0] & 0x0F);
|
||||||
|
|
||||||
|
// 5. Start the first conversion!
|
||||||
|
ADCSRA |= (1 << ADSC);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(ADC_vect) {
|
||||||
|
// 1. Read the result (must read ADCL first, then ADCH, or just use ADC word)
|
||||||
|
adc_results[current_channel_index] = ADC;
|
||||||
|
|
||||||
|
// 2. Increment to next channel
|
||||||
|
current_channel_index++;
|
||||||
|
if (current_channel_index >= NUM_PINS) {
|
||||||
|
current_channel_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Switch MUX to next channel
|
||||||
|
// Clear bottom 4 bits of ADMUX, then OR in the new pin number
|
||||||
|
ADMUX = (ADMUX & 0xF0) | (adc_pins[current_channel_index] & 0x0F);
|
||||||
|
|
||||||
|
// 4. Start next conversion
|
||||||
|
ADCSRA |= (1 << ADSC);
|
||||||
|
}
|
||||||
11
lib/ADC.hpp
Normal file
11
lib/ADC.hpp
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#ifndef ADC_H
|
||||||
|
#define ADC_H
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <util/atomic.h>
|
||||||
|
|
||||||
|
extern volatile uint16_t adc_results[];
|
||||||
|
|
||||||
|
void setupADC();
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "IndSensorMap.hpp"
|
#include "IndSensorMap.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
#include "ADC.hpp"
|
||||||
|
|
||||||
// Sensor calibration data
|
// Sensor calibration data
|
||||||
IndSensorMap ind0Map = {-8.976076325826309, 913.5463710698101, 0.29767471011439534, 5.6686184386250025, 0.3627635461289861};
|
IndSensorMap ind0Map = {-8.976076325826309, 913.5463710698101, 0.29767471011439534, 5.6686184386250025, 0.3627635461289861};
|
||||||
@@ -22,13 +23,19 @@ float IndSensor::toMM(uint16_t raw) {
|
|||||||
|
|
||||||
// Read sensor directly from pin and convert to millimeters
|
// Read sensor directly from pin and convert to millimeters
|
||||||
float IndSensor::readMM() {
|
float IndSensor::readMM() {
|
||||||
uint16_t raw = constrain(analogRead(pin), 0, 900);
|
uint8_t index = pin - A0;
|
||||||
|
index = (index > 3) ? index - 2 : index;
|
||||||
|
uint16_t raw;
|
||||||
|
|
||||||
|
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
|
||||||
|
raw = constrain(adc_results[index], 0, 900);
|
||||||
|
}
|
||||||
|
|
||||||
// Exponential moving average filter
|
// Exponential moving average filter
|
||||||
filteredRaw = alpha * raw + (1.0f - alpha) * filteredRaw;
|
filteredRaw = alpha * raw + (1.0f - alpha) * filteredRaw;
|
||||||
|
|
||||||
analog = (uint16_t)filteredRaw;
|
analog = (uint16_t)filteredRaw;
|
||||||
oor = (analog == 0 || analog > 870);
|
oor = (analog < 10 || analog > 870);
|
||||||
mmVal = toMM(analog);
|
mmVal = toMM(analog);
|
||||||
return mmVal;
|
return mmVal;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user