Go Down

Topic: Arduino Due and tone() (Read 10273 times) previous topic - next topic



I wanted to ask if standard tone function works on Arduino Due board? I bought Arduiono week ago, and built all the simple projects with LEDs etc. and now I wanted to use buzzer in project. I connected the circuit like in  http://arduino.cc/en/Tutorial/Tone but when I choose upload I get the message "error: 'tone' was not declared in this scope".

When I change the board to AVR (like Arduino Due) it compiles, so how can I use buzzer with my Arduino Due?



Has far has I can see, tone library is still disabled. I think you have to wait in case you don't know how to mess with timers. ;)


here's a monolithic proof-of-concept of tone()

Code: [Select]

  Melody on pin 8 of DUE



// notes in the melody:
int melody[] = { 262,196, 196, 220, 196, 0,  247, 262
  /*NOTE_C4, NOTE_G3,NOTE_G3, NOTE_A3, NOTE_G3,0, NOTE_B3, NOTE_C4*/ };

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int noteDurations[] = {
  4, 8, 8, 4,4,4,4,4 };

void setup() {

void loop() {
  // iterate over the notes of the melody:

  for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000/noteDurations[thisNote];
    tone(8, melody[thisNote],noteDuration);

    // to distinguish the notes, set a minimum time between them.
    // the note's duration + 30% seems to work well:
    int pauseBetweenNotes = noteDuration * 1.30;
    // stop the tone playing:


Tone generator
v1  use timer, and toggle any digital pin in ISR
   funky duration from arduino version
   TODO use FindMckDivisor?
   timer selected will preclude using associated pins for PWM etc.
    could also do timer/pwm hardware toggle where caller controls duration

// timers TC0 TC1 TC2   channels 0-2 ids 0-2  3-5  6-8     AB 0 1
// use TC1 channel 0
#define TONE_TIMER TC1
#define TONE_CHNL 0
#define TONE_IRQ TC3_IRQn

// TIMER_CLOCK4   84MHz/128 with 16 bit counter give 10 Hz to 656KHz
//  piano 27Hz to 4KHz

static uint8_t pinEnabled[PINS_COUNT];
static uint8_t TCChanEnabled = 0;
static boolean pin_state = false ;
static Tc *chTC = TONE_TIMER;
static uint32_t chNo = TONE_CHNL;

volatile static int32_t toggle_count;
static uint32_t tone_pin;

// frequency (in hertz) and duration (in milliseconds).

void tone(uint32_t ulPin, uint32_t frequency, int32_t duration)
const uint32_t rc = VARIANT_MCK / 256 / frequency;
tone_pin = ulPin;
toggle_count = 0;  // strange  wipe out previous duration
if (duration > 0 ) toggle_count = 2 * frequency * duration / 1000;
else toggle_count = -1;

if (!TCChanEnabled) {
TC_Configure(chTC, chNo,
TC_CMR_WAVE |         // Waveform mode
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC

chTC->TC_CHANNEL[chNo].TC_IER=TC_IER_CPCS;  // RC compare interrupt
                         TCChanEnabled = 1;
if (!pinEnabled[ulPin]) {
pinMode(ulPin, OUTPUT);
pinEnabled[ulPin] = 1;
TC_Stop(chTC, chNo);
                TC_SetRC(chTC, chNo, rc);    // set frequency
TC_Start(chTC, chNo);

void noTone(uint32_t ulPin)
TC_Stop(chTC, chNo);  // stop timer
digitalWrite(ulPin,LOW);  // no signal on pin

// timer ISR  TC1 ch 0
void TC3_Handler ( void ) {
TC_GetStatus(TC1, 0);
if (toggle_count != 0){
// toggle pin  TODO  better
digitalWrite(tone_pin,pin_state= !pin_state);
if (toggle_count > 0) toggle_count--;
} else {


May 26, 2013, 12:39 pm Last Edit: May 26, 2013, 12:42 pm by cdan Reason: 1
I have tried to change your code and configure TC0/Ch0 to use the TIOA0 pin as output for the square wave.
I have a piezo connected to Arduino PIN 2 (which, according to the mapping in http://arduino.cc/en/Hacking/PinMappingSAM3X should be PB25).

It seems that I am doing somethig wrong, since I get no output from pin 2.
If I enable the TC0_IRQn interrupt then I can see my handler being called, which means that at least the timer was configured correctly.

Can you please have a look over my code? I must have done something wrong.

I want to eliminate the need for interrupts and manual bit banging on pin 2.

Best regards,


I'll answer my own question:
In order to get your square wave out on TIOA you have to set the appropriate bits on the TC Channel Mode Register:
Code: [Select]

  TC_Configure(chTC, chNo,
       TC_CMR_WAVE |         // Waveform mode
       TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC
       TC_CMR_ACPA_SET |     // RA compare sets TIOA
       TC_CMR_ACPC_CLEAR );  // RC compare clears TIOA

This solution is much accurate than using interrupts but it has the drawback that you have to use the pin associated with the TIOA0 signal (on arduino DUE this is pin 2).

Best regards,


Aug 28, 2016, 03:05 am Last Edit: Aug 28, 2016, 03:09 am by ninja2
mantoiu, cdan, or anyone...

where can I find the documentation that details all the Timer/Counter programming names (like TC_CMR_WAVSEL_UP_RC) and functions (like TC_SetRC)

I have looked for these in the Atmel Software Framework, and the datahseet for ARM Cortex-M3 but no luck so far.



Aug 28, 2016, 12:39 pm Last Edit: Aug 28, 2016, 12:50 pm by GregorioW


Today at 12:32 am Last Edit: Today at 12:35 am by ninja2
Thanks GregorioW. Those links answer some of my queries, but there's too much detail !

For example in components_tc.h I can now see that TC_CMR_WAVSEL_UP_RC = 0x2u << 13 (woohoo!) but what I really need is a document that provides an explanation, or a bridge, between the datasheet and all these components. Also I couldn't find anything for functions, like TC_SetRC?

These may be somewhere in those GitHub repositories, but I'm not that familiar with finding my way around there yet.

Maybe I'm after a SAM programmers guide?

Go Up

Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

via Egeo 16
Torino, 10131