Skip to content

14. Networking and communications

assignment individual assignment:

  design, build, and connect wired or wireless node(s)
  with network or bus addresses

group assignment:

  send a message between two projects

This week I studied the I2c communication protocol I2C (for its acronym in English Inter-Integrated Circuit) is a serial communication protocol developed by Phillips Semiconductors, back in the 80s

I2C is also denoted as TWI (for its acronym in English Two Wired Interface) or two-wire interface. This alternative name arises for license reasons that prevented the use of the original term

The I2C protocol works with a master-slave architecture (master-slave)

With this communication protocol it is possible to connect: A master with several slaves: 1master_3slave

and also allows multiple masters. And each master can interact with the slave without affecting the operation between them (between masters):

2master_slsves

I find this very interesting for my final project. Because I just want to use two sensors that work at the same time but independently and even, although I don’t think I can do it for my final project, use two masters that are connected to the two sensors, in this case it would be the acceleration and gyroscope sensors.

I searched literature about I2C and found a lot of information

I2C protocol

These are some illustrative images about I2C and the way it establishes communication between the Master and the Slave:

caracteristic_I2C

Comunication_I2C

Communication between placa atMega 328 whith one and two sensor

As part of the final project I use the MPU6050 sensor (accelerometer / gyroscope) which uses the I2C protocol to communicate with the Atmega 328

I load a code for to read two sensor reading, getting a good result:

#include<Wire.h>
const int MPU2 = 0x69, MPU1 = 0x68;// OK
int16_t AcX1,AcY1,AcZ1,Tmp1,GyX1,GyY1,GyZ1;//OK
int16_t AcX2,AcY2,AcZ2,Tmp2,GyX2,GyY2,GyZ2;//OK


//-------------------------------------------------\setup loop\------------------------------------------------------------ 
 void setup(){ 
      Wire.begin(); 
      Wire.beginTransmission(MPU1);
      Wire.write(0x6B);// PWR_MGMT_1 register 
      Wire.write(0); // set to zero (wakes up the MPU-6050)
      Wire.endTransmission(true);
      Wire.begin(); 
      Wire.beginTransmission(MPU2);
      Wire.write(0x6B);// PWR_MGMT_1 register 
      Wire.write(0); // set to zero (wakes up the MPU-6050)
      Wire.endTransmission(true);
      Serial.begin(9600); 
     } 

//---------------------------------------------------\void loop\------------------------------------------------------------
 void loop(){

      //get values for first mpu having address of 0x68   
      GetMpuValue1(MPU1);
      Serial.print("  ");
      Serial.print("|||");

      //get values for second mpu having address of 0x69
      GetMpuValue2(MPU2);
      Serial.println("");
    }

//----------------------------------------------\user defined functions\-------------------------------------------------- 


 void GetMpuValue1(const int MPU){ 

      Wire.beginTransmission(MPU); 
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) 
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 14, true); // request a total of 14 registers 
      AcX1=Wire.read()<<8| Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) 
      AcY1=Wire.read()<<8|  Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      AcZ1=Wire.read()<<8| Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) 
      Tmp1=Wire.read()<<8| Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) 
      GyX1=Wire.read()<<8| Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) 
      GyY1=Wire.read()<<8| Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) 
      GyZ1=Wire.read()<<8| Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) 
      Serial.print("AcX = ");
      Serial.print(AcX1);
      Serial.print(" | AcY = "); 
      Serial.print(AcY1);
      Serial.print(" | AcZ = ");
      Serial.print(AcZ1); 
      Serial.print(" | GyX = ");
      Serial.print(GyX1); 
      Serial.print(" | GyY = "); 
      Serial.print(GyY1);
      Serial.print(" | GyZ = ");
      Serial.println(GyZ1); 
     }


 void GetMpuValue2(const int MPU){ 

      Wire.beginTransmission(MPU); 
      Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) 
      Wire.endTransmission(false);
      Wire.requestFrom(MPU, 14, true); // request a total of 14 registers 
      AcX2=Wire.read()<<8| Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L) 
      AcY2=Wire.read()<<8|  Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
      AcZ2=Wire.read()<<8| Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L) 
      Tmp2=Wire.read()<<8| Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L) 
      GyX2=Wire.read()<<8| Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L) 
      GyY2=Wire.read()<<8| Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L) 
      GyZ2=Wire.read()<<8| Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L) 
      Serial.print("AcX = ");
      Serial.print(AcX2);
      Serial.print(" | AcY = "); 
      Serial.print(AcY2);
      Serial.print(" | AcZ = ");
      Serial.print(AcZ2);  
      Serial.print(" | GyX = ");
      Serial.print(GyX2); 
      Serial.print(" | GyY = "); 
      Serial.print(GyY2);
      Serial.print(" | GyZ = ");
      Serial.println(GyZ2); 
     }

