using communication hardware on the ATMega - Page 1
Forum section: electronics / general

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 08:38:02 am
content: I'm designing a project where ultimately I want 2 chips to be able to communicate with each other and/or a PC.Should I use RS232 / serial interfaces ? or is there something better ? I've never done communication protocols before.I'll start reading the datasheet but ultimately I have no idea yet of how much is hardware based and how down and dirty i need to get to transmit and receive a piece of information.

author: Codemonkey
author_rank: Regular Contributor
timestamp: July 02, 2014, 08:55:12 am
content: How far apart are the devices going to be ?If the're located more than a few inches, using the UART will likely be the easiest. No need to bother with RS232 level shifting, just get one of the FTDI USB-TTL serial cables for interfacing to the PC (many of which don't even come with a serial RS232 port these days).

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 09:16:17 am
content: The actual MCU's would be close so no distance problems, I'd use an FTDI adapter yes for any PC communication. Can serial communication connect to more than one device ? I guessing not. Is there the equivalent of an FTDI for other protocols like SPI ?

author: Codemonkey
author_rank: Regular Contributor
timestamp: July 02, 2014, 09:24:09 am
content: When you say close, how close ? On the same board ?I think there is a way of using some of the FTDI chips in a SPI mode, but I have not done so my self.Multidrop comms with a UART can be done though, RS485 for example. Ideally you need to assign one device as a master that then polls the other devices since it is a half duplex protocol.So, if you have device A (master) and B, C, D etc which are slaves, you would need to create a protocol whereby the slaves all place the transceiver device in receive mode (RS485 devices have a direction pin which you must control), and then the master sends an address byte followed by the data and then goes into receive mode. The slave with the matching address then receives the message, processes it and if required places its transceiver device in transmit mode and sends a reply addressed to the master.

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 09:28:05 am
content: Do atmega's do RS485 ? Yes the two MCU's are on the same board.

author: Rerouter
author_rank: Super Contributor
timestamp: July 02, 2014, 09:28:30 am
content: if you want either to be able to talk directly over the same cable to the computer, you could have an RX/TX pair going between the 2 micros, and use some intermediary logic to swap one micros TX/RX lines with the computer at a time so it can talk directly with it, (analog switch with 2 enable pins and possibly and Xor Gate)

author: Codemonkey
author_rank: Regular Contributor
timestamp: July 02, 2014, 09:39:54 am
content: 1st thing you need to understand is that RS232 and RS485 are only electrical specifications for the voltages / signaling method. The data itself comes from the the UART (the bit in the microcontroller) and is just known as asynchronous serial data.If you want to implement RS232 or RS485, you buy a transceiver device which translates the TTL/CMOS signals from the micro to the appropriate voltages for RS232/485.The ATMega won't "do RS485", its up to you to add the transceiver to the UART pins of the micro.However, since your micros are on the same board, its a bit overkill to add RS485 for a few inches at the most. Does your microcontroller have more than one UART ? If so, use one to communicate with the PC, and the other to link the 2 micro's. If not, you might be better off using I2C or SPI for the link between the micro's and reserve the UART for the PC connection.Maybe if you could describe a bit more what you're trying to build and what the devices will be doing that would help.

author: nctnico
author_rank: Super Contributor
timestamp: July 02, 2014, 10:05:40 am
content: Quote from: Simon on July 02, 2014, 09:28:05 amIf you are using two MCUs I strongly suggest you choose a different MCU which can do all the work by itself. Getting a communication protocol to work reliably can be extremely tricky. You need to take care of things like missing a message, messages with an error. What do you do in case of a time-out? What if the watch-dog gets triggered on one MCU and it resets?Needing two MCUs suggest that these will be busy doing something so you get a lot of timing constraints on handling the communication. I have seen many novices fail when trying to stick to the MCU they know by using multiples MCUs! Please don't dig your own grave...

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 10:16:42 am
content: I am using two MCU's to provide redundancy in case of failure not for multitasking. At the moment I am using an ATMega328 family chip, I'll see how big my code is and probably be able to go down to a mega48 or 88. I'm not certain yet of actually doing serial coms between them, I might just use a pin outputting a fixed signal to act as a heartbeat that the other chip can verify, then I do have the single serial interface free to do PC communication but that is a later development and will mean me looking into how i can program variables from a PC over the serial interface and read back information for diagnostics. At the moment I'm trying to roughly work out what resources i need to ensure I have the right chip and use the right pins without creating conflicts.

