Shop OBEX P1 Docs P2 Docs Learn Events
Dynamic slave address? — Parallax Forums

Dynamic slave address?

BasilBasil Posts: 380
edited 2009-05-01 19:56 in Propeller 1
Hi All,

I have a concept floating around in my head and due to lack of experience can't answer this questions for myself.

Is there any way to automatically assign bus address' to slave devices on say an I2C or RS485 multidrop bus?
All slaves will start with address 0. On slave start up they will request an address from the master which will give them the next free address.

The problem I have in my head is at startup. All the slaves will start with address 0 at power up and so will all ask at the same time to the master which will corrupt all the data.

One thing I have thought up to prevent this, is on startup the slaves each wait a random amount of time, say between 0 and 500ms, and then make the request. There is only a small chance of collisions but I don't really want the delay.

Another option is on startup the master asks address 0 if there is anyone home, and if it gets a reponse then it tells device 0 to change its address. This will again cause trouble because all the slaves start with address 0 so will all respond.

Any thoughts? This has probably already been implemented by someone!

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
-Alec

Velden in N scale

Comments

  • TubularTubular Posts: 4,717
    edited 2009-04-30 22:21
    Is it/can it be a daisy chain i2c net? There was a thread not long ago about booting multiple props from a single EEPROM. The essence of it was a single line between each daisy node; connecting a digital output on the upstream prop to the reset input of the downstream prop via a pull-down resistor. As each prop boots it asserts the digital output, enabling the next prop in the sequence to initiate a boot.

    If your I2C slave has a digital output you could do something similar. After it resolves its address it asserts its output, which powers the next I2C slave in the chain.

    (edit) There would be a limit to how many you could connect depending on current loading, voltage drop, but I assume since you mentioned i2c you are working in a compact local area

    tubular

    Post Edited (Tubular) : 4/30/2009 10:26:20 PM GMT
  • BasilBasil Posts: 380
    edited 2009-04-30 22:26
    Hi Tubular,

    I would prefer it wasn't daisy chained. Also, i2c will probably have too shorter distance each run can be so would prefer to go in the direction on RS485 or something similar.

    Thanks for the thoughts though [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale
  • kwinnkwinn Posts: 8,697
    edited 2009-04-30 22:27
    Ethernet does something similar to your first idea as far as sending data goes. When a device wants to send data it waits until there is no data on the bus and then starts to send. While it is sending it also listens to the bus to see if the data is correct, and if it detects an error it stops sending for a random time and then starts over. This is known as carrier sense multiple access with collision detection (CSMA/CD).

    The second way of doing it is called token ring. The slaves are connected in a ring, and the master passes a token to the first slave in the ring, and the slave passes it to the next one when it it finished with it. The slave that has the token can communicate with the master.

    There are several other methods as well.
  • BasilBasil Posts: 380
    edited 2009-04-30 22:35
    I knew there was something obvious! I work with ethernet every day and never thought of CSMA/CD!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale
  • TubularTubular Posts: 4,717
    edited 2009-04-30 22:43
    Yeah RS485 is probably the way to go. I assume therefore you have some kind of programmable intelligence at the nodes.

    My thinking is that if you can spare a single wire you can save yourself a lot of coding effort (effectively its is a hardware token)

    Tell us a bit more about the topology and what you need to do at the nodes. Someone in the forum will have probably done something similar.

    tubular
  • BasilBasil Posts: 380
    edited 2009-04-30 23:02
    Hi Tubular,

    This concept is an addition to this one from Peter http://forums.parallax.com/forums/default.aspx?f=25&m=335216 where each node is a programmable, semi-smart slave IC on a multidrop bus.

    Only I don't want to have fixed slave address' because I want the end user to be able to just plug the slave in and it will work without configuration. I also don't want to have to assign a unique slave address to each and every slave at the time of programming.

    The nodes will be pretty simple to start with, recieving a byte sent from the prop (master) and transfering this byte to its 8 outputs. It will then read its 8 inputs and send the results as a byte back to the prop.

    There will be a bit of smarts to check the state of the devices connected to the I's and O's and generate error messages if required. This may involve A/D conversion and some basic continutity tests, but I have not gotten that far yet.

    In the future there will be more advanced nodes.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-01 00:50
    Alec,

    How will the master device know which slave device (i.e. which physical I/Os) it's talking to if nothing is preassigned? In other words, if I say my address is $0E, how will the master know whether I'm controlling the toaster or the lights?

    -Phil
  • BasilBasil Posts: 380
    edited 2009-05-01 00:59
    For this particular application that information is not required. All the master needs to know is if a node a specific type is available to talk to.

    Using your example, the toaster controller should only be connected to a toaster. If they user connects it to the lights then they have issues :P

    This is quite a specific application and so I don't need a one size fits all algorithim just yet.
    In saying that though, if a satisfactory solution can be found i'd like to adapt it into a generic solution. In which case there would be a small amount of user intervention required to assign a 'task' to each node.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale
  • TubularTubular Posts: 4,717
    edited 2009-05-01 01:19
    Alec, I'm working on exactly the same thing, also inspired by Peter's thread. Great minds think alike, yes?

    My approach is to use jumpers, read very briefly at power on, to configure the slave's operating mode and address. There are over 80 different jumper settings easily possible on the 4x2 GPIO header. After configuration the jumpers are permanenty removed, and the mode and address are retained in non volatile memory. Upon next boot the GPIO can be used for their chosen purpose (ADC PWM EEPROM emulation etc).

    For simple mass configuration, I plan to have one long configuration socket say a 32*2 to accept 8 modules at a time. Then I would simply plug 8 modules in side by side, power them up a couple of times, and bingo they're set to go on address 1-8.

    Peter's intention was to use the single wire BDM protocol to configure the slave from the Prop. That way standard Obex modules can be created and the end user doesn't have to get involved with the (Freescale/other) development environment at all. This has a lot of merit and also live debugging may be possible.

    tubular
  • BasilBasil Posts: 380
    edited 2009-05-01 01:26
    After a bit of googleing I found the following on www.embeddedrelated.com/groups/piclist/show/5690.php which slooks like a nice solution (similar to my possible solution in the OP)

    *************
    "Basically the server comes up and sends a global "HELLO ALL" packet
    which the slaves hear. The slaves accept this packet and a "prepare."
    The unidentified slaves then wait "A random amount of time" and send a
    three digit random number to the master. Once the data is quiet the
    master then sends the three digit sequence in reply tagging on an ID# for
    the slave. The slave (single) responds with the same and an OK packet.
    If received OK then the slave is told to standby and await data. This
    takes it out of the "HELLO ALL" loop.

    This sequence runs "for a reasonable time" until you are confident that all
    slaves are likely to have been identified.

    I've used this to allocate ID's to PC's in a random network when running
    applications that require a good amount of redundancy. In my application
    slaves pinged the server every few seconds and if my reply was found the
    slave then took over the server's job and maintained the network. This also
    involved distributing to all slaves the entire server data required for control.
    This was burst randomly as bandwidth allowed.

    It was a **** to get right but it was immensely stable and secure from
    machine fallouts when started. It also allowed new slaves to arrive at any
    time if the "HELLO ALL" was broadcast occasionally.


    *************
    Sounds good?

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale
  • TubularTubular Posts: 4,717
    edited 2009-05-01 01:46
    Alec,

    It does sound reasonable, but Phil has a perfectly valid point - you need a way of 'tagging' each slave IO so you know what you're talking to. It is possible for the tag info to be in the master or indeed in the slaves. Unless you are hooking up to something very generic (eg Chrismas tree lights) where the exact light being illuminated doesn't matter.

    tubular

    (edit) sorry... just realised you already answered this in part. Still intrigued how you can get away without it though

    Post Edited (Tubular) : 5/1/2009 2:04:35 AM GMT
  • BasilBasil Posts: 380
    edited 2009-05-01 02:05
    My application is similar to the example you just posted so this threadmy have solved the problem.

    However, for the purpose of continuing this conversation, lets consider the idea of a non-generic slave. Perhaps each type of node could have a variable (ID) and 1 constant (TYPE).
    'constant TYPE' would be defined at the time of coding and would hold information identifying the type of node. For example, an 8 digital i/o node would be one type, and a 4analog output would be another. Each node type would have a different programm anyway so this is no biggy.

    The variable ID starts defined as 0 and is stored in non-volitile memory.

    When the node is given its new bus address using the above algorithim, it is the asked 'what is your type and ID' by the master.
    If the ID returned is 0, then the this is the first time the node has been connected to the bus. The master then assigns a random ID (say 4 hex numbers in length) and records the node bus address, TYPE and its newly created ID in an array. The slave node then updates its ID with the same number.

    Because this is the first time the node has been on the network, the master does not know its purpose. This is where user intervention comes in. Perhaps a simple GUI could be implemented telling the user there are some un-indentified nodes and they need to give that node a task.

    In any subsequent reboots, the master will lookup the ID and TYPE of each node on the bus and check if the ID and TYPE match any nodes in its database. If so, then the node has already been configured and it uses the current settings. If the combination of TYPE and ID do not match, then the node could be from a different bus and so the master performs the new node procedure.

    Just a thought and I probably explained it funny :P Let me know what you think and if that makes sense [noparse]:)[/noparse]


    EDIT:
    Hi Tubular,

    Well in my application, each node will have an identical hardware setup (buttons and lights effectivly) and the logic behind each set of buttons and lights is identical.
    They are also location independent. The only commonality is a time clock which the master is to take care of.
    For all other types of node, there can be a maximum of 1 of each because that is all thats required.

    Its actually a very easy application and the prop is WAAAAYYYY overkill, but its fun [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale

    Post Edited (Basil) : 5/1/2009 2:12:35 AM GMT
  • kwinnkwinn Posts: 8,697
    edited 2009-05-01 04:10
    Alec, this sounds a bit like a simplified version of USB enumeration. Basically it sounds like the following needs to be done.

    1 - The slaves have to communicate with the master to get an address. To do this it needs to send some form of ID to the master, perhaps a randomly generated number
    appended to an address request. The rest of the slaves would compare their random number to this number and regenerate their random number if it is a match.

    2 - The master sends each slave an address when they request one, using the random number as an initial address.

    3 - The slave sends it's "type" information to acknowledge the receipt of the address.
  • BasilBasil Posts: 380
    edited 2009-05-01 04:14
    Oh lol. I don't actually know how USB works :P I will investigate [noparse]:)[/noparse]

    Thanks!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale
  • Brian FairchildBrian Fairchild Posts: 549
    edited 2009-05-01 06:33
    @Basil

    Yes, it's quite do-able in a distributed network; I do it all the while. My code is based on this...

    http://www.ibrtses.com/embedded/dynamicid.html
  • BasilBasil Posts: 380
    edited 2009-05-01 07:03
    Thanks Brian,

    Ill have a good read of that one [noparse]:)[/noparse]

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    -Alec

    Velden in N scale
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2009-05-01 16:57
    There's another method that would work on synchronous, open-drain busses like I2C. In this scenario, each slave unit carries a unique serial number. These numbers can be provided by such devices as the Maxim/Dallas DS2401 "silicon serial number". When the master starts up it polls the net by sending out a query, such as, "Who has unit number n?", where n starts at 1 and increments with each new query cycle. Each slave whose unit number has not been assigned starts to put its serial number on the bus, one bit with each SCK. At the end of each clock cycle, it then reads the bus back to see if the bit that's there agrees with its own. If not (i.e. if its bit is a 1 and the bus reads 0), it will know that another device with a lower serial number is transmitting, so it quits transmitting. If it gets to the end of the sequence without a mismatch, it accepts the proffered unit number as its own and can also continue transmitting information about what kind of hardware it is, etc, for the duration of the query cycle. The master continues this process with new query cycles until it receives back a serial number of all 1s, which means that all units on the bus have been assigned unit numbers.

    Using this technique, the master does not need to remember the serial numbers (which are rather long), since each unit remembers its unit number and can be addressed that way instead.

    -Phil
  • kwinnkwinn Posts: 8,697
    edited 2009-05-01 17:23
    Phil, that works very well, and can even be used if the slaves do not have an assigned serial number. A random number generated by the slave could also be used.

    PS - That method was also used as a bus access method for both serial and parallel open drain buses. Same protocol, but the bus addresses were fixed and based on device priority.
  • Brian FairchildBrian Fairchild Posts: 549
    edited 2009-05-01 19:56
    RDM, a protocol which runs alongside DMX for lighting applications, has a discovery phase which works over half-duplex RS-485 lines. It's basically a binary-tree search which accepts collisions as indicating that multiple slaves exist below that tree node.
Sign In or Register to comment.