jim hamblen / Mbed 2 deprecated mymbedDAQ

Dependencies:   FFT Terminal_VT100 mbed

Files at this revision

API Documentation at this revision

Comitter:
4180_1
Date:
Thu Nov 01 19:10:56 2012 +0000
Commit message:
ver 1.0 4180 student lab assignment - more code must be added by students

Changed in this revision

FFT.lib Show annotated file Show diff for this revision Revisions of this file
Terminal_VT100.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FFT.lib	Thu Nov 01 19:10:56 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/Suky/code/FFT/#e3af07c00c13
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Terminal_VT100.lib	Thu Nov 01 19:10:56 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/4180_1/code/Terminal_VT100/#ec59d22e0145
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Nov 01 19:10:56 2012 +0000
@@ -0,0 +1,474 @@
+// mymbedDAQ - Electronic Test Instrument Concept Demo & Lab assignment
+// CODE MUST BE ADDED BY STUDENTS WHERE INDICATED!!!!!!!!!!!!!!!
+// Uses VT100 terminal application on PC
+// Needs terminal and FFT libs
+//
+// NOTE: for test signals must connect
+// P18 to P16 (sine wave from D/A to A/D)
+// P13 to P12 (digital test signal from serial port to LA digital input)
+// P21 to P15 (PWM for square wave to A/D)
+//
+#include "mbed.h"
+#include "FFT.h"
+#include "Terminal.h"
+#include <vector>
+using namespace std;
+
+// **********************************************************************************************
+#define N 128 //number of analog samples to take - need power of two for FFT
+float FFT_Data[N*2]; //complex data space for analog signal's FFT-1D array with real & imag pairs
+float Data[N]; //data space for (real) analog signal samples
+float Analog_Voltage; //used for DMM voltage reading
+float Analog_out_value[N]; // Analog values of precomputed sine wave for D/A (function generator)
+unsigned char PowerInt[N/2]; //used to store scaled magnitude of FFT bars (positive only)
+
+// note use of volatile for an interrupt set global variable!
+volatile int take_sample; //sample period timer flag - set by interrupt
+
+vector <int> Digital_Signal (100); // use a vector for sample data for Logic Analyzer
+
+char input_char; //character read from PC terminal application window
+bool sine=true; //sine or square wave flag for test signal input
+bool square=true; //50% or 25% duty cycle on square wave test signal
+
+
+//Digital Signals for Logic Analyzer
+
+// Used to read in digital signals
+DigitalIn   LogicAnalyzer_test_signal_in(p12);
+// Used for digital test signal output
+Serial      LogicAnalyzer_test_signal_out(p13,p14);
+
+//Analog I/O Signals for DMM, Oscilloscope, and Spectrum Analyzer
+
+// Analog A/D Input
+AnalogIn    Analog_test_signal_in(p16);
+// Analog D/A output test signal (for sine wave function generation)
+AnalogOut   Analog_test_signal_out(p18);
+
+
+// PWM is used for alternate analog square wave signal source
+
+// Analog A/D Input used for square wave
+AnalogIn    PWM_test_signal(p15);
+// PWM output pint that generates a square wave
+PwmOut PWM_Output(p21);
+
+//unsed Analog input pins set to digital to reduce A/D noise
+DigitalOut  d2(p17);
+DigitalOut  d3(p19);
+DigitalOut  d4(p20);
+
+//VT100 ANSI Terminal connected to PC
+Terminal PC(USBTX, USBRX);
+
+
+// **********************************************************************************************
+
+void Take_Analog_Signal_Samples(float Analogs[]);
+void Graphic_Display_Spectrum(unsigned char *Data);
+void Graphic_Display_Time(float *Data);
+void Digital_Multimeter();
+void Logic_Analyzer();
+void Oscilloscope();
+void Spectrum_Analyzer();
+void Function_Select();
+void Duty_Cycle();
+
+// **********************************************************************************************
+
+int main()
+{
+// Start PWM hardware for a continuous square wave signal ouput with a 50% duty cycle
+    PWM_Output=0.5;
+    PWM_Output.period(0.0128);
+    while(1) {
+// clear screen and print user menu selections
+        PC.cls();
+        PC.locate(0,5);
+        PC.printf("       1 - Digital Multimeter\n\r");
+        PC.printf("       2 - Logic Analyzer\n\r");
+        PC.printf("       3 - Oscilloscope\n\r");
+        PC.printf("       4 - Spectrum Analyzer \n\r");
+        PC.printf("       5 - Function Generation - toggles between sine & square wave signal\n\r");
+        PC.printf("       6 - Duty Cycle - toggles between 50%% and 25%% duty cycle on square wave");
+        PC.locate(0,0);
+        PC.printf("   Select Electronic Test Instrument (type 1...5)");
+        // reads a character from the PC terminal appication window
+        input_char=PC.getc();
+        // echo back selection char for human display on PC
+        PC.putc(input_char);
+        // delay for slow human to see character
+        wait(.5);
+//ADD CODE HERE
+        // select instrument demo using input_char switch statement
+        // case for each function below
+        //  1 Digital_Multimeter();
+        //  2 Logic_Analyzer();
+        //  3 Oscilloscope();
+        //  4 Spectrum_Analyzer();
+        //  5 Function Select();
+        //  6 Duty Cycle();
+
+
+
+
+
+//END ADD CODE HERE
+    }
+}
+
+//*********************************************************************************************
+// toggles a flag between a sine or square wave test output
+// sine flag is used in Take_Analog_Signal_Samples
+void Function_Select()
+{
+    sine=!sine;
+}
+
+//**********************************************************************************************
+// Toggles the hardware PWM output between a 25% and 50% duty cycle square wave
+// square flag stores state
+void Duty_Cycle()
+{
+    if (square)
+        PWM_Output=0.25;
+    else
+        PWM_Output=0.5;
+    square=!square;
+    //PWM hardware needs a bit of setup time to adjust
+    wait(.25);
+}
+
+// **********************************************************************************************
+
+void Digital_Multimeter()
+{
+// PC.readable() indicates another character is available to read
+// but it does not read the character or wait for a character
+// It is a handy way to break out of a loop if any key is hit
+    while(!PC.readable()) {
+        // Digital Multimeter - reads an analog voltage on pin 16
+        // D/A output is connected to A/D input  (0..3.3V range only!)
+        PC.cls(); //clear screen
+        PC.locate(9,0); // move cursor to 9,0
+        PC.printf("Digital Multimeter"); // print title
+        PC.locate(22,12);
+        PC.printf("  volts DC"); // label for voltage reading
+        // Plot Y Axis tick marks with labels
+        for(int i=21; i>3; i--) {
+            PC.locate(7,i);
+            // put a label every 1 volt on axis
+            if((i-1)%5==0) {
+                PC.putc('+');
+                PC.locate(1,i);
+                PC.printf("%d.0V",int((21.0-i)/16.0*3.3));
+            } else PC.putc('-');
+        }
+        for(int i=0; i<=64; i++) {
+            // Output the Analog test signal using D/A output 'Analog_test_signal_out
+            // makes D/A outputvoltage increase linear from 0 to 3.3
+            // (but scaled from 0 to 1.0 in C/C++) using loop value i to change it
+//ADD CODE HERE - 1 line
+
+//END ADD CODE HERE
+            // Print voltage at 15,12
+            PC.locate(15,12);
+//ADD CODE HERE
+            // read in the analog voltage using A/D input "Analog_test_signal_in"
+            // multiply value by 3.3 to convert to actual voltage level
+            // save in "Analog_Voltage"
+
+            // Print Analog_Voltage*3.3 in "%7.3F" format
+
+            // Display Analog Level Bar but only every four display updates (i%4) for faster updates
+            // on PC use char(219) for a solid bar graphics character or a space ' ' to erase
+            // use locate to draw a vertical bar
+
+
+
+
+
+        }
+//END ADD CODE HERE
+    }
+    // delay to allow time to view each display
+    wait(1);
+}
+
+// **********************************************************************************************
+
+void Logic_Analyzer()
+{
+    // Logic Analyzer
+    // Reads in a serial digital output pin (0 or 3.3V)
+    // pin 13 TX serial output tied to pin12 digital input
+    while(!PC.readable()) {
+        // Loop through several ASCII characters for display test
+        for(int c='A'; c<='z'&&!PC.readable(); c=c+1) {
+            PC.cls();
+            Digital_Signal.clear();
+            PC.locate(15,0);
+            PC.printf("Logic Analyzer Display - RS-232 Serial ASCII character %c 0x%X",char(c), int(c));
+            // Sample digital data for display - need 80 samples (have 80 display cols)
+            for(int i=0; i<80; i++) {
+                // Test signal for Logic Analyzer
+                // Send out a new character char(c) using the serial port
+                // after a small delay so that it will show up in middle of display
+                if(i==6) LogicAnalyzer_test_signal_out.putc(char(c));
+//ADD CODE HERE
+// Use "Digital_Signal" vector to store data from "LogicAnalyzer_test_signal_in" (DigitalIn pin)
+
+                // time delay is used to adjust sample time interval
+                // a hardware timer would be more accurate
+                // that will be explained later in the oscilloscope example
+                // some adjustment to time delay here might be needed for your code
+                // scale so that you can see entire ASCII character on display
+                wait(.00002);
+            }
+            //Display data
+            //Move cursor to 0,15 or 0,5 based on first digital bit from Digital_Signal[i]
+            //Scan through data samples from left to right and draw the high or low line
+            //Locate is only needed when changing between high or low value
+            //loop through 80 sample values
+            PC.locate(0,(15 - int(float(Digital_Signal[0])*10.0)));
+            for(int i=0; i<80; i++) {
+                // If no change in digital signal, or fist bit just output a horiz bar char(196)?
+
+                // if A 1 to 0 transisition occured
+                // draw a vertical line with correct bar and corner characters (191, 179, 192)
+                // PC.locate(col,row) is needed for vertical line drawing
+
+
+
+
+
+                //if A 0 to 1 transisiton occured
+                // draw a vertical line with correct bar and corner characters (217, 179, 218)
+
+
+
+
+
+            }
+            //plot X axis tick marks and labels
+            //only initial locate needed
+            PC.locate(0,20);
+
+
+
+
+
+
+//END ADD CODE HERE
+            // delay to allow time to view each display
+            wait(1);
+        }
+    }
+}
+// **********************************************************************************************
+
+void Oscilloscope()
+{
+    while(!PC.readable()) {
+        // Oscilloscope
+        // D/A sends out a sine wave and the A/D reads it back in
+        // PWM hardware sends out a square wave to another A/D input
+        // loop through increasing the frequency of the test signals for each display
+        for(int i=1; i<11&&!PC.readable(); i++) {
+            //Setup square wave signal source period - increase each loop iteration
+            PWM_Output.period(0.0128/i);
+            wait(0.25);
+            // Precompute sine wave values for faster D/A output to save execution time
+            // Need to add DC bias and scale sine wave from 0...1.0 for analog out function
+            // (i.e. not just -1..1)
+            // need N samples of one sine cycle first time - then make it i times faster each
+            // loop iteration - samples go in Analog_out_value[k]
+            for(int k=0; k<N; k++) {
+//ADD CODE HERE - 1 line to compute sine values
+
+//END ADD CODE HERE
+            }
+            //Reads analog samples using test signals setup above
+            Take_Analog_Signal_Samples(Data);
+            //Displays an analog signal in time
+            Graphic_Display_Time(Data);
+            // delay to allow time to view each display
+            wait(2);
+        }
+    }
+}
+
+// **********************************************************************************************
+void Spectrum_Analyzer()
+{
+    while(!PC.readable()) {
+        // Spectrum Analyzer
+        // Compute FFT of sampled signal
+        // D/A sends out a sine wave and the A/D reads it back in
+        // loop through increasing the frequency of test signals for each display
+        for(int i=1; i<11&&!PC.readable(); i++) {
+            //Setup square wave signal source with correct period
+            PWM_Output.period(.0128/i);
+            wait(0.25);
+            //Precompute sine wave values for D/A output to save execution time
+            //same as Oscilloscope code earlier
+            for(int k=0; k<N; k++) {
+//ADD CODE HERE - line
+
+//END ADD CODE HERE
+            }
+            //Reads analog samples
+            Take_Analog_Signal_Samples(Data);
+            // put data in complex format for FFT code (real followed by imag=0 in 2*N 1D array)
+            // Required by Numerical Recipes in C++ Algorithm for FFT used in in vFFT.cpp
+            for(int k=0; k<N; k++) {
+                FFT_Data[k*2]=Data[k];
+                FFT_Data[k*2+1] = 0.0;
+            }
+            Graphic_Display_Time(Data);
+            // delay to allow time to view each time display
+            wait(2);
+            // Spectrum Analyzer
+            // Compute FFT of sampled signal
+            vFFT(FFT_Data-1,N);
+            // Compute magnitude for positive frequency display
+            // scaled and returned in a char array
+            vCalPowerInt(FFT_Data,PowerInt,N/2);
+            // Display Frequency content of sampled signal
+            Graphic_Display_Spectrum(PowerInt);
+            // delay to allow time to view each frequency display
+            wait(2);
+        }
+    }
+}
+
+
+// **********************************************************************************************
+// Functions to sample Analog input data at an accurate 10Khz rate (every 100 us)
+// used by Oscilloscope and Spectrum Analyzer
+void Sample_timer_interrupt(void)
+{
+    // Sets flag when time to read in another analog sample
+    // Timer interrupt comes here when a it hits every sample time interval
+    take_sample=1;
+}
+void Take_Analog_Signal_Samples(float Analogs[])
+{
+    // setup a timer to determine accurate sample time
+    Ticker Sample_Period;
+    // reset sample time interval flag
+    take_sample=0;
+    // output first D/A value for sine wave
+    Analog_test_signal_out=Analog_out_value[0];
+    // Start periodic timer interrupts to ensure accurate control of sample time interval
+    // Sample_timer_interrupt is "called" every 100 us by hardware interrupt signal
+    Sample_Period.attach_us(&Sample_timer_interrupt,100); // 100 us, 10.000 KHz
+    // Take N analog samples at sample period
+    // timing is critical inside loop here - needs to be fast
+    for(int k=0; k<N; k++) {
+        // wait and spin here until sample timer interrupt routine sets take sample flag
+        while(take_sample==0) {};
+        // next sample period reached (timer interrupt has set take_sample==1)
+        // reset take sample
+        take_sample=0;
+
+        // select sine or square input source using "sine" bool flag in if - two A/D input channels
+        //read in next sample into Analogs[k]
+//ADD CODE HERE
+
+
+
+
+
+//END ADD CODE HERE
+    }
+    // got the N analog samples
+    // so turn off sample timer interrupts
+    Sample_Period.detach();
+    return;
+}
+
+// **********************************************************************************************
+void Graphic_Display_Spectrum(unsigned char *Data)
+// plots frequency bars using data array - 64 values
+{
+    char max_value=0;
+// clear screen
+    PC.cls();
+    PC.locate(15,0);
+// print title
+    PC.printf("Spectrum Analyzer - Frequency Domain Display");
+//ADD CODE HERE
+    //plot X axis tick marks with labels
+
+
+
+
+
+//END ADD CODE HERE
+    // Find max Data[i] value for autoscaling feature
+    // max value bar should fill the screen display area
+    for (int i=0; i<N/2; i++) {
+        if (Data[i] > max_value) max_value = Data[i];
+    }
+//ADD CODE HERE
+    // Plot Y Axis tick marks with labels
+
+
+
+
+
+
+// use max value for Y axis auto scaling and axis label value calculations
+// draw the frequency bars using Data[i] values (0..N/2 i.e., the positive spectrum only)
+// loop though 20 lines starting at top left of bar display area (lines 1-20)
+    for(int i=2; i<=21; i++) {
+        // then loop through each display bar across 64 cols of display area
+        // if scaled Data[col] value> current line (height) move cursor and print a bar char(222)
+        // values in Data[col] are in range from 0 to max_value
+        // scale so that max_value bar height is number of characters in display area
+        // loop through 64 columns across display
+        for(int k=0; k<(N/2); k++) {
+//            if( Data[k]...
+        }
+//END ADD CODE HERE
+    }
+
+}
+
+//************************************************************************************************
+void Graphic_Display_Time(float *Data)
+// displays Data vs time for Oscilloscope style display
+{
+// clear screen
+    PC.cls();
+    PC.locate(20,0);
+// print title
+    PC.printf("Oscilloscope - Time Domain Display");
+//ADD CODE HERE
+    // Plot Y Axis tick marks with labels
+
+
+
+
+
+    // plot X axis tick marks with labels
+
+
+
+
+
+
+    // loop through each sampled Data[i] value (0..N)
+    // scale to display area, move to proper col,row
+    // and plot each point using a '.' (period)
+    // 128 points in 64 display columns so two samples per column
+    // (but likely value is in a different row)
+    // loop through data values
+    for(int i=0; i<N; i++ ) {
+
+    }
+//END ADD CODE HERE
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Thu Nov 01 19:10:56 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e2ed12d17f06
\ No newline at end of file