// PWM on D9 and D10 with 90kHz, 50% duty (D10 inverted PWM)
// Read ADC from A0 and apply a 3rd order moving average filter
// Display filtered ADC on Serial Monitor at 9600 baud
volatile uint16_t adcRaw = 0;
volatile uint16_t filteredADC = 0;
uint16_t adcSamples[3] = {0, 0, 0};
void setup()
{
// Configure PWM pins
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
// ADC input pin
pinMode(A0, INPUT);
// Start Serial communication at 9600 baud
Serial.begin(9600);
cli(); // Disable interrupts during timer setup
// Timer1 PWM setup for 90kHz with 50% duty cycle on D9 and inverted on D10
TCCR1A = 0;
TCCR1B = 0;
// Fast PWM, TOP = ICR1 (mode 14)
TCCR1A |= (1 << WGM11);
TCCR1B |= (1 << WGM13) | (1 << WGM12);
// Non-inverting OC1A (D9), inverting OC1B (D10)
TCCR1A |= (1 << COM1A1);
TCCR1A |= (1 << COM1B1) | (1 << COM1B0);
// TOP for 90kHz PWM (16MHz / (1 * (1 + TOP)) ≈ 90kHz)
ICR1 = 176;
// 50% duty cycle
OCR1A = ICR1 / 2;
OCR1B = ICR1 / 2;
// Start timer with prescaler = 1
TCCR1B |= (1 << CS10);
// ADC setup
ADMUX = (1 << REFS0); // AVcc reference, ADC0 (A0)
ADCSRA = (1 << ADEN) // ADC enable
| (1 << ADATE) // Auto trigger enable
| (1 << ADIE) // ADC interrupt enable
| (1 << ADPS2) | (1 << ADPS1) | (1<< ADPS0); // Prescaler 128
ADCSRB = 0; // Free running mode
ADCSRA |= (1 << ADSC); // Start ADC conversions
sei(); // Enable global interrupts
}
ISR(ADC_vect)
{
// Read raw ADC value
adcRaw = ADC;
// Shift samples for 3rd order moving average filter
adcSamples[2] = adcSamples[1];
adcSamples[1] = adcSamples[0];
adcSamples[0] = adcRaw;
// Simple 3rd order moving average
filteredADC = (adcSamples[0] + adcSamples[1] + adcSamples[2]) / 3;
}
void loop()
{
static unsigned long lastPrintTime = 0;
unsigned long currentTime = millis();
// Print filtered ADC every 100ms (adjust as needed)
if (currentTime - lastPrintTime >= 100)
{
lastPrintTime = currentTime;
Serial.print("Filtered ADC Value: ");
Serial.println(filteredADC);
if (filteredADC > 500 )
{
startPWM();
}
else
{
stopPWM();
}
}
}
void startPWM()
{
TCCR1B |= (1 << CS10); // Start Timer1
}
void stopPWM()
{
TCCR1B &= ~((1 << CS12) | (1 << CS11) | (1 << CS10)); // Stop Timer1
digitalWrite(9, LOW);
digitalWrite(10, LOW);
}