Hi,
I would like to be able to control the amplitude of a sine wave based on the position of a user controlled potentiometer. My system will be measuring the voltage of a couple other analog inputs, and hence I thought a good way to go about doing this was through an interrupt that would detect a change in position on the potentiometer.
I was wondering if this would be a good way to do this, or is there a better way? (This is my first time on the arduino due, and my first time really digging deep into a micro-controllers documentation, so I am not aware of all the nuances)
Note that the code below is not my full project, but simply a file used to test this concept out, additionally, the current code aims to pulse an LED when a threshold is reached (again simply to test the concept out).
My goal of the code below was to trigger a pulse when the pot was above or below a certain bound, and then reset the bound once the previous bound was reached (ex. first bound 0-1000 once 1000 is passed the new bound is between 1000-2000 etc. nothing should happen between the upper and lower bound values)
I have used this form post as a baseline for my code below as well: https://forum.arduino.cc/index.php?topic=482205.0
I am using an Arduino Due board.
I hope that makes sense. If not I can try to extrapolate more.
Thanks,
-H
/*
Simple Waveform generator with Arduino Due
* connect two push buttons to the digital pins 2 and 3
with a 10 kilohm pulldown resistor to choose the waveform
to send to the DAC0 and DAC1 channels
* connect a 10 kilohm potentiometer to A0 to control the
signal frequency
*/
#include "Waveform.h"
#define oneHzSample 1000000/maxSamplesNum // sample for the 1Hz signal expressed in microseconds
volatile int wave0 = 0;
int i = 0;
int sample;
int amplitude;
int val;
void setup() {
Serial.begin(9600);
pinMode(DAC0,OUTPUT);
pinMode(DAC1,OUTPUT);
pinMode(A0,INPUT);
pinMode(3,OUTPUT);
analogWriteResolution(12); // set the analog output resolution to 12 bit (4096 levels)
analogReadResolution(12); // set the analog input resolution to 12 bit
// attachInterrupt(val, poto, CHANGE); // Interrupt attached to the button connected to pin 2
pmc_enable_periph_clk(ID_ADC); // To use peripheral, we must enable clock distributon to it
adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST); // initialize, set maximum posibble speed
adc_disable_interrupt(ADC, 0xFFFFFFFF);
adc_set_resolution(ADC, ADC_12_BITS);
adc_configure_power_save(ADC, 0, 0); // Disable sleep
adc_configure_timing(ADC, 0, ADC_SETTLING_TIME_3, 1); // Set timings - standard values
adc_set_bias_current(ADC, 1); // Bias current - maximum performance over current consumption
adc_stop_sequencer(ADC); // not using it
adc_disable_tag(ADC); // it has to do with sequencer, not using it
adc_disable_ts(ADC); // disable temperature sensor
adc_disable_channel_differential_input(ADC, ADC_CHANNEL_7);
adc_configure_trigger(ADC, ADC_TRIG_SW, 1); // triggering from software, freerunning mode
adc_disable_all_channel(ADC);
adc_enable_channel(ADC, ADC_CHANNEL_7); // one channel enabled (pin A0 on arduino due)
ADC->ADC_EMR = ADC_EMR_CMPMODE_OUT
| ADC_EMR_CMPSEL(7) ;
ADC->ADC_CWR = ADC_CWR_HIGHTHRES(1000) | ADC_CWR_LOWTHRES(0); // Compare with a window
ADC->ADC_IER=ADC_IER_COMPE; // IER = interrupt enable register
ADC->ADC_IDR=~ADC_IER_COMPE; // IDR = interrupt disable register
NVIC_EnableIRQ (ADC_IRQn) ; // enable ADC interrupt vector
adc_start(ADC);
}
void loop() {
// Read the the potentiometer and map the value between the maximum and the minimum sample available
// 1 Hz is the minimum freq for the complete wave
// 170 Hz is the maximum freq for the complete wave. Measured considering the loop and the analogRead() time
//sample = map(analogRead(A0), 0, 4095, 0, oneHzSample);
//sample = constrain(t_sample, 0, oneHzSample);
// amplitude = analogRead(A0);
//
// if(amplitude < 820){val = 10;}
// else if (amplitude >= 820 && amplitude < 1640){val = 20;}
// else if (amplitude >= 1640 && amplitude < 2460){val = 40;}
// else if (amplitude >= 2460 && amplitude < 3280){val = 60;}
// else{val = 100;}
//
//
// Serial.print(val);
// Serial.print(", ");
// Serial.println(amplitude);
// analogWrite(DAC1, waveformsTable[wave0][i] / val); // write the selected waveform on DAC0
//
//
// i++;
// if(i == maxSamplesNum) // Reset the counter to repeat the wave
// i = 0;
//
// delayMicroseconds(oneHzSample/60); // Hold the sample value for the sample time
}
void ADC_Handler (void)
{
ADC->ADC_ISR; // Read and clear status register
int newThres = ADC->ADC_CDR[7]; //store the adc's read value to use for the next threshold value
REG_PIOC_SODR |= (0x01 << 28); //debug led
ADC->ADC_EMR = ADC_EMR_CMPMODE_OUT //set mode to window threshold
| ADC_EMR_CMPSEL(7) ; //on A0
if(newThres > 3095){newThres = 3095;} //define upper bound
else if(newThres < 1000){newThres = 1000;} //define lower bound
ADC->ADC_CWR = ADC_CWR_HIGHTHRES(newThres + 1000) | ADC_CWR_LOWTHRES(newThres); //indicate new threshold value that must be surpassed in order to trigger the interrupt again
REG_PIOC_CODR |= (0x01 << 28);
}