Dwenguino Labview Interface

Labview is a graphical development environment used by scientist and engineers for creating applications that interact with real-world data. With Labview you can easily design user interfaces controlled by a graphical programming language. Labview runs on Windows, Mac OSX and Linux.
This tutorial describes how you can use the dwenguino as a data acquisition board and how to control the dwenguino directly from your Labview interface. An example VI (Labview document) which demonstrates all the dwenguino functionality is included at the end of this tutorial. You can use this VI as an easy computer interface to your dwenguino or as a starting point to create your own VI.


Installation

Before you can start, you need to install some software: First of all you need Labview, it isn't free software, however you can get a free license for education purposes. NI-VISA provides the necessary Labview drivers to control the serial over USB port. You also need LINX, LINX is an open source project that provides easy-to-use VI's for interacting with embedded platforms like arduino and dwenguino.

Logos

  1. Install Labview (2011 or higher): you can request a student license here. Download the software and follow the steps to install Labview.
  2. Install NI-VISA drivers (v 5.2 or higher): Search for NI VISA driver downloads, choose your operating system and install the drivers.
  3. Install LINX (v 2.0 or higher) using VI package manager. Additional support to install LINX can be found in this tutorial, but skip the installation of the hardware and proceed with the following steps below.
  4. Install the arduino IDE (v 1.6 or higher) with the latest version of the dwenguino library as explained in the Getting acquainted tutorial.
  5. Open the arduino IDE, go to the menu Examples > Dwenguino > LabviewLinxInterface and upload this sketch (don't forget to connect the dwenguino using the USB cable, select the dwenguino platform in Tools > Board > Dwenguino and select the right serial port in Tools > Port ).

Getting Started

  1. Download and open the DwenguinoInterface.vi with LabView.
  2. Select the serial COM port associated with the dwenguino in the dropdown of the connection pane. If you only connect one dwenguino to your computer, you can simply select the only COM port in the list. If there are multiple devices connected to your computer, you can check the COM port in the device manager on Windows (right click on This Computer > Manage > Device Manager > Ports (COM & LPT). Note that this is the same COM port you selected in the arduino IDE to upload the sketch.
  3. Click the Labview run button to start the VI (first arrow icon in the toolbar at the top of your screen).
  4. Wait about 5 seconds until the connection to the dwenguino is initiated: When the red led in the Connection pane turns green, the connection was successfully established. From this moment you will also see the name of the connected device and the refresh rate of the interface.
  5. To stop the current session press the stop button. This will stop the connection and release the COM port.

Move further

The following sections will explain in more detail the different blocks of the example VI and how to use them in your own VI.

If this is your first experience with Labview: please make yourself familiar with the programming concepts of Labview. You can find a good series of starter tutorials at Labview MakerHub or take a look at the official NI Labview Basics page.

Connection

The structure of every dwenguino interface VI should be the same: first call the LINX initialize function to setup the connection, secondly keep doing something inside a while loop until you press the stop button or an error is generated. At the end it is important to call the LINX close function to break the connection and release the COM port. If you forget this close function, the COM port will stay in a busy state and you won't be able to setup a new connection with Labview or with the arduino IDE anymore.

connection

The initialize function will output a linx connection object (pink wire) and an error object (brown wire). It is important you connect both of these wires to each linx function in a serial way. Each linx function will send a command through the given connection to the dwenguino and will wait for a response of the dwenguino (this takes a couple of milliseconds depending on the command). After the dwenguino responds accordingly it will pass the connection object to the next command, if not it will generate an error on the error line.
This also explains why you shouldn't branch from the connection wire: when you try to pass the connection wire to 2 functions in parallel (at the same time), labview will also try to send 2 commands at the same time through the same serial connection as a consequence data packets will collide and an error will be generated.

Read analog and digital ports

You can read out any analog or digital port just like the corresponding arduino functions analogRead() and digitalRead().

graph read_AD

You need to pass the connection and error wire to the linx command as well as a portnumber(s) to read. To readout analog ports: pass number 7 to read A7, 6 to read A6, etc. For digital pins on the expansion connector, use the numbers printed next to the pin. For other ports you need the pass the arduino digital port number, which can be found in pin mapping table in the first tutorial. E.g. in the above example we want to readout port A3 as a digital pin (note that you can use every analog pin as a digital pin, but not the other way around): in the pin mapping table you see: A3 corresponds to portnumber 27. If you want to read the pin connected to the center switch, the corresponding port number is 47. Etc.
Also note in the example Interface pin 16 till 23 of the expansion connector pane are not used because these pins are multiplexed with other dwenguino functionality.

Hint: you can make your own analog oscilloscope or logic analyzer with a dwenguino and the graph function on the LabviewInterface. The sampling frequency depends on the sample speed of the dwenguino, the serial connection speed and the number of other actions the dwenguino needs to do. In the example VI you can observe the current refresh rate in the right corner of the connection pane, which is about 50 - 100 Hz. Note you can speedup the sampling frequency by removing all other interface functions: when you restrict the VI to readout 1 port, you can reach a refresh rate up to 1kHz.
To visualize the current refresh rate on the front panel you can add the linx Time function somewhere inside the while loop: refresh

Write analog and digital ports

You can write a value to the ports just like the corresponding arduino functions analogWrite() and digitalWrite(). Note that the arduino analogWrite() function actually puts a PWM signal on the port rather than writing an analog voltage to the port. For that reason the corresponding linx command is called 'Set Duty Cycle'.

write_AD write_AD_code

Use the corresponding linx commands 'Set Duty Cycle' and 'Digital Write'. Pass the connection and error wire as well as the port number(s) to control. For the Set Duty Cycle command you need to pass a number between 0 and 1, which corresponds to dutycycles between 0% and 100%. For the Digital Write command you need to pass a boolean which corresponds to a low and high value. Note you can set the linx command to control a single port or multiple ports at the same time. If you write (or read) multiple ports at the same time (as in the example above), you need to pass an array of portnumbers as well as an array of values.

Control the onboard leds

Since the onboard leds are directly connected to a certain digital port of the dwenguino, you can put them on and off by the Digital Write command.

leds leds_code

In the pin mapping table of the first tutorial, you can find the portnumbers that corresponds to the onboard leds: LED7-LED0 corresponds to digital port number: 39-32.

Read the buttons

The onboard buttons are also connected to digital ports of the dwenguino, however we can't simply use the Digital Read function here. To avoid floating pins when the buttons are not pressed, we need to configure the internal pull-up resistors before reading the port. Unfortunately there isn't a native linx command to do so, but linx allows us to design our own custom commands. In the dwenguino library a custom command to read out a port with the internal pull-up enabled, is already added. (More information on how to design your own custom command can be found in the last section of this tutorial)

buttons lbuttons_code

As usual you need to pass the connection and error wire to the linx Custom Command function. You also need to pass the custom command number which is 0 in this case and the port number(s) to read. In the pin mapping table you can find the corresponding digital port numbers: SW_C (center switch) = 47, SW_N = 16, SW_E = 17, SW_S = 18 and SW_N = 19. This function will return 1 byte per 8 ports to read, where each bit corresponds to the value on a specified port. In the above example we ask for 5 ports to read (which will fit in 1 byte) so we select the first byte (at index 0) in the return array of the command. This is followed by a 'not' function, which will invert all bits (remember when the button is released, the pull-up resistor will force a high value on the port and a logical 1 will be read, when the button is pressed, it connects the pin to the ground and a logical 0 will be read). At last we split this byte to lead each bit to the corresponding control on the front panel. Since the first port number is 16 (corresponding to SW_N), the result of this port will be at the MSB (most significant bit) on index 7. Second port is 17, corresponding to SW_E, the result will be at bit 6. Etc.

Control the lcd

The dwenguino also provides a 16 x 2 lcd screen. You can put the lcd backlight on and off with a Digital Write command. To print a certain text on the lcd screen, a custom command is added to the dwenguino library with command number 1.

lcd lcd_code

In the pinmapping table you will find the digital port number corresponding to the lcd backlight pin: 20. Pass this port number to the Digital Write function to control the backlight. To not overload the serial connection, we don't send the text in every iteration. Instead we only send the text when the 'Set Text' button on the front panel is pressed by putting the command in a case structure. This custom command also expects the text to print as a byte array of ascii codes. It will print a maximum of 16 characters on the first line and then automatically continue on the second line. You can also send a newline character \n (ascii code = 0x0A) to manually set the start of the second line.
The used newline character (when entering a return in the labview input box) will depend on your current operating system. Since the command will only recognize the \n character, we first convert the line-endings in the input string to the Unix-system. Secondly we limit the string to 33 characters (16 x 2 characters + 1 line ending char). Finally we convert the string to a byte array before passing it to the command.

Buzzer

You can control the onboard buzzer with the 'Digital Write Square Wave' command, which corresponds to the arduino Tone() function. Basically this command will generate a square wave with a given frequency.

lcd lcd_code

This command needs 3 extra parameters: the pin number to control (in the pinmapping table you'll find buzzerpin: 46), the frequency of the square wave and the duration of the waveform. In this case we set the note duration fixed to 100 ms, larger than the loop duration in order to produce a continuous tone as long as the Buzzer enable toggle button is set high.

Hint: You can play a melody by defining an array of frequencies (tones) together with an array of note durations and send the next command when the previous note has ended. Or you can implement a piano keyboard in the labview interface by assigning the corresponding frequency to each key.

DC motor

To control the direction and speed of the DC motors we need to produce the right waveforms from within labview. The direction of a motor can be controlled by the direction of the current through the motor, if we invert the voltages at both pins, the motor will also change its direction. The speed of a motor can be controlled by the duty cycle of a PWM signal. Both concepts are explained in the following pictures.

direction

lcd lcd_code

We can produce the necessary waveforms for motor 1 as follows: To drive forward, the input speed is a positive number between 0 and 100. In this case we pull the Motor 1 DIR pin (pinnumber 43) low by using the digital Write command. To set the speed, we initiate a PWM signal on the Motor 1 PWM pin (pinnumber 44) by converting the speed to a duty cycle between 0 and 1 and pass this to the Set Duty Cycle command. To drive backward: the input speed is a negative number between 0 and -100. In this case we set the DIR pin high, as a consequence we have to invert the duty-cycle (note that since the DIR pin is high a duty-cycle of 1 (high level) will stop the motor, while a duty-cycle of 0 (low level) will drive the motor full speed backwards). Exactly the same applies to the second motor, so we can use arrays instead of single values. The calculation of the duty-cycle is done in a loop which iterates over each value of the input speed array.

Servo

You can control a servo with the LINX commands 'Servo Open', 'Servo Set Pulse Width' and 'Servo Close'. The desired position of the servo is send in the form of a PWM signal, like shown in the picture below.

servo PWM

First we need to attach a servo to a certain pin number (just like the arduino servo.attach() function). Pass the pin-number you'll find In the pin mapping table (pin 40 and 41) to the LINX command 'Servo Open' to attach the servo's. You only need to do this once (typically at the beginning of your program). At the end you can detach a servo by using the 'Servo Close' command.

servo_open servo_close

Use the 'Servo Set Pulse Width' command to set the servo position. This command needs 2 extra arguments: the pinnumber(s) of the attached servo and the pulse width of the PWM signal. The calculation shown below, converts an angle in degrees (0 - 180) to the corresponding pulse-width (500 µs - 2100 µs). The min and max pulse-width depend on the servo type.

servo servo_code

Custom commands

LINX provides already a lot of commands to control digital and analog ports, servo, DC motor, buzzer but also commands to use SPI and I2C protocols (not discussed in this tutorial). A lot of your ideas can be build using this set of commands. However sometimes you can face a problem that isn't, for example if you want to do some dwenguino-specific things like driving an LCD display. LINX provides a way to implement your own custom commands: you can write your own function in the dwenguino firmware, which you can control from within labview.

  • Open the arduino IDE.
  • Open the LabviewLinxInterface firmware (from to the menu Examples > Dwenguino > LabviewLinxInterface) .
  • Add a new function at the end of the code, this function should have 4 arguments: the number of bytes you expect from Labview, the input array of bytes, a pointer to the variable defining the number of response bytes and a pointer to the actual response array (bytes that will be send to Labview as answer). Your function should return 0 if everything went well, otherwise it should return some error number. The following simple example echos the input array and returns 0 as acknowledgment.
  1. int myCustomCommand(unsigned char numInputBytes, unsigned char* input, unsigned char* numResponseBytes, unsigned char* response) {
  2.  
  3. for(int i = 0; i < numInputBytes; i++) {
  4. response[i] = input[i];
  5. }
  6.  
  7. *numResponseBytes = numInputBytes;
  8. return 0;
  9. }
  • Add your new command to the LINX listener with a an id between 2 and 63. Note that the custom commands 0 and 1 are already taken by the readPullup and writeLCD commands discussed in the previous sections. Add the following line to the setup function.
  1. LinxSerialConnection.AttachCustomCommand(0x02, myCustomCommand);
  • Upload this sketch to the Dwenguino.
  • Now you can use the custom command function in Labview. This command requires 2 extra inputs: the custom command id of your new function and an array of input bytes. The output of this command is an array containing the response bytes from your custom command.

Additional Materials