- Interesting: http://t.co/47hieivN #
- Rudolf Eb.er (R&G) http://t.co/qDKUAE3x #
- 高崎に着いたよ! #
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Recently, I needed to have a lot of digital outputs on my microcontroller. I needed more than what was available on the microcontroller and didn’t have any multiplexer nearby. After some thinking, I got the idea of using the digital pins in three states (HIGH OUTPUT, LOW OUTPUT and INPUT) instead of two (HIGH and LOW OUTPUT).
Of course, I quickly discovered that this idea is far from being an original one and is known as “charlieplexing”. Not need to go more in details as the wikipedia page has pretty much everything you need to start charlieplexing.
Thanks to charlieplexing, I could drive 8 modulated IR LEDs and 8 visible light LEDs without problem.
Powered by Twitter Tools
Setting of the registers for PCM audio on attiny85 (8MHz).
// Timer 0 for sampling rate (8kHz) TCCR0A = (1 << WGM01); // CTC mode TCCR0B = (1 << CS01); // prescaler 8, frequency is 1MHz (cpu is 8MHz) TIMSK = (1 << OCIE0A); // COMPA interrupt OCR0A=125; // 1MHz/125 = 8kHz, the sampling rate. // Timer 1 for PWM // PWM mode (250kHz) with duty cycle by OCR1A / toggle output on OC1A=PB1 / prescaler=1 (8MHz) DDRB = (1 << PB1); // PB1 as output TCCR1 = (1 << PWM1A)|(1 << COM1A1)|(1 << CS10);
Then, in the interrupt, the analog value is set through OCR1A. This is similar to reading from a wavetable in the case of DDS.
Powered by Twitter Tools
After playing a while with DDS (Direct Digital Synthesis), let’s see what we can do with PCM (Pulse-Code Modulation). Simply said, PCM is just a way to digitally encode analog signal (in our case, sound). PCM has two parameters, sampling rate and bit depth (resolution).
So what is the difference between DDS and PCM when it comes to generate sound with an AVR ? Basically nothing, as in both cases the signal is represented digitally and then a DAC (Digital Analog Converter) is used to generate the analog signal itself (for example, a sound).
The difference is mostly in the nature of the sound to be generated. PCM is used to represent any analog signal digitally. The longer the signal the more samples are necessary. In the case of AVRs, it means that the length of the signal that can be represented with PCM is rather limited as the memory is relatively small.
DDS is particularly adapted to periodic signals. That is why it is mostly used to generate waveforms. So if one wants to play sound samples (voice for example), PCM would be more adapted. If one wants to do a synthesizer, DDS is the way to go.
The other difference is that PCM has a sampling rate that can be changed to vary the pitch. While in the case of DDS , the sampling rate is basically constant. To change the frequency of a waveform, more or less samples are read but at a constant sampling rate. This technic is not adapted for PCM as for example, to read only one sample every two samples (increased frequency) means a loss of information that can make the original signal unrecognizable (especially in the case of voice).
In the case of DDS, the sampling rate is usually high (higher than the largest frequency in a typical sound signal) and thus, a single timer to generate both the sampling rate and the PWM (Pulse-Width Modulation) can be used to generate the analog signal (one cycle of PWM for one sample, the sampling rate and the PWM frequency are the same). In the case of PCM the sampling rate is usually low (a lower sampling rate means less samples per second, that is less samples in memory, but a lower sound quality) so using PWM at the same frequency that the sampling rate to generate the analog signal is not possible as one would “hear” the PWM signal. In this case two timers are necessary, one to generate the sampling rate and a second one to generate the PWM signal at a much higher frequency. That is for one sample, there will be significantly more PWM cycles. To play a PCM sound sample, you just have to encode it at a low sampling rate (8kHz for example) and with 8 bits resolution (this is the resolution of the PWM on attiny85 and a lot of other AVRs). Next time I’ll post an example of PCM code for the attiny85. In the meantime, you can check this example or this tutorial.
Powered by Twitter Tools
For my noisy dolls (Les Belles Noiseuses), I was using a slightly modified Atari Punk Console circuit. It’s nice but after building a dozen of dolls, I wanted to enlarge the variety of sounds the dolls could make.
For this, I decided to go digital and use a microcontroller (in my case an ATTINY85) instead of the previous 555 timer ICs. In addition to be able to generate more various sounds, the advantages of the ATTINY is its smaller size (8 pins instead of 14 for a 556 IC) and the need for less discrete components.
The question was then of how to generate a waveform with a microcontroller. Of course, you can easily generate a square waveform from PWM, but what if you want other waveforms (like a sine for example) ? In this case DDS (Direct Digital Synthesis) comes in handy. It is actually quite simple to implement and results are pretty nice as long as you don’t care about noisy results (which is what I’m aiming for anyway).
To show you how simple it is, here is the code to generate 4 types of waveforms. The frequency is selected with a pot and the type of waveform with a second one.
#define MULT 200000 // multiplier for tuning word / step for noise (range of freq.)
#define MMIN 2000000 // minimal value of tuning word
byte waveform=0; // waveform
unsigned long M,Mraw,C=0;
// M is the tuning word, Mraw is tuning word before processing
// C is the 32bits counter
const unsigned char sine256[] PROGMEM= { // sine wavetable
127,130,133,136,139,143,146,149,150,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,246,247,248,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,206,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,138,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,50,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,2,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,75,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124};
void setup() {
cli(); // Disable global interrupts
// use 64Mhz clock
PLLCSR= (1 << PLLE);
for(int i=0;i<100;i++); // wait a bit
PLLCSR|= (1 << PCKE);
// PB1 as output (OC1A)
DDRB = (1 << PB1);
// Overflow interrupt
TIMSK = (1 << TOIE1);
// PWM based on OCR1A / toggle output on OC1A=PB1 / prescaler=1 (64MHz)
TCCR1 = (1 << PWM1A)|(1 << COM1A1)|(1 << CS10);
sei(); // Enable global interrupts
OCR1A=0;
M=MMIN;
}
ISR(TIMER1_OVF_vect) // Interrupt Service Routine
{
switch(waveform) {
case 1: // sawtooth
OCR1A=((C+=M)>>24);
break;
case 0: // sine
OCR1A=pgm_read_byte(&sine256[((C+=M)>>24)]);
break;
case 2:// square
if(((C+=M)>>24)<128) OCR1A=0; else OCR1A=255;
break;
case 3: // random
if (C>Mraw) {
OCR1A=random(256);
C=0;
}
C+=MULT;
break;
}
}
void loop() {
Mraw=analogRead(3)*MULT;// Frequency pot
M=max(MMIN,Mraw);
waveform=floor(analogRead(0)/256); // // Waveform pot, 4 choices
}
Some comments about the code:
- MMIN gives the lower frequency you can get for a waveform (not including the random noise).
- MULT gives the highest frequency you can get as well as the steps in frequency. There is a trade-off here. Either you have a smaller range of frequencies but with finer steps or a larger range with bigger steps.
- The random noise has a higher frequency when M/Mraw is getting smaller while the other waveforms have a higher frequency when M/Mraw is getting larger.
- There is exactly one PWM cycle per sample.
- In theory, the sampling rate is 64M/256 that is approximately 250kHz. It is a bit lower because of the time needed to execute the interrupt.
- Why a 32bits counter if I use only 8bits ? It is to have a better resolution (and range) for the frequency without using floats that take to much of the CPU time.
- This is a very basic code. Each doll will have a different code with for example, random choice of the waveform, mix of waveforms, other custom waveforms defined as wavetables (instead of only a sine), other functions for the pots, …
- For the DAC, I’m using a simple RC low pass filter. It is sufficient for this application.
w/ HUH+野本直輝, いちろう, HALBACH, disk-3, 人間ドッグオーケストラ (The Ningen Dogs Orchestra), ASTRO+ROHCO, scum
人間ドッグオーケストラ は23N! + super utako + HIKOです。今回は ジャイアント人間ドッグ マサミもでるよ‼‼‼
The Ningen Dogs Orchestra is 23N! + super utako + HIKO. This time, Masami the giant ningen dog will participate too !!!!
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools
Powered by Twitter Tools