Wireless Data Acquisition System Project Report Tim Pieper...
Transcript of Wireless Data Acquisition System Project Report Tim Pieper...
Wireless Data Acquisition System
Project Report
Tim Pieper
Advisor: Professor Gutschlag
May 12, 2008
2
Abstract
The Wireless Data Acquisition System (WiDAS) is intended to be used with the Bradley University SAE
Formula Car. The Bradley University Formula SAE car is a yearly project task for mechanical engineering
seniors. WiDAS will gather data from the SAE car and display important information to the driver
through a LCD screen mounted in the car. Data will also be wirelessly transmitted to an off-track laptop
where the data can be displayed and recorded. Transmitted data includes information such as car
velocity, engine speed, acceleration, engine coolant and air temperatures, oil pressure, and suspension
travel. The in-car display is an Amulet Technologies LCD touch screen, and a pair of Aerocomm
transceivers are used for wireless transmission.
3
Table of Contents
Abstract …………………………………………………………………………………………………………………………. 2
Introduction …………………………………………………………………………………………………………………………. 4
System Block Diagram ……………………………………………………………………………………………………………. 5
System Functions ……………………………………………………………………………………………………………. 6
Data Acquisition ……………………….………………………………………………………………………. 6
Data Transmission ……………………….………………………………………………………………………. 8
Wireless Communication …………..………………………………………………………………………. 10
Data Destination ……………………….………………………………………………………………………. 12
WinWedge ……………………….….……………………………………………………………………. 12
DataQ XControls Toolbox ………………………………………………………………………. 13
Excel ………………………..………………………………………………………………………. 14
Results and Analysis …………………………………….………………………………………………………………………. 15
Equipment …………………………………….………………………………………………………………………. 18
Sources …………………………………….………………………………………………………………………. 18
Appendices
Appendix A – Aerocomm OEM Configuration Tool Screenshots …………………………………. 19
Appendix B – Software
B-1 Test Program Assembly Code ………………………………………………………….. 21
B-2 Excel Macros ………………………………………………………………………. 37
B-3 Proposed Code for Integration ………………………………………………………….. 39
4
Introduction The Wireless Data Acquisition System is intended to be used with the Bradley University SAE Formula
Car. This system will gather data from the SAE car and display important information to the driver
through a LCD screen mounted in the car. Data will also be wirelessly transmitted to an off-track laptop
where the data can be displayed and recorded. Transmitted data will include information such as car
velocity, engine speed, acceleration, engine coolant and air temperatures, oil pressure warning, and
minimum and maximum suspension travel.
The in-car display used will be an Amulet Technologies LCD touch screen. This display was developed
previously in a 2006 electrical engineering capstone project by David Pavlik. The system was fully
operational when tested in the lab, but due to time and schedule constraints, it was not implemented
on the SAE formula car. A pair of Aerocomm transceivers will be used for wireless transmission.
This system will provide additional design and testing feedback for the SAE car senior project. During
normal operation, both the driver and the supporting team will have a visual representation of the car’s
status. In addition to the expanded troubleshooting capabilities available with the presence of real-time
data, warning of component fatigue or failure can be communicated from the team to the driver.
To display the desired data on a laptop, two main programs will be utilized. A program called
WinWedge reads the data from the serial port and is capable of formatting the data as desired.
WinWedge then uses ‘dynamic data exchange’ (DDE) to import information into Excel in real-time. In
Excel, a special toolbox is used to create a virtual dashboard to display information. Finally, Excel
macros are used to log the incoming data and interface with WinWedge.
5
System Block Diagram An overall system block diagram is shown in Figure 1. The diagram shows the microcontroller that
samples the formula car ECU/sensors and its connection to both displays. The Amulet LCD and
Aerocomm transmitter utilize serial ports available on the microcontroller. The Aerocomm receiver is
connected to a laptop serial port. WinWedge and Excel software packages are used to import, display,
and log data received over the laptop serial port.
Figure 1 – Complete System Block Diagram
6
System Functions
Data Acquisition
The formula car ECU and/or sensors will be sampled using a microcontroller and its analog-to-digital
converter (ADC). The analog voltage signal is converted to a digital signal, and lookup tables are used to
find the air to fuel ratio, coolant temperature, and air temperature values. Engine speed and vehicle
speed are obtained by recording the number of pulses generated by each sensor in a fixed time. Table 1
lists the important sensors and a brief description.
Sensor Type Notes
Car Velocity Pulse Wheel Sensor
Engine Speed Pulse Ignition coil input
Oil Pressure Switch Activated when safe pressure is not maintained
Water Temperature Variable Resistor
Coolant Temperature Variable Resistor
O2 Variable Voltage
Suspension Travel (4) Variable Voltage
Table 1 – Formula Car Sensor List
An assembly language microcontroller program was developed to test the system in the lab
environment. When the project is fully completed, the functionality of this program will be added to the
current microcontroller driven LCD program in the form of function calls. Therefore, very little
modification of the microcontroller driven LCD program is necessary. The added functions will be
responsible for sending sampled data over the RF communication link. Figure 2 is a software flow chart
describing the test program developed for the system.
7
Figure 2 – Test System Software Flow Chart
The ADC inputs were protected by a circuit utilizing two Germanium diodes (1N270) and a 1kΩ resistor.
Figure 3 is the schematic for the protection circuitry. By using a 5VDC source, the input to the ADC is
never greater than 5.3 V. This protection circuitry is necessary to preserve the integrity of the
microcontroller’s analog inputs, but still allows full functionality of varying sensor voltages from 0-5
volts.
Figure 3 – ADC Protection Circuit
8
Data Transmission
Once the analog signals have been sampled and recorded, the next step is to send the data over one of
the microcontroller’s two available serial ports. The setup of the serial port used (COM1) is executed in
the “Init2861.a51” file where the following parameters are set: 9600 BAUD, 8 data bits, no CTS (clear to
send), no RTS (request to send), no parity, one stop bit. These parameters were setup using the
MicroPac 535 the microcontroller datasheet and the SC26C92 Dual Universal Asynchronous
Receiver/Transmitter (DUART). The second available serial port on the microcontroller (COM2) has
been implemented for the microcontroller driven display project of 2006. Asynchronous
communication was chosen since data is only flowing in one direction (from microcontroller to
Aerocomm transceivers). However, CTS and Session Status pins on the Aerocomm transceiver are still
monitored to prevent data loss due to the transceiver being busy.
In the test program for the microcontroller, the ADC data bytes are hexadecimal values. The
“breaknsend” function splits the single hexadecimal byte into two separate bytes. One byte
corresponds to the upper nibble (4 most significant bits), and the second byte corresponds to the lower
nibble (4 least significant bits). Both nibble bytes are then converted to ASCII to prepare them for
transmission.
The Tx signal pin of COM1 is routed through an MC1489 integrated circuit to convert the RS232 voltage
level signal to the TTL voltage level signal that is required by the Aerocomm transceivers. Figure 4
provides an oscilloscope output of the MC1489 implementation. The TTL serial signal is connected to
the Aerocomm transmitter “Rx” pin. The data on this pin is the data that will be transmitted to the
receiver.
9
Figure 4 – RS232 (Channel 1) to TTL (Channel 2) Conversion via MC1488
On the laptop end of the system, the “Tx” pin of the Aerocomm receiver outputs the data received from
the transmitter. This is a TTL serial signal that needs to be converted to RS232 voltage levels to be
received by the laptop serial port. Figure 5 shows the conversion of the TTL serial signal to RS232
voltage levels using a MC1489 integrated circuit.
Figure 5 – TTL (Channel 1) to TTL (Channel 2) Conversion via MC1489
10
Wireless Communication
Wireless communication is achieved by using Aerocomm AC4690-200 900MHz wireless transceivers.
The Aerocomm OEM System Development Kit (SDK) provided the wireless transceivers and also aided in
setting up and troubleshooting the transceiver
system. The SDK boards permitted direct
programming of the transceiver EEPROM settings
and preliminary transmission tests between the
transmitter and receiver before attempting to
implement the units into the test system. Table 2
below provides the list of EEPROM parameters,
settings, and descriptions. (See Appendix A for
Aerocomm software screenshots.)
Interface Timeout 0x05h Timeout = [Value x 2.5ms]
(determined by Baud selection)
RF Packet Size 0x0Ch Number of data bytes per transmission attempt
CTS On 0x0Ch (transmitter)
0x01h (receiver)
Specified number of bytes that need to be in transceiver
buffer before CTS is set to prevent additional filling of the
buffer
CTS Off 0x01h Maximum number of bytes left in the transceiver buffer
before CTS cleared (ready for more data)
Broadcast Attempts 0x01h Number of transmit attempts
Stop Bit Delay 0xFFh 0xFFh = Disabled
RF Channel Number 0x00h Determines hopping sequence for the chosen frequency
band (Frequency Hopping Spread Spectrum Protocol)
System ID 0x01h Must be the same for both transceivers
Interface Baud 9600 Communication settings
Table 2 – Important Transceiver EEPROM settings
Figure 6 – Aerocomm OEM System Development Kit
11
To transmit a data packet using the wireless transceiver with the previously stated settings, the
following minimum pin connections are necessary.
Pin – 2 – Tx (shows data received from RF
transmission – receiver)
Pin – 3 – Rx (send data for RF transmission –
transmitter)
Pin – 5 & 16 – Ground (internally connected)
Pin – 7 – CTS’ (active low, monitor for
transmit ready status)
Pin – 10 & 11 – Vcc (internally connected)
Pin – 17 – Command/Data (must be 5V for
Data, otherwise interpreted as
Commands for the device)
Pin – 20 – Session Status’ (active low,
monitor for transmit ready status)
The time needed to successfully transmit and receive a packet of information wirelessly was determined
through oscilloscope measurements. Figure 8 shows oscilloscope channel one monitoring the data
being transmitted, and oscilloscope channel two monitoring the data being received. The result was
measured as 56.4ms from the beginning of the transmitted TTL data to the end of the received RS232
data.
Figure 7 – Aerocomm Transceiver
Figure 8 – RF Packet Timing
12
Data Destination
The remote laptop is connected to the Aerocomm receiver signal after voltage conversion using the
previously mentioned MC1489. The laptop’s serial port Rx and Ground pins are connected to the RS232
voltage level output of the MC1489 and ground, respectively. With this setup, the laptop can read the
data packets that are sent over the RF link. Originally, a combination of Matlab and Simulink were to be
used to read and display serial port information. However, after much research and troubleshooting it
was evident that another method would be necessary.
WinWedge
WinWedge is a software package designed specifically for reading data from a serial port and interfacing
directly with other programs. For this project, WinWedge is used to inject the received data directly into
Excel via the Dynamic Data Exchange (DDE) protocol. “The DDE protocol is a set of messages and
guidelines. It sends messages between applications that share data and uses shared memory to
exchange data between applications. Applications can use the DDE protocol for one-time data transfers
and for continuous exchanges in which applications send updates to one another as new data becomes
available” [1].
The basic setup of WinWedge consists of selecting the appropriate serial port settings. In this case, 9600
Baud, eight data bits, no parity, one stop bit, and no flow control were selected. Specific DDE settings
include selecting the program name that WinWedge is communicating with and identifying additional
commands to run at the point of data transfer. WinWedge is set up to run a macro every time a data
string is imported into Excel. The macro is responsible for placing the data from WinWedge into the
Excel worksheet as well as copying the data to the “Log” worksheet. Incoming data can also be
formatted when fields of known lengths are set. For example, in the test program, AFR data, coolant
13
Figure 10 – DATAQ XControls Instrument Pack
temperature data, and air temperature data are two, four, and four ASCII bytes respectively. WinWedge
then separates these data fields which allow the Excel macro to distribute packet data into separate
cells.
DATAQ XControls Instrument Pack
The second software package used to display data on the laptop is the DATAQ XControls Toolbox. This
toolbox provides 27 configurable instrumentation
components for real-time data display. Figure 10
shows a variety of different types of instrument
displays that can be customized. (The displays
are based on the ActiveX environment.) This
software package is accessible from the Controls
Toolbox in Excel [2].
Figure 9 – WinWedge Setup Screenshots
14
The XControls Toolbox provides the perfect environment for creating a dashboard display for data sent
from the microcontroller on the formula car. Individual gauges were created to represent the
information being received by the laptop. Each gauge is setup for a specific sensor and displayed in real-
time by the “linked cell” property of the gauges. The virtual dashboard for the system is shown in Figure
11.
Excel
Visual Basic macros tied together the entire operation of displaying and recording received data.
Additional macro functions were created for the ease of loading and exiting WinWedge directly from the
virtual dashboard worksheet. The loading process includes opening WinWedge with the proper setup
parameters discussed and displayed in the WinWedge section of this report. Additional macro functions
Figure 11 – Virtual Dashboard Worksheet
15
were written to place the incoming data into specific cells in the virtual dashboard worksheet, as well as
add new entries to the data log. (See Appendix C-2 for Excel macro software.)
Results and Analysis The task of wireless data transmission based on requirements dictated by the Bradley University SAE
Formula car was successfully accomplished. A microcontroller test program was developed to simulate
the sampling of vehicle sensors and send that data over an available serial port. The simulated samples
are a subset of the total sensor sampling that will be implemented on the car. Functions to add to the
2006 Microcontroller Driven Display senior project include the previously mentioned ‘breaknsend’ and
‘transmit’ routine. (See Appendix B-3 for proposed add-on assembly software.) The 2006 project is
already setup to sample the sensors of interest, so the addition of these software modules will allow the
2006 project to include wireless data transmission. In addition to software modules, a separate bank of
variables will be necessary for temporarily storing data that will be transmitted over the wireless link.
The wireless transceivers function as desired for 120ms periodic data transmission from the
microcontroller to the laptop PC. Upon intial setup, the entire test system was operating at 9600 Baud
with one broadcast attempt for the transceivers as shown in Figure 12. This yielded 75% - 80% data
packet success. Extending the interval at which the sampling and transmission were made did not yield
significant improvement in the number of successful transmissions. The next step involved setting up
the transceivers for two broadcast attempts. This allows the receiver to request another transmission
attempt if it detects an error in the data packet or does not receive the entire data packet within a
timeout period. Implementing two broadcast attempts significantly increased the success rate of RF
data packets. Roughly 500 packets needed to be sent before the receiver failed to recover two
consecutive broadcast attempts. Figure 13 shows successful data transmission on the first try for the
16
first two RF packets, but note the third RF packet utilizes the second broadcast attempt to successfully
complete the transmission.
Further optimization attempts included increasing the system Baud rate to 19.2k. This decreases the
amount of time necessary to transmit data over the serial port by half. The time needed for wireless
transmission decreased from 56.4ms to 43.2ms, a change of 13.2ms. This demonstrates the fact that
there is a significant amount of overhead involved
with transceivers establishing communication with
each other and transmitting information using the
Spread Spectrum Protocol. Although transmission
time was decreased, greater than 30% of RF packets
were lost, so the system was reset with 9600 Baud
and two broadcast attempts.
Figure 12 – 9600 Baud Wireless Transmission Figure 13 – Two Broadcast Attempts (9600)
Wireless Transmission
Figure 14 – 19.2kBaud Wireless
Transmission
17
To integrate this project with the 2006 project, the Aerocomm transmitter will need to be packaged with
an MC1489 (RS232->TTL voltage conversion) on the formula car. Important transceiver pins (CTS,
Session Status, CMD/Data, Rx Data, Vcc, GND) will also need to interface with the existing
microcontroller package. On the laptop PC end, the receiver will need to be packaged with an MC1488
(TTL -> RS232 voltage conversion). Voltage will also need to be provided to the MC1488 (+/- 15V) and
the Aerocomm receiver (5VDC). The data line from the receiver (TxD), once converted by the MC1488,
is connected to the Rx line of the laptop serial port. The ground pins of the Aerocomm receiver and the
laptop serial port also need to be connected to ensure proper operation.
The 2008 Wireless Data Acquisition project is operational, but not complete. Additional steps, as
discussed above, are still necessary to integrate this system with the 2006 Microcontroller Driven
Display project.
18
Equipment
Aerocom AC4790-200 Transcievers (2)
EMAC 8051 Microcontroller Kit
MC1488 – TTL to RS232 conversion IC
MC1489 – RS232 to TTL conversion IC
1N270 Germanium Diodes (2), 1kΩ Resistor – protection circuit
RS232 Breakout Connectors (2) – for RS232 pin connections
Agilent DC Power Supply
Bradley University Lab Laptop
Sources
[1] About Dynamic Data Exchange
http://msdn2.microsoft.com/en-us/library/ms648774(VS.85).aspx
Aerocomm – “AC4790 900 MHz OEM Transceivers User’s Manual”
http://www.aerocomm.com/docs/User_Manual_AC4790.pdf
Amulet Technologies
http://www.amulettechnologies.com
[2] DATAQ XControls Instrument Pack
http://www.dataq.com/products/software/xcontrols.htm
19
Aercomm OEM Configuration Tool Screenshots: APPENDIX A
Figure A-1 Aerocomm OEM Configuration Tool, Transceiver Settings
20
Aercomm OEM Configuration Tool Screenshots: APPENDIX A
Figure A-1 Aerocomm OEM Configuration Tool, Transceiver Settings
21
Test Program Assembly Code: Appendix B-1
AD_DA.A51 ;functions for reading from a A/D or writing to a D/A
$NOMOD51 ; disable predefined 8051 registers
$INCLUDE(reg515.inc)
AD_DA_SEG SEGMENT CODE
RSEG AD_DA_SEG
PUBLIC ReadAD
;Reads from an A/D, A/D specified by acc, value returned on acc
;source: MicroPac 535 data sheet Copyright 1993-1997, EMAC Inc.
ReadAD:
ANL A,#111B ; ONLY 8 CHANNELS
ANL ADCON,#11000000B ; MODE FOR A/D CONVERSION: SINGLE
ORL ADCON,A ; "OR" IN THE CHANNEL
MOV DAPR,#0 ; START CONV W/NO REF VOLTAGE
JB BSY,$ ; LOOP TILL CONVERTED
MOV ACC,ADDAT ; ACC = CONVERSION
RET
End
AIRTEMP.A51 ;Stuff related to the AirTemp sensor
;written by Tim Pieper
;
$NOMOD51 ; disable predefined 8051 registers
$INCLUDE(reg515.inc)
$INCLUDE(AD_DA.inc) ;A/D function
$INCLUDE(var.inc)
;$INCLUDE(myregs.inc) ;my registers and constants
;$INCLUDE(amulet.inc) ;amulet comunication functions
;$INCLUDE(lcd.inc)
;$INCLUDE(puta.inc)
AirTemp_SEG SEGMENT CODE
RSEG AirTemp_SEG
PUBLIC GetAir
;will get temp from AirTemp sensor
;flags, DPTR, & acc modified
;gets address of A/D with AirTemp sensor from myregs.inc file
GetAir:
mov a,#AirADAddr
lcall ReadAD
push acc
mov dptr,#AirTempTableLSB
movc a,@a+dptr ; get a character
22
; mov b,a
mov AirLSB, a
pop acc
mov dptr,#AirTempTableMSB
movc a,@a+dptr ; get a character
mov AirMSB, a
ret
AirTempTableMSB:
db
0Dh,0Dh,0Dh,0Dh,0Dh,0Dh,0Dh,0Ch,0Ch,0Ch,0Bh,0Bh,0Bh,0Bh,0Ah,0Ah,0Ah,0Ah,0Ah,0
Ah,09h,09h,09h,09h,09h,09h,09h,09h,09h,08h,08h,08h,08h
db
08h,08h,08h,08h,08h,08h,08h,08h,08h,08h,08h,07h,07h,07h,07h,07h,07h,07h,07h,0
7h,07h,07h,07h,07h,07h,07h,07h,07h,07h,07h,07h,07h,06h
db
06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,06h,0
6h,06h,06h,06h,06h,06h,06h,06h,06h,06h,05h,05h,05h,05h
db
05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,0
5h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h,05h
db
04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,0
4h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h,04h
db
04h,04h,04h,04h,04h,04h,04h,03h,03h,03h,03h,03h,03h,03h,03h,03h,03h,03h,03h,0
3h,03h,03h,03h,03h,03h,03h,03h,03h,03h,03h,03h,03h,03h
db
03h,03h,03h,03h,03h,03h,03h,03h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,0
2h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,02h,01h
db
01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,01h,00h,00h,00h,00h,00h,00h,0
0h,00h,00h,00h,00h,00h
AirTempTableLSB:
db
048h,048h,048h,048h,048h,048h,048h,0D2h,06Eh,017h,0CAh,086h,048h,011h,0DDh,0A
Eh,082h,05Ah,032h,010h,0EEh,0CDh,0B0h,092h,076h
db
05Dh,044h,02Ah,013h,0FEh,0E8h,0D2h,0BEh,0ABh,099h,086h,073h,063h,053h,042h,03
2h,021h,012h,004h,0F6h,0E8h,0D9h,0CBh,0BDh,0B0h
db
0A4h,098h,08Ch,07Fh,073h,066h,05Bh,050h,045h,03Ah,02Fh,024h,019h,00Eh,004h,0F
Ah,0F1h,0E8h,0DEh,0D4h,0CBh,0C1h,0B7h,0ADh,0A5h
db
09Dh,094h,08Ch,083h,07Bh,072h,069h,060h,057h,04Fh,048h,040h,039h,031h,029h,02
1h,019h,011h,009h,001h,0F9h,0F2h,0EBh,0E5h,0DEh
db
0D6h,0CFh,0C8h,0C1h,0B9h,0B2h,0AAh,0A2h,09Ch,095h,08Fh,088h,082h,07Bh,074h,06
Dh,066h,05Fh,058h,051h,04Ah,043h,03Dh,037h,031h
db
02Bh,024h,01Eh,017h,011h,00Ah,003h,0FCh,0F5h,0EEh,0E8h,0E2h,0DCh,0D6h,0D0h,0C
Ah,0C3h,0BDh,0B6h,0B0h,0A9h,0A2h,09Bh,094h,08Eh
23
db
088h,082h,07Ch,076h,070h,069h,063h,05Ch,056h,04Fh,048h,041h,039h,033h,02Dh,02
7h,021h,01Bh,015h,00Eh,007h,000h,0F9h,0F2h,0EBh
db
0E3h,0DCh,0D6h,0D0h,0C9h,0C3h,0BCh,0B5h,0AEh,0A7h,09Fh,097h,08Fh,087h,080h,07
9h,073h,06Ch,064h,05Dh,055h,04Dh,045h,03Dh,034h
db
02Bh,023h,01Ch,014h,00Ch,004h,0FBh,0F3h,0E9h,0E0h,0D5h,0CCh,0C4h,0BBh,0B2h,0A
9h,09Fh,094h,089h,07Eh,072h,069h,05Fh,054h,048h
db
03Ch,02Fh,021h,015h,009h,0FCh,0EFh,0E0h,0D0h,0BFh,0B1h,0A2h,091h,07Eh,068h,05
7h,044h,02Dh,014h,0FDh,0E3h,0C5h,0A6h,085h,05Bh
db 033h,033h,033h,033h,033h,033h
end
COOLTEMP.A51 ;functions for accessing a tempeture sensor on an A/D
$NOMOD51 ; disable predefined 8051 registers
$INCLUDE(reg515.inc)
$INCLUDE(AD_DA.inc)
$INCLUDE(var.inc)
;$INCLUDE(myregs.inc)
CoolTemp_SEG SEGMENT CODE
RSEG CoolTemp_SEG
PUBLIC GetCool
;Read's Coolent A/D, goes into lookup table for value ammulet should divide
by 10 then
;
subbtract 40 from value for display
;returns MSB on A and LSB on B
;if out of range returns FFFF
;modifies flags and DPTR
GetCool:
mov a,#CoolADAddr
lcall ReadAD
clr c
subb a,#12
jc OutOfCoolRange
cjne a,#240,GetCool1
GetCool1:
;c=a<240
jnc OutOfCoolRange
push acc
mov dptr,#TempTableLSB
movc a,@a+dptr ; get a character
; mov b,a
mov CoolLSB, a
pop acc
24
mov dptr,#TempTableMSB
movc a,@a+dptr ; get a character
mov CoolMSB, a
ret
OutOfCoolRange:
; mov a,#0FFh
; mov b,#0FFh
mov CoolMSB,#0FFh
mov CoolLSB,#0FFh
ret
;index must be between 12 and 252 (then subbtract off 12)
TempTableMSB:
db 13, 13, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 9, 9, 9, 9, 9, 9, 9, 9
db 9, 9, 9, 9, 9, 9, 9, 9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
8, 8, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7
db 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6,
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6
db 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 5,
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
db 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4
db 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2
db 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0
TempTableLSB:
db 71, 6, 205, 150, 100, 54, 11, 226, 188, 150, 117, 84, 52, 23, 250, 222,
196, 171, 145, 123, 101, 78, 56, 36, 17, 253, 233, 214
db 197, 180, 163, 145, 128, 113, 98, 83, 68, 52, 37, 24, 10, 253, 240, 226,
212, 199, 188, 176, 164, 152, 140, 128, 116, 105, 94
db 84, 73, 63, 52, 41, 30, 19, 10, 1, 247, 238, 228, 218, 208, 198, 188, 179,
171, 162, 153, 144, 135, 126, 117, 108, 98, 90, 83
db 75, 67, 59, 50, 42, 34, 25, 16, 8, 1, 249, 242, 235, 227, 219, 212, 204,
196, 188, 179, 172, 165, 158, 151, 144, 136, 129, 122
db 114, 106, 99, 91, 83, 76, 70, 63, 56, 49, 42, 35, 28, 21, 13, 5, 254, 247,
240, 234, 227, 220, 213, 206, 199, 192, 184, 177, 169
db 161, 155, 148, 142, 135, 128, 121, 114, 106, 99, 91, 84, 76, 68, 61, 55,
48, 41, 34, 26, 19, 11, 3, 251, 243, 235, 228, 221, 214
db 207, 199, 191, 183, 175, 166, 158, 149, 141, 134, 126, 118, 110, 102, 93,
84, 75, 65, 55, 47, 39, 31, 22, 12, 3, 249, 239, 228
db 218, 209, 199, 189, 179, 168, 157, 145, 132, 122, 111, 100, 88, 76, 62,
48, 35, 23, 10, 252, 237, 220, 204, 189, 174, 157, 138
db 117, 100, 81, 59, 34, 12, 244, 217, 187, 158, 123, 86, 46, 254, 200, 137,
56
end
25
EMACLCD.A51 $NOMOD51
$include(reg515.inc)
$include(var.inc)
;name main
public movlcd
EXTRN CODE(LCDOUT)
LCD_seg segment code
rseg LCD_seg
;***************************************************
;This file moves the LCD cursor to the begining of the next line
;***************************************************
movlcd: push acc
mov a,#0dh ;begin of line
lcall lcdout
acall check_status
;check busy flag bit of lcd and wait
mov a,#0ah ;next line
lcall lcdout
pop acc
ret
check_status: ;check status of lcd busy flag
push acc
push dph
push dpl
busy: mov dph,#0ah
mov dpl,#00h
mov a,#20h
movc a,@a+dptr
jb acc.7,busy
pop dpl
pop dph
pop acc
ret
end
26
INIT2681.A51 ;INIT2681 FILE: initialization and setup of Serial Port 1 (A)
$NOMOD51
$include(reg515.inc)
$include(var.inc)
public INIT2681, selectBaud
INIT2681_seg segment code
rseg INIT2681_seg
INIT2681:
; DO RESET COMMANDS FOR PORTS A AND B. THIS WILL
; EXECUTE CHANNEL A & B's MISCELLANEOUS COMMANDS NUMBERED
; 101,100,011,010,001.
mov A,#01010000B ; DO FROM THIS COMMAND, DOWN TO 00010000
crinit:
mov P2,#CRA
movx @R1,A
add A,#-16 ; SUBTRACT 1 FROM UPPER NIBBLE
jnz crinit ; LOOP TILL 0
mov P2,#MR1A ; SETUP PROTOCOL FOR PORT A
mov A,#MR2ADAT
movx @R1,A
; SELECT BAUD RATE
selectBaud:
mov P2,#ACR
mov A,#80H
movx @R1,A ; SELECT SET 2 OF BAUD RATES
mov P2,#CSRA
mov A,#10111011b ; RX AND TX AT 9600 FOR B
;mov A,#11001100b ; RX AND TX AT 19.2k FOR B
movx @R1,A
mov P2,#CRA
mov A,#00000101B ; ENABLE TXER AND RXER
movx @R1,A
RET
End
INIT.A51 ;INIT FILE:
;EE-451
;Initialization File
$NOMOD51
$include(reg515.inc)
$include(var.inc)
PUBLIC INIT
EXTRN CODE(MAIN, LCDINIT, INIT2681, KEY)
CSEG AT 8000h
27
LJMP INIT
cseg at 802Bh
ljmp timer2int
cseg at 804Bh
inc cnt
reti
cseg at 8013h
ljmp key ;ISR for IE1 <keypad> key routine
INIT_SEG SEGMENT CODE
RSEG INIT_SEG
;***************************************************************
;This file initializes all registers, as well as the LCD
;It also sets up the Serial Port Interface for TRANSMITTING DATA
;***************************************************************
;****************************AC4790 PINOUTS*********************
; P1.1 - CTS (Pin 7)
; P1.2 - Session Status (Pin 20)
;***************************************************************
INIT:
LCALL LCDINIT
mov psw,#00h
erase:
mov r0,#7fh ;clear memory
erase_loop:
mov @r0,#00h
djnz r0, erase_loop
mov B,#00h
MOV SP, #55h
clr p5.1 ;enable MMIO
lcall INIT2681
setb eal ;enable all interrupts
setb ET2 ;set timer 2 overflow interrupt
; setb EX2 ;setup external interrupt 2
setb tcon.2 ;sets falling edgeinterrupts for key routine
setb ien0.2 ;enable INT1 vector to ISR
mov TH2, #0FCh
mov TL2, #65h
mov t2con,#10h ;setb t2con.4 ;enable timer2 auto reload
mov crch,#0fch ;auto reload register CRC (CC0)
mov crcl,#65h
mov tenms,#0ah ;10ms counter
mov hunms,#12d ;120ms counter (10ms * 12)
; mov PackCnt,#100d ;set specific # of packets to send (in Key
routine)
clr secflag ;sec flag
clr hunms_fl
28
clr ten_fl
mov sec_cnt,#100d ;100*10ms = 1 sec
setb t2con.0 ;start timer 2
setb key_press
GOMAIN:
ljmp MAIN
timer2int:
push acc
push psw
clr tf2 ;t2 overflow flag
setb onems
ten_loop:
djnz tenms,next
setb ten_fl
mov tenms,#0Ah ;reset 10ms count
djnz hunms,next
setb hunms_fl
mov hunms,#12d ;reset 120ms count (12 counts * 10ms)
next:
pop psw
pop acc
reti
END
KEY.A51 ; Tim Pieper ee365 hardware design project
; created: 12/1/2005
; edited:
; major revisions:
$nomod51
$include(reg515.inc)
$include(var.inc)
public key
;extrn code
keypad_code segment code
rseg keypad_code
key:
cpl p1.3
push acc
push dph
push dpl
push psw
mov dph,#30h ;"keyport"
29
movx a,@dptr ;copy coordinates of keypad press into A
anl a,#1fh ;mask off upper bits
;clr tcon.3 ;b/c use of polling--manually reset interrupt
mov dptr,#keytable
movc a, @a+dptr
; mov keypad_entry,a ;store key since acc gets popped
cpl key_press
pop psw
pop dpl
pop dph
pop acc
mov PackCnt,#100d ;set specific # of packets to send
mov ascii1,#30h ;reset count
mov ascii2,#30h
mov ascii3,#30h
mov ascii4,#30h
reti ;ret if polling
keytable:
db "1","2","3","C","4","5","6","D","7","8","9","E","A","0","B","F"
end
MAIN.A51 ;MAIN FILE:
$NOMOD51
$include(reg515.inc)
$include(var.inc)
name main
public main
EXTRN CODE(LCDOUT,TRANSMIT, ReadAD, GetAFR, GetCool, GetAir, movlcd)
main_seg segment code
rseg main_seg
;***************************************************
;This file samples the A/D converter and sends
;the signal out on the serial port to the other
;microcontroller. It then enters reveive mode once
;the transmission is over and will receive the data
;back from the other microcontroller.
;***************************************************
main:
jb key_press, $ ;wait here if key pressed (key routine toggles
instead of setting bit)
;setb key_press ;if commented, then streaming enabled
mov a, PackCnt
30
JZ main ;loop from here to main after packet number has been exhausted
dec acc
mov PackCnt, a ;decremented count value
jnb hunms_fl,$
clr hunms_fl
lcall GetAFR
lcall GetCool
lcall GetAir
lcall counter ;used to number the data packets sent
mov a,AFRhex
lcall breaknsend ;split byte and send ASCII over serial port
mov a,CoolMSB
lcall breaknsend
mov a,CoolLSB
lcall breaknsend
;mov a,AirMSB ;temporarily replaced with counter values below
;lcall breaknsend
;mov a,AirLSB
;lcall breaknsend
mov a,ascii4
lcall transmit
lcall lcdout
mov a,ascii3
lcall transmit
lcall lcdout
mov a,ascii2
lcall transmit
lcall lcdout
mov a,ascii1
lcall transmit
lcall lcdout
mov a,#0Ah ;new line
lcall transmit
mov a,#0Dh ;carriage return...end of data record
lcall transmit
lcall movlcd
ljmp main
;*******************************;
breaknsend:
push acc ;save acc data
anl a,#0F0h
swap a ;upper nibble -> lower nibble
lcall ltrchk
lcall transmit
lcall lcdout
31
pop acc
anl a,#0Fh
lcall ltrchk ;hex to ascii
lcall transmit
lcall lcdout
ret
;hex -> ascii for A-F
ltrchk:
cjne a,#0Ah,check_cy
mov a,#41h ;equal to A
sjmp fin
check_cy:
jc fin2 ;if carry set, then acc < #0Ah so no letter
cjne a, #0Dh, check_cy2
mov a, #44h ; equal to D
sjmp fin
check_cy2:
jc try_c
cjne a,#0Eh, setF
mov a,#45h ; equal to E
sjmp fin
setF:
mov a,#46h
sjmp fin
try_c:
cjne a,#0Ch,set_B
mov a,#43h ; equal to C
sjmp fin
set_B:
mov a,#42h ; equal to B
fin:
ret
fin2:
orl a,#30h ; a contains ascii of upper nibble
ret
counter:
push acc
mov a,ascii1
cjne a,#39h,inc_a1
mov ascii1,#30h
sjmp chk_a2
inc_a1:
inc a
mov ascii1,a
sjmp doneAdd
chk_a2:
mov a,ascii2
cjne a,#39h, inc_a2
mov ascii2,#30h
sjmp chk_a3
inc_a2:
inc a
32
mov ascii2,a
sjmp doneAdd
chk_a3:
mov a,ascii3
cjne a,#39h, inc_a3
mov ascii2,#30h
inc_a3:
inc a
mov ascii3,a
sjmp doneAdd
chk_a4:
mov a,ascii4
cjne a,#39h, inc_a4
mov ascii4,#30h
sjmp doneAdd
inc_a4:
inc a
mov ascii4,a
;sjmp doneAdd
doneAdd:
pop acc
ret
END
O2.A51 ;Stuff related to the O2 sensor
;written by David Pavlik
;equation for table provided by Mark Barnas
$NOMOD51 ; disable predefined 8051 registers
$INCLUDE(reg515.inc)
$INCLUDE(AD_DA.inc) ;A/D function
$INCLUDE(var.inc)
;$INCLUDE(myregs.inc) ;my registers and constants
;$INCLUDE(amulet.inc) ;amulet comunication functions
;$INCLUDE(lcd.inc)
;$INCLUDE(puta.inc)
O2_SEG SEGMENT CODE
RSEG O2_SEG
PUBLIC GetAFR
;will get AFR from O2 sensor
;sends AFR value to amulet
;sends AFR error to amulet
;flags, DPTR, & acc modified
;all other registeres OK
;gets address of A/D with O2 sensor from myregs.inc file
GetAFR:
push 2
33
mov a,#O2ADAddr ;get O2 A/D port
lcall ReadAD
mov dptr,#AFRTable ;point to table
movc a,@a+dptr ;look up in table
mov r2,a
mov AFRhex, a ;variable to hold O2 table value
; skip Amulet code
; push b
; mov b,#AmuletAfrByte
; lcall SetByte
; pop b
;;;;;;;;;;
;;;AFR Error Variable
;;;;;;;;;;
; push b ;request target from amulet
; clr c
; mov a,r2 ;Current + 3.0 - Target
; add a,#30 ;will not generate carry (higest table entry is 195)
; subb a,AFRTarget
; jnc NoBigUnder ;if carry AFR < (Target-3.0) force resulet of calc to
display Optimal-3.0 (ex 0)
; mov a,#0
;NoBigUnder:
; cjne a,#61,OverCheckNoJump
;OverCheckNoJump:
; ;c = Calc < 61
; jc NoBigOver
; mov a,#60
;NoBigOver:
; mov b,#AmuletAFRError
; lcall SetByte
; pop b
pop 2
ret ;done
AFRTable: ;table of A/D output to AFR to display (amulet will divide by 10)
;if x is the voltage level AFR=0.0048x^6 -
0.0629x^5 + 0.3246x^4 - 0.7599x^3 + 0.8897x^2 + 0.5365x + 8.4136
;table is adjusted by table=int(AFR*10+0.5) to
round and simplify storage (amulet restores decimal)
db
4,84,84,84,85,85,85,85,85,85,85,86,86,86,86,86,86,87,87,87,87,87,88,88,88,88,
88,89,89,89,89,89,90,90,90,90,90,91,91,91,91,91
db
92,92,92,92,92,93,93,93,93,93,94,94,94,94,94,95,95,95,95,95,96,96,96,96,97,97
,97,97,97,98,98,98,98,98,99,99,99,99,99,100,100
db
100,100,101,101,101,101,101,102,102,102,102,103,103,103,103,103,104,104,104,1
04,105,105,105,105,106,106,106,106,107,107,107
34
db
108,108,108,108,109,109,109,109,110,110,110,111,111,111,112,112,112,112,113,1
13,113,114,114,114,115,115,115,116,116,116,117
db
117,117,118,118,118,119,119,120,120,120,121,121,122,122,122,123,123,124,124,1
24,125,125,126,126,126,127,127,128,128,129,129
db
130,130,131,131,131,132,132,133,133,134,134,135,135,136,137,137,138,138,139,1
39,140,140,141,142,142,143,143,144,145,145,146
db
147,147,148,149,149,150,151,151,152,153,154,154,155,156,157,158,158,159,160,1
61,162,163,164,165,166,166,167,168,170,171,172
db 173,174,175,176,177,179,180,181,182,184,185,186,188,189,191,192,194,195
end
TXDATA.A51 ;TRANSMIT DATA FILE:
;J.P. Haberkorn
;EE-451
;Sending File
$NOMOD51
$include(reg515.inc)
$include(var.inc)
name TRANSMIT
public TRANSMIT
EXTRN CODE(SelectBaud)
TRANSMIT_SEG SEGMENT CODE
RSEG TRANSMIT_SEG
;*************************************************
;This module takes whatever was last put into ACC and
;puts it out on the COM2. It can be called from the
;MAIN program only.
;*************************************************
TRANSMIT:
PUSH ACC ;PUSHES LAST VALUE IN A (OUTPUT ON COM2)
MOV P2,#SRA
CHIPRDY:
jb p1.1, CHIPRDY ;Check "Clear To Send" Pin7
jnb p1.2, CHIPRDY ;Check "Session Status" Pin20
SENDA1:
MOVX A,@R1
JNB ACC.2,SENDA1 ; LOOP TILL TXrdy
POP ACC
MOV P2,#THRA ; SEND IT OUT
MOVX @R1,A
RET
END
35
AD_DA.INC EXTRN CODE(ReadAD)
;Reads from an A/D, A/D specified by acc, value returned on acc
;source: MicroPac 535 data sheet Copyright 1993-1997, EMAC Inc.
O2.INC EXTRN CODE(GetAFR)
;will get AFR from O2 sensor
;sends AFR value to amulet
;sends AFR error to amulet
;flags, DPTR, & acc modified
;all other registeres OK
;gets address of A/D with O2 sensor from myregs.inc file
36
VAR.INC ;Variables List
$save
$nolist
sec_cnt data 32h ;count to 8 for .5 sec
cntsv data 31h ;counts during .5 sec (?) saved
cnt data 30h ;current count
ascii0 data 33h
ascii1 data 34h
ascii2 data 35h
ascii3 data 36h
ascii4 data 37h
datain data 38h
chan1 data 39h
chan2 data 3ah
broad1 data 3ch
broad2 data 3dh
tenms data 3eh
hunms data 3fh
AFRhex data 40h
CoolMSB data 41h
CoolLSB data 42h
AirMSB data 43h
AirLSB data 44h
PackCnt data 45h
O2ADAddr EQU 01h
CoolADAddr EQU 01h
AirADAddr EQU 01h
;Constants found in the MicroPac535 Data Sheet
MR2ADAT EQU 00000111B ; normal,no TxRTS, no CTS, 1 stop bit
MR2BDAT EQU 00000111B ; normal,no TxRTS, no CTS, 1 stop bit
CRA EQU 02h
CRB EQU 0Ah
MR1A EQU 00h
MR1B EQU 08h
ACR EQU 04h
CSRA EQU 01h
CSRB EQU 09h
SRA EQU 01h
SRB EQU 09h
RHRA EQU 03h
RHRB EQU 0Bh
THRA EQU 03h
THRB EQU 0Bh
secflag bit 4fh ;flag for .5 sec
key_press bit 50h ;flag for keypad press
onems bit 51h ;flag for 1ms
ten_fl bit 52h ;flag for 10ms
hunms_fl bit 53h ;flag for 100ms
37
Excel Visual Basic Macros: Appendix B-2
Worksheet1 Private Sub CommandButton1_Click()
Call ResetLog
End Sub
Private Sub CommandButton3_Click()
Call RunWedge
LogRow = 2
End Sub
Private Sub CommandButton4_Click()
Call CloseWedge
End Sub
Module1 Global LogRow As Long
Sub LogIt()
‘copy cells on “sheet1” for dashboard into “Log”
Worksheets("Log").Cells(LogRow, 2).Value = Worksheets("Sheet1").Cells(3, 1).Value
Worksheets("Log").Cells(LogRow, 3).Value = Worksheets("Sheet1").Cells(3, 2).Value
Worksheets("Log").Cells(LogRow, 4).Value = Worksheets("Sheet1").Cells(3, 3).Value
Worksheets("Log").Cells(LogRow, 8).Value = 1 ‘used for counting incoming packets
LogRow = LogRow + 1 'increment for next log entry
End Sub
Sub GetSWData()
'Static RowPointer As Long ' preserve variable values between calls
RowPointer = 2 ' point to second row
' the first time through, RowPointer will automatically initialize to point to Row 1
Chan = DDEInitiate("WinWedge", "Com4") ' establish DDE link to WinWedge on Com1
‘WinWedge separates Data Packet into 3 Fields (AFR, Coolant, Air)
‘The following code imports each field to a separate cell for the
‘virtual dashboard “sheet1”
F1 = DDERequest(Chan, "Field(1)") ' get Field(1) data into a variant array
WedgeData$ = F1(1) ' convert variant array to a string
Sheets("Sheet1").Cells(RowPointer, 1).Formula = WedgeData$
' Write the data to cell address: (RowPointer,1) in Sheet1, i.e. fill up Column 1
‘(Column A)
' repeat for each Data Field set in WinWedge
F1 = DDERequest(ChannelNum, "Field(2)") ' get Field(2) data into a variant array
WedgeData$ = F1(1) ' convert variant array to a string
Sheets("Sheet1").Cells(RowPointer, 2).Formula = WedgeData$ 'write the data to Column 2
F1 = DDERequest(ChannelNum, "Field(3)") ' get Field(3) data into a variant array
WedgeData$ = F1(1) ' convert variant array to a string
Sheets("Sheet1").Cells(RowPointer, 3).Formula = WedgeData$ 'write the data to Column 3
‘repeat for additional fields (when adding remaining sensors)
DDETerminate Chan ' kill the DDE link
' YOUR CODE GOES HERE TO DO SOMETHING WITH THE DATA MAYBE?
Call LogIt
End Sub
38
Module2 Public Const MyPort$ = "COM4" ' change port if necessary
Sub RunWedge()
x% = Shell("C:\Program Files\WinWedge\winwedge.exe
c:\temp\winwedge\com4setup.SW3")
ThreeSecsFromNow = TimeValue(Now) + TimeValue("00:00:03")
Do While TimeValue(Now) < ThreeSecsFromNow
DoEvents ' give WinWedge time to load
Loop
End Sub
Sub CloseWedge()
On Error Resume Next ' ignore errors
Chan = DDEInitiate("WinWedge", MyPort$) ' open a dde link with WinWedge
DDEExecute Chan, "[Appexit]" ' tell WinWedge to quit
DDETerminate Chan
End Sub
Sub ResetLog()
LogRow = 2 'reset row index for data logging
Worksheets("Log").Range("A2:H65536").ClearContents
End Sub
39
Proposed Code for Integration with 2006 Project: Appendix B-3
RFSEND.A51 ;Routine for RF Packet Transmission:
$NOMOD51
$include(reg515.inc)
$include(var.inc)
name rfsend
public rfsend
EXTRN CODE(TRANSMIT)
rfsend_seg segment code
rseg rfsend_seg
;***************************************************
;This file sends formatted data to serial port 1 (A)
;for transmission using Aerocomm transceivers.
;
;Variables must be added in .inc of 2006 proj as well
;as in sensor subroutines to save results to be recalled
;and sent here.
; AFRhex
; CoolMSB
; CoolLSB
; AirMSB
; AirLSB
; Transmit (COM1) and ‘breaknsend’ also need to be
;included in 2006 project
;***************************************************
RFSEND:
mov a,AFRhex
lcall breaknsend ;split byte and send ASCII over serial port
mov a,CoolMSB
lcall breaknsend
mov a,CoolLSB
lcall breaknsend
mov a,AirMSB
lcall breaknsend
mov a,AirLSB
lcall breaknsend
;***add remaining sensors
;***update RF Packet Size EEPROM setting
;***update WinWedge data fields
;***update Excel Macro for new data fields
;***add new gauges to virtual dashboard
mov a,#0Ah ;new line
lcall transmit
mov a,#0Dh ;carriage return...end of data record
lcall transmit
ret
end