Networking and Communications

Week 14

This assignment will be a real challenge to me because I will try to communicate with a Bluetooth device, the Nordic Semiconductor nrf52. As I do not know anything about what I'm trying to attempt, I will design a small board and communicate with it.

RTFM (Read the Ffff..ffff...FINE! Manual)

As I learn many years ago, reading the documentation when provided is a first step, especially if it's well made. But technical documentation is not for noobies, it's hard to understand and, especially for chips, very long. But in a way, Nordic's documentation is a little less obscure than Atmel's. Or maybe not.

The first step.

The first step is to recreate the nrf52 board tutorial at the MIT gitlab repository page. Although looking like an easy exercice in reverse engineering, I had to verify every component's purpose by checking the chip's documentation. I learned a lot, but I ended up with a lot more questions than when I started out. This result is not unexpected because this is a very sophisticated chip after all.

The custom board made at MIT.
Figure 1: The custom board made at MIT.

Nordic's library is not included by default into Eagle. You have to download them. Fortunately, it's easy. You just have to open the Library Manager, click on the "Available" tab, select "Nordic_nRF" library and you're done. You'll find the new library under "Nordic_nRF" tab. I picked my chip, then the FTDI header under the Fab Library and started from there.

The first exercice that I did was to compare the chip's pins usage in the gitlab's page and the pin assignments(...) from the manufacturer. As I built my Eagle schematic, I came to undestand some components. As an example, what was a cryptic number on the MIT's board (32.768) I came to understant that it was a crystal and the number was the frequency. This crystal must be used with pins XL1 and XL2 with capacitors of 22 pF under MIT's. Later, at the bottom of the document (Chapter 53, page 539), I found a pcb schematic with this crystal connected to the appropriate pins but with 12pF capacitors instead. Why this discrepancy? And why use this frequency, which are declared optionnal instead of the recommended 32MHz? Also, all the VDDs pins (3 volts) are feeded with current, but not MIT's. Why? These are some unanwered questions.

Figure 2: My schematic extrapolated from the MIT's board.
Figure 3: Recommended practice from Nordic.

I stopped when I had to place the RX and TX lines as these goes under the chip and I haven't been able to locate the appropriate pins.

When the reality of the Fab Academy sets in...

I had to abandon the idea of using the nrf52 for Fab Academy. The learning curve of EVERYTHING is steep now and I can't imagine to complete the course in time trying to understand such a complex chip. I had to kill this nice idea.

In retrospect, it was a good decision as networking is really complex.

Trying to engage the conversation between two boards

As Mathieu my instructor suggested, I needed a simple communication device and see how they communicate between them. I followed his process, described here.

Essentially, what I will do is make a master board the will talk to a slave board. The real basics of network communication. I will include a led for visual signal and the chip will be an ATtiny44. The rest are pins for communication between the two boards.

Eagle schematic
Figure 4: Eagle schematic, Master board.

Out of this sketch I made the board which looked like this:

Eagle board, Master board
Figure 5: Eagle board, Master board.

This board looks really nice as it is. I hope that I haven't forgot anything...

While at it, here's the slave board schematic and board file

Figure 6: Eagle board, Slave board.
Figure 6: Eagle board, Slave board.

By carefully looking at it you'll notice one big difference between the two: the slave board has an FTDI header. This was added after I consulted with my instructor who told me to add this feature. But in my hurry to go to the shop and mill those board, I forgot to add it in the Master board! Gosh, I really don't think when I'm stressed.

The milling.

The milling went as expected. Except some small adjustment, namely going to a depth of 0.07 instead of my regular 0.08, and changing the tool diameter from the default .4 to .35. The first because the mill has a tendency to go deeper somehow, and the latter force FabModule to separe some traces that were joined together.

The soldering

The soldering went fast by now. I made both of them in less than an hour.

Figure 7: Master board.
Figure 8: Slave board.

The programming

The programming was a little more difficult as expected, which was difficult at first. Since the master didn't had the FTDI header to communicate, I realised that, although really nice, it was pretty much useless. But a nice solution came up while talking with the people around me, especially François Auclair: use my Hello Board. I sweated blood and tears to make this one functionnal.

So I had my new master board, and the slave board. I also had the code for the master and the slave that I needed for my boards.

This is the code taken from François's webpage. It's very well explained. The following code is for the Master Board:

#include <SoftwareSerial.h> //
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 3;     // the number of the pushbutton pin
const int ledPin = 8;
const int rx = 5;
const int tx = 6;
bool flashing = false;
SoftwareSerial mySerial(rx, tx);
// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status
void setup() {
  mySerial.begin(4800);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}
void loop() {
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == LOW) {
    flashing = !flashing;
    if (flashing) {
      mySerial.write(1);
    }
    delay(1000);
  }
  if (flashing ) {
    if (mySerial.available() > 0) {
      mySerial.read();
      digitalWrite (ledPin, HIGH);
      delay (1000);
      digitalWrite (ledPin, LOW);
      mySerial.write(1);
    }
  }
}  

And this is the Slave Board code, much simpler:

#include <SoftwareSerial.h>
const int ledPin = 8; // the pin that the LED is attached to
const int rx = 6;
const int tx = 5;
SoftwareSerial mySerial(rx, tx);
void setup() {
  // initialize serial communication:
  mySerial.begin(4800);
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
}
void loop() {
  if (mySerial.available() > 0) {
    mySerial.read ();
     digitalWrite (ledPin, HIGH);
     delay (1000);
     digitalWrite (ledPin, LOW);
     mySerial.write(1);
  }
}

Now was the time to read the code and transfer it to my board. I started out by making an upload of the master code and see where it gets me. As expected the upload went ok but the board did nothing. Good.

I then began to adapt the code and upload the code to the master via my FabISP. I've done this for the master and the slave. Then I tried to connect the two but nothing happenned. The uploads were ok but the boards didn't respond. Something was wrong. I had to isolate my problems.

I went back to the original program for the Hello Board. Somehow, the led is blinking but the pressing the button doen't change the output. No good. I started to study the sketch and found something wrong: the

if (buttonState == HIGH)
should be
if (buttonState == LOW)
to indicate the input pressure on the button. Uploading the code, the master behaved as expected.

With the previous code, I translated the pins to PA3 and PA7 for the button and led pin. The master board sketch was modified accordingly but somehow, I the board stayed silent. It then that I noticed that I was uploading the Slave Board code to the Master Board! Damn!

Went back, corrected the mistake, uploaded the master and the slave code to their appropriate location and made the connections. Nothing. The only recourse was to check side by side the code. Guess what, I found a discrepancy: the RX and TX channel were the same for both boards. I changed them to

const int rx = PA1;
const int tx = PA0;
for the Master and
const int rx = PA0;
const int tx = PA1;
for the Slave. I made the connections again and, finally, the boards we communicating.

Final thoughts

Networking is really tough. Trying to understand what's going on under stress and in a noisy environment is not evident but I manage to get it done. I also got a glipse of that essential process that I need to master.