Data Acq for a Live Project.doc
PROJECT REPORT ON DATA ACQUISITION SYSTEM FOR A LIVE PROJECT
Project Participant : SUNAYANA GHOSH Project Location
: CMC Ltd. Embedded Systems Kolkata.
Project Duration
: June’06 to Dec’06
Page 1 of 44
Data Acq for a Live Project.doc
ACKNOWLEDGEMENT
I would like to thank Mr.Tarun Kanti Sinha and Mr.Goutam Nandy of CMC Ltd. Kolkata for their patient guidance and support without which my project would not have been possible.
Page 2 of 44
Data Acq for a Live Project.doc
INDEX Topic
Page number
1. About Draglines. What is a dragline?
4
2. Block Diagram of the entire system
6
3. Project scope
7
4. Circuit diagram
8
5. Testing and debugging
10
6. Hardware and Software platform
11
7. Flowchart for timer interrupt routine (server)
13
8. Flowchart for serial interrupt routine(server)
14
9. Flowchart for main routine(server)
15
10. Flowchart for encoder side routine
16
11. Program listing for encoder side
17
12. Program listing for server side
21
13. Program listing for encoder side (revised)
27
14. Program listing for server side (revised)
33
15. Future scope of work
42
Page 3 of 44
Data Acq for a Live Project.doc
WHAT IS A DRAGLINE? Draglines can be classified as heavy equipment, used for a number of purposes like road construction or port construction. Of the various fields of application, one of the most important fields in which they are used is in mining they are used to extract coal and can even weigh up to 2000 tonnes.
Constructionally, the dragline system basically consists of a boom from which is suspended a large bucket that can be used to dig and scoop out material. A large number of ropes and chains are used to control the bucket ; that is, to raise it or lower it as and when required .The bucket’s motion along the horizontal direction, can be controlled using a drag rope while the hoist ropes can be used to raise or lower the bucket system.
Thus, the bucket’s motion along the horizontal and the vertical direction can be controlled.
Draglines can be stationary devices, but they can ‘crawl’ or ‘walk’. Motors are provided specially for the purpose of enabling motion of the dragline. The dragline system that has been considered in this project is capable of crawling and can also rotate along with its hoist system and bucket. The degree of rotation that has occurred can be measured using a capacitive transducer arrangement.
The basic operation of a dragline can be said to consist of three basic movements of the bucket, namely –
Drag Hoist Swing The bucket is dragged using a drag rope on the material and thus the material is deposited in the bucket. Two motors in series connection can be used. The pinions are rotated at high speed which rotate the drag rope drum at the required speed and direction using reduction
Page 4 of 44
Data Acq for a Live Project.doc gears. During excavation, the tension is maximum in the drag rope and so the motor current is large.
The hoist operation is also carried out by the motors. Unloading is done by releasing the drag rope and a hoist movement occurs causing unloading. The duration of the stall current through the hoist motors indicate the amount of load in the bucket.
As the hoist operation is completed, the operator starts swinging the dragline to unload the bucket. Three motors are used in this case. They attain a high rotational speed. The motor pinions are coupled to a two stage reduction gear which rotates the main central shaft to the desired angle. The picture of a dragline for which the system was made is shown below:
Page 5 of 44
Data Acq for a Live Project.doc
Description of monitoring system for dragline developed by Embedded Systems, Kolkata
Page 6 of 44
Data Acq for a Live Project.doc
PROJECT
SCOPE
The part of the project that was assigned to me, dealt with acquisition of data regarding height to which the bucket has been lifted.
The bucket can be raised or lowered to the required height with the help of a steel rope that is wound around a pulley. A shaft encoder is used to register the motion of the shaft connected to the pulley. Based on the data obtained from the shaft encoder, which is basically in the form of an 8-bit gray code, the data is converted to an 8-bit binary code and then transmitted to the main computer for desired manipulation and display of relevant information.
SHAFT ENCODER SPECIFICATIONS PURPOSE : The shaft encoder is mounted on a shaft connected to the pulley which actually pulls up the Bucket through Hoist rope. As the bucket moves up or down, the pulley rotates in clockwise or anti clockwise direction and the shaft rotates accordingly. The encoder itself has a shaft which is coupled with the pulley shaft. It consists a Optical Disc which is printed with 8 bit Gray code pattern. There is a sensor-LED arrangement with the Encoder Disc interposed in between the sensor-led panel. There is a unique pattern to specify the shaft absolute angular position with a resolution of 1.4 degree. The level sensed by the sensor arrangement is quite weak (0.2v to 2v) and cannot be used further as it is not the standard TTL level. So comparators are used to generate TTL levels according to the sensor output voltage. The comparator chip which is used here is LM339. For the sensor, if the LED is blocked by the Disk pattern i.e. Black part, then a level of 0.2 to 0.5 volts is detected and if the Light from the LED passes through the transparent part of the disk, then a level of 1.5 to 2 volts is detected. The common mode voltage of the comparator has been set at 1 volt (approx), so when the voltage drops below 1 volt then it produces High at output and above one volt produces logic Low at output. The TTL output from the comparator then goes to the µcontroller and is then passed onto the server during polling.
Page 7 of 44
Data Acq for a Live Project.doc
Picture of the Shaft Encoder is shown below:
A screen printed encoder disc that was used to generate the gray code pattern has been shown here. For the purpose of determination of the height of the bucket, there are mainly 2 µcontrollers required – •
One µcontroller on the encoder side that will receive the data from the encoder and convert the gray code to binary and transmit it when polled. Page 8 of 44
Data Acq for a Live Project.doc
•
Another µcontroller on the server side that will poll one of such many µcontrollers at the different locations and collect the data. The data will then be transmitted for further processing.
The circuit that was implemented for the purposes of testing.
Page 9 of 44
Data Acq for a Live Project.doc
POLLING PROCEDURE Now in general, the µcontroller on the server side, polls the µcontrollers at the respective ports for a period of 30 ms (configurable) for each port. It sends out a data packet consisting of •
STX byte – it is a single byte which is used to denote the start of the packet.
•
ID byte – each of the µcontrollers at the respective ports have their own id to distinguish the ports.
•
ETX byte – the etx byte is used to denote the end of text. It serves as a marker to denote the end of the packet. The packet is sent to the different ports in order. The timer of the server µcontroller has its count set to a proper value so that it after 30 ms the next port is polled. The port, whose id matches with the id transmitted in the packet, then sends the data to the server. This process has to be within the time frame of 30 ms or else the data packet will then be rejected.
The data at the end of optical shaft encoder is in form of Gray code, so it has been converted to binary using bitwise – xor operation. The data is then transmitted serially through the serial port. For proper handshaking between transmission side of the port and reception of data on the server side, we have used certain flags to indicate different stages of transmission and reception. TI is a flag which is set to low after a byte is completely transmitted and RI is a flag which is set to high after a byte is received. The serial buffer SBUF is used for serial transmission of bytes. After the encoder side µcontroller transmits a byte, its TI flag is set to low and after the server side µcontroller receives the byte, the RI flag is set to high. The data packet is thus transferred serially from each port to the server in this manner. The data packet which the encoder side µcontroller sends to the server consists of•
STX byte - to indicate the start of text.
•
ID byte – to denote the address of the port from which the data packet is being sent
The data byte is converted to character and converted thereby by a suitable algorithm into two bytes. This is done so as to keep the range of values for id separate from the data range. Page 10 of 44
Data Acq for a Live Project.doc
•
The cyclic redundancy check is done using suitable algorithm. It is used to check if a
data packet that has been received by the server is a valid data packet or not. The crc basically consists of a crchi byte and a crclo byte. The µcontroller on the site generates a crc using the id and the data and then the crchi byte and the crclo byte is generated. The crchi and the crclo byte are each converted to char for transmission and thereby are each converted to two bytes for transmission. The server side µcontroller on receiving the data packet generates its own crc and compares it with the crc obtained from the data packet. if the crchi and the crclo bytes match, then the data packet is a valid data packet and is accepted or else rejected. •
ETX-byte – this byte is used to designate the end of the packet. The server µcontroller receives the data packets and stores the data in a cyclic buffer that can store 1024 bytes of data for each port. After the limit is exhausted for a particular port the counter for the memory location is set to 0 and the next set of data is stored each time the server polls the different ports for data.
This data is read by a pc through the parallel port in a while and then the data is manipulated to be displayed accordingly. Handshaking is done using the pin-10 of parallel port connected to pin-6 of the 89C2051 designated as the INTR line, to generate an interrupt in the PC that is to tell the pc to read the data of the buffer as the pc may be busy with other jobs and may not be able to devote the entire time to the server. The other line that is used as an acknowledgement signal by the PC is connected between pin-11 of the parallel port and pin-8 of 89C2051.
Page 11 of 44
Data Acq for a Live Project.doc
TESTING AND DEBUGGING The circuits which were made for the encoder side µcontroller and the server side µcontroller are now been tested with some test data. The respective codes written were flashed into the µcontroller using LAB TOOL and then connections were made between the two µcontroller boards. The transmit pin of the server side µcontroller (pin 3) and the receiving pin of the encoder side µcontroller (pin 2) were monitored to see if the polling occurred properly. In the second phase the data from the transmitter side µcontroller and the server side µcontroller were checked to see if handshaking was occurring properly. Test data had been incorporated in the code and it was checked if the test data was being properly sent and received. An oscilloscope was used to check the status of different pins of the µcontroller. It was also been checked that the data transmitted by the transmitting side is in proper sequence of polling. Debugging was carried out by considering a certain pin of the µcontroller and changing its status at different portions of the program and then tested to see if the change in the status of the pin has occurred thereby showing whether a certain part of the code has been executed or not. The responses at the different pins of the µcontroller were also been observed. Thus by following this procedure bugs in the program were removed.
Page 12 of 44
Data Acq for a Live Project.doc
HARDWARE AND SOFTWARE PLATFORM USED Microcontroller Specification The µcontroller which I used here is an ATMEL’s AT89C4051. It is a low voltage CMOS 8 bit microcomputer and has 4 KB flash programmable and erasable ROM. It has been fabricated using Atmel’s high density, non volatile memory technology. It has an 8 bit cpu with flash on a monolithic chip.
FEATURES The main features of the AT89C4051 include – • • • • • • • • • •
128 bytes RAM, 15 I/O lines , two 16 bit timer /counters , a 5 vector 2 level interrupt architecture , a full duplex serial port , a precision analog comparator , on chip oscillator and clock circuitry. It is designed with static logic for operation down to zero frequency and supports It also supports 2 software selectable power saving modes
The idle mode stops the CPU while allowing RAM, timer/counters, serial port and interrupt system to continue functioning. The power down mode saves RAM contents but freezes oscillator disabling all chip functions until next hardware reset.
Vcc is the supply voltage and Gnd is used to refer to ground.
Port 1 – it is an 8 bit bi-directional I/O port. P1.0 and P1.1 require external pull-ups and serve as positive input and negative input of the analog comparator. When the port 1 pins are tied to a high (tie high), then they can be used as inputs.
Port 3 pins P3.0 to P3.5,P3.7 are seven bi-directional I/O pins with internal pull-ups. P3.6 is hard wired as an input to the output of the on chip comparator and is not accessible as a Page 13 of 44
Data Acq for a Live Project.doc general purpose input/output pin. When 1’s are written to port 3 pins they are pulled high by internal pull-ups and can be used as inputs.
RST- reset input pin. As soon as the reset goes high, all I/O pins are reset to 1. Holding RST pin high for two machine cycles while the oscillator is running resets the device.
XTAL1- It is the input to inverting oscillator amplifier and input to external clock operating circuit.
XTAL2- It is the output from the inverting oscillator amplifier.
The pin configuration of the µcontroller is shown below:
The circuit was made as has been shown in the circuit diagram by proper soldering using the soldering tool. The serial communication link that was used is RS-232C serial link. The maximum data rate is 20Kb/s and has one driver and one receiver. Programming was done in visual C. The programs that were written were compiled using Keil software - µ vision 2.
The
programs were then loaded into the µcontroller chip using Dynalog Labtool – 48 that is an intelligent universal programmer. The documentation has been done in MS-WORD.
Page 14 of 44
Data Acq for a Live Project.doc Server Side Flowchart – TIMER INTERRUPT ROUTINE
START
EA = 0
LOAD COUNT VALUE
SEND STX, ID AND ETX
IS ID++>END_ID
Y ID=START_ID
N EA = 1
STOP Page 15 of 44
Data Acq for a Live Project.doc
SERIAL INTERRUPT ROUTINE START
EA = 0
IS RI = 1
N
EA = 1
1
Y N IS SBUF =ETX
a [j]=SBUF
Y N
IS j< 9 N
j=0
IS a[j-8]=STX Y Y
2
INCREASE J
GENERATE CRC USING ID AND DATA
RI=0
2 CONVERT CRC TO 2 BYTES
1 N DO THE CRC MATCH?
1
Y SEND DATA TO PC AND WRITE IN BUFFER
Page 16 of 44
STOP
Data Acq for a Live Project.doc
MAIN ROUTINE
START
INITIALIZE SERIAL PORT
INITIALIZE TIMER
ENABLE INTERRUPTS
START TIMER
STOP
Page 17 of 44
Data Acq for a Live Project.doc
Microcontroller flowchart START
RECEIVE CHARACTER
SAVE AND INCREASE N POINTER
IS CHAR=ETX Y CHECK FOR STX AND ID
DO STX AND ID MATCH?
N
Y READ ENCODER
CONVERT FROM GRAY TO BINARY
GENERATE CRC
ENCODE TO TWO BYTES
TRANSMIT DATA
SET POINTER TO ZERO
ENABLE INTERRUPTS
Page 18 of 44
STOP
Data Acq for a Live Project.doc
Program listing The programs that were developed in the initial stages of the project for the purpose of testing is shown below. The server routine and the encoder side microcontroller routine are being shown. After that the final routines have been given. Encoder side routine:
#include <stdio.h> #include
#define STX 0x01 #define ID 0x11 #define ETX 0x03 #define BUS P3_3 static unsigned char code acrchi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 };
static unsigned char code acrclo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, Page 19 of 44
Data Acq for a Live Project.doc 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40}; unsigned char code data1[] = { 02,05,60,10,55 } ; /* these are gray codes */ unsigned char crchi,crclo,crchi1,crchi2,crclo1,crclo2,j=0,a[3]; unsigned char index,k=0; void output(void); void gencrc(unsigned char); void data_to_char(unsigned char); void transmit(void); unsigned char char_buff[2],tx_pkt[] = { 0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03 }; unsigned char y; void main() {
/* serial port setup */ SCON = 0x50; TMOD = 0x21; TH1 = 250; TR1 = 1; ES=1; RI =0; EA=1; /* ----------------- */
Page 20 of 44
Data Acq for a Live Project.doc tx_pkt[1] = ID; P1 = 0xff; while(1); } serial_interrupt() interrupt 4 { EA=0; if(RI) { if(SBUF==ETX) { if ((a[j-2]==STX) && (a[j-1]==ID)) { output(); crchi=0xff; crclo=0xff; gencrc(ID); gencrc(y); data_to_char(y); tx_pkt[2] = char_buff[0]; tx_pkt[3] = char_buff[1]; data_to_char(crchi); tx_pkt[4] = char_buff[0]; tx_pkt[5] = char_buff[1]; data_to_char(crclo); tx_pkt[6] = char_buff[0]; tx_pkt[7] = char_buff[1]; transmit(); } j=0; } else { a[j++]=SBUF; } RI = 0; } EA=1; } void output(void) { unsigned char x,a,b,c,i; x=P1; /* This portion is for testing with test data; comment out to exclude testing */ x=data1[k++]; if(k>=5) Page 21 of 44
Data Acq for a Live Project.doc k=0; /******************************************************************************/ y=x&128; for(i=1;i<8;i++) { a=y<<(i-1); b=x<>i; y=y+c; } }
void transmit(void) { unsigned char i=0; BUS = 1; /* used or the output enable of the BUS driver */ TI=1; for(i=0; i<9; i++) { while(!TI); TI=0; SBUF = tx_pkt[i]; } while(!TI); TI=0; BUS = 0; } void gencrc(unsigned char r_char) { index=crchi^r_char; crchi=crclo^acrchi[index]; crclo=acrclo[index]; } void data_to_char(unsigned char chb) { unsigned char temp1, i ; for (i=0; i<8 ; i+=4) { temp1 = (chb >> i) & 0x0f; if (temp1 > 0x09) { Page 22 of 44
Data Acq for a Live Project.doc temp1 += 0x57; } else { temp1 += 0x30; } char_buff[i/4] = temp1; } }
The server side routine that was initially developed is shown: /*This polls a number of slave units for its data through serial port and sends the received data to the PC using parallel port with handshaking using Pins 6 and 7. It also indicates to the PC that ID is sent by making SEND_ID line high and data by making SEND_ID line low */ #include #include <stdio.h> #define STX 0x01 #define ETX 0x03 #define INTR P3_2 /* Pin 6 of 89C2051, bit-6 of 0x379, connected to Pin-10 of the parallel port */ #define ACK P3_3 /* Pin-7 of 89C2051, bit-0 of 0x37a , connected to Pin-1 of the parallel port */ #define START_ID 0x10 #define END_ID 0x11 #define SEND_ID P3_4 /* Pin-8 of 89C2051, bit-7 of 0x379, connected to Pin-11 of parallel port*/ /* Pin-14 f parallel port is connected to the reset pin of 89C2051 so that PC can reset it */ /*unsigned char array[END_ID - START_ID + 1][32];*/ void gen_crc(unsigned char); void char_to_data(void); unsigned char ID = START_ID ,write_ptr=0,read_ptr,arr_ptr[END_ID-START_ID + 1], crchi_pkt, crclo_pkt; static unsigned char code acrchi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, Page 23 of 44
Data Acq for a Live Project.doc 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 }; static unsigned char code acrclo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 }; unsigned char crchi,crclo,data_received,data_byte,data_buff[2] , a[10]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, j = 0,char_buff[2],data1, pol_pkt[3]={ 0x01,0x00,0x03}; /*unsigned char ch;*/ timer0_interrupt() interrupt 1 { unsigned char i=0; EA=0; TL0=0xff; Page 24 of 44
Data Acq for a Live Project.doc TH0=0x93; pol_pkt[1] = ID; TI=1; /* polling done */ for(i=0;i<3;i++) { while(!TI); TI=0; SBUF = pol_pkt[i]; } if (ID++ > END_ID) ID = START_ID; EA=1; } serial_interrupt () interrupt 4 { EA=0; TRO=0; /* for debugging */ if(RI) { /* for debugging */ /*INTR=1; while(!ACK); P1=SBUF; INTR=0; while(ACK); INTR=1; while(ACK);*/ /* upto this */ if(SBUF==ETX) { if((a[j-8]==STX)) { crchi=0xff;crclo=0xff; /* conversion from char to data for id for generating crc */ gen_crc(a[j-7]); /* ID */ /* crc with data */ data_buff[0] = a[j-6]; data_buff[1] = a[j-5]; char_to_data(); data_byte = data_received; gen_crc(data_received); data_buff[0] = a[j-4]; data_buff[1] = a[j-3]; char_to_data(); crclo_pkt = data_received;
Page 25 of 44
Data Acq for a Live Project.doc /* for debugging */ /*INTR = 1; while(!ACK); P1=crchi; INTR=0; while(ACK); INTR = 1; while(!ACK); P1=crclo; INTR=0; while(ACK); INTR = 1; while(!ACK); P1=crchi_pkt; INTR=0; while(ACK); INTR = 1; while(!ACK); P1=crclo_pkt; INTR=0; while(ACK);*/ /*
upto this */
if((crclo_pkt==crclo)&&(crchi_pkt==crchi)) { INTR=1; /* to generate interrupt and start handshaking */ while(!ACK); /* wait for ACK going high */ SEND_ID = 1 ; /* to inform the pc that this is ID */ P1 = a[j-7];/*send ID*/ INTR = 0; SEND_ID= 0; /* to inform the pc that this is data */ while(ACK); INTR=1; while(!ACK); P1=data_byte; INTR=0; while(ACK); /*
array[ID-START_ID][write_ptr++]= data_received; write_ptr&=0x1f; */ }
} Page 26 of 44
Data Acq for a Live Project.doc j=0; } else { a[j]=SBUF; if(j<9) { j++; } } RI=0; } TRO=1; /* for debugging */ EA=1; }
main() { /* serial port setup */ SCON = 0x50; TMOD = 0x21; TH1 = 250; TR1 = 1; /* ----------------- */ TL0 = 0xff; TH0 = 0x93; ET0 =1; /* made 0 for testing */ INTR=0; ACK=1; ES=1; /* made 0 for testing */ TR0 = 1; EA = 1; while(1); /*{ INTR=1; /* INTR line made high to generate parallel port interrupt in PC */ while (!ACK); /* wait for ACK line ( from STB of parallel port ) to be made high by the PC to indicate that it is ready to accept data */ P1 = ID; /* first send the ID byte over data lines of parallel port */ ID++; ID = (ID & 0X01) | 0X10; /* use only addresses 0x10 AND 0x11 */ INTR = 0; /* INTR made 0 to indicate the data placement */ while(ACK); /* wait for ACK which indicates that the PC has accepted the data */ INTR = 1; /*once again initiate the transfer for actual data from the ID */ while(!ACK); P1 = 0x41; Page 27 of 44
Data Acq for a Live Project.doc INTR = 0; while(ACK);*/ /*
read_ptr=arr_ptr[ID-START_ID]; if(arr_ptr[ID-START_ID]!=write_ptr) { INTR=1; while(!ACK); P1=ID; INTR=0; while(ACK); INTR=1; P1=array[ID-START_ID][arr_ptr[ID-START_ID]]; arr_ptr[ID-START_ID]++; arr_ptr[ID-start_id]&=0x1f; INTR=0; while(ACK); } if(ID++>END_ID) { ID = START_ID; } */
} }
void gen_crc(unsigned char r_char) { unsigned char index; index=crchi^r_char; crchi=crclo^acrchi[index]; crclo=acrclo[index]; } void char_to_data(void) { unsigned char j; unsigned short temp1=0; for (j=0; j<2; j++) { if (data_buff[j] > 0x60) temp1 |= (data_buff[j] - 0x57); else temp1 |= (data_buff[j] - 0x30); data_received |= (temp1 <<= (j)*4); temp1 =0; } Page 28 of 44
Data Acq for a Live Project.doc } The codes were suitably modified during repeated testing procedures . Here the code developed had basically taken into account a single port which was at the optical encoder side . but in actuality , a large number of ports are present acquiring different kinds of information and then sending them to the server during polling. So the server side code had to be modified to take into account these considerations. Other factors that were considered were time taken for code execution, proper coordination between the main pc and the server ,that is execution of the steps in a proper sequence between the port side µcontrollers and the server and the pc and coordination of interrupts. The final codes are listed below: The code at the port side is as shown below: #include
#define STX 0x01 #define ETX 0x03 #define BUS P3_3 #define ID 0x61 static unsigned char code gr2bin[] = { 0x00, 0x01, 0x03, 0x02, 0x07, 0x06, 0x04, 0x05, 0x0f, 0x0e, 0x0c, 0x0d, 0x08, 0x09, 0x0b, 0x0a, 0x1f, 0x1e, 0x1c, 0x1d, 0x18, 0x19, 0x1b, 0x1a, 0x10, 0x11, 0x13, 0x12, 0x17, 0x16, 0x14, 0x15, 0x3f, 0x3e, 0x3c, 0x3d, 0x38, 0x39, 0x3b, 0x3a, 0x30, 0x31, 0x33, 0x32, 0x37, 0x36, 0x34, 0x35, 0x20, 0x21, 0x23, 0x22, 0x27, 0x26, 0x24, 0x25, 0x2f, 0x2e, 0x2c, 0x2d, 0x28, 0x29, 0x2b, 0x2a, 0x7f, 0x7e, 0x7c, 0x7d, 0x78, 0x79, 0x7b, 0x7a, 0x70, 0x71, 0x73, 0x72, 0x77, 0x76, 0x74, 0x75, 0x60, 0x61, 0x63, 0x62, 0x67, 0x66, 0x64, 0x65, 0x6f, 0x6e, 0x6c, 0x6d, 0x68, 0x69, 0x6b, 0x6a, 0x40, 0x41, 0x43, 0x42, 0x47, 0x46, 0x44, 0x45, 0x4f, 0x4e, 0x4c, 0x4d, 0x48, 0x49, 0x4b, 0x4a, 0x5f, 0x5e, 0x5c, 0x5d, 0x58, 0x59, 0x5b, 0x5a, 0x50, 0x51, 0x53, 0x52, 0x57, 0x56, 0x54, 0x55, 0xff, 0xfe, 0xfc, 0xfd, 0xf8, 0xf9, 0xfb, 0xfa, 0xf0, 0xf1, 0xf3, 0xf2, 0xf7, 0xf6, 0xf4, 0xf5, 0xe0, 0xe1, 0xe3, 0xe2, 0xe7, 0xe6, 0xe4, 0xe5, 0xef, 0xee, 0xec, 0xed, 0xe8, 0xe9, 0xeb, 0xea, 0xc0, 0xc1, 0xc3, 0xc2, 0xc7, 0xc6, 0xc4, 0xc5, 0xcf, 0xce, 0xcc, 0xcd, 0xc8, 0xc9, 0xcb, 0xca, 0xdf, 0xde, 0xdc, 0xdd, 0xd8, 0xd9, 0xdb, 0xda, 0xd0, 0xd1, 0xd3, 0xd2, 0xd7, 0xd6, 0xd4, 0xd5, 0x80, 0x81, 0x83, 0x82, 0x87, 0x86, 0x84, 0x85, 0x8f, 0x8e, 0x8c, 0x8d, 0x88, 0x89, 0x8b, 0x8a, 0x9f, 0x9e, 0x9c, 0x9d, 0x98, 0x99, 0x9b, 0x9a, 0x90, 0x91, 0x93, 0x92, 0x97, 0x96, 0x94, 0x95, 0xbf, 0xbe, 0xbc, 0xbd, 0xb8, 0xb9, 0xbb, 0xba, 0xb0, 0xb1, 0xb3, 0xb2, 0xb7, 0xb6, 0xb4, 0xb5, 0xa0, 0xa1, 0xa3, 0xa2, 0xa7, 0xa6, 0xa4, 0xa5, 0xaf, 0xae, 0xac, 0xad, 0xa8, 0xa9, 0xab, 0xaa};
Page 29 of 44
Data Acq for a Live Project.doc static unsigned char code acrchi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 }; static unsigned char code acrclo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, Page 30 of 44
Data Acq for a Live Project.doc 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 }; unsigned char code data1[] = { 0x02,0x05,0x60,0x10,0x55 }; unsigned char crchi,crclo,crchi1,crclo1,crchi2,crclo2,j=0; unsigned char index,k=0, stx_ptr=0, id_ptr=0; void output(void); void gencrc(unsigned char); void data_to_char(unsigned char); void transmit(void); unsigned char char_buff[2], tx_pkt[] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}; unsigned char y, STS=0, poll_packet_received=0; /* for test */ unsigned char cnt1=0; timer0_interrupt() interrupt 1 { cnt1++; } /* upto this */
serial_interrupt() interrupt 4 { EA=0; if(RI) { if (j == 2) { if (SBUF == ETX) { j =0; poll_packet_received =1; } } if ( j == 1) { if (SBUF == ID) j =2; else j =0; } Page 31 of 44
Data Acq for a Live Project.doc if ( j == 0) { if (SBUF == STX) j =1; } RI =0; } else TI =0; EA =1; } void output(void) { unsigned char x; /* unsigned char a,b,c,i; */ x= P1; /* This portion is for testing with test data comment out to exculde testing */ x=data1[k++]; if(k>=5) k= 0; y =x; /***upto this******************************************/ /* y=x&128; for(i=1;i<8;i++) { a=y<<(i-1); b=x<>i; y=y+c; } */ } void transmit(void) { unsigned char i=0; EA =0; BUS = 1; /* used for the output enable of the BUS driver */ TI = 1; for (i=0; i<11; i++) { while (!TI); TI=0; Page 32 of 44
Data Acq for a Live Project.doc SBUF = tx_pkt[i]; } while (!TI); TI=0; BUS = 0; EA =1; } void gencrc(unsigned char r_char) { index=crchi^r_char; crchi=crclo^acrchi[index]; crclo=acrclo[index]; } /* void data_to_char(unsigned char chb) { unsigned char temp1, i; for (i=0; i<8; i+=4) { temp1 = (chb >> i) & 0x0f; if (temp1 > 0x09) { temp1 += 0x57; } else { temp1 += 0x30; } char_buff[i/4] = temp1; } } */ void data_to_char(unsigned char chb) { char_buff[0] = (chb &0x0f)|0x30; /* lower order nibble encoded to character */ char_buff[1] = ((chb >> 4)&0x0f)|0x30; /* higher order nibble encoded to character */ }
void main() {
/* serial port setup */ Page 33 of 44
Data Acq for a Live Project.doc SCON = 0x50; TMOD = 0x21; TH1 = 250; TR1 = 1; ES=1; ET0 =1; RI =0; TR0 =1; EA=1; /* ----------------- */
tx_pkt[1] = ID; P1 =0xff; /* for input mode */ /* For testing */ /* TR0 =1; */ /* upto this */ while(1) { /* For testing */ /* if (cnt1 > 10) { poll_packet_received =1; cnt1 = 0; } */ /* upto this */ if (poll_packet_received) { /* for test */ TR0 =0; cnt1 = 0; TH0 =0; TL0 =0; /* upto this */ crchi=0xff; crclo=0xff; y=gr2bin[(P1 ^ 0xff)]; gencrc(ID); /* gencrc(y); gencrc(STS); */ data_to_char(STS); tx_pkt[2] = char_buff[0]; tx_pkt[3] = char_buff[1]; gencrc(char_buff[0]); gencrc(char_buff[1]); data_to_char(y); tx_pkt[4] = char_buff[0]; tx_pkt[5] = char_buff[1]; gencrc(char_buff[0]); Page 34 of 44
Data Acq for a Live Project.doc gencrc(char_buff[1]); data_to_char(crclo); tx_pkt[6] = char_buff[0]; tx_pkt[7] = char_buff[1]; data_to_char(crchi); tx_pkt[8] = char_buff[0]; tx_pkt[9] = char_buff[1]; transmit(); poll_packet_received =0; /* for testing */ /* TR0 =1; */ /* upto this */ } } } The final code at the server side is as shown below: /* This polls a number of slave units for its data through serial port and sends the received data to the PC using parallel port with handshaking using Pins 6 & 7 and 8. The select lines select the channel of MUX at the input of U-ctlr. Lowest order two bits select the channel. Address starts with 0x61. Address 0x65 will use the same channel and has to be daisy chained with address 0x61 and so on. */ #include #include <stdio.h> #define STX 0x01 #define ETX 0x03 #define INTR P3_2 /* Pin-6 of 89C2051, bit-6 of 0x379, connected to Pin-10 of parallel port */ #define ACK P3_3 /* Pin-7 of 89C2051, bit-0 of 0x37a, connected to Pin-1 of parallel port */ #define START_ID 0x61 #define END_ID 0x64 #define STB P3_4 /* Pin-8 of 89C2051, bit-7 of 0x379, connected to Pin-11 of parallel port */ #define SEL_0 P3_5 /* Pin-9 of 89C2051 */ #define SEL_1 P3_7 /* Pin-11 of 89C2051 */ #define CRC_ERROR 0x10 #define DATA_LENGTH_ERROR 0x20 /* Pin-14 of parallel port is connected to the reset pin of 89C2051 so that PC can reset it */ /* unsigned char array[END_ID - START_ID + 1][32]; */ void gen_crc(unsigned char, char *); unsigned char char_to_data(void); void data_to_char(unsigned char, char *); static unsigned char code acrchi[] = { 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, Page 35 of 44
Data Acq for a Live Project.doc 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40 }; static unsigned char code acrclo[] = { 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B, Page 36 of 44
Data Acq for a Live Project.doc 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, 0x40 }; unsigned char code data_length[] = {2, 6, 16, 10}; unsigned char pkt_recv=0, crchi, crclo, STS, data_buff[2] ,data_leng; unsigned char recv_buffer[25], no_of_bytes= 0; unsigned char data_00=0, data_10=0, data_11=0, data_12=0, data_20=0, data_21=0, data_22=0, data_23=0, polling_done =0; unsigned char pol_pkt[3]={ 0x01,0x00,0x03}, ID = START_ID , crchi_pkt, crclo_pkt, ID_recv; timer0_interrupt() interrupt 1 { unsigned char i=0; EA=0; TL0=0xff; TH0=0x93; pol_pkt[1] = ID; REN =0; SEL_0 = ID&0x01; SEL_1 = ID&0x02; REN =1; TI=1; /* polling done */ for(i=0;i<3;i++) { while(!TI); TI=0; SBUF = pol_pkt[i]; } while (!TI); TI=0; ID++; if (ID > END_ID) ID = START_ID; polling_done =1; /* TR0 =0; */ /* This line is for testing only. comment out in normal mode */ EA=1; } serial_interrupt () interrupt 4 { EA=0; if(RI) { TL0=0xff; TH0=0x93; Page 37 of 44
Data Acq for a Live Project.doc if(SBUF == ETX) { if (recv_buffer[0]==STX) { pkt_recv =1; } } else { if (SBUF == STX) { no_of_bytes =0; } recv_buffer[no_of_bytes]=SBUF; if (no_of_bytes < 25) { no_of_bytes++; } } RI=0; } EA=1; }
main() { unsigned char i; /* serial port setup */ SCON = 0x50; TMOD = 0x21; TH1 = 250; TR1 = 1; /* ----------------- */ TL0 = 0xff; TH0 = 0x93; TI =0; ET0 =1; /* made 0 for testing */ INTR=0; ACK=1; ES = 0; /* made 0 for testing */ TR0 =1; EA = 1; STB =0; INTR =0; recv_buffer[0] = 0x01; recv_buffer[2] = 0x30; Page 38 of 44
Data Acq for a Live Project.doc recv_buffer[3] = 0x30; while (1) { if (polling_done == 1) { TR0 = 0; crchi=0xff; crclo=0xff; recv_buffer[1] = ID; if (ID == 0x61) data_to_char(data_00++, recv_buffer+4); if (ID == 0x62) { data_to_char(data_10++, recv_buffer+4); if (data_10 == 0) data_to_char(data_11++, recv_buffer+6); else data_to_char(data_11, recv_buffer+6); if (data_11 == 0) data_to_char(data_12++, recv_buffer+8); else data_to_char(data_12, recv_buffer+8); } if (ID == 0x63) { data_to_char(data_20++, recv_buffer+4); if (data_20 == 0) data_to_char(data_21++, recv_buffer+6); else data_to_char(data_21, recv_buffer+6); if (data_21 == 0) data_to_char(data_22++, recv_buffer+8); else data_to_char(data_22, recv_buffer+8); if (data_22 == 0) data_to_char(data_23++, recv_buffer+10); else data_to_char(data_23, recv_buffer+10); for (i=4; i<11; i++) recv_buffer[i+8] = recv_buffer[i]; } if (ID == 0x64) {
recv_buffer[4] = 0x30; recv_buffer[5] = 0x30; recv_buffer[6] = 0x38; Page 39 of 44
Data Acq for a Live Project.doc recv_buffer[7] = 0x35; recv_buffer[8] = 0x31; recv_buffer[4] = 0x31; recv_buffer[5] = 0x30; recv_buffer[6] = 0x36; recv_buffer[7] = 0x33; recv_buffer[8] = 0x31; } gen_crc((data_length[ID - START_ID]+ 3), (recv_buffer + 1)); data_to_char(crclo, recv_buffer+(data_length[ID - START_ID]+ 4)); data_to_char(crclo, (recv_buffer+data_length[ID - START_ID]+ 6)); no_of_bytes = data_length[ID - START_ID]+ 8; TR0 =1; pkt_recv =1; polling_done =0; }
if (pkt_recv == 1) { TR0 =0; crchi=0xff; crclo=0xff; /* calculate crc for ID, STS and data bytes */ gen_crc(no_of_bytes -4, recv_buffer+1); data_buff[0] = recv_buffer[no_of_bytes -4]; data_buff[1] = recv_buffer[no_of_bytes -3]; crclo_pkt = char_to_data(); data_buff[0] = recv_buffer[no_of_bytes -2]; data_buff[1] = recv_buffer[no_of_bytes -1]; crchi_pkt = char_to_data(); if ((crclo_pkt == crclo) && (crchi_pkt == crchi)) {
ID_recv = recv_buffer[1]; data_leng = data_length[ID_recv-0x61]; data_buff[0]=recv_buffer[2]; data_buff[1]=recv_buffer[3]; STS = char_to_data(); if (data_leng == ((no_of_bytes -8)) || (no_of_bytes == 8)) /* 1 for STX, 1 for ID, 2 for STS and 4 for crc */ { STS &=0x0f; /* length of data valid */ Page 40 of 44
Data Acq for a Live Project.doc
} else { STS &=0x0f; STS |= DATA_LENGTH_ERROR; } } else { STS &=0x0f; STS |= CRC_ERROR; }
/* send through parallel port */ STB =1; INTR=1; /* to generate interrupt and start handshaking */ while(!ACK); /* wait for ACK going high */ P1 = ID_recv;
STB =0; while(ACK); /* wait for ACK going lo */ STB =1; while(!ACK); /* wait for ACK going high */ P1 = STS; if (STS != 0x00) INTR =0; STB =0; while(ACK); /* wait for ACK going lo */ if (STS == 0x00) { for (i=4; i<(no_of_bytes -4); i++) { STB =1; while(!ACK); /* wait for ACK going high */ P1 = recv_buffer[i]; Page 41 of 44
Data Acq for a Live Project.doc if (i < no_of_bytes -5) /* while transmitting last byte it will make INTR lo to inform the server abt it */ STB =0; else { INTR =0; STB =0; } while(ACK); /* wait for ACK going lo */ } } /* for debugging */ /* STB =1; INTR=1; while(!ACK); P1= crchi; STB =0; while(ACK); STB =1; while(!ACK); P1= crclo; STB =0; while(ACK); STB =1; while(!ACK); P1= crchi_pkt; STB =0; while(ACK); STB =1; while(!ACK); P1= crclo_pkt; STB =0; while(ACK); */ /* upto this */ pkt_recv =0; no_of_bytes =0; TR0 =1; } } Page 42 of 44
Data Acq for a Live Project.doc } void gen_crc(unsigned char count, char * ptr) { unsigned char index, i; for (i=0; i< count; i++) { index=crchi^*(ptr + i); crchi=crclo^acrchi[index]; crclo=acrclo[index]; } } /* unsigned char char_to_data(void) { unsigned char j, data_received=0; unsigned short temp1=0; for (j=0; j<2; j++) { if (data_buff[j] > 0x60) temp1 |= (data_buff[j] - 0x57); else temp1 |= (data_buff[j] - 0x30); data_received |= (temp1 <<= (j)*4); temp1 =0; } return (data_received); } */ unsigned char char_to_data(void) { unsigned char chb; chb = (data_buff[0] &0x0f) | ((data_buff[1] &0x0f) << 4); return (chb); } void data_to_char(unsigned char chb, char * char_buff) { char_buff[0] = (chb &0x0f)|0x30; /* lower order nibble encoded to character */ char_buff[1] = ((chb >> 4)&0x0f)|0x30; /* higher order nibble encoded to character */ }
Page 43 of 44
Data Acq for a Live Project.doc
Future Scope of the Project
This project has a lot of scope for future use. Since the part of the system dealing with the shaft encoder to get an idea about the angle of rotation of the pulley around which the steel rope is wound the same idea can be implemented in other situation where absolute shaft angle position sensing is necessary. The display system can be web enabled where data about motion of the different parts of the system can be displayed in real time as in this case where different parameters are displayed in real time such as current in the series motors used in the dragline, Hoist height, Swing angle etc. The communication protocol which I have used here can be implemented in other Data acquisition system where real time data needs to be captured.
Page 44 of 44