author: nctnico
author_rank: Super Contributor
timestamp: July 02, 2014, 10:20:42 am
content: For communicating with a PC the easiest way is to implement a command line interpreter. That way you can test/demonstrate the communication with any terminal emulation program (like Hyperterminal).

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 10:23:21 am
content: uh, now your running ahead of mewhat I'd hope is that the pc can receive data from the chip about selected working conditions but also send data back to modify variables that I gather will have to be stored on the eeprom ? or can I alter the main flash ?

author: Psi
author_rank: Super Contributor
timestamp: July 02, 2014, 10:26:21 am
content: All AVRs (that i know of) have "Multi-processor Communication Mode" which is a hardware feature so the MCU can ignore serial data not intended for it when there are many serial devices on the same bus.It uses an extra bit to indicate if a frame is an "address frame" or not. If the address matches the MCU it will receive all bytes until a new address frame comes along.I've never actually used this feature but it looks quite useful for multi-node communications.So to answer your question yes, you can have multiple serial devices connected together.There's a few different ways to do it though....You can pass the data along serially in a chain and not have the issues of collision (two devices transmitting at once). If a mcu receives info it checks the address part of the data packet and does whatever action is needed, otherwise it re-transmits it to the next device.(Note: This mode can not work with Multi-processor Communication Mode because you need to receive the data to re-transmit it. You need to write your own address info into your protocol)|--TX PC RX-----TX mcuB RX-----TX mcuC RX -||----------------------------------------------------|or, for simple one-way coms you can just connect one TX to multiple RXPC TX--|----- RX mcuB|----- RX mcuC|----- RX mcuDor, combine TX/RX into a bidirectional line and connect all MCUs together with a single 2 wire bus.You have to make sure your protocol wont transmit on two devices at once. eg, you can pass a token around or have a master that polls slaves to see if they have anything to say. Or have each MCU talk at a specific time which is different between all mcus.This method is what Multi-processor Communication Mode was intended for. You can have 100's of devices on the bus and not keep wasting interrupt/cpu time on every mcu checking all messages for some data only intended for one mcu.---|----------|--------|-----TX&RX TX&RX TX&RXPC MCUB MCUCThere maybe other ways too.

author: nctnico
author_rank: Super Contributor
timestamp: July 02, 2014, 10:47:57 am
content: Quote from: Simon on July 02, 2014, 10:23:21 amWith a command line interpreter you can create commands to do that. You could create a command like 'write_setting 1234' which will then alter a setting somewhere in flash or eeprom.

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 10:49:48 am
content: so presumably I have some code in my MCU that scans through what it is receiving from the PC and when it recognizes a code it carries out instructions.

author: Psi
author_rank: Super Contributor
timestamp: July 02, 2014, 10:59:43 am
content: Quote from: Simon on July 02, 2014, 10:49:48 amYes, you decide on a packet length you want. (or you can code a variable packet length protocol if you want something a bit more robust for large data transfers)It's easy/fast to use a fixed length and have a hardcoded start of packet marker.This is really crude, but you might have a 8 byte frame like this..STR,a,cdWhereSTR = 3 byte start of packet markera = 1 address byte (so 255 possible nodes on the bus)c = 1 command byted = 1 data/payload byte, = separator (more on this later)You would start filling up an array when you detect the letters STR in sequence. After 8 bytes you run some packet handling code to do whatever events you want based on the a,c,d data.You can ignore the packet if the address doesn't match the address of the mcu checking it. etc..Use a C switch statement on the command byte. That would give you 255 possible commands and each could carry 1 byte of info.eg, command=45 (says flash LED1) payload=10 (says flash this led 10 times)The reason i included the 2 commas was so you cannot physically have a STR in the data/address section, this is crude but means you can never get out of sync (where STR inside the packet gets interpreted as the start of a packet).You could add a checksum as well, a simple XOR of all the bytes and attach the result to the end of the packet.If, when receiving a packet, it doesn't match ignore the packet (it's corrupt).It gets more complex if you need a protocol that ensures a packet gets to the destination without being corrupted.You then need to code an packet acknowledge and resend system etc..

author: bwat
author_rank: Frequent Contributor
timestamp: July 02, 2014, 11:01:05 am
content: Quote from: nctnico on July 02, 2014, 10:47:57 amYes, the command line interpreter interface is almost always a winning design for an interface. In fact designing in terms of interpreters is quite nifty and often structurally very "clean". Anybody in any doubt should read Hal Abelson's foreward to the book "Essentials of Programming Languages, 2nd Edition". You can read it herehttp://books.google.se/books?id=GtPoyremy4EC&printsec=frontcover&hl=sv&source=gbs_ge_summary_r&cad=0#v=onepage&q&f=false

