Download TR11-211 - Faculty of Computer Science

Transcript
Communication and Control of a Digital Wind Sensor
by
Victoria Pimentel and Bradford G. Nickerson
TR11-211, October 14, 2011
Faculty of Computer Science
University of New Brunswick
Fredericton, N.B. E3B 5A3
Canada
Phone: (506) 453-4566
Fax: (506) 453-3566
E-mail: [email protected]
http://www.cs.unb.ca
Contents
1 Introduction
2
2 Activities
2
3 Tests Settings
2
4 WindSonic Installation
4
5 Data Communication
5.1 Java RXTX Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
5.2 Solution to Avoid Extra Characters in Even Positions . . . . . . . . . . . . . . . . .
5
9
9
6 Interface Approach
10
References
12
A USPP Readme File
13
B Example of a Kermit Input File
14
C WindSonic Command Description
15
D Interface File
16
E RXTX Library Example
19
1
1
Introduction
This report describes the integration of a solid state wind sensor with sensor web based hardware
and software. The work described is part of the project entitled Web Display of Real-time
Environmental Sensor Data as part of the course “Pasantı́a Larga” code EP3420, from the
Computing Engineering program in Universidad Simón Bolı́var, Caracas, Venezuela.
2
Activities
The following activities were carried out:
1. Installation of WindSonic wind sensor and first tests.
2. Investigate and test data communication with WindSonic wind sensor.
3. A first approach to the interface for displaying sensor data.
3
Tests Settings
The computers needs for this exercise are shown in Figure 1.
Figure 1: Hardware requirements for WindSonic software development.
In order to use the manufacturer’s software(e.g. WindView) the development computer must be
running Windows XP or above. For the rest of the tests carried out here, the development computer
was running CentOS version 5.6 with Minicom text-based modem control with terminal emulation
installed and the Python programming language version 2.7.2. The development computer is used
to receive and display data received from the WindSonic.
The Gill WindSonic, option 3 with analog plus serial (RS232, RS422 and RS485) output and serial
number 08320007, is connected to the development computer through an RS232 output cable. An
2
RS232 to USB adapter is used to connect the cable to an USB serial port in the development
computer. The serial cable has a special connector fabricated by the manufacturer [12]. A picture
of the Gill WindSonic with attached RS232 serial cable is shown in Figure 2 (a). A picture of all
the devices and instruments used for the tests described is shown in Figure 2 (b).
Figure 2 (a): Gill WindSonic with the special connector fabricated by the manufacturer.
Figure 2 (b): Devices and instruments used to test the Gill WindSonic.
3
4
WindSonic Installation
The WindSonic was connected to a 12V, lead acid Discovery battery. For the first test the software
WindView was downloaded from the WindSonic manufacturer webpage [10] and installed in a
computer runnig Windows 7. This software works for WindSonic wind sensors with serial numbers
08100001 and onwards. WindView communicates with the sensor, receives data and displays it.
WindView can show the data as received from the sensor, as shown in Figure 3. For example, the
first line of data displayed has “Q” that is the instrument identifier,“123” stands for the direction
the wind is blowing from, “002.70” stands for the current wind speed in meters per second, “M”
indicates that the unit for wind speed is meters per second, “00” is the status code, and “1B” is the
checksum. Note that no date and time is available from the instrument. Further details of setting
display options are found in [12].
Figure 3: WindView displays the sensor data as received.
It can also display a graphic that plots both wind speed and direction, as shown in Figure 4.
Figure 4: WindView plots both wind speed and direction.
4
For a more graphic approach, WindView can also display a compass-like graphic where the number
corresponding to wind speed is displayed and wind direction is represented with an arrow that
moves pointing on the current wind direction, as shown in Figure 5.
Figure 5: WindView displays a compass-like graphic for wind direction and displays the number
corresponding wind speed.
Tests were done using a floor fan to significantly increase and decrease wind speed and rotating
the sensor to vary wind direction. Changes in wind speed and direction were observed through the
WindView interface.
The WindSonic sensor operates in two modes; continuous or polled. In continuous mode, the
WindSonic takes and sends measurements from one to four times a second, while the polled mode
sends a measurement only upon a host request. The WindView software does not allow changing
to polled mode so it was only tested in continuous mode.
5
Data Communication
Data communication between the wind sensor and the development computer ib222m07 running
CentOS 5.6, was tested using three differents strategies and following the command descriptions
found in the WindSonic user manual [12] for continuous, polled and configuration mode. Appendix
C shows an extract of the WindSonic user manual that explains the available commands on polled
mode and their meaning.
1. Minicom.
With the following settings:
Serial Port Setup:
| A Serial Device
| B - Lockfile Location
| C Callin Program
| D - Callout Program
| E Bps/Par/Bits
| F - Hardware Flow Control
| G - Software Flow Control
:
:
:
:
:
:
:
/dev/ttyUSB0
/var/lock
9600 8N1
No
No
5
|
|
|
|
|
|
|
Modem and Dialing:
|A - Init string .........
|
Minicom provided an easy way for receiving and configuring the WindSonic. If the WindSonic
is turned on and connected in continuous mode (which is the default mode), as soon as
Minicom starts the messages received are displayed in near real time, as shown in Figure 6.
Figure 6: Screenshot of a Minicom window showing measurements received in continuous
mode.
To configure the WindSonic (command “*”) and return to measurement mode (command
“Q”), the instructions and commands on the WindSonic user manual were strictly followed,
and the expected output was observed. Tests were done changing configuration options and
observing the expected changes in bahavior. Switching from continous to polled mode and
vice versa can be done as well as sending a measurement request and receiving the answer.
Figure 7 shows the change to polled mode with the command “M4” followed by the echo
made from the WindSonic. Then the command “?” was sent to activate the polled mode
and command “Q” (which is the node unique identifier) was sent four times to request four
measurements. In polled mode the commands written and sent to the WindSonic are not
displayed, only the received answer.
6
Figure 7: Screenshot of a Minicom window were change to polled mode and four
measurement requests are done and answered.
2. Python 2.7.2.
The USPP [11] library was downloaded and installed. It is a tool to communicate from a
Python environment to the serial port by calling simple methods for reading and writing.
The USPP library has three main functions, its use is explained in the Readme file shown in
appendix A.
To read from the serial port; the function inWaiting() was called first; it returns the number
of characters left unread. Then, the function read(n) was called with n being a number less
than or equal to the one returned by the inWaiting() function.
Writing to the serial port uses the function write(str), with str being the command that is
intended to be sent to the WindSonic. In configuration mode, the command string needs to
end with the “\r” character; otherwise the sensor will not recognize it.
Some problems arose when the configuration was changed to polled mode. Apparently the
sensor is not reading all the characters sent but only the ones at odd positions on the command
string. In order to get the command “D3” sent, the method call write(“D3\r”) would not
work. If called with any other character on the even positions like write(“DA3B\r”), the
sensor reads the command “D3\r”, and answers correctly.
3. Kermit.
The command kermit input.txt >output.txt was used to call Kermit with the commands on
the input file and get the responses written to an output file. An example input file for Kermit
is shown in appendix B.
The use of Kermit gave the same problem of reading only every second character that was
found with the USPP Python library when trying to execute any command from the polled
mode.
7
In summary, changing configuration and polled mode works fine with minicom, but not with Kermit and Python. Both Kermit and Python require extra characters in even positions to get the
WindSonic to correctly accept polling and configuration commands in polled mode.
The following steps were carried out to compare Minicom and the USPP Python library:
Minicom is so far the clearer and most robust strategy for communicating with the Gill WindSonic
. Minicom’s weakness shows when binding with a web application interface because a file is going
to be needed and it may slow down the application. The easiest way of working with command
files is using Kermit as explained. Kermit has problems when running commands from the polled
mode, so we might just as well use the Python library avoiding the need to use command files.
Now a new problem arises and it is how do we show these wind sensor observations using a web
based interface? Three strategies are proposed.
1. Access Python code from JavaScript.
Pico [7] is a small web application framework that allows us to write Python modules, classes
and functions that can be imported and called directly from JavaScript. Testing is required.
2. Access the serial port from a JavaScript file.
Node Serial Port [6] is a library that allows access to a serial port from JavaScript. Testing
8
is required.
3. Use a file that saves Python output and is read by JavaScript.
JSON [5] can be used as a format for serializing Python objects [9] and make them accessible
to other programming lenguages like JavaScript. Testing is required.
None of these strategies were tried as a Java communication library was discovered.
5.1
Java RXTX Library
RXTX [8] is a Java library that provides serial and parallel communication for the Java Development
Toolkit (JDK). To get RXTX working on CentOS, Java JDK 7 with Netbeans IDE 7.0.1 [4] were
installed.
The Netbeans project has to include the .jar library file under the lib project folder. Also an
environment variable called LD LIBRARY PATH has to be set from Netbeans by adding the target
“-init-macrodef-java” found on the build-impl.xml file under nbproject directory, to the file buil.xml
and editing it by adding the following line above the “customize” tag:
<env key="LD_LIBRARY_PATH" value=path />
The word “path” should be replaced by the path to the library librxtxSerial.so and librxtxParallel.so
files. On the ib222m07 test computer, the path was specified as follows:
<env key="LD_LIBRARY_PATH"
value=/usr/java/rxtx-2.1-7-bins-r2/Linux/i686-unknown-linux-gnu />
Once the installation is successfull, the import to gnu.io methods should be done along with the
correct initializations, as shown in Appendix E.
Once a successfull connection with the serial device is established, the RXTX library returns a Java
InputStream for reading from the serial port and a Java OutputStream for writing into the serial
port. These two Java classes give flexibility for reading and writing because they can work with
chars or become BufferedReader and BufferedWriter respectively, to work with strings.
The RXTX was tested with the WindSonic in both polled and continuos mode and the expected
behavior was observed. The RXTX library also requires extra characters in even positions to get the
WindSonic to correctly accept polled and configuration commands in polled mode, just as Python
and Kermit do. After a command is written to the WindSonic a delay occurs before data is available
to be read. Our tests indicate that a sleep period of at least 250 ms is required to consistently read
the data, except for commands that change configuration settings of the WindSonic, such as mode
change, that require at least 750 ms. Without a sleep period blank answers are observed.
Using a Java library to communicate to the WindSonic throught the serial port, will make easier
to display sensor data in a web based interface. Java applets or servlets can be used to access Java
code from a web application.
5.2
Solution to Avoid Extra Characters in Even Positions
Gill Instruments technical support [1] was contacted in September 2011 to see if they could provide
fix for missing odd characters in polled mode. Murree Sims was able to provide a solution to this
problem. Their solution consists of sending a command character by character with an added delay
between characters. Tests were done using RXTX Java library adding a 20 ms delay by calling the
Java Thread.sleep(20) method as show in the following code:
9
char[] arr = command.toCharArray();
for(int k=0; k<arr.length; k++){
Thread.sleep(20);
serialOut.write(arr[k]);
}
This solved the need for extra characters. Polled and configuration commands can now be sent in
polled mode without adding extra characters to the odd positions in the command string.
Similar results were obtained for the Python USPP library. The method write(ch) was called once
for each character of the commad string.
Adding delay and sending a command string character by character is not ideal. Fortunately, most
of the commands for the WindSonic are 2 characters in length which would imply only a 40 ms
delay when sending a command string.
6
Interface Approach
Canvas - HTML5 [2] and JavaScript [3] were used to create a first approach of the interface for
displaying sensor data with a compass like graphic.
The WindSonic output for wind direction is an integer interpreted in degrees; North direction
corresponds to zero degrees and the angles increase clockwise, which means East is 90 degrees,
South is 180, and West is 270. This angle will be used to obtain a line pointing in the direction
of the wind. On the other hand, drawing a line with the Canvas element of HTML5 requires the
start and end points of the line in the Canvas plane. Geometry concepts where applied to the input
angle so the end point could be calculated being the start point the known center of the compass
as shown in Figure 8.
Figure 8: Compass with the representation of a 130 degree wind direction.
Some HTML and JavaScript code were written to create a one field form where the user can enter
an angle assuming it to be the current wind direction and press a button that causes the line
representing that direction to be drawn in the compass, appendix D shows this code. The user
input was used because the interface is not connected to the sensor output yet. Figure 9 shows the
interface with a user input of 45 degrees.
10
Figure 9: Screenshot of wind direction interface first draft with a 45 degree input.
11
References
[1] Anemometer contact details - gill. Internet (accessed September, 2011). http://www.gill.
co.uk/main/contactan.htm.
[2] Html5 canvas tutorial (accessed
html5canvastutorials.com/.
august,
2011).
Internet.
http://www.
[3] Javascript tutorial. Internet (accessed August, 2011). http://w3schools.com/js/default.
asp.
[4] Jdk 7 with netbeans. Internet (accessed September, 2011). http://www.oracle.com/
technetwork/java/javase/downloads/jdk-7-netbeans-download-432126.html.
[5] Json. Internet (accessed August, 2011). http://www.json.org/.
[6] Node serial port - github. Internet (accessed August, 2011).
voodootikigod/node-serialport.
https://github.com/
[7] Pico - github. Internet (accessed August, 2011). https://github.com/fergalwalsh/pico.
[8] Rxtx wiki. Internet (accessed September, 2011). http://rxtx.qbang.org/wiki/index.php/
Main Page.
[9] Serializing python objects. Internet (accessed August, 2011). http://diveintopython3.org/
serializing.html.
[10] Ultrasonic wind sensor - windsonic. Internet (accessed August, 2011). http://www.gill.co.
uk/products/anemometer/windsonic.html.
[11] Uspp(universal serial port python library) - ibarona. Internet (accessed August, 2011). http:
//sites.google.com/site/ibarona/uspp.
[12] Gill Instruments Limited. WindSonic GPA Manual - Issue 20, July 2011. http://www.gill.
co.uk/data/manuals/WindSonic-GPA-manual-issue-20.pdf.
12
A
USPP Readme File
This file is part of the Python library USPP. This section was extracted from the Readme file and
it explains how to use the library and provides an example.
6. Usage and documentation
-------------------------You only have to import in your program the uspp module and automatically
it loads the correct classes for the platform in which you are running
the program.
First of all you have to create a SerialPort object with the settings you
want. If a SerialPortException is not generated then you just can
use the read and write methods of the object to read and write to
the serial port.
Example:
>>> from uspp import *
>>> tty=SerialPort("COM2", 1000, 9600)
>>> # Opens COM2 at 9600 bps and with a read timeout of 1 second.
>>> tty.write("a") # Writes a character to the COM2 port
>>> # Now suppose we receive the string "abc"
>>> tty.inWaiting()
3
>>> tty.read()
’a’
>>> tty.inWaiting()
2
>>> tty.read(2)
’bc’
Documentation of the different classes and methods can be found on
uspp module docstring.
13
B
Example of a Kermit Input File
This is the input file used to run Kermit, it contains the list of the commands to be executed on
the serial port.
SET MODEM TYPE NONE
SET LINE /dev/ttyUSB0
IF FAIL EXIT 1 "Device not available"
;SET SPEED 9600
;SET FLOW-CONTROL RTS/CTS
;SET INPUT ECHO ON
set carrier-watch off
OUTPUT *
INPUT 3 OK
OUTPUT D3\13
INPUT 3 OK
OUTPUT M4\13
INPUT 3 OK
OUTPUT Q\13
INPUT 3 OK
exit
14
C
WindSonic Command Description
These commands are only for the polled mode, as explained in the WindSonic user manual.
15
D
Interface File
The following file was created as the first approach to the sensor data interface. It is written in
JavaScript and HTML5.
<!DOCTYPE HTML>
<html>
<head>
<title>Test - HTML5 Canvas</title>
<center>
<b>Test Using HTML5 Canvas</b>
</center><br />
</head>
<body>
<center>
<canvas id="element" width="800" height="610">
This browser does not support Canvas elements
</canvas><br />
</center>
<script type="text/javascript">
/* Calculates the second point on a line which origin is (Ax, Ay), has
a length of c and forms an angle alpha with the North */
function getPoint(alpha, Ax, Ay, c){
var alphaR = alpha*0.0174532925;
var a = c*Math.sin(alphaR);
var b = c*Math.cos(alphaR);
return [a+Ax, b+Ay];
}
/* Draws a line which origin is the center of the main circle, has a
length of the circle’s radius and forms the angle inserted by the
user with the north */
function displayLine(){
var angle = document.getElementById("angle").value;
var point = getPoint(angle, centerX, centerY, radius);
refresh();
elem.moveTo(centerX, centerY);
elem.lineTo(point[0], 600-point[1]);
elem.stroke();
}
/* Refreshes the Canvas element for a new drawing */
function refresh(){
elem.clearRect(0,0,canvas.width,canvas.height);
drawCircle();
drawLetters();
}
16
/* Draws the main circle and its center */
function drawCircle(){
elem.beginPath();
elem.arc(centerX, centerY, radius, 0,2*Math.PI, false);
elem.lineWidth = 5;
elem.strokeStyle = "black";
elem.stroke();
elem.beginPath();
elem.arc(centerX, centerY, 3, 0,2*Math.PI, false);
elem.fill();
elem.lineWidth = 3;
elem.stroke();
}
/* Draws the letters indicating the North, East, South and West
directions with their angles*/
function drawLetters(){
elem.font = "30pt Calibri";
elem.textAlign = "center";
elem.textBaseline = "top";
elem.fillText("N", 400, 10);
elem.textAlign = "center";
elem.textBaseline = "bottom";
elem.fillText("S", 400, 610);
elem.textAlign = "center";
elem.textBaseline = "middle";
elem.fillText("E", 685, 300);
elem.textAlign = "center";
elem.textBaseline = "middle";
elem.fillText("W", 90, 300);
elem.font = "20pt Calibri";
elem.textAlign = "center";
elem.textBaseline = "top";
elem.fillText("0", 400, 45);
elem.textAlign = "center";
elem.textBaseline = "bottom";
elem.fillText("180", 400, 565);
elem.textAlign = "center";
elem.textBaseline = "middle";
elem.fillText("90", 650, 300);
elem.textAlign = "center";
elem.textBaseline = "middle";
elem.fillText("270", 140, 300);
}
17
var radius = 225;
var centerX = 400;
var centerY = 300;
/* Initiates the Canvas element */
var canvas = document.getElementById("element");
var elem = canvas.getContext("2d");
drawCircle();
drawLetters();
</script>
<center>
<br /><form>
Angle: <input type="text" name="angle" id="angle"/>
<input type="button" value="Draw Line" onclick="displayLine()"
id="b1" />
</form><br />
</center>
This small application shows a compass like drawing that is going to be used to
display wind direction. It receives an angle in degrees as input, this angle is
asumed to be the current wind direction and the application draws a line to
display it in a graphic sense. North corresponds to zero degrees and the angles
increase clockwise, which means East is 90 degrees, South is 180, and West is
270.
</body>
</html>
18
E
RXTX Library Example
The following file shows an example of serial communication for the WindSonic using the RXTX
Java library.
import
import
import
import
import
gnu.io.*;
java.io.InputStream;
java.io.BufferedReader;
java.io.InputStreamReader;
java.io.OutputStream;
public class TalkingSerialPort {
/*
* @params: portName string
* This method access and returns a connection to the serial device on the address
* passed as argument
*/
static SerialPort connect (String portName) throws Exception {
CommPortIdentifier portIdentifier = CommPortIdentifier.getPortIdentifier(portName);
SerialPort sp = null;
if(portIdentifier.isCurrentlyOwned()){
System.out.println("Error: Port is currently in use");
return sp;
} else {
CommPort commPort = portIdentifier.open("TalkingSerialPort",2000);
if(commPort instanceof SerialPort) {
sp = (SerialPort) commPort;
sp.setSerialPortParams(9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.FLOWCONTROL_NONE);
} else {
System.out.println("Error: Only serial ports are handled by this example.");
}
}
return sp;
}
public static void main(String[] args) {
SerialPort sp = null;
InputStream in = null;
OutputStream out = null;
String command = "";
try {
/* Call to connect method with the known WindSonic serial address */
sp = connect("/dev/ttyUSB0");
19
if(sp != null){
in = sp.getInputStream();
out = sp.getOutputStream();
} else
System.out.println("The connection was not successfull.");
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
BufferedReader user = new BufferedReader(new InputStreamReader(System.in));
/* This loop performs interaction to execute on the serial device the commands
written by the user and read the number of bytes selected by the user */
while(true){
System.out.print("Enter command:");
command = user.readLine();
if(command.equals("bye"))
break;
command = command + "\r";
try {
/* Send the bytes corresponding to the string entered by the user */
out.write(command.getBytes());
System.out.println("Written");
} catch(Exception e) {
e.printStackTrace();
}
try {
/* Sleep a prudential time to wait for the WindSonic answer */
Thread.sleep(2000);
} catch (Exception e) {
System.out.println("Sleep error");
}
/* Shows to the user the availabre number of chars to be read, the user
should select a less or equal number of bytes to avoid blocking */
System.out.print("Chars available to read:");
System.out.println(in.available());
System.out.print("Enter number of Chars to read:");
command = user.readLine();
int num = Integer.parseInt(command);
/* Read the number of chars selected by the user */
for(int i=0; i<num; i++){
char c = (char) reader.read();
System.out.print(c);
}
}
System.out.println("Program closed");
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
20