Tuesday, October 28, 2014

Using the AndroiDAQ oScope for LabVIEW®.


The AndroiDAQ oScope for LabVIEW is a new LabVIEW application VI that is now included in Controlled Capture Systems’ AndroiDAQ DEMO for LabVIEW library project. oScope allows you to acquire a user set number of analog to digital samples at user set time-based intervals, much like a digital oscilloscope. oScope uses LabVIEW’s Waveform graph to plot the received sample data from the AndroiDAQ module to give you a visual representation of the signal on channel zero of the AndroiDAQ ADC.

To use oScope with your AndroiDAQ module, ensure that you have the newest version of AndroiDAQ firmware installed on your AndroiDAQ module, which is firmware version 4.07. You will also need to download the newest version of the AndroiDAQ DEMO for LabVIEW library project that has a filename of AndroiDAQLabVIEW_Project_Rev07.zip. These two files are located for download at:


 and


Unzip the two downloaded files into a folder location that you can remember on your computer, for example your desktop. First open and reprogram your AndroiDAQ module with the newest 4.07 firmware using the Propeller Tool and then open LabVIEW and browse to find and open the AndroiDAQ.lvprog file. The oScope application is called AndroiDAQ_Waveform.vi which is listed in the AndroiDAQ.lvprog project list. Click on the AndroiDAQ_Waveform.vi file to open the front panel of new AndroiDAQ oScope. The AndroiDAQ oScope can be used via USB, Bluetooth, or Wi-Fi with an appropriately equipped AndroiDAQ module. When the VI is ran, the oScope application will ask you if you want to connect via Bluetooth or Wi-Fi if the application doesn’t sense the FTDI chip used on the AndroiDAQ module for USB communication. Enter your desired connection type and then enter the asked for parameters. Upon completion, AndroiDAQ oScope will inform you of the connection status and port number, and the “connected?” Boolean light will turn green. If your connection fails, please ensure that you have the FTDI driver installed on your computer, or that the Bluetooth radio paired with Windows, or that you are using the correct IP address for Wi-Fi communications.

The AndroiDAQ oScope application utilizes the FTDI driver for LabVIEW methods, or functions, to check if the USB port senses a FTDI chip. If it does sense a FTDI chip on the USB port, the oScope application requests the USB COM port number and then uses LabVIEW’s VISA communication VIs to connect and communicate with the AndroiDAQ module. Below is a LabVIEW wiring diagram that shows how oScope is wired to perform these functions. This wiring diagram can be seen in OScope by double clicking the CWDConnectionStatus.vi:


Setup FTDI chip, detect COM port and connect status

If you follow the above wiring diagram, you will see that the FT_Get_Device Description_By_Index VI is called, which looks at all COM ports on the computer system and then reports back if it found any FTDI chip. Then the FT_ Open_Device_By_Description and Get_COM_Port_Number VIs are run, which gives us which COM port number that the FTDI chip is connected to. The FT_Status LabVIEW Property node returns a numerical value, which if not zero, is converted to a ‘true’ Boolean value if the FTDI chip is found. The FT_Status RingText property is used to show the various text codes outputted if an FTDI chip is found and also if there is a problem with communications with the chip. 

Following the wiring diagram passed the CWDConnectionStatus.vi in oScope, we then enter a communications setup while loop (see below), which uses the VISA communications VIs to configure the serial COM port’s protocols. Special characters are also enabled in VISA to provide end of line implementation, via the ASCII line feed character (TermChar 10). You will note that in this diagram that we also control Wi-Fi (TCP) and Bluetooth setup, depending on if the FTDI chip on USB is detected. If it is not detected, the application opens a dialog box to ask you how you would like to connect to the AndroiDAQ module. The choices are Wi-Fi or Bluetooth. Depending on which choice is made by the user, another dialog box opens, via BluetoothDialog.vi or WiFiDialog.vi, which asks for the Bluetooth COM port name or TCP address and port number, respectively. After the user’s input, the communications while loop then runs the appropriate conditional statement to setup VISA/TCP communication for that selected communications protocol using the input from the user.


USB Setup using VISA VIs and Linefeed Character as TermChar


Bluetooth Setup, similar to USB setup


TCP or Wi-Fi Setup using VISA TCP VIs

After all VISA protocol settings are set, the communications setup while loop exits giving us a VISA or TCP string reference data type and also an Error out data type to use with other VISA functions. These data types allow us to read to and write from the COM or TCP port via VISA read/write VIs or TCP read/write VIs. Following along the wiring diagram of oScope, we then enter the main state machine, or main while loop, of the AndroiDAQ communications engine, which also controls the user’s interface. We will now review some of the oScope functions in this main while loop wiring diagram.

In oScope for LabVIEW you can read the AndroiDAQ SD-card log file, delete this log file, and also read and set AndroiDAQ’s real-time clock. Below is the LabVIEW wiring diagram for these functions. You should also note that Bytes at Port is utilized to read serial data from the AndroiDAQ module. To ensure all bytes are received before plotting the data on to the Waveform graph, we use a SampleBits variable which represents the expected number of bytes we expect to receive depending on the number of samples entered by the user. This number is calculated in the next diagram.


