If I want to send out say, 10 bit data serially via shiftOut() (To a shift register), how can I make sure that the data is sent out at a precise frequency?
I am guessing that if I do it in loop() with delay*() calls, it won't be accurate? Will I have look into using a timer?
The frequency I am interested is in the audio range: 20-20,000 Hz.
Shift registers work in groups of 8, check that you can shift out 10 bits.
audio range: 20-20,000 Hz.
I don't think you will be able to up date a 10 bit sample that fast. I assume you are sending it to a D/A converter.
The way to send out data precisely is to have an interrupt based on a timer and have the interrupt service routine send out the data.
I assume you want to send out audio samples. Please be aware that the amount of memory the arduino has is limited for this sort of thing.
I use the TimerOne library myself which is nice and simple to use. However, for very high frequencies you'd probably need to do direct port manipulation. Like Mike says, it sounds like the frequency you are thinking about would be well above the Arduino's capabilities. Maybe a few thousand Hz tops, but I may be wrong.
Shift registers work in groups of 8, check that you can shift out 10 bits.
I was thinking of using 2 x 74HC595 8-bit shift registers, I thought I'd shift out 16 bits via 2 calls to shiftOut() and ignore the higher order bits.
Mike MC:
I use the TimerOne library myself which is nice and simple to use. However, for very high frequencies you'd probably need to do direct port manipulation. Like Mike says, it sounds like the frequency you are thinking about would be well above the Arduino's capabilities. Maybe a few thousand Hz tops, but I may be wrong.
Is there a standard way of replacing shiftOut() with port manipulation calls?
Despite the limitations, I thought I'd give this a try. If I can get something going, I would consider moving to the ATMega644 based Sanguino.
It shouldn't be out of the question for speed -- 10 bits @ 20 kHz is still 80 cycles per bit and that really ought to be enough. Coding in straight C rather than in the Arduino language may be required -- not sure of how much of a pig the ShiftOut() library is.
If you're using 595s, the contents of the shift register only get transferred to the output latches on a rising edge applied to RCK (pin 12). Therefore, if you connect pin 12 of your 595s to one of the timer output pins, you can cycle its output only on your desired frequency and shift in the data more or less at leisure.
Also, if you end up interfacing directly to the shift registers rather than using ShiftOut(), you can only shift the ten bits you care about and ignore the top six bits. If you take a look at the internal logic diagram of the 595, you'll see why this is. On each cycle of the SCK pin, each cell reads in the output of the cell before it (or the input pin). In this way, a bit shifted in to the input pin gets shifted one cell along for each cycle of SCK. If you do it ten times to a series-connected pair of 595s, you have put values in the low 10 bits of your output and not spent the time to shift out 6 zeroes you really don't care about.
It shouldn't be out of the question for speed -- 10 bits @ 20 kHz is still 80 cycles per bit and that really ought to be enough...
I am trying to send a PCM signal, so to support the full audio range, I'd try for 44,100 Hz. But I could do with much less to start with.
If you're using 595s, the contents of the shift register only get transferred to the output latches on a rising edge applied to RCK (pin 12). Therefore, if you connect pin 12 of your 595s to one of the timer output pins, you can cycle its output only on your desired frequency and shift in the data more or less at leisure.
I am not sure if I fully understand the above. Is that assuming you can shift out much faster than the frequency at which you need to update pin 12? Or should I have 2 timers?
Also, if you end up interfacing directly to the shift registers rather than using ShiftOut(), you can only shift the ten bits you care about and ignore the top six bits...
I am trying to send a PCM signal, so to support the full audio range, I'd try for 44,100 Hz. But I could do with much less to start with.
That might start to be a bit of a problem -- that cuts the number of cycles per bit down to ~36, and that might get a little tight since the bit shift itself consumes ~4 cycles (coding in C and optimizing your data structure), unless you are very clever. Depends on what else you expect it to do, of course.
I am not sure if I fully understand the above. Is that assuming you can shift out much faster than the frequency at which you need to update pin 12? Or should I have 2 timers?
Yes, you can shift data in much faster than you need to update the output -- up to the maximum rate you can push data out of the Arduino. However, SCK shouldn't be hooked up to a timer; you should control it as part of your data shifting. Just use one timer, hooked to RCK; that will give you the ability to precisely control the output frequency without imposing that requirement too heavily on the rest of your code.