- Published: Thursday, 10 June 2010
- Written by Jon Chandler
- Hits: 11762
A square wave generator can be handy for simulating sensors and providing an input to a micro-controller. This signal generator can be adjusted from 10 Hz - 10 kHz, with an adjustable duty cycle from 1 to 99 percent.
Theory of Operation
There are a variety of methods that can be used to generate a string of pulses. Among the easiest to understand is based on delay statements. Turn an output on for a period of time, and then turn it off for a period of time. If these two periods are equal, the result will be a square wave with a 50% duty cycle. The down side of this method is that the controller is always occupied waiting to change state, and can't do anything else while an output is being generated.
This is the method that has been used here. The main program loop turns a port pin on, and at a prescribed time later, turns it off in an endless loop. To this simple loop, 2 "if-then" statements have been added to check if a switch is pressed, in which case, a subroutine is called to set frequency and duty cycle parameters. If you examine the code, you'll notice one of these if-then statements occurs in the "on" part of the loop, and one occurs in the "off" part of the loop. This has been done to keep the "delay" caused by checking the port pin symmetric in both parts of the loop. These if-then statements don't require much time to execute. Allowing 2 µsec for each of these subroutines provides fairly accurate frequency results.
The period of a waveform or the time for one complete cycle, is equal to 1/frequency of the signal. For a 10 kHz signal, the period is 100 µsec. For a 50 Hz signal, it's 20,00 µsec.
The duty cycle is the percentage of time a signal is high during each cycle. A duty cycle of 0 means it's a 0 volt DC signal. 50% is a symmetric square wave. a duty cycle of 99% means the signal is at its positive potential 99% of the time, and 0 for 1% of the time.
Multiplying the duty cycle x the period yields the time for the output to be on. The remainder of the period the output is off.
When a push button is pressed, the subroutine to set the frequency and duty cycle is called. The subroutine sends a message out via the UART, asking first for frequency followed by duty cycle. Error-checking is done to see that the input value is a valid integer number in the operating range - 10 Hz - 10 kHz for frequency and 1 - 99 for duty cycle. Additionally, just pressing [Enter] keeps the previous value. Note that this subroutine preempts generating the signal.
The hardware for this signal generator is non-critical. I built the signal generator around a TAP-28 board with an 18F242 controller and a 20 MHz crystal. The hardware is pretty simple and any 18F-series part should work fine.
PortC.2 is used for the output. S2 on PortB.4 is used to exit the main program loop for setting the parameters. The PIC's hardware USART is used to communicate via the Tx and Rx pins to the PC using the PICkit 2 UART tool. The TAP-28 is powered by the PICkit 2.
This signal generator is a handy tool of reasonable accuracy. It's low cost and if a USB-UART cable was used to replace the PICkit 2 interface, it would be a nice low-cost addition to the electronics bench. On the other hand, the software will run on most PIC hardware with only a couple minor changes, so it could be loaded onto a handy dev board when it's needed.
The picture below is the interface shown on the PICkit 2 UART tool screen. I've input a frequency of 1000 Hz. My trusty Fluke 45 benchtop meter reads 1001.2 Hz. Close enough for me!
The traces below were made with the PICKit 2 logic analyzer.
I believe they're pretty self-explanatory.
Finally, the revised, working code.