author: nctnico
author_rank: Super Contributor
timestamp: July 02, 2014, 12:19:26 pm
content: Quote from: Psi on July 02, 2014, 10:59:43 amDon't go this route. It makes debugging the communication with a PC much harder because you have no way to sit in between the PC and the microcontroller. Besides that the communication is always limited to the maximum packet length. It is much easier to fill a buffer with incoming characters and look if it is a command when a carriage return and/or linefeed comes along.

author: Psi
author_rank: Super Contributor
timestamp: July 02, 2014, 12:26:43 pm
content: There are advantages both ways.If you go the command line interpreter way you have to deal with encoding/decoding numbers between multiple bytes of ascii and a byte/word variable.eg, if you want to send the number 123 you have to encode that to 3 byte ascii "1" "2" "3". Send it, then decode that back into a number on the mcu at the other end.Where as, if you have a packet system, you just send one byte.. the ascii character 123 with no translation needed.Yes, you can use printf to convert things with one function, but it's not exactly the fastest of methods. (it generates a lot of code behind the scenes)It really depends what sort of coms you want and the speed you need.If its at the human interaction level or a fast stream of data.Command line interpreters aren't intended for fast MCU->MCU commsBut yeah, i totally agree about debugging being easier with CLI

author: bwat
author_rank: Frequent Contributor
timestamp: July 02, 2014, 12:43:00 pm
content: Quote from: Psi on July 02, 2014, 12:26:43 pmWhich eliminates any potential issues to do with different endianness.Quote from: Psi on July 02, 2014, 12:26:43 pmExactly, and until we've seen a specification we're all just revealing our technical prejudices - which is fun.

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 12:57:39 pm
content: Well it's all mostly academic at the moment but something I'm likely to be asked to do sooner or later, basically read data being spat out of the serial port by the program with the ability to receive commands that alter variables for in the field tweaking.

author: Psi
author_rank: Super Contributor
timestamp: July 02, 2014, 01:19:11 pm
content: Your better off with a CLI then.It's good for easy in-field changing of parameters, you can change things with any serial terminal app on any PC.

author: Simon
author_rank: Unknown
timestamp: July 02, 2014, 01:20:06 pm
content: CLI ?

author: Psi
author_rank: Super Contributor
timestamp: July 02, 2014, 01:20:29 pm
content: command line interpreter.Store the serial data into an array up until a carriage return/LF then decode the array text to perform a function.Then write code to understand a fixed number of keywords, each keyword denotes what follows it.egSET EEPROM 56 234Could be set eeprom address 56 to 234orENABLE MY_FEATUREDISABLE MY_FEATUREQUERY MY_FEATURE (this would return word enabled or disabled)

author: nctnico
author_rank: Super Contributor
timestamp: July 02, 2014, 01:43:47 pm
content: Please don't allow to set eeprom values externally using a fixed address. Whenever you need to change the layout of the eeprom the PC application will break also. It also takes careful documentation of the eeprom layout. A couple of years ago I had to re-implement something like that and it was a total nightmare because the documentation wasn't up to date and the software wasn't very clear on what a value meant.

author: Kremmen
author_rank: Super Contributor
timestamp: July 02, 2014, 08:08:43 pm
content: Quote from: Codemonkey on July 02, 2014, 09:39:54 am+1 to this strategy.You can use SPI in a master/slave configuration between the 2 processors and there it would be entirely practical to implement a frame based message format. A simple command+ optional data from master to slave, and simple response + optional data back. Just be aware of the nature of SPI so that you design a proper message header structure. Say you poll the slave and it responds with e.g. an 8 byte payload in the response data unit. The master must send the query command followed by a sufficient number of NOP frames to collect all the incoming response bytes, because the transfers are always bidirectional. (NOP = no operation). I have done a lot of these over the years so i can help if you want me to.For the human interface by all means do use UART and CLI. The proper way to do it is already laid out in previous messages. Here you need to implement the command parser and ASCII-to-xxx conversion routines. Also a very good idea would be to implement a simple configuration parameter setup support that can output a list of parameter names and values. I have written systems where you have parameter values stored in EEPROM, minimum and maximum values in flash (program code) as well as the parameter cleartext name in flash. Outputing a simple numbered list with parameter name, curent value and min, max permited values is then simple. And you can set the values by referring to them by number instead of name (easier parser).Also i have had good luck with RS485 (or i guess it is properly RS422 as it is not party-line) implemented so that the MCU board has a native RS485 interface and the PC end has a simple RS485/RS232 converter. Not strictly necessary on short distances but the only thing that works if you are say half a km away.

