1 Módulo EEPROM compartida por I2C

Ante todo decir que he visto un tema del año pasado que habla de compartir un display por I2C y que casi casi se consiguió que funcionase Compartir display por I2C.

Mi idea es ahora compartir un módulo EEPROM por I2C, la pregunta de rigor es... ¿y para que? Pues sencillo, tengo un ESP8266 que recibe información importante y la almacena en el módulo EEPROM conectado por I2C. Pero quiero que esa información esté disponible también para el arduino Mega que controla el proyecto. Puedo pedirle la información por serie al ESP todo el rato, pero me parece que la velocidad y el riesgo de perder información es más grande que si puedo cogerla directamente de la EEPROM con el Mega.
Supongo que el riesgo de colisión es menor ya que normalmente se usa mucho menos una EEPROM que un display pero aún así mi idea es que el ESP habilite una entrada del Mega cuando escribe o lee y a la inversa para "solicitar permiso".

La pregunta es para los que estuvieron haciendo pruebas con el display o para los que se quieran sumar ¿Creeis que es viable?

arkarash:
Puedo pedirle la información por serie al ESP todo el rato, pero me parece que la velocidad y el riesgo de perder información es más grande que si puedo cogerla directamente de la EEPROM con el Mega.

En ese caso sería implementar mecanismos de detección de errores: bit de paridad (ya implementado en los UART por hardware), suma de verificación, hashing, especificando la longitud de la carga útil, etc.

arkarash:
Supongo que el riesgo de colisión es menor ya que normalmente se usa mucho menos una EEPROM que un display

Cuando hay múltiples "maestros" utilizando el mismo bus, el riesgo de colisión siempre está presente. No recuerdo si I2C ya implementaba algún mecanismo de prevención, porque de lo contrario es necesario crear uno.

De momento solo se me ocurre que el "maestro" que deseé utilizar el bus, debe primero medir el estado digital de ambas líneas durante un lapso prudente (al menos el doble de la supuesta duración de un ciclo de reloj); si durante todo ese tiempo las líneas se mantuvieron en estado alto, se puede asumir que el bus está libre.
El único desacierto que le encuentro a esta técnica, es cuando las frecuencias de reloj utlilizadas por los distintos "maestros" (o la maxíma entre los "esclavos") no es la misma. Si un ciclo tardase más que el tiempo de espera estimado, la asunción eventualmente sería incorrecta y una colisión ocurriría.

arkarash:
pero aún así mi idea es que el ESP habilite una entrada del Mega cuando escribe o lee y a la inversa para "solicitar permiso".

En caso de ser señalamiento por una línea digital, los pines de ambas partes deben ser capaces de cambiar dinámicamente su impedancia (entrada o salida). Quien haga uso del bus I2C, debe ser la salida y poner dicha línea en el estado que se defina como "ocupado"; mientras que quien espera a que el bus sea liberado, debe ser la entrada.
Siguiendo estas reglas, eso quiere decir que cuando el bus incialmente está libre, ambas partes son entradas que verifican el estado de esa señal para ya sea utilizarlo inmediantamente, o esperar a que libere.

El desacierto de esta técnica es un problema típico de la concurrencia: ¿qué pasa si ambos "maestros" leen el estado de la señal exactamente al mismo tiempo (problema de atomicidad)? Ambos leerían que está libre y por ende se garantiza que habrá una colisión.
No hay que ahogarse en un vaso de agua, la solución es más simple de lo que crees: desfasar intencionalmente ambos eventos. Esto se puede lograr con un pequeño retraso antes de la lectura, aunque sí debe ser de duración aleatoria.

arkarash:
La pregunta es para los que estuvieron haciendo pruebas con el display o para los que se quieran sumar ¿Creeis que es viable?

Eso depende de cómo quieras resolver el problema: con detección de errores en la parte serial; o con arbitraje de bus en el I2C.

Ante todo gracias por tu respuesta.

No hay que ahogarse en un vaso de agua, la solución es más simple de lo que crees: desfasar intencionalmente ambos eventos. Esto se puede lograr con un pequeño retraso antes de la lectura, aunque sí debe ser de duración aleatoria.

Leyendo esto se me ha venido a la cabeza que puedo dar preferencia a uno de ellos. Explico.

Arduino quiere leer/escribir --- Salida UP --- comprueba entrada del ESP --- Si es 0 --- espera 100ms --- comprueba de nuevo entrada del ESP --- Si es 0 --- Entonces Lee/Escribe --- Salida DOWN

Si en cualquiera de las comprobaciones el resultado es que la entrada está activada permanece con la salida arriba para pedir turno al ESP.

