![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Function Generator and Oscilloscope
Dependencies: C12832_lcd DebounceIn mbed
Diff: main.cpp
- Revision:
- 3:920cc6573be0
- Parent:
- 2:218abf68fe93
- Child:
- 4:7340e7a6eb14
diff -r 218abf68fe93 -r 920cc6573be0 main.cpp --- a/main.cpp Sat May 24 22:45:38 2014 +0000 +++ b/main.cpp Fri May 30 04:07:27 2014 +0000 @@ -1,7 +1,19 @@ +//*************************************************************** +// Function Generator - main entry and sole source file for an +// MBED based function generator. The program will output +// waveforms sinewave, squarewave, sawtooth, and flat DC on the +// MBED analog out pin (P18). The joystick buttons are used +// to control the period and amplitude of the output waveforms. +// This is because the pots are a little too unstable to be read +// out in a tight update loop for the waveforms. The exception +// is the DC output. That uses the pot as it doesn't need a tight +// loop. +// +// Author: Terry Richards +// Date: 5/29/2014 +// #include "mbed.h" #include "C12832_lcd.h" -#include "DebounceIn.h" -//#include "rtos.h" Serial pc(USBTX, USBRX); C12832_LCD LCD; @@ -9,118 +21,259 @@ AnalogOut Aout(p18); AnalogIn pot1(p19); AnalogIn pot2(p20); + DigitalIn up(p15); DigitalIn down(p12); DigitalIn left(p13); DigitalIn right(p16); BusIn joy(p15,p12,p13,p16); DigitalIn OnOff(p14); -PwmOut testout(p21); -PwmOut tled(LED1); -/* -DebounceIn OnOff(p14); -DebounceIn up(p15); -DebounceIn down(p12); -DebounceIn left(p13); -DebounceIn right(p16); -*/ +bool first = true; -// SineWave thread - is initiated when the user selects sinewave output -// print a sin function in a small window -// the value of pot 1 changes the period of the sine wave -// The value of pot 2 changes the height of the sine wave -void sineWave(void) -{ - double i, vert, horiz, outval; - while(!OnOff) { // thread loop - horiz = pot1.read(); // get value of pot 1 - vert = pot2.read(); // scale the height of wave - for (i=0; i<2; i=i+0.05) { - outval = 0.5 + 0.5*vert*sin(i*3.14159); - Aout.write(outval); // Compute the sine value, + half the range - wait_ms(0.0002*horiz); // Controls the sine wave period - } +// check_update - checks the buttons to see if the user wants +// to update either the vertical (in volts) or the horizontal +// (in uS) for the currently selected waveform. It also updates +// the LCD +// **** The joystick is used instead of the pots because ***** +// **** I found that the pots were to unstable *************** +// Inputs - the vert and horiz from the calling waveform routine +// Outputs - the updated vert and horiz based on the button presses +// +#define SINE 1 +#define SQUARE 2 +#define DC 3 +#define SAW 4 +void check_update( int type, //what type of waveform + double *vert, //vertical in volts + int *horiz, //horizontal in us + float vertmax, //max vertical in volts + int horizmax, //max horizontal in us + bool init ) //put initial vert and horiz +{ //on LCD screen if set + if( type ) { //The header is static once the waveform is chosen + LCD.locate(0, 3); + switch( type ) { //only done if type is set + case SINE: + LCD.printf("Current WaveForm: Sine "); + break; + case SQUARE: + LCD.printf("Current WaveForm: Square "); + break; + case DC: + LCD.printf("Current WaveForm: DC "); + break; + case SAW: + LCD.printf("Current WaveForm: SawTooth"); + } + } + if( up ) { //if user pushes up button + if( *vert < (1.0 - 0.001) ) + *vert += 0.01; //update the vertical + LCD.locate(0, 23); //vert is a percentage between 0 and 1 + LCD.printf("Height: %5.3f V", *vert*3.3); + } + if( down ) { + if( *vert > 0.01 ) + *vert -= 0.01; //update the vertical down + LCD.locate(0, 23); + LCD.printf("Height: %5.3f V", *vert*3.3); + } + if( right ) { //right updates the horizontal in us + if( *horiz < 100 ) //fine grain if below 100 + *horiz += 1; + else if( *horiz < 1000 ) //little coarser + *horiz += 100; + else + *horiz += 1000; + if( *horiz > 100000 ) //most coarse + *horiz = 100000; + LCD.locate(0, 13); + LCD.printf("PW/Period: %d uS ", *horiz); + } + if( left ) { //left updates horizontal down + if( *horiz < 100 ) + *horiz -= 1; + else if( *horiz < 1000 ) + *horiz -= 100; + else + *horiz -= 1000; + if( *horiz <= 0 ) + *horiz = 1; + LCD.locate(0, 13); + LCD.printf("PW/Period: %d uS ", *horiz); + } + if( init ) { //only done if bool init is true + LCD.locate(0, 13); //used for initial LCD update + LCD.printf("PW/Period: %d uS ", *horiz); + LCD.locate(0, 23); + LCD.printf("Height: %5.3f V", *vert*3.3); } } -// Thread squareWave - called if user selects squarewave -// pot1 controls the width of pulse -// pot2 controls the height of pulse +// SineWave - is initiated when the user selects sinewave output +// Sends a sine wave to the Aout pin. +// The up and down buttons of the joystick control the amplitude +// The right and left buttons control the period +void sineWave(void) +{ + int horiz=1000; + double vert=1.0, outval, i; + while( OnOff ) + wait_ms(10); + check_update( SINE, &vert, &horiz, 1.0, 10000, true ); + while(!OnOff) { // thread loop + check_update( 0, &vert, &horiz, 1.0, 10000, false ); + for (i=0; i<2; i=i+0.05) { + outval = 0.5 + 0.5*vert*sin(i*3.14159); + Aout.write(outval); // Compute the sine value, + half the range + wait_us(horiz); // Controls the sine wave period + } + } + while( OnOff ) + first = true; +} + +// squareWave - called if user selects squarewave. Sends the +// square wave to the Aout pin. +// The up and down buttons of the joystick control the amplitude +// The right and left buttons control the period void squareWave(void) { - float height=0; - unsigned int width=0, cnt=0; + static double height = 1.0; + static int width = 20; + check_update( SQUARE, &height, &width, 1.0, 10000, true ); while(!OnOff) { // thread loop - if( cnt == 1000 ) { - width = pot1.read_u16(); // get value of - height = pot2.read(); // scale the height of wave - cnt = 0; - } + check_update( 0, &height, &width, 1.0, 100000, false ); Aout.write(height); - wait_ms(0.1*width); + wait_us(width); Aout.write(0); - wait_ms(0.1*width); - cnt++; + wait_us(width); } + while( OnOff ) + first = true; } -// Thread flatdc - called if user selects dc sig +// flatdc - called if user selects dc sig // pot2 controls the height of dc signal +// The check_update is not used here because the +// pot does not interrupt dc operation. void flatdc(void) { + float current = pot2.read(); + LCD.locate(0, 3); + LCD.printf("Current WaveForm: DC "); + LCD.locate(0, 13); + LCD.printf("DC Volts: %f V", current*3.3); + LCD.locate(0, 23); + LCD.printf(" "); while(!OnOff) { // thread loop Aout.write(pot2.read()); // scale the height of wave - wait_ms(10); + if( current != pot2.read() ) { + current = pot2.read(); + LCD.locate(0, 13); + LCD.printf("DC Volts: %f V", current*3.3); + } + wait_ms(2); } + while( OnOff ) + first = true; } +// SawTooth - called if the user selects sawTooth. Sends the +// saw tooth waveform out to the Aout pin. +// The up and down buttons of the joystick control the amplitude +// The right and left buttons control the period void sawTooth(void) { + static double height = 1.0, inc; + static int width = 200, i; + check_update( SAW, &height, &width, 1.0, 10000, true ); + while(!OnOff) { // thread loop + check_update( 0, &height, &width, 1.0, 100000, false ); + inc = height/width; + for( i=0; i<width; i++) { + Aout.write(i*inc); + //wait_us(1); + } + } + while( OnOff ) + first = true; } - +// Banner - Output a welcome and select screen for +// the user to select the desired waveform to +// output. +// Inputs: none +// Outputs: none +void banner(void) +{ + LCD.locate(0,3); + LCD.printf("Select Waveform: "); + LCD.locate(0,13); + LCD.printf("UP=Sawtooth, DOWN=DC"); + LCD.locate(0,23); + LCD.printf("LEFT=Sine , RIGHT=Square"); +} + +// main - main entry point to program and where the +// user selects the desired waveform. int main() { + //booleans to select waveform bool do_sine=false, do_saw=false; - bool do_dc=false, do_square=false; - pc.baud(19200); + bool do_dc=false, do_square=false; + pc.baud(19200); //debug + banner(); //put the selection banner on LCD while(1) { - if( up ) { - do_saw=true; - do_sine=false; + if( up ) { //is UP pressed? + do_saw=true; //select Sawtooth + do_sine=false; //ensure nothing else selected do_dc=false; do_square=false; } - if( down ) { + if( down ) { //is DOWN pressed? do_saw=false; do_sine=false; - do_dc=true; + do_dc=true; //user wants DC do_square=false; } - if( right ) { + if( right ) { //is RIGHT pressed? do_saw=false; do_sine=false; do_dc=false; - do_square=true; + do_square=true; //user wants squarewave } - if( left ) { + if( left ) { //is LEFT pressed? do_saw=false; - do_sine=true; + do_sine=true; //user wants sinewave do_dc=false; do_square=false; } - if( OnOff ) { - if( do_saw ) + if( OnOff && first ) { //pressing center button starts + while( OnOff ) //ensure we only get in here once + first = false; //sync signal + if( do_saw ) { + pc.printf("I'm doing saw\r\n"); sawTooth(); - else if( do_dc ) + } + else if( do_dc ) { + pc.printf("I'm doing dc\r\n"); flatdc(); - else if( do_square ) + } + else if( do_square ) { + pc.printf("I'm doing square\r\n"); squareWave(); - else if( do_sine ) + } + else if( do_sine ) { + pc.printf("I'm doing sine\r\n"); sineWave(); - else + } + else { + pc.printf("I'm doing default (sine)\r\n"); sineWave(); + } + banner(); //we came back, ask user what next } } }