Outputing 80 kHz from Arduino UNO

Hi everyone,

My name is Aneel Devaraju. I am working on a Senior Design project at University of North Texas, USA.

This project is where I and another person build an inductive charger which gives maximum results, while using minimum power.

We are using the Arduino UNO, Rev 3 MCU for this project.

We initial found a code where we can changed the UNO frequency output from 40kHz to any frequency higher then 40. The original code is in the website below:
http://www.fiz-ix.com/2012/01/how-to-configure-arduino-timer-2-registers-to-drive-an-ultrasonic-transducer-with-a-square-wave/
(This is listed to source the person of the original code; my partner and I DO NOT want ourselves to get in trouble)

Our code below is a modified version of the code to suit our pruposes:

// constants won't change. Used here to 
// set pin numbers:
const int ledPin =  13
;      // the number of the LED pin

// Variables will change:
int ledState = LOW;             // ledState used to set the LED
long previousstate = 0;
long interval =400;
void startTransducer()
{
  TCCR2A = _BV(COM2A0) | _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(WGM22) | _BV(CS20);
  OCR2A = B10010000; // 400, so timer2 counts from 0 to 400 (400 cycles at 16 MHz)
}

void setup()
{
pinMode(ledPin, OUTPUT);
startTransducer();
}

void loop()
{
    // here is where you'd put code that needs to be running all the time.

  // check to see if it's time to blink the LED; that is, if the 
  // difference between the current time and last time you blinked 
  // the LED is bigger than the interval at which you want to 
  // blink the LED.
 unsigned long currentstate = OCR2A;
 if(currentstate=110) {
   //previousstate=currentstate;
 

  // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
}}

We started the long interval with 99, then went to, 100, then 110 (these values are the number of cycles)

For a 40kHz frequency, we know that it requires 200 cycles to produce that frequency. So what I did was that in order to produce an 80kHz frequency, I calculated that 400 cycles would be needed. However, I have learned that 400 cycles would give us 1/2 of 40kHz.

I tested the above code, and somehow it gives an output of 90kHz, instead of 80kHz. (I tested the code with 99,100,110 cycles , and still we result an output of 90 kHz, instead)

Please review the above code and let me know as soon as possible with what is wrong in the syntax of the code. Thanks.

BR,

Aneel Devaraju

This whole section is slow

if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);

Use direct port manipulation and speed it up. LEDpin on 13 is PortB, bit 5, so:

PINB = 0b00100000; // writing 1 to an input pin toggles the output pin

Please do not use "B10010000", use "400" or "interval".

I'm very curious what the transducer is, and what the led is for.
Do you want to blink a led with 80kHz ? or do you want a PWM signal at 80kHz for the led ?

The ATmega328p microcontroller on the Arduino Uno board can do a lot of PWM things. That might even be the most complicated thing of the microcontroller, because there are so many options and possibilities for PWM.

Are you trying to write 400 to Timer2 register? 8-bits register?

  OCR2A = B10010000; // 400, so timer2 counts from 0 to 400 (400 cycles at 16 MHz)

Change preselector, to run at slower speed.

Hi everyone,

Thanks for all the suggestions.

