Data from one PC to another. HOME. TUTORIALS INDEX. Other material for programmers Bookmark this on Delicious. Recommend to Stumble. Upon. This tutorial is a little rough around the edges, but it is far enough along that I thought you'd want what's here. Despite its sins, it has been tested.. April 2. 01. 0, using Windows XP and Delphi 4, and everything was fine down to ".. Write. String is, of course capable of sending more..". It is probably fine past there, too.. I revisited the program in the course of working with serial comms with the marvelous Arduino microprocessor. There are a number of articles about serial comms with Arduinos at my Arduino "How To" site.. This is a library for sending and receiving DMX codes using the Arduino plattform or a ATmega (ATmega168, ATmega328 or similar) processor with a clock speed of. To do that I have used a computer with Ubuntu 12.04 and the program language C++, but if you want to used Windows the code works too, only have to change the port. DEV-11021: This is the new Arduino Uno R3. In addition to all the features of the previous board, the Uno now uses an ATmega16U2 instead of the 8U2 found on the Uno. Level 4" section, but I make no promises! The best is probably the Delphi tutorial about bi- directional serial comms. That is built upon the work done in the tutorial you are currently reading. Unless you have some expertise, you might want to finish this one before attempting the more advanced tutorial. Things you can learn here will make it easier for you to understand it. Maybe you, like me, wanted to hook a microprocessor up to your "big" computer, for instance an Arduino? While I was doing the April 2. I created a zip file you can download with the sourcecode and even the compiled . It shows you how to send messages from one PC to another via the serial port. It does not require anything more than Delphi 2 and Win. I think it will work with higher versions of Delphi and Windows. For a different approach to accessing not only the COM ports, but other ports too, see my tutorial about the free DLL Inp. Out. For more about using the serial port, see my serial port tutorial. I also offer a page about using a COM port to communicate between microprocessors and Windows PCs. Although it is couched in Arduino terms, much of the information is applicable to other contexts. Don't forget: There are inexpensive USB devices which provide a Windows PC with a virtual COM port. Sadly, the USB to parallel port printer devices seem less well suited to connecting things other than printers.). At the moment, this tutorial tells you about sending data only one way, from PC "A", to PC "B". For bi- directional serial communications, you have to work harder. I would suggest that you finish the page you are reading first, as everything here is part of the bidirectional answer. I have done a further tutorial on how to accomplish bi- directional serial comms with Windows, when you are ready for it. This will not give you an all singing, all dancing application! What it will do, I hope, is give you a starting point, useful in its own limited way, and perhaps also useful if you want to go further. Along the way, the tutorial illustrates the general skill of using Windows API calls directly, instead of with the help of Delphi wrappers. The latter is preferable.. ![]() ![]() ![]() Before you try to do anything yourself with the serial port, make sure that your hardware is working properly. I make many references to Hyperterminal in what follows. That used to come with Windows, but doesn't now, and isn't always installed on older machines. You can use any simple serial terminal software. I've been using Pu. TTY, but haven't used it much yet. It is free, and runs on Windows an Linux. For what we're doing here, you only need to download putty. Connect two PCs with a null modem cable. Start Hyperterminal on each of them. Win 9. 8: It is in Programs|Accessories|Communications.. It is one of the free things which come with Windows, but it isn't always installed. To install: Settings | Control Panel | Add/Remove Programs, The Windows Setup tab. Once your computers have Hyperterminal, start it up.. Your start menu will probably have been given a link to the Hyperterminal folder. You need to double- click on "Hypertrm. The entries with . When you first start Hyperterminal, you'll probably get the New Connection Wizard. If you want your machines to be consistent with what I say in this tutorial, create a connection called DD5. HTC (Delphi Demo 5. Hyper. Terminal Connection). It doesn't matter what you put in the phone number fields. Just "Connect Using.." one of your Com ports. Of course it has to be the right Com port. Oh goodie.. the fun has started already. I really hate serial comms). A detour: On one of my machines, a laptop, the port has a little sticker I put on it saying it is Com. Hyperterminal didn't offer a Com. Com. 1 gave rise to "Could not open.".. File | Properties is what you need to try again. The Configure button "worked" for Com. Next I right clicked "My Computer", clicked "Properties", went into Device Manager, Infra Red Devices. I said "Disable in this profile". Rebooted.. At last I COULD "talk" from one computer to the other over the null modem, using Com. Bah. I then went to the second machine, started Hyperterminal, started a new connection. Called it DD5. 5HTC, too. No need for different names.. Thence to the Configure dialog for each machine's Com port. Most of the settings don't matter much in this application.. Try. Bits per second: 9. Flow: Hardware or none. One more thing to do.. Call | Call via the menus, or just click on the "Call" button (a little telephone). You should see "Connnected" in the status bar, window's lower left. Now, all being well (it is quite possible that it won't be!), when you type on one of the computers, what you typed will appear on the other. And vice versa. Without "local echo", you won't see what you type on the machine you are on. Get that much working!!! Good luck. Serial comms.. Did I say that?). If you want, you can turn on a local echo.. File | Properties | Settings.. When you leave Hyperterminal, you are asked "Do you want to save session?" Saying yes preserves any settings you may have made. Shut down Hyperterminal on the machine you have Delphi on. Start a new Delphi application. Put five buttons on it. Name them... bu. Open. Connection. bu. Close. Connection. .. and make the labels the obvious things. Name the main form DD5. Save the project in a folder called DD5. Call the unit DD5. DD5. 5. Make bu. Quit's On. Click. application. Before I go any further.. Borland (Inprise) for the good information that used to be at http: //community. Use the Object Inspector to set to false the "enabled" property of bu. Send. X, bu. Send. Y and bu. Close. Connection. Declare a global variable.. Comm. File : THandle. Private declarations}" in the TDD5. F1 class declaration. Then, just after.. Comm. File : THandle. Write. String(s. To. Send: string). Then, just before the unit's terminal "end.", insert... TDD5. 5F1. Write. String(s. To. Send: string). Number. Written : d. Word. {N. B.: I saw the following in a newsgroup post. Warning: There is an error in the FAQ - Number. Written must be. dword not Long. Int"}. if Write. File(h. Comm. File. PChar(s. To. Send)^. Length(s. To. Send). Number. Written. nil)=false then. Unable to send'). We'll see what this is good for in a moment!). Make bu. Open. Connection's On. Click... procedure TDD5. F1. bu. Open. Connection. Click(Sender: TObject). Comm. Port : string. Comm. Port : = 'COM1'. Comm. File : = Create. File(PChar(Comm. Port). GENERIC_WRITE. 0. OPEN_EXISTING. FILE_ATTRIBUTE_NORMAL. Comm. File=INVALID_HANDLE_VALUE then begin. Show. Message('Unable to open '+ Comm. Port). end // no ; here. Send. X. enabled: =true. Send. Y. enabled: =true. Close. Connection. Open. Connection. Note: If when you connected via Hyperterminal, you were using a Com port other than 1, then you will need to modify the COM1 above accordingly. Now make bu. Send. X's On. Click... procedure TDD5. F1. bu. Send. XClick(Sender: TObject). Write. String('X'). Run the program. Click on the "Open connection" button. Click the "Send X" button. You should see an "X" appear on the other computer! You should click on the "Close Connection" button before exiting the program, though Windows may clean up after you if you fail to do so. A "proper" application would need to monitor whether the connection was open or closed, close it when the program is closed, if not closed. Add the following for bu. Send. Y's On. Click... TDD5. 5F1. bu. Send. YClick(Sender: TObject). Write. String('Y'). Now you can send "X" or "Y" to the other computer (Useful, when you've sent a bunch of Xs, and it is a little hard to see if another is arriving! The procedure Write. String is, of course capable of sending more than a single byte. Set up a button called bu. Hello. World, make it's On. Click.. procedure TDD5. F1. bu. Hello. World. Click(Sender: TObject). Write. String('Hello World '). Hello World" to the destination computer. Gammon Forum : Electronics : Microprocessors : I2. C - Two- Wire Peripheral Interface. Tip. A summary of everything shown below is available further down this page: This post describes how the I2. C (Inter- Integrated Circuit, or "Two- Wire") interface works, with particular reference to the Arduino Uno which is based on the ATmega. P microprocessor chip. A lot of the details however will be of more general interest. The Two- Wire interface is extremely useful for connecting multiple devices, as they can all share the same two pins (plus a ground return). This is because the devices are "addressable". Each device needs to have a unique address in the range 8 to 1. Address 0 is reserved as a "broadcast" address, addresses 1 to 7 are reserved for other purposes, and addresses 1. Because of this you could have an LCD screen (say) at address 1. More information about I2. C at: http: //en. I2c. More information about the Arduino Two- Wire interface at: http: //www. Reference/Wire. Other protocols. Pinouts. On the Arduino Uno the pins you need are: Analog port 4 (A4) = SDA (serial data)Analog port 5 (A5) = SCL (serial clock)On the Arduino Mega, SDA is digital pin 2. SCL is digital pin 2. SDA and SCL on the board itself). On the Arduino Leonardo, the SDA and SCL pins are separate pins, so marked, on the board (next to AREF). They are also connected to D2 (SDA) and D3 (SCL). These pins may require pull- up resistors (that is, connect them to +5v via something like a 4. K resistor each). The Atmega. 32. 8 is configured to use internal pull- up resistors which may be adequate for short cable runs. Warning: for multiple I2. C devices, or longer cable runs, the 4. K pull- up resistor (for each line) is recommended. Also see further down in this thread for some screen- shots of the effect of using different pull- up resistors. Of course, you also need to connect the GND (ground) pins to complete the circuit. The pins should be connected together (that is, pin 4 to pin 4, and pin 5 to pin 5, if you are connecting Arduino Unos together). This is because the pull- up resistors keep the lines high until one of the devices wants to use it by pulling a line low. In other words, you don't swap pins (like you do with serial communications, where you connect Tx to Rx and vice- versa). Note also that the Atmega specifies a maximum bus capacitance of 4. Sending data. Let's start with an image - this is a screenshot taken with a logic analyser. It shows the character "S" (0x. Arduino to the device at address 4. From the above graphic note the following points of interest: The transmission starts with the "Start condition" (labelled Start). This is when SDA (serial data) is pulled low while SCL (serial clock) stays high. The 7- bit address of the required slave is then transmitted, most significant bit first. In this case it was 4. A or 0b. 01. 01. 01. The logic analyser reports the address as being 0x. A (this is, 4. 2) shifted left one bit, so that the "write" bit (0) is in the least- significant bit place. Then the read/write bit is transmitted. The master then waits for the slave to pull the SDA line low which is an ACK (acknowledge) that a slave of that address exists and is ready to receive data. If there is no slave connected and powered on, or it does not have the required address, then it will ignore the address, leaving the SDA line high (by the pull- up resistor). This counts as a NAK (negative acknowledgement). This can be tested for in the software. Then the data byte (0x. Again, after the 8 bits of data, the master checks that the slave acknowledges by pulling the SDA line low. Thus, each byte is acknowledged. More data bytes could be transmitted, but are not shown here. The transmission is ended by the "Stop condition" (labelled Stop) which is sent by releasing the SDA line to allow it to be pulled up while SCL stays high. The code to produce this (in Arduino's C++ language) was. Written by Nick Gammon. February 2. 01. 2. Wire. h>. const byte SLAVE_ADDRESS = 4. LED = 1. 3. Wire. Mode (LED, OUTPUT). Wire. begin. Transmission (SLAVE_ADDRESS). Wire. write (x). if (Wire. Transmission () == 0). Write (LED, HIGH). Write (LED, LOW). EDIT] Updated February 2. Arduino IDE. This uses Wire. Wire. send. Tip: Wire. Transmission returns zero if the transmission was a success. It is a good idea to check that you got zero, otherwise you are sending "blind". If you do not get zero maybe you have the wrong slave address. Try running the "I2. C scanner" described later in this thread. The code above uses address 4. LED on pin 1. 3 (which is standard on the Arduino Uno) to confirm visually that the transmission took place. If it succeeded then the LED is turned on, otherwise off. You can see this in operation by noting that the LED is only on if a slave of address 4. The code for the slave in my case was. Written by Nick Gammon. February 2. 01. 2. Wire. h>. const byte MY_ADDRESS = 4. Wire. begin (MY_ADDRESS). Mode (i, OUTPUT). Wire. on. Receive (receive. Event). } // end of setup. Event (int how. Many). Many; i++). byte c = Wire. LED. if (digital. Read (c) == LOW). Write (c, HIGH). digital. Write (c, LOW). } // end of for loop. Event. The slave code has nothing in the main loop, because the two- wire interface generates an interrupt when data arrives. This was displayed on LEDs plugged into pins D2 through to D7 using an appropriate resistor in series with each one (eg. EDIT] Updated February 2. Arduino IDE. This uses Wire. Wire. receive. Example of connecting two Unos together to communicate via I2. CACK or NAKThe above graphic shows what happens if the slave device responds. Below is what happens if it doesn't. In this case I changed the address from 4. This condition can be tested for in Wire. Transmission(). That returns zero on success and various error codes on failure. Timing. The timing for the entire transaction above (address byte and data byte) was that from the start condition to the stop condition took 0. Thus at that rate you could send around 4. However that is a bit inefficient because half of it was the address. The time taken to send one byte was 9. This is reasonable enough if you are just driving a LCD display or similar. You can increase the clock speed by adding this line after "Wire. TWBR = 1. 2; With that in place, the speeds are 4 times as fast. So a single byte then takes around 2. Sample TWBR values. The formula for converting TWBR into frequency is. TWBR * prescaler)). The default prescaler is 1, and the default value for TWBR (on the Uno etc.) is 7. Thus: freq = 1. 60. TWBR prescaler Frequency. Hz (the maximum supported frequency). Hz. 7. 2 1 1. Hz (the default). Hz. 7. 8 4 2. Hz. 1. 58 4 1. Hz. To set the prescaler to 4 you need to set the bit TWPS0 in TWSR, so for example to have a clock of 1. Hz. Wire. begin (). TWBR = 1. 58. TWSR |= bit (TWPS0). EDIT] Updated 1. 7 June 2. TWBR values and related frequencies. Buffer Length. It isn't currently mentioned in the documentation, but the internal buffer used for I2. C communications is 3. That means you can transfer a maximum of 3. It also isn't particularly clear, but the functions Wire. Transmission and Wire. They simply prepare an internal buffer (with a maximum length of 3. This is so that the hardware can then clock out the data at a high rate. For example. Wire. Transmission (SLAVE_ADDRESS); // prepare internal buffer. Wire. write ("hello world"); // put data into buffer. Wire. end. Transmission (); // transmission occurs here. After calling Wire. Transmission, if zero was returned, you know the call was a success. Communicating with other devices. So all this I2. C stuff is great, you can use just two wires (plus ground) to talk to up to 1. But what if you have a device (like a keypad) that doesn't support I2. C? Well, the simple answer is that you can use something that does as an interface. For example, a second Arduino. My examples above do just that, using one as the master and second one to display text on LEDs. In fact, the "master" can also act as a slave, since you can have multiple masters on one wire. The example below shows how you can send data from one Arduino to another, whilst waiting for information to be sent from the second back to the first. Master. // Written by Nick Gammon. February 2. 01. 2. Wire. h>. const byte MY_ADDRESS = 2. SLAVE_ADDRESS = 4. LED = 1. 3. Wire. MY_ADDRESS). Wire. Receive (receive. Event). pin. Mode (LED, OUTPUT). Wire. begin. Transmission (SLAVE_ADDRESS). Wire. write (x). Wire. Transmission (). delay (2. Event (int how. Many). Many; i++). byte b = Wire.
0 Comments
Leave a Reply. |
AuthorWrite something about yourself. No need to be fancy, just an overview. Archives
November 2017
Categories |