Con esto creo que el ESP tiene 100ms de preferencia en caso de que los dos activen las salidas al mismo tiempo.

¿Crees que sería correcto?

arkarash:
Arduino quiere leer/escribir --- Salida UP --- comprueba entrada del ESP --- Si es 0 --- espera 100ms --- comprueba de nuevo entrada del ESP --- Si es 0 --- Entonces Lee/Escribe --- Salida DOWN

Reduce las probabilidades de colisión, pero todavía no las elimina del todo. Razón: se puede dar el muuuuuuy raro caso que el Arduino esté por comenzar a transmitir por I2C cuando el ESP tomó la segunda lectura que resultó en cero por segunda vez consecutiva.

Además, ¿el ESP no debería señalar también que tiene el bus ocupado? Por más que alguno tenga prioridad sobre otro, una transmisión I2C no se puede interrumpir a medio camino (de lo contrario se considera una colisión también).
Si el ESP no señala que tiene el bus ocupado, el Arduino asumiría que está libre cuando no necesariamente es así.

Mi mecanismo de desfase tampoco es infalible; pero la probabilidad de que ambos detecten el bus libre al mismo tiempo y que los retrasos tarden también lo mismo (sabiendo que la duración es aleatoria), es tan diminuta que prácticamente no vale la pena tomarla en cuenta. Dicha probabilidad disminuye si se aumenta el rango de posibles duraciones.

Lucario448:
Además, ¿el ESP no debería señalar también que tiene el bus ocupado? Por más que alguno tenga prioridad sobre otro, una transmisión I2C no se puede interrumpir a medio camino (de lo contrario se considera una colisión también).
Si el ESP no señala que tiene el bus ocupado, el Arduino asumiría que está libre cuando no necesariamente es así.

Si perdón, se me olvidó señalar algo que para mi cabeza estaba claro. El ESP a su vez:

ESP quiere leer/escribir --- Salida UP --- comprueba entrada del Mega --- Si es 0 --- Entonces Lee/Escribe --- Salida DOWN

El ESP digo que tiene preferencia porque no espera, si digamos el flag del Mega no está levantado el sin esperar usa la EEPROM, sin embargo el Mega si espera por lo que se evita que los dos levanten la bandera al mismo tiempo.

Lucario448:
Mi mecanismo de desfase tampoco es infalible; pero la probabilidad de que ambos detecten el bus libre al mismo tiempo y que los retrasos tarden también lo mismo (sabiendo que la duración es aleatoria), es tan diminuta que prácticamente no vale la pena tomarla en cuenta. Dicha probabilidad disminuye si se aumenta el rango de posibles duraciones.

Tu idea es buena, pero no tengo buenas relaciones con los randoms, seguro que me salen iguales y se cruzan jajaja.

Si nadie más quiere decir nada, creo que es bastante factible que funcione de una de las dos maneras propuestas, así que en breve lo probaré y cerraré el post con SOLUCIONADO si funciona, gracias!!

arkarash:
Si perdón, se me olvidó señalar algo que para mi cabeza estaba claro. El ESP a su vez:

ESP quiere leer/escribir --- Salida UP --- comprueba entrada del Mega --- Si es 0 --- Entonces Lee/Escribe --- Salida DOWN

El ESP digo que tiene preferencia porque no espera

Espera o no, de cualquier modo se puede dar la coincidencia; aunque tampoco es que vaya a ocurrir con frecuencia, por eso se dice que es una "coincidencia"

arkarash:
si digamos el flag del Mega no está levantado el sin esperar usa la EEPROM.

Display, EEPROM... es lo mismo. Bus ocupado es bus ocupado independientemente de cuál "esclavo" se le intenta dirigir.

arkarash:
Tu idea es buena, pero no tengo buenas relaciones con los randoms, seguro que me salen iguales y se cruzan jajaja.

No tiene por qué ser así. Si las "semillas" se obtuvieran en tiempo de ejecución (no con un valor preprogramado) mediante una fuente de naturaleza aleatoria (ej.: una entrada analógica "flotante"), sería casi imposible que los dos resultados generen exactamente el mismo valor (a menos que las posibilidades sean pocas).
Ej: si te limitas a generar dos posibles valores, es muy probable (50%) que haya repetición; pero si son un millón de posibles valores, la probabilidad de repetición sería insignificante (0.000001%).

Pues sí, este tema de la aleatoriedad es un tanto matemático y estadístico; no me sorprendería que alguien acabara confundido, sin entender o con la cabeza a punto de explotar... :slight_smile: