News:

Let's find out together what makes a PIC Tick!

Main Menu

Generate a 1 Khz sine wave with the Freqout

Started by Giuseppe, Aug 16, 2022, 10:07 PM

Previous topic - Next topic

Giuseppe

Top204 i just tried your listing on a 12f1822 and the result looks good :https://ibb.co/BgnMSK0
Since the 12f1822 internal oscillator reaches 32Mhz I wanted to modify the program's income in:
DDS_SineWave (500, 1000)
Surely I was wrong with the Freqout, since I was trying with a 12f1501 which has a maximum internal oscillator at 16Mhz.
Out of curiosity I want to try again with the 12f1822 which reaches up to 32 Mhz.
Thanks again Top204

top204

I was experimenting last night with the PIC16F1823 device, which is essentially the same as the PIC16F1822 device, and came up with the program below that uses the 5-bit DAC peripheral to generate the sine wave, and the results were actually remarkable for such a small sine table and a low resolution DAC:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' DDS algorithm for generating a sinewave from the 5-bit DAC on a PIC16F1823 device.
' Written for the Positron8 compiler by Les Johnson.
'
' A simple low pass filter circuit, as shown below, can be used to get a sine waveform out.
' The filter's components will need to be changed for different frequency sine waves.
'
'         |     1K
' PORTA.0 |----/\/\/\-----o-----> Output
'         |               |
'         |             __|__
' PORTA.1 |--- +5V      _____ 10nF
'         |               |
'         |               |
'         |             -----
'                        ---  Gnd
'
    Device = 16F1823                                        ' Tell the compiler what device it will compile for
    Declare Xtal = 16                                       ' Tell the compiler what frequency the device will be operating at

'-----------------------------------------------------------------------------------------
' The main program starts here
'
Main:
    Setup()                                                 ' Setup the program
    DDS_SineWave(1000, 10000)                               ' Output a 1 KHz sinewave for approx 10 seconds

'-----------------------------------------------------------------------------------------
' Generate a sinewave signal from the 5-bit DAC pin
' Input     : pFreq holds the DDS value for the frequency to generate
'           : pDuration holds the approximate time (in ms) for the waveform to be outputted
' Output    : None
' Notes     : None
'
Proc DDS_SineWave(pFreq As Dword, pDuration As Dword)
    Dim lAccum As Long                                      ' Accumulator for the DDS
    Symbol cDivisor = (((_xtal / 4) * 1000000) / 2240.5)    ' Create a divisor based upon the device's operating frequency and the loop speed
    Symbol cMult = (65536.0 / cDivisor)                     ' Create a floating point multiplier constant
'
' Sine wave data for the 5-bit DAC
'
    Dim SineTable As Flash8 = {16, 17, 19, 20, 21, 23, 24, 25,
                               26, 27, 28, 29, 30, 30, 31, 31,
                               31, 31, 31, 30, 30, 29, 28, 27,
                               26, 25, 24, 23, 21, 20, 19, 17,
                               16, 14, 12, 11, 10, 08, 07, 06,
                               05, 04, 03, 02, 01, 01, 00, 00,
                               00, 00, 00, 01, 01, 02, 03, 04,
                               05, 06, 07, 08, 10, 11, 12, 14}

    pDuration = pDuration * 114                             ' Calculate the duration in approx milliseconds
    pFreq = pFreq * cMult                                   ' Calculate the value for the DDS based upon the frequency required
    lAccum = 0                                              ' Reset the accumulator
    DACCON0bits_DACEN = 1                                   ' Enable the DAC
    Do                                                      ' Create a loop
        lAccum = lAccum + pFreq.Long                        ' Accumulation of the frequency
        DACCON1 = CRead8 SineTable[lAccum.Byte2 & $3F]      ' Divide output by 65536 and keep the first 6 bits
        Dec pDuration                                       ' Decrement the duration counter
        If pDuration = 0 Then                               ' Has the duration reached 0?
            DACCON0bits_DACEN = 0                           ' Yes. So disable the DAC
            ExitProc                                        ' Exit the procedure
        EndIf
    Loop
EndProc

'-----------------------------------------------------------------------------------------
' Initialise the 5-bit DAC peripheral on a PIC16F1823 device
' Input     : None
' Output    : None
' Notes     : Disables the DAC for now
'
Proc DAC_Init()
    DACCON0 = %00100100
    DACCON1 = 0
    ANSELA.0 = 1                      ' Make the DAC pin analogue
    ANSELA.1 = 1                      ' Make the +Vref pin analogue
    PinInput PORTA.0                  ' Make the DAC pin an input
    PinInput PORTA.1                  ' Make the +Vref pin an input
EndProc

'-----------------------------------------------------------------------------------------
' Setup the program
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    Osc_16MHz()                                         ' Setup the device to operate at 16Mhz with its internal oscillator
    DAC_Init()                                          ' Initialise the DAC
EndProc

'-----------------------------------------------------------------------------------------
' Setup the PIC16F1823 to use the internal oscillator at 16 MHz
' Input     : None
' Output    : None
' Notes     : None
'
Proc Osc_16MHz()
    OSCCON  = 0b01111010
    OSCTUNE = $00
    BORCON  = $00
EndProc

'-----------------------------------------------------------------------------------------
' Setup the config fuses for the internal oscillator on a PIC16F1823 device
'
    Config1 FOSC_INTOSC, WDTE_OFF, MCLRE_ON, CP_OFF, BOREN_OFF
    Config2 PLLEN_OFF, LVP_OFF, WRT_OFF, STVREN_OFF

The line of code:

Symbol cDivisor = (((_xtal / 4) * 1000000) / 2240.5)    ' Create a divisor based upon the device's operating frequency and the loop speed

will need to be tweaked a bit to get the frequency as exact as the parameter's value, because the frequency of the DDS relies on the loop iteration timing, and that can change slightly if it is in a program where the variables are not all in the same RAM space etc... The frequency calculation could also be changed to use integer only values, or a specific value placed in the DDS procedure for a particular frequency required, if the frequency is not to be passed to the procedure.

And the line of code:

pDuration = pDuration * 114                            ' Calculate the duration in approx milliseconds

will need to be tweaked if there are changes made within the loop for the time the waveform will be outputted for.

Here is a good site for generating the sine table data that can be adapted for programs:

Sine-Generator-Calculator

Below is a screenshot of the above program being simulated and generating a 1 KHz sine waveform:

DDS Sinewave Generator with 5-bit DAC.jpg





david

That's a great application for the 5 bit DAC that's inside many even basic PIC micros.  I've rarely used it but this is ideal for a simple sinewave generator.  You're on a bit of a roll here Les.....

I believe the first use of a Pic for DDS was a project written by Tom Napier in Nuts and Volts magazine back about 2003 (ish) He referred to it as a Numerically Controlled Oscillator (now found in many PICs).  I've tried to locate the article but to no avail and it was for interest only.
No doubt you will want to try a triangle wave table, sawtooth, square and I even saw one application with simulated ECG waveforms. (Why?)

Cheers,
David 

top204

#23
I did those types of waveforms in my Commodore 64 computer, SID chip emulator about 11 years ago. It also uses a form of DDS for the three channel audio outputs, but I did not realise I was designing code for the buzz word "DDS" at the time. It was just a natural way of producing different frequencies from a wave table. :-) The SID chip was, and still is, a wonderfully designed sound chip and has stood the test of time, and some of the creators of the music for them back in the 1980s were true creative geniuses. :-)

Simple PIC SID Chip Emulator

I still play some the game tunes I adapted for it on a breadboard, just for nostalgia. Here is one of my favourites, played from the PIC SID emulator chip through a simple low pass filter and recorded on the PC:

BombJack emulated SID chip tune

Not a bad sound is it, for a single 8-bit device written in BASIC and using PWM as the DAC?

I have created a better SID player with a dsPIC33 device that actually plays SID files and emulates a 6502 microprocessor, with Positron16. But on the 8-bit device at the time I created the original emulator, I could never get the filters correct, so I did not add them to it. Maybe one day, when I am more settled, I will add a simple IIR filter to the 8-bit emulator as well, to make it fully emulate the SID chip (easier said than done!). :-)

John Lawton

If you have enough port lines an alternative to an internal DAC is to use a weighted resistor network, then you can have more than 5 bit resolution. The limitation with this is on the maximum frequency that can be generated due to the maximum PIC clock speed, although they can be overclocked to some extent as we know...

david

Nothing wrong with that sound - quite impressive for an 8 bit micro.   Kids dance to stuff that sounds worse than that!

David