Go Down

Topic: Creating an LFO / Timer question (Read 1 time) previous topic - next topic

yan_g

Feb 18, 2012, 01:53 am Last Edit: Feb 18, 2012, 09:58 pm by yan_g Reason: 1
Hello,

I'm trying to find how to generate an LFO using a PWM output, I searched the web without success though there are innumerable examples, I only found either sketches using delay() which I want to avoid, or stuff way too complicated for my noobish understanding. I chose to post here rather than in the audio forum because it seemed a rather basic coding thing.

I have no idea how to proceed... The method I tried seems to be completely wrong (waiting for a number of milliseconds between each output value in/decrementation, which makes a 511ms duty cycle for a complete sweep up and down through all 256 values when the delay is 1ms).

How should this be done instead? (Besides I want to be able to output more waveforms than stupid triangles or sawteeth)

Any help appreciated!

Thanks!

Magician

Use a timer, basically it almost like you did, only more precision with interrupt driven increment in PWM. You can generate a sine if you feed linearly changing value to sin(2*pi* i/256) function (math.h), or check on a link how it's done with LUT:
http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/

yan_g

Thanks, I searched the web for timer tutorials and found this interesting blog post: http://letsmakerobots.com/node/28278

I loaded that sketch:
Quote
#define ledPin 13

void setup()
{
  pinMode(ledPin, OUTPUT);
 
  // initialize timer1
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;

  OCR1A = 31250;            // compare match register 16MHz/256/2Hz
  TCCR1B |= (1 << WGM12);   // CTC mode
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  interrupts();             // enable all interrupts
}

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
  digitalWrite(ledPin, digitalRead(ledPin) ^ 1);   // toggle LED pin
}

void loop()
{
  // your program here...
}


I played with OCR1A to change frequency, but I really don't get what this means (among other lines):

Code: [Select]
TCCR1B |= (1 << WGM12);

I know nothing about bitwise operators so I searched again and I found out it's like:

Code: [Select]
TCCR1B = TCCR1B | (1 << WGM12);

Now I'm wondering what "1 << WGM12" means... I think I understand this:
A = 0011 1100
B = A << 2
which makes B = 1111 0000, but in this example A is a series of 0s and 1s and the shifter is a decimal, but it isn't the case in the code line, which is confusing me. Can anyone help me understand that code?

Thanks!

yan_g

Ok I finally understood that WGM12 *is* a decimal and equals 3 (just printed it out via serial), but where does this 3 come from?

Is

Code: [Select]
TCCR1B |= (1 << WGM12);

the same as

Code: [Select]
TCCR1B |= 1000;

?

Magician

Visit Atmel.com and download datasheet for your uCPU (depends on board, for UNO - AtMega328). There is an extract, which show 16! different modes of timer settings. WGM12 is a bit, or position in the register, it's not "3" or number, rather a "switch" in line of 16 others switches, which you could turn on or off. 
Quote
Mode WGM13 WGM12 WGM11 WGM10
           (CTC1) (PWM11) (PWM10)
Timer/Counter Mode of TOP Update of TOV1 Flag
Operation OCR1x at Set on
0 0 0 0 0 Normal 0xFFFF Immediate MAX
1 0 0 0 1 PWM, Phase Correct, 8-bit 0x00FF TOP BOTTOM
2 0 0 1 0 PWM, Phase Correct, 9-bit 0x01FF TOP BOTTOM
3 0 0 1 1 PWM, Phase Correct, 10-bit 0x03FF TOP BOTTOM
4 0 1 0 0 CTC OCR1A Immediate MAX
5 0 1 0 1 Fast PWM, 8-bit 0x00FF BOTTOM TOP
6 0 1 1 0 Fast PWM, 9-bit 0x01FF BOTTOM TOP
7 0 1 1 1 Fast PWM, 10-bit 0x03FF BOTTOM TOP
8 1 0 0 0 PWM, Phase and Frequency ICR1 BOTTOM BOTTOM
          Correct
9 1 0 0 1 PWM, Phase and Frequency OCR1A BOTTOM BOTTOM
          Correct
10 1 0 1 0 PWM, Phase Correct ICR1 TOP BOTTOM
11 1 0 1 1 PWM, Phase Correct OCR1A TOP BOTTOM
12 1 1 0 0 CTC ICR1 Immediate MAX
13 1 1 0 1 (Reserved) - - -
14 1 1 1 0 Fast PWM ICR1 BOTTOM TOP
15 1 1 1 1 Fast PWM OCR1A BOTTOM TOP

yan_g

Where do I learn about all this? I can't read a datasheet, I don't even know what a register is for instance...

Isn't there a way to do it without using a timer?

jfenwick

I found this to be a good tutorial on AVRs:
https://sites.google.com/site/qeewiki/books/avr-guide

Magician

#7
Feb 19, 2012, 08:19 pm Last Edit: Feb 19, 2012, 08:23 pm by Magician Reason: 1
You don't have to study all registers, following basic motto of C++ language "use a library and save a time". In this circumstances, libraries are: http://arduino.cc/en/Reference/Libraries
Or you can copy-paste code linked in reply #1.
What is your spec for LFO, freq. range, stability, distortion?
 

yan_g


I found this to be a good tutorial on AVRs:
https://sites.google.com/site/qeewiki/books/avr-guide

The table of contents looks like my last night's dream come true! Thanks!


You don't have to study all registers, following basic motto of C++ language "use a library and save a time". In this circumstances, libraries are: http://arduino.cc/en/Reference/Libraries
Or you can copy-paste code linked in reply #1.
What is your spec for LFO, freq. range, stability, distortion?

I found this library as I was searching for tutorials about timers: http://arduino.cc/playground/Code/Timer1
I thought I might give it a try.

Actually what I want to do is generate waveforms and send them over MIDI, and beeing able to change the frequency/amplitude with sensors. Ideal frequency range would be 2 to 80Hz (I'm that bad) though I might consider a lower high end (and a higher low end) if the tweaking can't be precise enough. I was thinking about generating CV curves as well, which actually seems simpler but I really want to send them over MIDI.

yan_g

Timers seem a little difficult for me to master quickly so I thought I'd focus on the MIDI communication and sensors, which is essential to my project, and reprogram the AVR later when I learn more about timers, to add the LFO functions.

I need to know one important thing before I start thinking more seriously about the features of my controller: can I use the PWM outputs to dim LEDs if I use timers? If I understood correctly, I can't use pins 9 & 11 when I'm using timer1, am I right?

Thanks!

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!

Arduino
via Egeo 16
Torino, 10131
Italy