4
\$\begingroup\$

I have built this ID sensor for a Scalextric slot car track, based on a PIC12F629. The ID sensor sends the ID of a detected car as a RS232 signal on one pin (TTL level).

My question is, how can I receive data from like four of these micro controllers into another micro controller's (PIC18F2550) USART?

I came up with these possibilities:

  1. Just connect all of the serial lines "directly" to the RX pin of the PIC18 and hope that two cars doesn't pass any sensor that close in time so the signals are overlapping each other. This could actually be a good start and will probably work 99.9% of the time. I mean, the mathematical probability that two cars are detected that close in time cannot be worth the effort of the other suggestions...after all, it's a hobby project.
  2. Implement a busy signal that is raised when the ID sensors sends data and checked before sending.
  3. Add some fancy multiplexer chip that eats the serial signals and outs them on a single line.

Each ID sensor chip will be coded with an identifier that is sent as part of the data, so they can be separated at the receiving end.

Update: Added some more info about the sensor hardware.

\$\endgroup\$
4
  • \$\begingroup\$ This is really a job for CAN. Using a UART for this a kludge. \$\endgroup\$ Commented Mar 19, 2012 at 17:40
  • \$\begingroup\$ CAN pulls in a lot of protocol baggage and limits your choice of micro controllers, but if you can swing it, sure. \$\endgroup\$ Commented Mar 19, 2012 at 18:58
  • \$\begingroup\$ Actually I think CAN is a very overkill solution for this little project. I would like to keep it as simple as possible. \$\endgroup\$
    – Anttu
    Commented Mar 19, 2012 at 20:25
  • \$\begingroup\$ I appreciate all your answers and comments. However, I would still like to keep it far more simple (I'm not an expert on electronics, but I'm learning...). As I mentioned in my first alternative, the probability is very low that a data collision will ever happen, and if it does, it's not the end of the world (it's a toy thing after all). I can upgrade the solution in the future if I find it to be too "fragile". Please give an example on how to just hook up all these sensor PICs to the same RX pin on the receiving PIC. Thanks! \$\endgroup\$
    – Anttu
    Commented Mar 20, 2012 at 16:01

5 Answers 5

2
\$\begingroup\$

If you set your protocol up so the cars only respond when queries by the controller, then you can just tie (at the logical level, at least) everyone together.

The trick is whether you have real RS-232 (with 1 = -6 to -12 V, and 0 = 6 to 12 V) or just a standard logic line (1 = VCC, 0 = GND). Either the data sheet or a scope should answer this.

If it's standard logic, it could be really easy. If your sensors can control their output drivers, then program them to not drive the output unless a message is going out. If you have to leave the output driver on all the time, have it drive a transistor or two to make an "open-collector" configuration, connect all the sensors' collectors together, and pull up the connected line to VCC and hook it to your main controller's RX pin. This works because the RS-232 protocol idles at a logic 1 state. If RS-232 signal levels are used, then you have to change the transistor configuration a bit, but it'll still be open-collector at heart.

The main controller simply asks each sensor for its data in sequence. Each sensor responds when queried. That way you don't have more than one driving the RX line at a time, which is the main goal.

Now if you can't get your sensors to speak only when spoken to... then your problem got a lot hard. So much that the simple answer is to give each sensor its own serial port, maybe using 8-pin controllers as sensor managers, which can then be hooked up on a cooperative serial bus. Other techniques, such as collision detection with message retransmission (like 10base-T Ethernet did), are much more complex.

