¡Hola! Comunicar dos Arduinos a través del protocolo I2C es una tarea bastante común y relativamente sencilla de lograr.
Muchos proyectos de electrónica y robótica requieren la comunicación entre dispositivos electrónicos. El Inter-Integrated Circuit (I2C) es uno de los protocolos de comunicación más utilizados, y permite la transferencia de datos entre múltiples dispositivos con solo dos cables de comunicación. En este tutorial aprenderemos cómo utilizar el protocolo I2C de Arduino para conectar varios dispositivos y realizar una comunicación bidireccional fiable y eficiente, y de esta manera controlar luces.
Tal vez pueda interesarte proyectos en arduino, pic, robótica, telecomunicaciones, suscribete en http://www.youtube.com/user/carlosvolt?sub_confirmation=1 mucho videos con código fuentes completos y diagramas
Introducción:
El protocolo I2C, que significa Inter-Integrated Circuit, es un estándar de comunicación serial de dos hilos utilizado ampliamente en sistemas embebidos y dispositivos electrónicos. Desarrollado por Philips Semiconductor (ahora NXP Semiconductors) en la década de 1980, el protocolo I2C ofrece una forma eficiente y versátil de interconectar múltiples dispositivos en un solo bus.
Funcionamiento del Protocolo I2C:
El protocolo I2C utiliza dos líneas de comunicación: SDA (Serial Data) y SCL (Serial Clock). Estas líneas son bidireccionales y se conectan a todos los dispositivos en el bus. El protocolo I2C utiliza un esquema de comunicación maestro/esclavo, donde un dispositivo maestro controla la comunicación y uno o más dispositivos esclavos responden a las solicitudes del maestro.
La comunicación en el protocolo I2C se realiza en forma de transmisiones de datos secuenciales. El maestro inicia la comunicación enviando una señal de inicio seguida de la dirección del dispositivo esclavo al que desea comunicarse y una señal de lectura/escritura. Los dispositivos esclavos que coinciden con la dirección responden al maestro, y luego la transferencia de datos puede tener lugar.
Características Principales del Protocolo I2C:
- Simplicidad: El protocolo I2C utiliza solo dos cables para la comunicación, lo que simplifica la conexión entre dispositivos y reduce el número de pines necesarios en los microcontroladores.
- Versatilidad: El protocolo I2C es adecuado para una amplia gama de aplicaciones, desde la comunicación entre chips en una placa de circuito hasta la interconexión de dispositivos en sistemas embebidos complejos.
- Soporte para Múltiples Dispositivos: El protocolo I2C permite la conexión de múltiples dispositivos en el mismo bus, lo que facilita la expansión y escalabilidad de los sistemas.
Aplicaciones del Protocolo I2C:
El protocolo I2C se utiliza en una variedad de aplicaciones, incluyendo:
- Sensores y actuadores en sistemas embebidos.
- Memorias EEPROM para almacenamiento de datos.
- Conversores analógico-digitales (ADC) y digitales-analógicos (DAC).
- Pantallas LCD y OLED.
- Circuitos integrados de temperatura, presión y otros sensores.
- Controladores de dispositivos periféricos como el audio y el motor.
Consideraciones Finales:
El protocolo I2C es una herramienta poderosa y versátil para la comunicación entre dispositivos electrónicos. Su simplicidad, versatilidad y soporte para múltiples dispositivos lo hacen ideal para una amplia gama de aplicaciones en la electrónica y la programación de microcontroladores. Con una comprensión básica del protocolo I2C, los ingenieros y diseñadores pueden crear sistemas más complejos y eficientes en una variedad de campos.
Referencias:
- “The I2C-Bus Specification”, Versión 6.0, NXP Semiconductors.
- “Arduino – Wire Library”, https://www.arduino.cc/en/Reference/Wire.
Este informe proporciona una visión general del protocolo I2C, su funcionamiento, características y aplicaciones. Para obtener información más detallada sobre aspectos específicos del protocolo I2C, se recomienda consultar las especificaciones técnicas y recursos adicionales proporcionados por los fabricantes y la comunidad de desarrollo.
Circuito
Captura del dato set1on, vista en un analizador lógico
Podemos ver en el canal 0 el pin scl que es la linea de clock, en el canal 1 el pin sda que es al linea de datos
Código fuente Maestro
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
#include <Wire.h> #include <Keypad.h> int pul1 = 0; int pul2 = 0; int pul3 = 0; int pul4 = 0; int pul5 = 0; int pul6 = 0; int pul7 = 0; int pul8 = 0; int pul9 = 0; int pul10 = 0; int pul11 = 0; int pul12 = 0; int pul13 = 0; int pul14 = 0; int pul15 = 0; int pul16 = 0; int estado1 = 0; int estado2 = 0; int estado3 = 0; int estado4 = 0; int estado5 = 0; int estado6 = 0; int estado7 = 0; int estado8 = 0; int estado9 = 0; int estado10 = 0; int estado11 = 0; int estado12 = 0; int estado13 = 0; int estado14 = 0; int estado15 = 0; int estado16 = 0; //String botonSet = ""; const byte ROWS = 4; //cuatro filas const byte COLS = 4; //cuatro columnas //definimos los caracteres del teclado char hexaKeys[ROWS][COLS] = { {'1','2','3','4'}, {'5','6','7','8'}, {'9','0','A','B'}, {'C','D','E','F'} }; byte rowPins[ROWS] = {4, 6, 7, 8}; //conectarse a las salidas de pines de fila del teclado byte colPins[COLS] = {9, 10, 14, 15}; //conectarse a las salidas de pines de la columna del teclado //inicializar una instancia de la clase NewKeypad Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); void setup() { Wire.begin(); // Inicia la comunicación I2C como maestro Serial.begin(9600); // Inicia la comunicación serial } void loop() { char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos if (customKey == '1'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos if(estado1 ==0){//Si la variable estado1 es igual a 0 se cumple esta condición Wire.beginTransmission(9); // Dirección del esclavo Wire.write("set1on"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado1 =1;//Asignamos el valor 1 a la variable "estado1" } else{ Wire.beginTransmission(9); // Dirección del esclavo Wire.write("set1off"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado1 =0; } while(customKey == '1'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos } } /////////// if (customKey == '2'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos if(estado2 ==0){//Si la variable estado2 es igual a 0 se cumple esta condición Wire.beginTransmission(9); // Dirección del esclavo Wire.write("set2on"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado2 =1;//Asignamos el valor 1 a la variable "estado2" } else{ Wire.beginTransmission(9); // Dirección del esclavo Wire.write("set2off"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado2 =0; } while(customKey == '2'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos } } ////////// if (customKey == '3'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos if(estado3 ==0){//Si la variable estado3 es igual a 0 se cumple esta condición Wire.beginTransmission(10); // Dirección del esclavo Wire.write("set1on"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado3 =1;//Asignamos el valor 1 a la variable "estado3" } else{ Wire.beginTransmission(10); // Dirección del esclavo Wire.write("set1off"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado3 =0; } while(customKey == '3'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos } } /////////// if (customKey == '4'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos if(estado4 ==0){//Si la variable estado4 es igual a 0 se cumple esta condición Wire.beginTransmission(10); // Dirección del esclavo Wire.write("set2on"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado4 =1;//Asignamos el valor 1 a la variable "estado4" } else{ Wire.beginTransmission(10); // Dirección del esclavo Wire.write("set2off"); // Envía un mensaje al esclavo Wire.endTransmission(); // Finaliza la transmisión estado4 =0; } while(customKey == '4'){ char customKey = customKeypad.getKey();//Obtenemos la tecla que precionamos } } //////////// if (customKey == '5'){ } /////////// if (customKey == '6'){ } //////// if (customKey == '7'){ } if (customKey == '8'){ } ///////// if (customKey == '9'){ } ///////// if (customKey == '0'){ } /////////// if (customKey == 'A'){ } ///////// if (customKey == 'B'){ } if (customKey == 'C'){ } if (customKey == 'D'){ } if (customKey == 'E'){ } if (customKey == 'F'){ } } |
Código Fuente esclavo
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
#include <Wire.h> String cadena; int led2 = 2; int led3 = 3; void setup() { Wire.begin(9);//Inicia la comunicación I2C como esclavo con dirección 9(del 9 al 119) Wire.onReceive(receiveEvent); //Llama a la función 'receiveEvent' cuando se recibe un mensaje Serial.begin(9600); //Inicia la comunicación serial //Configura pin 2 y 3 como salida pinMode(led2, OUTPUT); pinMode(led3, OUTPUT); } void loop() { delay(100); } void receiveEvent(int bytes) { while (Wire.available()) { //Mientras haya datos disponibles para leer char c = Wire.read(); //Lee el siguiente byte recibido cadena = cadena + c; //Se almacena los caracteres en la varible cadena Serial.print(c); //Muestra el byte recibido en el monitor serial } //Se cumple si la cadena en set1on if(cadena == "set1on"){ digitalWrite(led2, HIGH); } //Se cumple si la cadena en set1off if(cadena == "set1off"){ digitalWrite(led2, LOW); } //Se cumple si la cadena en set2on if(cadena == "set2on"){ digitalWrite(led3, HIGH); } //Se cumple si la cadena en set2off if(cadena == "set2off"){ digitalWrite(led3, LOW); } //Limpia la variable cadena cadena=""; } |
PROYECTO RECOMENDADO