Half duplex: ¿Cómo prevenir los cortocircuitos?

Considere dos Arduinos (ATmega328P), con los pines 2 conectados para comunicación semidúplex (por ejemplo, usando SoftwareSerialWithHalfDuplex ):

Conexión directa de pines 2

Ambos Arduinos pueden estar transmitiendo al mismo tiempo, ya sea por razones lógicas o si algo anda mal. En este caso, un Arduino puede configurar el pin 2 en alto, el otro Arduino puede configurarlo en bajo. El resultado es un cortocircuito. Para limitar la corriente a 5 mA, podría agregar una resistencia de 1 kΩ:

Conexión con resistencia

¿Es esa la solución preferida? ¿Me estoy perdiendo de algo?

Lee atentamente la respuesta de Pipe. El diagrama en su respuesta no está completo. Como no conoce la solución, sospecho que no sabe qué es una resistencia pull-up. Google "resistencia pull-up". Y sí, la tubería es correcta: no se comunique configurando el pin alto y bajo. Comuníquese codificando el pin en bajo y configurándolo como entrada y salida. Cuando está en modo de salida, intentará drenar todo el voltaje en la línea y le dará 0. En el modo de entrada, no producirá ningún voltaje, por lo que la resistencia pull-up está libre para suministrar voltaje y le dará 1. Si ambos transmiten 0 = no hay problema . Ambos transmiten 1 también sin problema
@slebetman Consulte la sección de ayuda sobre comentarios para saber cómo se utilizan los comentarios en el intercambio de pilas. Si hay problemas con mi respuesta, el comentario pertenece allí. Si desea responder a la pregunta, debe publicarla como una respuesta real que se puede votar. Las respuestas en los comentarios van en contra del modelo de Stack Exchange de respuestas examinadas por la comunidad.

Respuestas (2)

Esa es una forma razonable de resolver el problema de las colisiones accidentales.

Otro método común es usar una salida de drenaje abierta . Es el método utilizado por I2C para garantizar que dos controladores en colisión no consumirán demasiada corriente y para garantizar que la señal sea baja o alta, y no algo intermedio.

ingrese la descripción de la imagen aquí

De esta manera, puede conectar tantas salidas como desee, porque no hacen nada o conectan la salida a tierra. Si dos o más pines conducen la misma señal a tierra, no sucede nada malo.

Para que esto funcione, necesita una sola resistencia pull-up en el bus, y dado que nadie está elevando activamente la señal, esto genera una tasa de bits máxima más baja.

Dado que está utilizando una interfaz serial controlada por software, debería ser fácil de adaptar a sus necesidades. En lugar de configurar los puertos como salidas push-pull y luego configurarlos como bajo o alto, los configura como entradas con pull-up cuando se supone que deben tener salida alta o entrada , y configurarlos como salida baja cuando se supone que deben tener una salida baja .

Puede imitar el drenaje abierto usando las funciones de Arduino. En la configuración (), baje el pin con digitalWrite(pin,LOW). Al realizar comunicaciones, alterne entre entrada y salida usando pinMode(pin,INPUT)para alto y pinMode(pin,OUTPUT)para bajo. O use los registros IO directamente, configurando el PORTbit correspondiente bajo y alternando el DDRbit correspondiente.
Incluso puede usarlo pinMode(pin, INPUT_PULLUP)para enviar 'alto' haciendo uso de las resistencias pull-up internas del AVR.
@JimmyB: Sin embargo, eso no protege contra errores de programación.
@TomCarpenter ¡Buena sugerencia! Como efecto secundario, y si no me equivoco, esta técnica permite que un Arduino, mientras está transmitiendo, detecte si el otro también está transmitiendo. Esto sería muy útil para la aplicación en cuestión.
@feklee I2C puede detectar colisiones de bus leyendo el valor del pin cada vez que escribe un bit. Si escribe un uno pero lee un cero, sabe que alguien más está usando la línea, así que se da por vencido.
@JimmyB puedes, pero debes tener cuidado. Si usa la resistencia pull-up, debe recordar apagar el pull-up antes de cambiar a una salida. De lo contrario, conduces la línea alta.
@JimmyB Como acabo de enterarme de una respuesta a otra pregunta, uno tiene que agregar un retraso entre tirar del pin alto y leerlo: "Se necesita tiempo para que el pullup resistivo en el AVR tire del pin alto". La ralentización resultante de la comunicación puede ser indeseable.

Es tan bueno como cualquier otra cosa. Una alternativa sería operar los pines en modo de drenaje abierto, pero luego necesitaría una resistencia pull-up externa.