13_networking.md 10.2 KB
Newer Older
Erik Strand's avatar
Erik Strand committed
1 2 3 4 5 6 7
+++
title = "Networking"
date = "2018-12-05"
menu = "main"
weight = 15
+++

Erik Strand's avatar
Erik Strand committed
8
Files: [audio_interface.sch](/designs/13_audio_interface.sch) [audio_interface.brd](/designs/13_audio_interface.brd) [audio_interface_2.sch](/designs/13_audio_interface_2.sch) [audio_interface_2.brd](/designs/13_audio_interface_2.brd) [serial_cpp](https://gitlab.cba.mit.edu/erik/serial_cpp) [lufa](https://gitlab.cba.mit.edu/erik/lufa) (see Demos/Devices/ClassDriver/VirtualSerial)
Erik Strand's avatar
Erik Strand committed
9

Erik Strand's avatar
Erik Strand committed
10
This week we're making machines talk to each other. I've used I2C before, so I'm curious to venture into the wonderful world of USB.
Erik Strand's avatar
Erik Strand committed
11 12 13 14


## Board Design

Erik Strand's avatar
Erik Strand committed
15
For part of my final project I want to make my own USB audio recording device. So I'll try to develop all the necessary electronics this week. I have the analog circuitry I need from [inputs week](../10_input_devices). But I don't have a board ready to go with a USB-capable microcontroller (bit-banging will not suffice, since I need the CPU to be available for audio processing). I've heard that [LUFA](http://www.fourwalledcubicle.com/LUFA.php) is much nicer than ATMEL's own USB [libraries](https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591207) so I'll try to use that. I'd like to use an XMEGA board, since they are fast, have a good amount of memory for audio applications, and I've used them [recently](../12_machine_week). LUFA's [XMEGA support](http://www.fourwalledcubicle.com/files/LUFA/Doc/120219/html/_page__x_m_e_g_a_support.html) is technically experimental, but people have been using it since [2013](https://www.avrfreaks.net/forum/lufa-xmega-hello-world). So I think it should be ok.
Erik Strand's avatar
Erik Strand committed
16

Erik Strand's avatar
Erik Strand committed
17
![](/img/13_schematic.png)
Erik Strand's avatar
Erik Strand committed
18

Erik Strand's avatar
Erik Strand committed
19
On the left I have my microcontroller. I'm using an external 16MHz crystal to give it an accurate clock signal. High speed USB 2.0 requires a 48MHz clock, which I can get by multiplying the crystal's output by 3 using the XMEGA's phase locked loop (PLL). On top I have my power section, including a regulator to bump USB's 5V power down to 3.3V, some filtering capacitors, and a power indicator LED. The two circuit groups with op-amps together amplify and bias the audio input, as I learned in [inputs week](../10_input_devices). Finally I have some headers that provide convenient debugging access to certain signals, and a 0-ohm resistor I needed to connect all my ground signals.
Erik Strand's avatar
Erik Strand committed
20

Erik Strand's avatar
Erik Strand committed
21
![](/img/13_board.png)
Erik Strand's avatar
Erik Strand committed
22 23 24 25 26 27 28 29

Laying out the board took a long time, since this is the most complex circuit I've designed from scratch. I'm using thinner traces than before, so that they can reach all the XMEGA's pins without shorting and so that I can route multiple traces under a single 1206 component. I kept the USB signal traces as short as possible. One open question I have is what to do with the USB connector's shield. Plenty people have [asked](https://electronics.stackexchange.com/questions/4515/how-to-connect-usb-connector-shield) this [question](https://forum.allaboutcircuits.com/threads/usb-device-cable-shield-connection-grounding-it-or-not.58811/) online, but the answers are split between grounding it directly and connecting it to ground via a capacitor and a large (ex 1MΩ) resistor. I don't yet have the expertise to know which makes more sense in this situation. [This](https://www.ti.com/sc/docs/apps/msp/intrface/usb/emitest.pdf) document looks like it might help, but I haven't had time to read it all yet.


## Fabrication

I milled the board on a Roland SRM-20. For the most part the smaller traces worked fine. However the end of the power trace for the USB port did get pulled off. (The same is true for part of the 'S' in the text, but that won't require any jumper wires.)

Erik Strand's avatar
Erik Strand committed
30
![](/img/13_milled.jpg)
Erik Strand's avatar
Erik Strand committed
31

Erik Strand's avatar
Erik Strand committed
32
I soldered the XMEGA and the USB connector first, since I knew jumping the USB power wire and dealing with the tiny XMEGA traces would be the trickiest tasks. The XMEGA's leads are smaller than anything I'd soldered before, but it still went fine. Most of them I soldered individually, but in a few places I globed pins together and later removed the excess solder to unshort them. Generous amounts of flux were essential, since I used a very fine gauge of solder that doesn't have a flux core. To connect the USB power, I took a small piece of wire and used it to jump directly from the USB connector pin to the trace. It was so short that it was almost impossible to solder one side without melting (and thus destabilizing) the other, but eventually I got it to stick in place with good quality joints on both sides. (In the photo below it looks like it's shorted to the USB plug chassis, but the jumper wire is safely above the leftmost lead.) After these I soldered on the minimal number of other components to get the power indicator LED working (ok, the crystal wasn't necessary but I had already taken it out). 
Erik Strand's avatar
Erik Strand committed
33

Erik Strand's avatar
Erik Strand committed
34
![](/img/13_powered_on.jpg)
Erik Strand's avatar
Erik Strand committed
35 36 37

From here it was a routine soldering job.

Erik Strand's avatar
Erik Strand committed
38
![](/img/13_stuffed.jpg)
Erik Strand's avatar
Erik Strand committed
39 40


Erik Strand's avatar
Erik Strand committed
41
## Software (First Attempt)
Erik Strand's avatar
Erik Strand committed
42

Erik Strand's avatar
Erik Strand committed
43
I started by flashing it with an empty hello world program, to verify that it could be programmed at all. Then I cloned LUFA and started trying to adapt an example to work for my board. Unfortunately, disaster struck: I accidentally tore off the USB connector. I knew this was a risk, since I decided to delay soldering the USB jack shield until I knew what to do with it. The cable I used required fairly high force to remove, though, so I think once I plugged it in the board's fate was sealed. You can also see that leftover flux greatly sped up oxidation, leaving spots of green copper oxide.
Erik Strand's avatar
Erik Strand committed
44

Erik Strand's avatar
Erik Strand committed
45
![](/img/13_broken_connector.jpg)
Erik Strand's avatar
Erik Strand committed
46

Erik Strand's avatar
Erik Strand committed
47 48
I figured it was worth a shot at repairing.

Erik Strand's avatar
Erik Strand committed
49
![](/img/13_almost_repaired.jpg)
Erik Strand's avatar
Erik Strand committed
50 51 52 53 54 55 56 57 58 59 60 61 62

I think I got most of the leads reconnected, though in the image above the power jumper has some really ugly (and maybe cold) joints. Eventually I decided I should save myself the frustration of working with a damaged board. Especially since I learned of a few things I could have done better.


## Back to the Drawing Board

Or back to board drawing, as it were. Anyway, I wanted to make a few changes before milling again:

- Add additional bypass capacitors near all the XMEGA's power pins
- Get rid of the 22 ohm resistors (unlike the ATmegas, the ATxmegas have these internally)
- Switch to a single-ended op-amp configuration
- Add mounting holes and pads for an external audio jack and volume knob

Erik Strand's avatar
Erik Strand committed
63
The first is just good practice for microcontrollers. I added 0.1uF caps near all the XMEGA's power pins, and a few 10uF caps near potentially large current sinks (i.e. LEDs and op-amps). I had added the 22ohm resistors because all the [examples](../../../../../863.17/CBA/people/tomasero/index.html) I [looked at](../../../../../863.14/people/andrew_mao/week11) had them. But after going through the XMEGA's datasheet in more detail, I found that it has an "integrated on-chip USB transceiver, no external components needed". I wanted to go to a single-ended op-amp configuration to make it simpler to add a potentiometer to control gain. With my current differential setup, I would have to use a double-ganged pot, and if the two resistances didn't stay exactly the same at all times there'd be additional error in my output. So I'll just connect one side of the input to ground, and send the other through an AC-coupled non-inverting amplifier with a DC bias. Finally, the gain control knob and audio jack will be better off mounted to the chassis of the device rather than the board, so that the board doesn't bear any unnecessary mechanical load. It would be nice to attach the USB jack to the chassis as well, but the USB jacks we have in stock are surface mount, and since it's good to keep the data leads as short as possible, I'll leave it on the board.
Erik Strand's avatar
Erik Strand committed
64

Erik Strand's avatar
Erik Strand committed
65 66
![](/img/13_schematic_v2.png)
![](/img/13_board_v2.jpg)
Erik Strand's avatar
Erik Strand committed
67 68 69 70 71 72 73 74

If I lay this out a third time, I'll make more careful use of the grid. I could also move the LEDS to the left of the XMEGA, and connect the audio signal to a pin on its bottom side, to shorten my critical analog traces. Speaking of which, I could have a separate analog ground plane and voltage rail. But this will definitely work for now.


## More Milling

I hoped that the ripped leads on my first board were a fluke, so I milled the second one just like the first. But the same thing happened, in the exact same place.

Erik Strand's avatar
Erik Strand committed
75
![](/img/13_ripped_traces_again.jpg)
Erik Strand's avatar
Erik Strand committed
76 77 78

Rather than deal with jumpers again, I thought I'd fix the manufacturing. So I grabbed a 0.01" endmill to use just for the USB pads.

Erik Strand's avatar
Erik Strand committed
79
![](/img/13_good_traces.jpg)
Erik Strand's avatar
Erik Strand committed
80

Erik Strand's avatar
Erik Strand committed
81
![](/img/13_stuffed_v2.jpg)
Erik Strand's avatar
Erik Strand committed
82

Erik Strand's avatar
Erik Strand committed
83 84
This time I cleaned the whole board with isopropyl alcohol (70%) to remove leftover flux and prevent early oxidation.

Erik Strand's avatar
Erik Strand committed
85 86 87 88 89 90 91 92 93

## Software (Second Attempt)

To begin I'd like to make my board become a USB virtual serial device, since this is probably the simplest example that LUFA has, and I already have my own C++ to listen to serial devices. (Side note: I wasn't sure my code would work with USB virtual serial devices, but Linux presents these devices as device files in `/dev` just like the FTDI device I used before. So though different drivers are being invoked under the hood, at the level of `libserialport` they look the same.)

Though the LUFA code looked quite daunting at first, I only needed to change a few things to get it to run on my board. First, I commented out everything referencing code from `LEDS.h` and `Joystick.h`, since I don't want to create these files for my board (and I don't even have a joystick). Instead of reading a value from a joystick, I'll just spam "hello world" all the time. In the Makefile, I set `ARCH` to `XMEGA`, and the clock rate to 48MHz.

After programming, my serial port code detects a new device: `/dev/ttyACM0`. When I open the port, I get see a constant stream of "hello world" as expected.

Erik Strand's avatar
Erik Strand committed
94
![](/img/13_hello_world_usb.png)
Erik Strand's avatar
Erik Strand committed
95 96 97 98 99 100 101 102 103 104 105 106

Since this week is ultimately about networks with addresses, let's try to find the address that my board is assigned by my computer. I grepped for "address" in LUFA and after following a few function calls found my way to `LUFA/Drivers/USB/Core/XMEGA/Device_XMEGA.h`. At line 217 LUFA is writing the newly assigned address to one of the XMEGA's registers.

{{< highlight c >}}
static inline void USB_Device_EnableDeviceAddress(const uint8_t Address)
{
    USB.ADDR = Address;
}
{{< /highlight >}}

Instead of spamming hello world, I can read back this register and make my board output its own address.

Erik Strand's avatar
Erik Strand committed
107
![](/img/13_usb_address.png)
Erik Strand's avatar
Erik Strand committed
108