Wiring Diagram to Read the Serial Data from AndroiDAQ and other Functions

To get samples, you enter the desired number of samples that you want to take (1 to 2048 samples are possible) and also the sample rate at which you want the samples to be acquired. When “Read Samples” is pressed, oScope will calculate and inform you of the required time for you to wait to receive the desired samples, and then when the samples are received by oScope, the oScope application will then plot the waveform of the samples on a Wavform graph. You will note in the diagram that SampleBits is calculated to determine the expected number of bytes per number of samples desired. Below is the wiring diagram of the readSample function:


Read Sample Button Sends Serial Menu Command


oScope uses LabVIEW’s Waveform graph to plot the received sample from the AndroiDAQ module. The y-axis is the number of samples from 1 to 2048, which automatically adjusts depending on the sample number you entered to read. The x-axis is the range of the AndroiDAQ ADC chip 0 to 4096, as it is a 12-bit device. As you can see there are no conversions to voltage or other units in oScope, this is left to you. Both axis plots are divided into division of ten segments, depending on the number of samples taken, for ease of interpretation after the plot is completed.


Waveform Graph Plotting of Data Received

If you review the new firmware (snippets shown below) by opening the AndroiDAQRev4.07.spin file, you will notice that we added three new functions under the MenuLoop subroutine: ReadADC, ReadADC2, and ReadADC3, which correspond to menu items 16, 17, and 18 respectively (if these subroutines are missing in your AndroiDAQ spin file, please ensure that you have the correct version of firmware).

PUB MenuLoop                                              'MenuLoop for user input via menu number commands 
''MenuLoop for user input via Serial numerical commands
  menu := 0
                        
  Repeat
      
    menu := debug.rxcheck                                'This section allows menu driven actions via USB
    if menu > 0                                          'using value of "set" depending on what GUI sends 
        item := debug.GetDec
                                   
        if item == 0                                       'if set=0, Setup Prop Pins
          'debug.str(String("Set Pins of AndroiDAQ", CR, LF))
          SetPins
         
        if item == 1                                       'if set=1, Setup Prop Operation
          'debug.str(String("Set Config of AndroiDAQ", CR, LF))
          SetOutputs
          
        if item == 2                                       'if set=2, Return input values
          GetInputs
           
        if item == 3                                       'if set=3, this is a testloop to add your code
         
          Testloop
            
        if item == 4                                       'if set=4, Read values from ADC and convert then send
          GetVolts
                                                                              
        if item == 5                                   
          debug.str(String("AndroiDAQ Clock set at: ", CR, LF))
          GetTime                                          'Get RTC chip time
         
        if item == 6
          debug.str(String("Auto Setting AndroiDAQ Clock", CR, LF))
          SetTime                                          'Set RTC chip time via system clock
        if item == 7
          debug.str(String("AndroiDAQ Log File Contents: ", CR, LF))
          ReadLog                                           'Read SD card log.txt file
           
        if item == 8                                    
          debug.str(String("Deleted AndroiDAQ Log File", CR, LF))
          DeleteLog                                         'Delete SD card log.txt file
         
        if item == 9
          COGSTOP(stop)                                     'Stop continuous read of inputs
           
        if item == 10
          stop := COGNEW(GetInputsCont, @stack2[0])         'Read inputs continuously
         
        if item == 11
          voltsStop := COGNEW(GetVoltsCont, @stack2[0])     'Read ADC voltage levels continuously
            
        if item == 12
          COGSTOP(voltsStop)                                'Stop reading ADC voltage levels continuously

        if item == 13
          CenterPanTilt                                     'Center Pan/Tilt assembly with servo and stepper
          
        if item == 14
          MoveServo                                         'Move servo motor(s)

        if item == 15
          MoveStepper                                       'Move stepper motor

        if item == 16
          ReadADC
          
        if item == 17
          ReadADC2

        if item == 18
          ReadADC3

PUB ReadADC | rate, tStart, t1, t2, time, x
''Reads channel 0 of ADC

  ADC.start(19, 20, 18, 00_0001)                      'Start ADC  
  menu := 0
   
  if autoADC == 0
    repeat
      menu := debug.rxcheck                         'This section gets #samples and rate from Serail port
      if menu > 0
          samples := debug.GetDec            'Get number of samples limited to 4096 due to array limit
          rate := debug.GetDec                            'Get number to use as sample rate
                                                          'Enter preset rates (10k, 2k, 1k, 100, 20, 10, 2, 1)
          if samples > 4096
             samples := 4096
          if samples =< 0
             samples := 1  
          quit
  else                                                   'This is triggered by pin 16 going high via pushbutton
    samples := 4096                                      'Sample size default to 4096 readings
    rate := 1000                                         'Rate default is 1mSec
 
  x := 0                                                'Place holder for array indexing
  t1 := tStart := cnt                                   'Timer to derive timing accuracy
                                                       
  repeat samples                                       
    t1 := t1+clkfreq/rate                               'Time between samples clfkfreq=80,000,000
    'adcreads[x] := ADC.average(0,10)                   'This line uses averages to smooth S/N ration
    adcreads[x] := ADC.in(0)                            'This line reads one sample at designated time
    waitcnt(t1)                                         'This line waits for t1 calculated time to resample
    x++                                                 'Increment x for next reading
 
  ADC.stop
  WriteToSDADC                                          'save to log.txt
  debug.dec(samples)
  debug.str(String(" Samples Taken "))
  debug.tx(CR)
  debug.tx(LF)
 
  MenuLoop