\$\endgroup\$
5
  • \$\begingroup\$ I would expect, having looked very briefly at the posted link, that it would be difficult for the remote controllers to simultaneously watch for a command from a remote CPU while they are watching for a car. What they could do, however, would be to watch for a car to arrive, and then stop watching for cars while they wait for a chance to send the one they saw. \$\endgroup\$
    – supercat
    Commented Mar 19, 2012 at 19:47
  • \$\begingroup\$ @supercat Yes, that's my assumption too. However, I would like to use push logic, not having to poll the ID sensor PICs, so that every sensor has the same delay from detection all the way to the computer, as this will be used for lap timing of the cars. \$\endgroup\$
    – Anttu
    Commented Mar 19, 2012 at 20:38
  • \$\begingroup\$ @Anttu: If you don't mind changing the code for the sensors, you might be able to extend the report from each sensor so that the transmitted data includes the time between when the sensor was tripped and when the report was sent. Otherwise, if the data rate and responsiveness of the sensors are fast enough, you may be able to poll each sensor 100 or even 1000 times/second. \$\endgroup\$
    – supercat
    Commented Mar 19, 2012 at 20:44
  • \$\begingroup\$ You should have the main controller send out a sync message that sets all the sensor's on-board timers, so the sensors can timestamp their data. As for a push solution, see my last paragraph. Push will come to shove; it's only a matter of time. \$\endgroup\$ Commented Mar 19, 2012 at 21:52
  • \$\begingroup\$ @MikeDeSimone these cars are 1:32 or 1:45 scale. I'm sure his controllers are just the PIC with logic-level outputs. \$\endgroup\$
    – joeforker
    Commented Mar 20, 2012 at 19:02
2
\$\begingroup\$

If your sensor can accommodate a "ready" line, and defer any events which arrive when it's not asserted, transmitting them when it is, your best bet may be to send a separate busy wire to each sensor and use an "AND" gate to combine the signals from all the sensors. I would suggest that if you have four sensors, you should cycle the "ready" wires in round-robin fashion, with some "dead" time between them (when nobody is "ready"); if a byte comes in during the "dead" time, assume it was sent by the last active sensor. Set the "ready" time long enough that a sensor will be able to react, and the dead time long enough that a sensor will have time to finish transmitting an event that occurs just before its "ready" line was deasserted.

Edit

Based upon further descriptions, given that apparently each sensor has a distinct known ID number, I'm thinking the best approach may be to have a single serial line which is connected to a PWM output via parallel resistor and diode, so that it is pulled up for 1,900us every 2ms but pulled down for 200us (if one could have a PWM switch between active-low and floating, that would be even better). As soon as a car is seen, a sensor should start the following state machine, keeping track of how many tens of microseconds have elapsed since it began executing.

  1. Wait for data line to be high.
  2. Wait for data line to be low.
  3. Clear line-low timer
  4. Wait for data line to go high, incrementing line-low timer (and main timer) while waiting.
  5. If timer indicates line was low less than 200us, go back to step 2
  6. Keep incrementing line-low timer while watching for line to go low, until that timer reaches some duration which is unique for the node's ID. If line goes low within that time, go back to step 3.
  7. Set data line to output, transmit the data at a rate of 16us/bit or so (driving the line actively for both high and low), and start looking for the next car. Note that the data should include the number of 10us intervals that have elapsed between seeing the car and commencing transmission.

Using a UART, this approach should allow one to process cars that arrive on any sensor, in any order, and resolve their timings within 10us, with the proviso that cars will be processed sequentially at a rate of one every 2ms, and sensors will be "blind" between the time they see a car and the main CPU gets around to processing it. Unless there are a really huge number of sensors, that shouldn't pose a problem. Note that the main CPU doesn't have to have any precise timing on anything but its PWM output. Everything else can be inferred from the serial data stream (including the "long breaks" resulting from the PWM "low" pulses).

\$\endgroup\$
5
  • \$\begingroup\$ As I wrote in another comment, I would like to have a push solution. How about having the sensor PICs pulling a common "transmitting" line high instead and have that line checked before sending the data? \$\endgroup\$
    – Anttu
    Commented Mar 19, 2012 at 20:48
  • \$\begingroup\$ @Anttu: As noted in my comment to your earlier comment, having the transmitter note the precise time between the car being seen and the start of transmission should provide the precision you need, even if two cars hit different sensors simultaneously. One could have all the nodes sit on an externally pulled-up bus and use some collision-resolution protocol, but that would probably add more uncertainty to transmission timings than would polling. BTW, one thing to consider about polling, which I forgot to mention above: ... \$\endgroup\$
    – supercat
    Commented Mar 19, 2012 at 20:52
  • \$\begingroup\$ @Anttu: It's often easier for microcontrollers to generate consistent timings for outgoing signals than to measure accurately the timings of incoming signals. If the sensor waited until the falling edge of its 'transmit' line to transmit, and if the main processor generated the falling edge for each transmitter precisely once every 40ms (100 polling intervals per second, divided four ways), knowing when it sent the polling pulse and the reported time (from the sensor) between the event and the pulse would allow the main CPU to resolve times with sub-ms precision. \$\endgroup\$
    – supercat
    Commented Mar 19, 2012 at 20:55
  • \$\begingroup\$ You're probably right about that. The only problem then is that the receiving PIC18F2550 only has 2 pins available. So in that case I would have to upgrade to a PIC18F4550 that has more I/O pins. \$\endgroup\$
    – Anttu
    Commented Mar 19, 2012 at 21:01
  • \$\begingroup\$ @Anttu: I would suggest that you consider using an external counter chip driven by one of the PIC's PWM lines; perhaps something like a 74HC4017. Perhaps feed one of the outputs from that to an inverter which is tied via resistor to the "bus" (so it would be pulled up 9/10 of the time, and pulled down 1/10, thus allowing you to tell which state the counter is in). If you can configure the output for PWM operation, it could generate nice precise timings independent of what code is doing. \$\endgroup\$
    – supercat
    Commented Mar 19, 2012 at 21:19