The idea was always to use two sensors as it is in the human being. For this reason I test the reading of two sensors by modifying the code based on several tutorials

I made several unsuccessful attempts, I only got a reading from one sensor.

I verified that the problem was not in the code, because I provided several.

I was able to discover based on tutorials that when using two MPU6050 sensors, the address must be modified and that is achieved by using the AD0 pin of the sensor.

Photo of part of the tutorial that enlightened me and after 3 hours of trying I got it to work:

tutorial_AD0_MPU6050

Photo of conections

Two_MPU_conection

Conection_Two_MPU6050_arduino

Video

MPU6050 left
MPU6050_letf

MPU6050 rigth
MPU6050_rigth

I did the same test using the integrated circuit, connecting it to the two MPU6050 sensors, the files and the manufacture of said circuit can be seen in task 11 output device

Connection between the atmega 328 board and two MPU6050 sensor:

Danduino_PINS

A problem arose, my integrated circuit does not have a 3.5 volt output. In any case, I tried connecting the two sensors with VCC 5Volt on the board and the result was negative, only one sensor was captured.

Conection_atmega328_twosensors_5volt

Failed result observed on serial monitor Failed result observed on serial monitor

I used the 3.5 volt arduino uno power supply and that’s how it worked

Photo showing the connection between the 3.5 volt of the arduino and the AD0 pin of the MPU6050

Conection_3.5volt_arduino_AD0 MPU6050

Arduino_3.5volt

Correct result observed on serial monitor Correct result observed on serial monitor

Network connection between two PCBs

I will do it through the UART protocol

UART

UART, or universal asynchronous receiver-transmitter, is one of the most used device-to-device communication protocols.

The UART lines serve as the communication medium to transmit and receive one data to another. Take note that a UART device has a transmit and receive pin dedicated for either transmitting or receiving.

The UART interface does not use a clock signal to synchronize the transmitter and receiver devices; it transmits data asynchronously. Instead of a clock signal, the transmitter generates a bitstream based on its clock signal while the receiver is using its internal clock signal to sample the incoming data. The point of synchronization is managed by having the same baud rate on both devices

This one intresting link about UART

Network connection between two boards: the atMega328 and the attiny45 using UART protocol

I want to connect the atMega328 board with the attiny45 with built-in LED, both manufactured in previous tasks

As a first step I analyze the pins of each board to better define the connections

Photo Schematic PCB with LED and conection Rx PIN 1 y Tx PIN 2 attiny 45 (SLAVE)

Schematic PCB with LED and conection SDA y SCL

Photo pinout atMega Rx y Tx

Pinout atMega328 Rx y Tx

Pohto Schematic PCB atmega320 Rx y Tx

Phto Schematic PCB atmega320 Rx y Tx

CODE 1 for atMega328 (master)

#define LED_PIN 13

void setup()
{
  Serial.begin(9600);
  pinMode(LED_PIN, OUTPUT);
}

