I have a Nano and is programming through the USB connector. I copied a sketch from the community and it worked fine. "Analog sampler. Trigger analog samples at a time interval selected by timer1".
This is the start code:
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("AnalogSampler started");
When i compile and load up this it produces a first line as expected: AnalogSampler started .
Then I rewrites the next code to change the mode of using the timer1.
Then the first line of the print will be: Ana?
And there will be no more output.
Welcome to the forum
Please post your complete sketch using code tags when you do
what is the code within loop() ?
This is the changed code:
// Analog sampler. Trigger analog samples at a time interval selected by Timer1
const uint32_t INTERVAL_MICROSECONDS = 40; // 25 kHz
const uint32_t CLOCKS_PER_MICROSECOND = F_CPU / 1000000ul;
const uint16_t TIMER1_TOP = 1280; //(INTERVAL_MICROSECONDS * CLOCKS_PER_MICROSECOND) - 1;
const byte MAX_SAMPLE_COUNT = 100;
volatile byte SampleCounter = 0;
volatile uint16_t SampleBuffer[MAX_SAMPLE_COUNT];
volatile uint16_t Comparev = TIMER1_TOP;
void setup() {
Serial.begin(115200);
delay(200);
Serial.println("AnalogSampler started");
// Set up the ADC to start a conversion when Timer1 overflows
ADMUX = 0;
ADCSRA = 0;
ADCSRB = 0;
DIDR0 = 0x3e; // only ch0 enabled
DDRB |= _BV(DDB5);
// Select the AVCC reference and input pin A0
ADMUX |= _BV(REFS0);
// Set ADC clock prescale.
// For full resolution (10 bits) the ADC clock must be
// lower than 200 kHz. At the expense of a few
// LSBs we can crank the ADC clock up to 1 MHz
// and get 74000 samples per second.
//#if (F_CPU > 8000000ul)
// On a 16 MHz Arduino use a prescale of 16
// The next higher available prescale is 128.
ADCSRA |= _BV(ADPS2) | _BV(ADPS0); // Prescale = 16 = 1 MHz =500kHZ
//#else
// On an 8 MHz Arduino use a prescale of 8.
// The next higher available prescale is 64.
// ADCSRA |= _BV(ADPS = 1) | _BV(ADPS0); // Prescale = 8 = 1 MHz
//#endif
// Select auto-trigger source: Begin Conversion on Timer1 Overflow
ADCSRB |= _BV(ADTS2) | _BV(ADTS0); //counter1 compareB match
// ADC Enable, Auto-trigger enable, Clear interrupt flag, Enable interrupt
ADCSRA |= _BV(ADEN) | _BV(ADATE) | _BV(ADIF) | _BV(ADIE);
// Start Timer1 overflowing every INTERVAL_MICROSECONDS
TCCR1A = 0;
TCCR1B = 0;
TIMSK1 = 0; // Disable all Timer1 interrupts
OCR1B = TIMER1_TOP; // Set INTERVAL_MICROSECONDS
// Set WGM 14 (0b1110): Fast PWM, TOP in ICR1, TOV1 at TOP
TCCR1A |= _BV(COM1B0);
TIMSK1 |= _BV(OCIE1B);
TIFR1 |= _BV(OCF1B); // Clear any pending Timer1 Overflow
// Start Timer1 with Prescale=1
TCCR1B |= _BV(CS10);
}
// ADC Conversion Complete interrupt service routine
ISR(ADC_vect) {
uint16_t val = ADC;
Comparev = Comparev + TIMER1_TOP;
OCR1B = Comparev;
// TIFR1 |= _BV(OCF1B) | _BV(TOV1); // Clear the pending Timer1 Overflow Interrupt
PORTB ^= _BV(PORTB5); //koll på sampleintervall
if (SampleCounter < MAX_SAMPLE_COUNT) {
SampleBuffer[SampleCounter++] = val;
}
}
void loop() {
if (SampleCounter == MAX_SAMPLE_COUNT) {
// All samples have been collected. The ISR won't be doing anything
// until the SampleCount is reset.
Serial.print(micros());
Serial.print(", ");
Serial.print(SampleBuffer[0]);
Serial.print(", ");
Serial.print(SampleBuffer[1]);
Serial.print(", ");
Serial.println(SampleBuffer[2]);
Serial.flush(); // Make sure all the character get sent
SampleCounter = 0;
}
}
i don't see where "ISR()" is configured as the interrupt.
i didn't think you can pass an argument to an ISR
Is not the row
ADCSRB |= _BV(ADTS2) | _BV(ADTS0); //counter1 compareB match
defining the ISR?
i don't know.
looks like you're trying to configure a timer interrupt. how does it know what code that you've written needs to be executed
ADCSRB is a register to the Analog converter, not the timer1
???
You can see for yourself by looking up the definition of the 'ISR' macro in interrupt.h.
It runs the ISR a few times before it hangs up. I can see it on port B5, only used in the IRS.
thanks for answering my question.
are the prints taking longer than acquisition of the samples?
Where do I get
the 'ISR' macro in interrupt.h. ?
If I increase the baud rate to 500000bps, it produces "AnalogSampler ?
and if I use 9600bps it comes out ??
You're already using it.
I'm using the Aurdino 1.8.19 and dont know where to get the used files .
What used files?
What did you change? You didn't post the original working code...
This is the original that works:
// Analog sampler. Trigger analog samples at a time interval selected by Timer1
const uint32_t INTERVAL_MICROSECONDS = 40; // 25 kHz
const uint32_t CLOCKS_PER_MICROSECOND = F_CPU / 1000000ul;
const uint16_t TIMER1_TOP = (INTERVAL_MICROSECONDS * CLOCKS_PER_MICROSECOND) - 1;
const byte MAX_SAMPLE_COUNT = 3;
volatile byte SampleCounter = 0;
volatile uint16_t SampleBuffer[MAX_SAMPLE_COUNT];
void setup()
{
Serial.begin(115200);
delay(200);
Serial.println("AnalogSampler started");
// Set up the ADC to start a conversion when Timer1 overflows
ADMUX = 0;
ADCSRA = 0;
ADCSRB = 0;
DIDR0 = 0;
// Select the AVCC reference and input pin A0
ADMUX |= _BV(REFS0);
// Set ADC clock prescale.
// For full resolution (10 bits) the ADC clock must be
// lower than 200 kHz. At the expense of a few
// LSBs we can crank the ADC clock up to 1 MHz
// and get 74000 samples per second.
#if (F_CPU > 8000000ul)
// On a 16 MHz Arduino use a prescale of 16
// The next higher available prescale is 128.
ADCSRA |= _BV(ADPS2) | _BV(ADPS0); // Prescale = 16 = 1 MHz
#else
// On an 8 MHz Arduino use a prescale of 8.
// The next higher available prescale is 64.
ADCSRA |= _BV(ADPS=1) | _BV(ADPS0); // Prescale = 8 = 1 MHz
#endif
// Select auto-trigger source: Begin Conversion on Timer1 Overflow
ADCSRB |= _BV(ADTS2) | _BV(ADTS1);
// ADC Enable, Auto-trigger enable, Clear interrupt flag, Enable interrupt
ADCSRA |= _BV(ADEN) | _BV(ADATE) | _BV(ADIF) | _BV(ADIE);
// Start Timer1 overflowing every INTERVAL_MICROSECONDS
TCCR1A = 0;
TCCR1B = 0;
TIMSK1 = 0; // Disable all Timer1 interrupts
ICR1 = TIMER1_TOP; // Set INTERVAL_MICROSECONDS
// Set WGM 14 (0b1110): Fast PWM, TOP in ICR1, TOV1 at TOP
TCCR1A |= _BV(WGM11);
TCCR1B |= _BV(WGM13) | _BV(WGM12);
TIFR1 |= _BV(TOV1); // Clear any pending Timer1 Overflow
// Start Timer1 with Prescale=1
TCCR1B |= _BV(CS10);
}
// ADC Conversion Complete interrupt service routine
ISR(ADC_vect)
{
TIFR1 |= _BV(TOV1); // Clear the pending Timer1 Overflow Interrupt
uint16_t val = ADC;
if (SampleCounter < MAX_SAMPLE_COUNT)
{
SampleBuffer[SampleCounter++] = val;
}
}
void loop()
{
if (SampleCounter == MAX_SAMPLE_COUNT)
{
// All samples have been collected. The ISR won't be doing anything
// until the SampleCount is reset.
Serial.print(micros());
Serial.print(", ");
Serial.print(SampleBuffer[0]);
Serial.print(", ");
Serial.print(SampleBuffer[1]);
Serial.print(", ");
Serial.println(SampleBuffer[2]);
Serial.flush(); // Make sure all the character get sent
SampleCounter = 0;
}
}