Week 13: Networking and Communications

keywords: electronics design, programming, arduino, pcb board, serial communication protocol, I2C

The goal this week is to have two microcontroller boards communicating with each other. In order to do this, we need to learn about serial communication protocol. Serial communication is the process of sending data at one bit per time over communication channel or computer bus. Neil covered different types of serial buses, including asynchronous, I2C, SPI, CAN and USB. We are using I2C (Inter-Integrated Circuit) as our protocol. It was invented by Philps in 1982 for two-wire interface to connect low-speed devices like microcontrollers, EEPROMs, A/D and D/A converters, I/O interfaces and other similar peripherals in embedded systems. It allow multiple "slave" digital integrated circuits ("chips") to communicate with one or more "master" chips. The communication requires the SDA and SCL pins on the slave and the master to be connected, as well as VCC and GND for power.

SDA - data signal

SCL - clock signal

Group Assignment

In class this week, I tried to have my board communicating with my classmates' boards. My classmate Flavie has more extensive documentation on this week’s group assignment, which can be found HERE.

Master and Slave Communication: siyUno and Nickino

First, we used master_writer and slave_receiver codes from the Arduino library to test out I2C between two boards:


Master communicating to multiple Slave Boards

Then, we tried to have one master writes into multiple slave receivers:


This diagram illustrates the connection when there are multiple slave boards. The boards need to share common GND, SCL and SDK connections:

Each slave board needs to specify their name under:

Wire.begin();                // join i2c bus with address

These names are included in the master writer code:

void loop() {
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write("Hello 8");    	// sends five bytes

  Wire.endTransmission();	// stop transmitting

  Wire.beginTransmission(7); // transmit to device #8
  Wire.write("hello 7");    	// sends five bytes

  Wire.endTransmission();	// stop transmitting

  delay(500);
}

The full code we have used can be found on Flavie's page.

You can also customize the lines, which looks like:

Chatting with Flavino

The chatting function requires serial communication from two IDE sessions. We followed THIS simple chat tutorial.

Individual Assignment

This week's group assignment is to design, build, and connect wired or wireless node(s) with network or bus addresses.

SIYUno 2.0 D,,,,,;

First, I made a SIYUno 2.0, since I would need another microcontroller board for I2C and also I would like to have more VCC and GND connections. I may be using sensors with I2C protocol in the future. Here is the modification I made on my board:

NOTE

Since the gap between the pins on the ATTmega 328 from the Sparkfun microcontroller library that I have downloaded is smaller than the endmill of the milling machine, I have modified its size as you can see in the image above. Last time I did it in Photoshop, meaning I would need to change its size manually every time I made a change in Eagle. Here is my workflow:

1. Select the component in Board Window/Right Click/Open Footprint

2. Under footprint, go to layer setting and only turn on the top layer

3. Select the microcontroller pins that are horizontal and click on Change/SMD/..

4. Type in the desired size of the microcontroller pins in mil (the original size is 48 x 28, which I changed to 48 x 11)

5. Then right click on the selected leg in the board window and right click Change:Group

6. Repeat step 4 and 5 for the vertical pins, the dimension is 11 x 48 instead

7. Save, and in the Board Window click on Library/Update All

Here is SIYUno 2.0. However, the FTDI does not work:/

I got the same message (sck_not_sync) as I did for the first SIYUno 1.0 I made, even this time the only change was adding more GND and VCC connection pins. I tried the following to debug, although it is still not working:

1. Clean gap between the copper traces with a shape blade, since the new endmill at our lab makes the traces rougher than the old one (although the old one breaks more easily. Then, cleaning the board with alcohol.

2. Give more solder to some of the components

3. Checking with multimeter (although all the connections are okay)

I lost most of my time in debugging my new board. At the end, I decided to use my 2.0 as a master writer board and my 1.0 as a slave receiver board. I used the same code as of in the group assignment to check whether I2C protocol works between the two boards. It works!

Here is the code used on the master writer board:

// Wire Master Writer
// by Nicholas Zambetti 

#include 

void setup() {
  Wire.begin(); // join i2c bus (address optional for master)
}

byte x = 0;

void loop() {
  Wire.beginTransmission(8); // transmit to device #8
  Wire.write("x is ");        // sends five bytes
  Wire.write(x);              // sends one byte
  Wire.endTransmission();    // stop transmitting

  x++;
  delay(500);
}

The master address the address of the slave receiver board, which is device 8 in this case:

Wire.beginTransmission(8);

Wire.write is similar to Serial.print. It is command for printing the line that shows on serial monitor.

The initial x value in Wire.write(x) is 0 as indicated in byte x = 0;. After Wire.endTransmission();, the next line shows the x value adds up every time it loops back to Wire.beginTransmission after 500 miliseconds delay.

Here is the code used on the slave receiver board:

// Wire Slave Receiver
// by Nicholas Zambetti 

#include 

void setup() {
  Wire.begin(8);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  delay(100);
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  while (1 < Wire.available()) { // loop through all but the last
    char c = Wire.read(); // receive byte as a character
    Serial.print(c);         // print the character
  }
  int x = Wire.read();    // receive byte as an integer
  Serial.println(x);         // print the integer
}

The line prints into the serial monitor of the slave receiver board. Wire.begin(8) shows that the slave receiver board joins the master writer board through address 8.

When an event is received, serial begins. The receiveEvent begins under the condition of reading byte. Then, the byte, initialized as an integer, prints into the serial monitor.

Later, we found out that bootloading the board as an Arduino Pro instead of an Arduino Uno would resolve the FTDI issue!

Wireless connection with ESP8266

I followed Neil's schematics for ESP8266 and made a WiFi board to make wireless communication. I will update soon with more details. NOTE: solder 3.3V jumper on the FTDI; RX and TX connection is extremely critical, otherwise the board burns (former student Travis's advice).