author: nctnico
author_rank: Super Contributor
timestamp: July 02, 2014, 08:20:06 pm
content: Actually you don't need to implement ASCII to text and vice versa routines. These are available in the standard C library and usually these are written pretty efficient. They stem from an era where they could only dream of the programming space available in an Atmega

author: rob77
author_rank: Super Contributor
timestamp: July 02, 2014, 08:31:58 pm
content: have you considered rs485 multidrop ? nice 2 wire bus - multiple nodes. it's robust , immune to noise...etc...you just need to write a "few" lines of code to implement the communication protocol of yours.

author: Kremmen
author_rank: Super Contributor
timestamp: July 02, 2014, 08:40:12 pm
content: Quote from: Psi on July 02, 2014, 10:26:21 amIf you plan to do multihost communications one of the first things you must specify is what they call the "access method". Put in simple terms, there are at least these simple alternatives:- point-to-point where A and B communicate using separate data lines A -> B and B -> A- single master, multiple slave where Master A communicates with a number of slaves 1...n. There is one transmit line from A -> 1...n and one receive line from 1...n -> A. This means that only A can hear 1...n and 1...n can only hear A. There must be a way to tell which of 1...n is the intended recipient. It can be done in hardware (chip select type thing) or an adress field in the frame header data. The latter means that all slaves must lift every frame at least until the address frame is received, to see if they must bother further.- peer-to-peer partyline access method. Stations A...N communicate using a shared transmit/receive line (often RS485). There is no master/slave relationship. This option requires the use of a _media access protocol_. It can be implemented either in software or supported by hardware. I2C is a typical example. The idea is that any station is free to communicate with any other station. To do so it must somehow check that the media (line) is available an nobody else is transmitting. To do this you need some kind of _collision detection_ because it is always possible that 2 stations start a frame exactly at the same time. Usually the collision detection selects one station as the collision arbitration winner and it can continue while the loser withdraws and starts a resend delay. Classical Ethernet works this way as do many other shared media protocols. You probably do not wish to start from this alternative nor should it be necessary.The human interface CLI is clearly point-to-point.The inter-MCU link is most likely master/slave but reading your earlier posts it looks like you need to build in a master status renegotiation protocol in case you ever actually switch the roles. Or else plan how to restore the initial status outside the protocols. To clarify, the problem is this:- somehow the 2 MCUs have been started "normally" and one is master, the other slave.- the master crashes or something. The slave is supposed to be alerted by some mechanism and it assumes the role of master (doing the stuff the master did earlier)- when the orignal master is restored there is a potential point of conflict. There is a new master in operation and the restored one should not barge in just like that because there will be issues. Instead the 2 MCUs should negotiate their new status somehow. I have been there and the strategy i suggest is to minimize the role changes. It works like this:-- the unit that is master, stays master until it is shut off or crashes.-- when a unit boots, it opens a link with its partner and arbitrates the startup role. If the partner is running it will indicate status of active master which would make the booting unit a slave. But if there is no response from the partner or it indicates problems, the starting unit assumes the role of master and communicates this to the partner. It is then supposed to revert to slave status.

author: Psi
author_rank: Super Contributor
timestamp: July 03, 2014, 01:41:55 am
content: Quote from: nctnico on July 02, 2014, 08:20:06 pmIt's still quite cpu cycle intensive compared with not doing it and using the raw value with no conversion.You're talking maybe 2 cpu instructions to copy a value from ram to the uart data registerCompared with 100's of instructions to divide down the integer with remainder into multiple values and then offset them to an ascii value. Plus the overhead of the limit checks and other misc stuff imposed by the function itself and the calling of it.

author: nctnico
author_rank: Super Contributor
timestamp: July 03, 2014, 10:54:02 am
content: You'll need limit checks anyway. Just look at your C library for the atoi function and see what it does with just a few (5 or so) lines of code. Besides that just copying bytes from ram to a UART doesn't solve byte order (endianess) issues. And if you ever need to alter or update the packet format you'll be seriously screwed. It will take a lot of time and effort to change so what is gained by using a cheaper/slower processor is lost 10 times by having to do more development work. Besides all that: how many commands need to be send per second? Probably less than 0.00001 so the extra overhead from ASCII conversion routines is near zero anyway.