Llevo días con un problema que no se de que modo abordar. Os pongo en situación.
Tengo un arduino como maestro i2c, y dos o más esclavos (por el momento estoy realizando pruebas con 2). El tema está en que los esclavos leen unos datos y envían una señal de interrupción al maestro, que comienza la transmisión i2c para leer del esclavo los datos. Posteriormente el esclavo duerme hasta que pasa un tiempo y vuelve a necesitar enviar datos. Todo esto funciona a la perfección. El maestro también duerme si ningún esclavo le requiere un envío de datos o necesita hacer otra cosa (por el tema del ahorro energético al alimentarse a baterías). Cada esclavo puede necesitar tiempos entre envíos diferentes, por eso es el esclavo el que envía la interrupción cuando necesita enviar datos, y no es el maestro el que lo solicita directamente.
Ahora necesito que el maestro, en determinadas ocasiones, pueda despertar a un esclavo y enviarle datos o requerir alguna acción. Incluir otra linea de interrupción del maestro al esclavo no me es posible ya que solo dispongo de 5 hilos (gnd, vcc, sda, scl y la int del esclavo al maestro).
He pensado usar la linea scl de modo que active la interrupción del esclavo, pero no sé si es posible hacerlo de algún modo sin alterar el bus.
Hi,
Yo nunca he usado el DS3231 clock pero muchos recomienda el uso de este para despertar el arduino. Tiene una alarma que manda un interrupt. Haz un google del ds3231 para despertar el arduino.
Gracias tauro0221 por tu respuesta. Conozco el DS3231, pero no es exactamente eso lo que necesito. Creo que te refieres a programar una alarma en el rtc y que cuando llegue el momento la alarma active la interrupción que despierte al arduino. Yo necesito que el esclavo despierte al maestro (que ya lo hace) y que el maestro despierte al esclavo cuando sea oportuno sin tener que utilizar mas hilos de los que ya tengo.
Muy sencillo, pongamos el ejemplo de un esclavo que envie datos cada 5 min y otro cada 10 min. Cuando el esclavo despierta, manda la señal de interrupcion al maestro y este, si esta dormido, despierta y comienza la transmision por i2c. Si está ya despierto no hay problema porque recibe la interrupción y comienza igualmente la transmision. Cuando todo acaba ambos duermen. Necesito hacerlo así porque cada esclavo tiene tiempos diferentes y deben ser ellos los que indiquen al maestro cuando necesitan enviar datos.
Ahora bien, si el maestro detecta algo o por motivo X debe enviar algún dato al esclavo y este está dormido, debe poder enviar una señal para que el esclavo despierte y pueda aceptar las peticiones del maestro.
Cuando el esclavo despierta, manda la señal de interrupción al maestro
Imposible. El protocolo I2C no funciona como tu lo estas detallando.
Esa tarea la hace el maestro no el esclavo. Y no puede invertir roles.
Lo único que puedes hacer es usar pines que despierten los esclavos. Maneja el SLEEP de cada esclavo supeditado a cierto pin. SI el pin cambia sea LOW o HIGH como lo programes entonces se despierta. Eso lo debería enviar el MAESTRO vía pin digital.
Y luego la comunicación se establece por I2C normal.
Gracias surbyte por la respuesta, aunque debo discrepar en lo que dices, aunque quizás no me explicado bien.
Dentro de la comunicacion i2c, es el maestro quien la comienza, no podria ser de otro modo porque el protocolo es así, pero es el esclavo quien dice cuando comenzar esa comunicación mediante una interrupción.
Algo que he obviado en la explicación anterior para no liarlo más es el uso de un multiplexor, concretamente el modelo TCA9545A que dispone de 4 canales con interrupción, es decir, tiene 4 interrupciones de entrada y 1 de salida. Cuando un esclavo envia una interrupcion la int de salida de activa despertando al maestro. En el TCA al leer el registro hay 4 bits que indican que canal es el que ha enviado la interrupcion. En cada canal solo tengo un esclavo y todos los esclavos tienen la misma dirección. De este modo y con la ayuda del TCA9545 solvento este problema. Y de hecho esta parte me funciona a la perfección. Por eso te decia al comienzo que discrepaba con lo que decias.
Ahora el problema está en, usando los mismos hilos que ya tengo, poder despertar al esclavo que hay en cierto canal del multiplexor.
Hi,
Si yo entiendo tu quires usar las 4 lineas que entran al TCA9545 para que el master despierte los esclavos? Creo que una forma de hacerlo es de conectar un pin del master a cada entrada del TCA9545 y cuando lo lleva a ground despierta el esclavo pero para hacer esto tiene que condicionar todas las salidas de los pines de los esclavos y el master a 5 voltios o "PULLUP" todo el tiempo. Asi puedes seleccionar y despertar los esclavos con solamente llevando el pin a ground.
En el marco de un protocolo I2C mi comentario sigue siendo válido pero si luego afirmas que discrepas conmigo pero que has olvidado algo que cambia todo como lo siguiente
Algo que he obviado en la explicación anterior para no liarlo más es el uso de un multiplexor, concretamente el modelo TCA9545A que dispone de 4 canales con interrupción, es decir, tiene 4 interrupciones de entrada y 1 de salida.
Eso cambie el eje del debate.
En el post inicial no mencionas al TCA9545.
Si usaras un simple PCA8574 también podrías hacer lo que quieres porque dispone de capacidad de interrupción, pero como dije, no fue mencionado ni uno ni otro.
Si estas utilizando un cable para despertar al maestro mediante una interrupción, nada te impide utilizarlo para despertar a los esclavos utilizando attachinterrup, detachinterrup y con pinmode cambiar los modos de los pines.
Otra forma de hacerlo ( menos elegante), si te sobra algún pin en el arduino, es conectar ese cable a dos pines de cada arduino. uno seria la interrupción y otro el que se utilizaría para despertar a todos.
Saludos