Before programming the board, a ESP library needs to be installed:

https://raw.githubusercontent.com/damellis/attiny/ide-1.6.x-boards-manager/package_damellis_attiny_index.json

Then, select ''Generic ESP8266 Module'' under Board.

When I connected the ESP module to FTDI and tried to upload a Blink code from the ESP library, it was not working. I went back the schematic and realized the connection for one of the capacitor doesn't make sense. It should be connected to VCC and GND.

After I soldered jumper wires, I connected again to FTDI (3.3V). I got an error message in Arduino:

Failed to connect to ESP8266: Timed out waiting for pocket header.

I changed to a 5V FTDI, since I have a voltage regulator to ensure exact 3.3V input (which needs voltage higher than 3.3 V in order to activate). But my RX, TX remains 5V, which I was concerned whether it will be an issue. Although I still had error message when trying to upload Blink, since ESP is used for hosting an application, it is more important to test out whether it works as a host.

Communication with the WiFi module can be done via Serial Monitor. I went through THIS (http://archive.fabacademy.org/2018/labs/fablabirbid/students/kusay-malahmeh/week13.html) student’s documentation on programming ESP and followed the following procedure:

AT

OK
AT+CWLAP

+CWLAP:(3,''HAGIBIS-FABO'',-68,''4a:98:ca:a8:ce:71'',1,1)
+CWLAP:(4,''MERCURY8AD4F0'',-80,''9c:21:6a:8a:d4:f0'',1,10)
+CWLAP:(0,''HP-HOTSPOT-A7-LaserJet M1218'',-71,"54:35:30:0c:6f:a7",6,-37)
+CWLAP:(0,''alink'',-80,''04:78:63:17:d2:30'',6,0)
+CWLAP:(3,''3085'',-89,''00:34:cb:74:91:da'',6,-7)
+CWLAP:(4,''Fablab O",-85,''d0:76:e7:95:46:ec",12,-17)
+CWLAP:(4,''Fablab O 5G'',-56,''d0:76:e7:95:48:6e'',13,-16)

OK

AT+CWJAP=''Fablab O'',''fablabshanghai''

WIFI CONNECTED
WIFI GOT IP

OK
AT+CIPSTA?

+CIPSTA:ip:''192.168.1.105''
+CIPSTA:gateway:''192.168.1.1''
+CIPSTA:netmask:''255.255.255.0''

OK
AT+CWSAP?

+CWSAP:''AI-THINKER_1AB2AD'','',12,0,4

OK

AT+CWMODE=2

OK


1. AT: check whether WiFi module works fine

2. AT+CWLAP: lists all available WiFi to connect to

3. AT+CWJAP=''ssid'',''password'': specify the network to connect to from the listed ones

4. AT+CIPSTA?: used to get the IP address of the chip

5. AT+CWMODE=2: switch to host mode

6. AT+CWSAP?: check name of network

7. AT+CWSAP=''ssid'',''password'',ch,ecn

*ecn: 0 = OPEN 2 = WPA_PSK 3 = WPA2_PSK 4 = WPA_WPA2_PSK

But in my case, I often get very unstable connections. When it disconnects during the process, I have to restart the procedure. You can see in the image below that I’ve encountered many ERRORs:

I was not able to carry out AT+CWSAP. Before I tried this step again, the module disconnected. It happened many times.

In the future, I will try this module again with a 5VVCCGND+3.3RXTX all in one FTDI.

Files from this week:

SIYUno2.0 Eagle files (with schematic and board)

wifiboard schematic

wifiboard board

wifiboard trace

wifiboard outline



back to Assignments