void loop()
{
  int buttonState =  Serial.read();

  if (buttonState == '1') {
    digitalWrite(LED_PIN, HIGH);
  }
  else if (buttonState == '0') {
     digitalWrite(LED_PIN, LOW);
  }
  delay(100);
}

This video shows that by putting “1” in the Serial Monitor the LED of the atMega328 turns on and when putting “0” it turns off

VIDEO: CODE 1 working

CODE 2 for Attiny45 (eslave)

#include <SoftwareSerial.h>

int rx = 1;    //Declares the RX pin
int tx = 2;    //Declares the TX pin

SoftwareSerial mySerial(rx, tx);  //Setting up the RX/TX pins as a SoftwareSerial

char buttonState = '1';//Declares the character that represents the virtual button current state
char lastButtonState = '0'; //Declares the character that represents the virtual button last state

void setup(){
  mySerial.begin(9600);       //Start the serial communication and select the its speed that deppends of the frequency that it will be program the attiny
}

void loop() {

  buttonState = mySerial.read();    //Reads the message a "1" or a "0" from the command line      

  if (buttonState != lastButtonState) {   //Checks if there exist a change in the virtual button state

    if (buttonState == '1') {         // Condition For Motor ON

      mySerial.println("1");         //Prints in the screen the actual state

    }
    else if (buttonState == '0'){      // Condition For Motor OFF

      mySerial.println("0");         //Prints in the screen the actual state

    }

    delay(50);
  }

  lastButtonState = buttonState;        //Sets the current state as a last state

}

FIRST CODE 2 (not working)

Il y a probablement un problème avec le code et je suis en train de chercher une solution.

SECOND CODE 2 (that works)

#include <SoftwareSerial.h>

int rx = 2;    //Declares the RX pin
int tx = 1;    //Declares the TX pin

SoftwareSerial mySerial(rx, tx);  //Setting up the RX/TX pins as a SoftwareSerial

char buttonState = '1';//Declares the character that represents the virtual button current state
char lastButtonState = '0'; //Declares the character that represents the virtual button last state

void setup(){
  mySerial.begin(9600);       //Start the serial communication and select the its speed that deppends of the frequency that it will be program the attiny
  pinMode(4, INPUT);           // set pin to input

}

void loop() {

  buttonState = digitalRead(4);    //Reads the message a "1" or a "0" from the command line      

  // if (buttonState != lastButtonState) {   //Checks if there exist a change in the virtual button state

    if (buttonState == HIGH) {         // Condition For Motor ON

      mySerial.println("1");         //Prints in the screen the actual state

    }
    else if (buttonState == LOW){      // Condition For Motor OFF

      mySerial.println("0");         //Prints in the screen the actual state

    }

    delay(50);
//  }

  // lastButtonState = buttonState;        //Sets the current state as a last state

}

This video shows that pressing the button generates the value “1” in the Serial Monitor and when you stop pressing the value “0”

VIDEO attiny45 MonitorSerial comunication

In this way I already have it configured so that the two plates work together.

The idea is that pressing the attiny45 button turns on the atMega 328 LED

Photo showing the conections betwen atMega 328 and attiny45 UART protocol

Conection_PCB

VIDEO SOWING THE GOOD RESULT

References
1- https://programarfacil.com/blog/arduino-blog/comunicacion-i2c-con-arduino/

Today I learned

I learned what I2C communication is and how it works
That there are several communication protocols and to name two more: UART and ISP, with their advantages and disadvantages

Other things that I learned when reviewing

When comparing circuits with different microprocessors, I corroborated that there are fixed provisions regarding:

The Reset of the microprocessor: this is connected to the reset of the ISP and to the VCC, the latter interposing a 10 kohm resistor
The GND bridges the VCC with a 1uF capacitor although they differ in number (two capacitors for the Danduino).
The Crystal: it has two 10 pF capacitors and is connected to the GND and to the specific pins for the microprocessor crystal.


Last update: July 15, 2022