PUB ReadADC2 | rate, tStart, t1, t2, time, x
''Reads channel 0 of ADC for AndroiDAQ DEMO O-Scope

  ADC.start(19, 20, 18, 00_0001)                      'Start ADC  
  waitcnt(clkfreq/1000 + cnt)                            'one millisecond between readings
  samples := 448                                         'Sample size default to 448 for o-scope readings

  repeat
      menu := debug.rxcheck                           'This section gets #samples and rate from Serial port
      if menu > 0
          rate := debug.GetDec                            'Get number to use as sample rate
          quit
 
  x := 0                                                 'Place holder for array indexing
  t1 := tStart := cnt                                    'Timer to derive timing accuracy
                                                       
  repeat samples                                       
    t1 := t1+clkfreq/rate                               'Time between samples clfkfreq=80,000,000
    'adcreads[x] := ADC.average(0,10)                   'This line uses averages to smooth S/N ration
    adcreads[x] := ADC.in(0)                            'This line reads one sample at designated time
    waitcnt(t1)                                         'This line waits for t1 calculated time to resample
    x++                                                 'Increment x for next reading
 
  x := 0
  debug.str(String("Readings: "))
  repeat x from 0 to samples - 1                         'read out the samples to Serial and save to log.txt
      debug.str(num.decz(adcreads[x], 4))
      if x < samples - 1
        debug.str(String(", "))

  debug.tx(CR)                                          'line feed for end of line for LabVIEW
  debug.tx(LF)                                          'line feed for end of line for LabVIEW
 
  ADC.stop
  WriteToSDADC                                          'save to log.txt

  MenuLoop

PUB ReadADC3 | rate, tStart, t1, t2, time, x
''Reads channel 0 of ADC for AndroiDAQ DEMO O-Scope using #samples and rate, no save to SD

  ADC.start(19, 20, 18, 00_0001)                      'Start ADC  

  repeat
      menu := debug.rxcheck                            'This section gets #samples and rate from Serial port
      if menu > 0
          samples := debug.GetDec             'Get number of samples limited to 4096 due to array limit
          rate := debug.GetDec                            'Get number to use as sample rate
                                                          'Enter preset rates (20k, 10k, 2k, 1k, 100, 20, 10, 2, 1)
          if samples > 2048
             samples := 2048
          if samples =< 0
             samples := 1  
          quit
 
  x := 0                                                 'Place holder for array indexing
  t1 := tStart := cnt                                    'Timer to derive timing accuracy
                                                       
  repeat samples                                        
    t1 := t1+clkfreq/rate                               'Time between samples clfkfreq=80,000,000
    'adcreads[x] := ADC.average(0,10)                   'This line uses averages to smooth S/N ration
    adcreads[x] := ADC.in(0)                            'This line reads one sample at designated time
    waitcnt(t1)                                         'This line waits for t1 calculated time to resample
    x++                                                 'Increment x for next reading
 
  x := 0
  debug.str(String("Readings: "))
  repeat x from 0 to samples - 1                         'read out the samples to Serial
      debug.str(num.decz(adcreads[x], 4))
      if x < samples - 1
        debug.str(String(", "))

  debug.tx(CR)                                          'line feed for end of line for LabVIEW
  debug.tx(LF)                                          'line feed for end of line for LabVIEW
 
  ADC.stop
 
  MenuLoop
  

oScope uses menu item 18 during serial communications, which triggers the ReadADC3 subroutine in the firmware. Here you will find the ReadADC3 waits for two more parameters to be sent via the serial port: the number of samples and sample rate. After these values are received from the serial port, the firmware reads ADC channel zero, which is sampled the number of samples desired and at the sample rate iteration. A serial command to do this would look like this 018\r 01000\r, 01000\r. This example command would give you 1000 samples taken at 1-millisecond intervals. For more information on how the AndroiDAQ firmware interacts with LabVIEW, please refer to my previous article titled: “LabVIEW How-to, with the AndroiDAQ Data Acquisition Module” which is available at:



These are the basics of operation and for using the new AndroiDAQ oScope for LabVIEW. We hope that you find that it is a useful tool to help you in designing your next Internet of Things project using the AndroiDAQ module. Feel free to modify this VI and share your changes on our forums, so that all AndroiDAQ users can benefit from this new visual electronic analog to digital conversion tool. 

No comments :