@Magician: Thanks...I think we are trying to run the UNO at a faster speed (the goal of our project is to give out maximum output over shorter time, with minimum input. I'll be changing the preselector to give a faster speed.

@Caltoa: Thanks for suggesting me to use "400" or "interval", instead of "B10010000", . I think it might ease the coding. I'll test it out. Also, I was just wanting to toggle Pin13 at 80 kHz. And the transducer did not necessarily mean much to us. As I mentioned we were using the websites code and modified it for the project purposes.

@CorssRoads: Thanks for suggesting the one line code. that also might help us in coding.

I welcome all suggestions for the code. Thanks.

BR,

Aneel Devaraju

Hmm... sadly, the Tone library is only rated to go up to about 65.6kHz with a 16MHz clock. Because that would be a very simple way to do this. If you changed the clock to 20MHz, that would mean the max would be about 82kHz.

http://arduino.cc/en/Reference/Tone

https://code.google.com/p/rogue-code/wiki/ToneLibraryDocumentation#Ugly_Details

No idea if a 32 bit Arduino/variant like the Due or Teensy 3 would make a difference with Tone, but I'd think you'd not be bumping the limits with one of those as compared to an 8 bit 16MHz Arduino vs >=48MHz 32 bit ARM Cortex processor. The Teensy 3.1 is only $20.

The Teensy 3.0/3.1 have a PWM that is settable to 93.76kHz and still have 9 bits of resolution when used at 48MHz or 96MHz.

https://www.pjrc.com/teensy/td_pulse.html

I know toneAC can go higher.
And toneAC uses two pins, but you can use just one.
http://playground.arduino.cc/Code/ToneAC

Frequency limit: Google Code Archive - Long-term storage for Google Code Project Hosting.
It says 2.6MHz ? !

Wow!

Hi everyone,

Thanks for suggesting. Sorry for the late response to messages as I was a bit busy.

Let me test all the suggestions you all have given me.

Then I'll give the results within 2 weeks time.

Thanks.

BR,

Aneel

CrossRoads:
This whole section is slow

if (ledState == LOW)

ledState = HIGH;
    else
      ledState = LOW;

// set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);




Use direct port manipulation and speed it up. LEDpin on 13 is PortB, bit 5, so:


PINB = 0b00100000; // writing 1 to an input pin toggles the output pin

How did you figure out that LEDpin on 13 is that? Is there a schematic that describes each pin, such as pin 10? Please respond as soon as possible? Thanks.

BR,

Aneel

if(currentstate=110)

AWOL:

if(currentstate=110)

Yes I have that line. I just want to change the output pin from 13 to 10.

That's why I asked how CrossRoads got this:

PINB =0b00100000;

I was pointing that line out for a very good reason.
Can you see what it is?

The schematic for any board can be found on the products page.

Writing a 1 to a bit in the input registers causes the output to toggle.
From 14.1 in the '328P datasheet:
"Three I/O memory address locations are allocated for each port, one each for the Data Register – PORTx, Data Direction Register – DDRx, and the Port Input Pins – PINx. The Port Input Pins I/O location is read only, while the Data Register and the Data Direction Register are read/write. However, writing a logic one to a bit in the PINx Register,
will result in a toggle in the corresponding bit in the Data Register."

A common mistake:
if(currentstate=110)

needs == for comparisin. Single = assigns a value.

CrossRoads:
The schematic for any board can be found on the products page.

Writing a 1 to a bit in the input registers causes the output to toggle.
From 14.1 in the '328P datasheet:
"Three I/O memory address locations are allocated for each port, one each for the Data Register – PORTx, Data Direction Register – DDRx, and the Port Input Pins – PINx. The Port Input Pins I/O location is read only, while the Data Register and the Data Direction Register are read/write. However, writing a logic one to a bit in the PINx Register,
will result in a toggle in the corresponding bit in the Data Register."

A common mistake:
if(currentstate=110)

needs == for comparisin. Single = assigns a value.

Thank you CrossRoads. I'll check on that and make the corrections. I'll check the diagrams on the website.

The = vs == is a correction.

Using PINx = value; is just another way of changing the output bit.

There's also this software name to pins description from the pins_arduino.h file:

//
//                  +-\/-+
//            PC6  1|    |28  PC5 (AI 5)
//      (D 0) PD0  2|    |27  PC4 (AI 4)
//      (D 1) PD1  3|    |26  PC3 (AI 3)
//      (D 2) PD2  4|    |25  PC2 (AI 2)
// PWM+ (D 3) PD3  5|    |24  PC1 (AI 1)
//      (D 4) PD4  6|    |23  PC0 (AI 0)
//            VCC  7|    |22  GND
//            GND  8|    |21  AREF
//            PB6  9|    |20  AVCC
//            PB7 10|    |19  PB5 (D 13)
// PWM+ (D 5) PD5 11|    |18  PB4 (D 12)
// PWM+ (D 6) PD6 12|    |17  PB3 (D 11) PWM
//      (D 7) PD7 13|    |16  PB2 (D 10) PWM
//      (D 8) PB0 14|    |15  PB1 (D 9) PWM
//                  +----+
//
// (PWM+ indicates the additional PWM pins

None is hard to find if you don't mind poking into files.

CrossRoads:
The = vs == is a correction.

Using PINx = value; is just another way of changing the output bit.

Cool thanks.