PDA

View Full Version : Using a pin interrupt to activate listening over Serial.



gregcotten
01-27-2013, 07:08 PM
Hello all!

So a have a project that requires one micro to talk to six slave micros (teensy 3.0s) via serial (TX lines are all connected). Packet is structured like this: [ID byte, Command Byte, data1, data2, data3, ...]. I'm trying to save every millisecond I can in CPU time on the slaves so I don't really want to have a slave ignore the packets intended for other slaves.

Is there a way I can have the master micro have six digital pins (each one connected to a different slave) and have a rising edge interrupt on each slave that "turns on" Serial1 to start listening? Is this even possible? Any other solutions if not?

Thanks so much!

Greg

PaulStoffregen
01-27-2013, 07:44 PM
In terms of milliseconds, the time for each slave to parse and discard the messages (with such a simple protocol) meant for the other 5 is very small. In terms of microseconds, yes, you will save several microseconds of CPU time.... but unless you write horribly inefficient code, the savings will be very small on a scale of milliseconds.

Probably the simplest approach would involve a little extra hardware. You could use OR gates, like 74HC32 chips, or a MUX chip like a 74HC4051 with pullup resistors on all the outputs. The master could cause the transmission to go to only 1 of the 6 slave boards. This approach is probably the easiest to get working, because you can easily observe if 1 slave is getting the signal and the other 5 are remaining at logic high.

You could use interrupts too. Probably the easiest way would be using attachInterrupt(). You could connect the signal to 2 pins, and use attachInterrupt on both, one RISING and the other FALLING. Inside one interrupt function, you'd call Serial1.begin(baud), and inside the other you'd call Serial1.end(). Or you could use a single attachInterrupt() with CHANGE, and then use digitalRead() inside the interrupt to see if you should call Serial1.begin() or Serial1.end().

Obviously, with either of these approaches, the enable signal for the desired board would need to remain high during the entire transmission.

But I would first try just parsing and discarding the unwanted data. Teensy 3.0 is very fast. If you're doing special stuff that requires extreme speed (but inter-board communication by slow serial is ok), you'll almost always achieve superior results by focusing your efforts on way to leverage the on-chip peripherals to help you do the high speed tasks efficiently.

gregcotten
01-27-2013, 07:57 PM
In terms of milliseconds, the time for each slave to parse and discard the messages (with such a simple protocol) meant for the other 5 is very small. In terms of microseconds, yes, you will save several microseconds of CPU time.... but unless you write horribly inefficient code, the savings will be very small on a scale of milliseconds.

Probably the simplest approach would involve a little extra hardware. You could use OR gates, like 74HC32 chips, or a MUX chip like a 74HC4051 with pullup resistors on all the outputs. The master could cause the transmission to go to only 1 of the 6 slave boards. This approach is probably the easiest to get working, because you can easily observe if 1 slave is getting the signal and the other 5 are remaining at logic high.

You could use interrupts too. Probably the easiest way would be using attachInterrupt(). You could connect the signal to 2 pins, and use attachInterrupt on both, one RISING and the other FALLING. Inside one interrupt function, you'd call Serial1.begin(baud), and inside the other you'd call Serial1.end(). Or you could use a single attachInterrupt() with CHANGE, and then use digitalRead() inside the interrupt to see if you should call Serial1.begin() or Serial1.end().

Obviously, with either of these approaches, the enable signal for the desired board would need to remain high during the entire transmission.

But I would first try just parsing and discarding the unwanted data. Teensy 3.0 is very fast. If you're doing special stuff that requires extreme speed (but inter-board communication by slow serial is ok), you'll almost always achieve superior results by focusing your efforts on way to leverage the on-chip peripherals to help you do the high speed tasks efficiently.

Thanks for the quick reply Paul! I will try parsing and discarding first - just trying to cover my bases. I like the OR gate and MUX chip ideas too.

Greg

t3andy
01-27-2013, 09:37 PM
You could use interrupts too. Probably the easiest way would be using attachInterrupt(). You could connect the signal to 2 pins, and use attachInterrupt on both, one RISING and the other FALLING. Inside one interrupt function, you'd call Serial1.begin(baud), and inside the other you'd call Serial1.end(). Or you could use a single attachInterrupt() with CHANGE, and then use digitalRead() inside the interrupt to see if you should call Serial1.begin() or Serial1.end().


@Paul I thought the T3 interrupts are "work in progress" so what interrupts on the Teensy 3 are functional now?

PaulStoffregen
01-27-2013, 10:43 PM
@Paul I thought the T3 interrupts are "work in progress" so what interrupts on the Teensy 3 are functional now?

Arduino's attachInterrupt() has worked since the first beta. That's the simplest to use, but it does have a little overhead. If it will work for your needs (it's plenty fast compared to even faster serial baud rates), use that.

All the native interrupts work using the names defined in mk20dx128.c.

Currently there's no emulation of AVR interrupts. There may never been AVR interrupt emulation.... I'm still not 100% decided on that, but at the moment it's looking AVR emulation just isn't a good approach. Simply porting libraries is probably better.

gregcotten
01-31-2013, 05:37 AM
One other question - if I tie all the slave TX lines to the RX line on the master, and I can guarantee that none of them will talk over the others, will the master be able to receive the TX from the slave?

Thanks!