0
\$\begingroup\$

You can implement a MODBUS protocol in RTU mode with RS485 interface which works fine on PIC(Not that sure about your PIC).

You can have a multidrop line to rest your different microcontroller devices and have a nice communication between them on the serial UART.

You can make your PIC18F2550 as a master which will initiate the transaction from any other 4 controllers.

\$\endgroup\$
4
  • \$\begingroup\$ Please rewrite your answer with proper language; this site aims to create a permanent reference, which is better if properly formatted. \$\endgroup\$
    – clabacchio
    Commented Mar 23, 2012 at 11:38
  • \$\begingroup\$ Apologies if you find the language being improper. I just used the default format. Can you pls tell where the actual problem lies? \$\endgroup\$
    – OnkarK
    Commented Mar 23, 2012 at 11:57
  • \$\begingroup\$ Just care about grammar and don't use abbreviations or that sort of things. I've edited your answer for you. Welcome! \$\endgroup\$
    – clabacchio
    Commented Mar 23, 2012 at 13:29
  • \$\begingroup\$ @clabacchio Ok. I'll be careful from next time. \$\endgroup\$
    – OnkarK
    Commented Mar 26, 2012 at 8:34
0
\$\begingroup\$

Use time-division multiplexing. The master sends a sync pulse on a separate line that the slaves use to reset a timer. When a slave has data to send it waits until the timer equals (slave number * timeslot width) ticks before sending. The timeslot should be long enough to send the packet and account for clock inaccuracy between sensors.

Electrically, you may want to pull-up the shared TX line and toggle between 0 and tri-state to transmit instead of sourcing current to assert a 1.

\$\endgroup\$
2
  • \$\begingroup\$ There is some advantage to having all sensors' processors running the same code; there is also some advantage to having everything sit on the same wires (rather than e.g. using a 74HC4017 to strobe each sensor in sequence). One complication I see for time-division multiplexing, though, is that I'm not sure how much the sensor CPU can do while it's waiting for a car. If one were to use TDM, it would more likely wait for a car, then wait for the next sync pulse, and then send the data. If desired, the data wire could easily handle the sync pulse as well if it were longer than the data. \$\endgroup\$
    – supercat
    Commented Mar 20, 2012 at 20:44
  • \$\begingroup\$ The sensors each know their unique ID already. It doesn't have to matter if the micro misses a sync pulse. Configure the micro's 16-bit timer to have the same period as the sync pulse, reset the timer on a sync pulse, and wait for the timer to equal (id number) * (timer ticks per timeslot) before sending. \$\endgroup\$
    – joeforker
    Commented Mar 20, 2012 at 20:57
0
\$\begingroup\$

I found this site with a solution called BlackNet. It's based on a pretty simple protocol where the idea is that every node on the network has an own timeslot. I.e. it's some sort of round-robin logic. The last image on the page shows a schema with the least amount of components needed for it to work.

I used this idea and just connected the two sensors that I've built directly to the RX pin on the PIC18F2550. However, I didn't implement the round-robin protocol, but just bit-banging the data onto the line (and hope that only one transmits at a time). So far it have actually worked pretty well...

For future readers: If it's critical that your data always gets through, the solution I've used is probably not a good idea. However, if you rarely sends data and can live with the possibility that it collides and you want the easiest solution possible, I think this one is good enough.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.