Introduction: PIC18 Development Board With Ethernet and USB
In this instructable I'm going to show you how to make your own PIC18 development board that features both Ethernet and Full Speed USB 2.0 at a low cost.
Features:
The development board is based on a PIC18LF4553 microcontroller. The microcontroller features a Full Speed USB 2.0 (12Mbit/s) interface without the need for any external components. Also, it has 32KB of program memory, 2KB of RAM and it supports an external clock up to 48MHz, which is optional because it also has an 8MHz internal clock.
The ENC28J60 Ethernet controller is used to provide Ethernet connectivity to the microcontroller thought the SPI interface. The ENC28J60 has an integrated MAC and a 10Base-T PHY, 8KB of buffer RAM, supports both Full and Half-Duplex modes and it is fully compatible with 10/100/1000Base-T networks.
The microcontroller is not soldered directly on the PCB but mounted on an IC socket. The advantage of doing this is that when you are done with the development of the code and you want to make a prototype, you can just pop the microcontroller out and make a new PCB with only the components you actually need for your project.
Because the ENC28J60 needs a 3.3V supply to function I decided to power the microcontroller from 3.3V too. That eliminates the need for two different voltage regulators and for logic shifters between the microcontroller and the Ethernet controller. That means reduction of the BOM cost and more space available on the PCB for other components. On the other hand the LF version of a PIC microcontroller can function over an extended VDD range of 2.0V to 5.5V, so if your project needs to run on 5V instead of 3.3V when you move the microcontroller from the development board to a more permanent board you can power it from 5V if you want.
The board can be powered either from the USB port or from an external source from 4.5V up to 12V though the power jack. Keep in mind though that the ENC28J60 can draw up to 180mA so if you try to power the board from a standard 9V battery you may have problems. The selection of the voltage source is done by a jumper.
Step 1: The Parts
To make the development board you will need the following parts:
- 10 x 100nF Ceramic SMD Capacitors (0603 package)
- 2 x 10uF Tantalum SMD Capacitors (3528 package)
- 4 x 22pF Ceramic SMD Capacitors (0805 package)
- 1 x PIC18LF4553 or PIC18LF4550 (PDIP package) - I recommend using a PIC18LF4553 because it has a 12 bit ADC (which is basically the only difference between the two). The PIC18LF445x microcontrollers are also compatible with the board but they have 24KB of program memory instead of 32KB.
- 1 x 40 pin PDIP IC Socket
- 1 x ENC28J60 (SPDIP package)
- 1 x MagJack RJ45 Connector - The particular I used is this and its part number is MJF13T3L-KF06B3YG-0808. If you are going to use a different one make sure to check the datasheet first, because you may need to modify the design files in that case. For example, I was able to find some HR911105A ones from eBay for very cheap, but unfortunately if you check the of HR911105A datasheet it doesn't 't have the same pinout. Sure, it will work but you will have to modify the board layout.
- 1 x DC Barrel Jack 5.5mm (Through hole)
- 1 x USB Mini-B SMD Connector
- 1 x 25MHz XTAL SMD (HC49/UP package)
- 1 x 8MHz XTAL SMD (HC49/UP package) - I used an 8MHz XTAL but any XTAL up to 48MHz will work.
- 2 x 10K SMD Resistors (0805 package)
- 8 x 100Ω SMD Resistors (0805 package) - 1% tolerance if possible.
- 1 x 1.5K SMD Resistor (0805 package)
- 1 x 2.2K SMD Resistor (0805 package) - 1% tolerance if possible.
- 1 x 120Ω SMD Resistor (0805 package) - 1% tolerance if possible.
- 2 x 470Ω SMD Resistors (0805 package)
- 1 x Momentary SMD Switch - The particular I used is this, but you can use any momentary switch you want with the same footprint.
- 1 x Ferrite Bead rated for at least 80mA (Through hole) - If you can't find one you can make one yourself using a small toroid ferrite core and a little solid core wire (like I did). Five to six turns is all you need.
- 1 x LD1117V33 SMD Voltage Regulator, also known as LD33 (SOT223 package)
- 1 x 2.54mm (100mil) 40-pin Male Pin Header (Through hole) - You will need to cut it to smaller pieces.
- 1 x 2.54mm (100mil) 4x2-pin Male Pin Header (Through hole)
- 1 x 2.54mm (100mil) 40-pin Female Pin Header (Through hole) - You will need to cut it to smaller pieces.
- Solid core wire to use it for the jumpers on the PCB - To fit the holes on the PCB the copper inside the wire needs to be around 0.65mm (22 AWG). A slight thicker solid core wire should also work.
- 1 x 80x62mm PCB - Photoresist or bare copper depending on the etching method you are going to use.
- 1 x 2.54mm (100mil) jumper - The same like the ones that are used on computer motherboards.
Optional Parts:
- 4 x Female to Female Brass Standoff Spacers
- 4 x Screws for the Spacers
The BOM cost will be around 13€ to 15€ ($14.8 to $17) depending from where you'll buy the parts. Most of the parts can be found easily on eBay.
Step 2: Making the PCB
The next step is to make the PCB. Because this is not a tutorial about PCB etching I'm not going to get into details about the process, but instead I'm going to give you some guidelines specific to this project.
[ Credits to Chris Meletis for the PCB layout ]
Etching the PCB:
Before you choose the etching method you want to follow keep in mind that some traces have a clearance of 0.3mm
(12mil) so if you try use the toner transfer method you might experience some issues. I don't say it's not possible but it will definitely be more difficult than the photoresist method to get a good result. Personally, I used the photoresist method and the result was great on the first try. I only had a minor issue with one of the traces, but that was caused by a clearance error on the layout not by the etching process itself. Now the layout has been corrected so you won't have any issues.
If you choose the photoresist method, about the exposure make sure to use only one high resolution transparency otherwise you might fail to expose correctly the traces that have very small clearance and/or the thermal pads. I had great success using a good inkjet printer and high resolution inkjet transparencies. The transparencies were a little expensive but worth every cent.
About the development of the PCB, the trick to know when you are done is to wait for the thermal pads to show up. When you are able to see the thermal pads then you know that the board is ready for etching.
Drilling the Holes:
After you etch the PCB you will have to drill the holes for the through hole components. Most of the holes need either a 0.8mm or a 1mm drill bit. The holes for the ICs and the ferrite bead are 0.8mm. The holes for the pin headers and the jumper wires are 1mm. The MagJack connector has 2 holes that are 1.6mm for the shield ground and 2 for the plastics that are 3.2mm, the rest are 1mm. The barrel jack needs 3 holes with a diameter of 3.2mm. The Mini-B USB connector needs two 0.9mm holes, that don't have to go all the way though the PCB but only half way. If you don't have a 0.9mm drill bit then an 1mm bit will work fine. Finally, the board also has 4 mounting holes 3.2mm each on the edges that is up to you if you want to drill them.
Update January 2017:
A new revision of the development board is now available, which especially if you plan to get your board fabricated from a professional PCB manufacture you should make sure to use instead. The Gerber files are also available, so if you don’t plan making any changes to the design you can just send them as they are to your favorite PCB manufacturer and get your hands into some professional made PCBs with almost no effort.
If you plan to make the PCB yourself as described in this instructable I recommend using the old design instead, because the new one has reduced trace widths and clearances which make home etching much harder.
The old schematic also has a minor mistake, the VCAP capacitor (C3) has been placed backwards. This is not a problem though if you plan to solder the PCB yourself, you just have to be aware of it so you will put it properly while soldering.
Step 3: Soldering the Components
After drilling the holes it's time for the fun part, to solder the components on the PCB. Most of the components are SMD so you gonna need a little bit of flux to assist you and of course a pair of tweezers. Start by soldering all the 100nF capacitors first since they are the smallest of all the components. After the 0603 capacitors, go for all the 0805 components and after that for the two 3528 tantalum capacitors. Finally, solder the crystals, the USB port and the momentary switch and you are done with the SMD components.
When you are finished soldering the SMD components it's time for the through hole. Note that all the through hole components are mirrored on the PCB layout so they need to be soldered on the non copper side of the PCB. Also, note that there are two jumpers under the microcontroller. You will need to solder them first before you solder the IC socket.
Before soldering the MagJack connector you will have first to cut the pins 4, 5 and 6 because since they are not used they were omitted on the board layout in favor of some extra space for the traces.
Furthermore, because the ENC28J60 unlike the microcontroller needs to dissipate a fair amount of heat, it needs to be soldered directly on the PCB without a socket. That way the copper of the ground plane will act as a heat sink and will dissipate an amount of heat. Another reason you want to solder the ENC28J60 directly on the PCB is to minimize the parasitic capacitance and inductance which can introduce noise.
Finally, on the trace that is connected with the top pad of the voltage regulator make sure to add a fair amount of solder. This is going to help a lot with the heat dissipation of the regulator.
When you are done with the soldering don't forget to clean the PCB from the flux residue. If you use rosin flux then isopropyl alcohol is all you need.
The last thing you need to do after soldering is to put the jumper on the pin header that selects the voltage source.
Step 4: Testing
Now that your development board is finished you need to test it to see if everything is OK. Before you insert the microcontroller to the socket power the PCB and test the voltages on the VDD, VSS and Reset pins of both ICs. You should measure about 3.3V on the VDD and Reset pins referenced to any of the VSS pins.
If the voltages are fine then while the board is still powered plug it to a switch or router and watch the LEDs of the MagJack. If the status LED (yellow in my case) lights up and stays on that means a connection at the physical layer between the two devices is established.
If all the tests are passed then you are ready to insert a microcontroller to the IC socket and program it through the ICSP header. Or if you don't have an ICSP programmer, program it first and then insert it to the socket.
Step 5: Start Coding
The last step is to actually start working with your development board. Depending on the compiler you use this is going to be very different.
Personally, I prefer to work with Microchip's MPLAB X IDE and the XC8 compiler. If that is also the case for you, Michael P. from Microchip's forums has already done a great job writing a small but functional web server with support also for ICMP and Telnet protocols for PIC16F/18F microcontrollers.
Based on his work I made some small modifications to the code to make it run on my development board. Basically, the only thing I did is that I added support for the PIC18LF4553 microcontroller, and I also moved the CS pin from RC2 to RC6 because that is the one I use on my development board. By having this project as a starting point you can study it and expand it by adding more functionality.
To get started, first download the attached zip file, extract it inside your MPLAB X project folder and open it using the MPLAB X IDE. To test the code the only thing you have to do before compiling and uploading it to the microcontroller is to change the default IP (inside main.c at line 17) in order to be in your own network. For example the IP of my desktop computer is 192.168.2.180 with the subnet mask 255.255.255.0. That means my desktop is in the network 192.168.2.0/24 or in other words a valid IP address for a device in my network is every IP between 192.168.2.1 and 192.168.2.254. So, I gave it the IP 192.168.2.111 which belongs to the 192.168.2.0/24 network and is not already occupied by another device on my network.
After compiling and uploading the code to the microcontroller you should be able to see the default web page of the microcontroller by typing its IP to the address bar of your web browser. Furthermore, you should be able to ping the device and access it via Telnet.
If the compiler of your choice is not XC8 but Mikroelektronika's MikroC for example, unfortunately I can't help you much since I have very little experience with MikroC. The only think I know for sure is that MikroC has an Ethernet library that supports the ENC28J60 but apart from that I can't help you any further.
Beyond Ethernet:
As you may noticed I spent the largest part of this step talking about how to get started with Ethernet. The reason I did that is because many people find it more complicated than other subjects and don't know were to start.
But the fact that the development board features Ethernet connectivity does not mean that you have to use it on every project. The board can be used as a general purpose development board for any project you are working on. The only thing you have to remember is to keep the CS pin high (RC6) in order be able to use the SPI bus with other devices than the ENC28J60.
Attachments

Participated in the
Soldering Challenge
40 Comments
5 years ago
Hello,
first, it is a great Project. Now for my problem. I have set up to test a few Radio Buttons to control a Bit Variable. Everything works fine in the browser, but interestingly, the logic is twisted. Furthermore, the Variable in the Microcontroller keeps its state and does not change. Can anybody help me further?
bool Bit0_Status=0;
static void handleHTTP( TClient *crec, uint8_t sock )
{
char s[40] = { 0 };
int8_t i;
const char* cmd = gBuffers[ crec->buffer ].data;
if ( strncasecmppgm( cmd, "GET /?status=1", 14 ))
{
Bit0_Status=1;
}
else if ( strncasecmppgm( cmd, "GET /?status=0", 14 ))
{
Bit0_Status=0;
}
netPutBegin( sock );
soutpgm( sock, "HTTP/1.0 200 OK" CRLF );
soutpgm( sock, CRLF );
soutpgm( sock, "<html>" CRLF );
soutpgm( sock, "<head>" CRLF );
soutpgm( sock, "<title>" CRLF );
soutpgm( sock, "PIC Status Page" CRLF );
soutpgm( sock, "</title>" CRLF );
soutpgm( sock, "</head>" CRLF );
soutpgm( sock, "<body>" CRLF );
soutpgm( sock,"<P><HR>" CRLF );
if(Bit0_Status==1)
{
soutpgm( sock,"Bit 0 is <font color=’green’>ON</font>" CRLF );
}
if(Bit0_Status==0)
{
soutpgm( sock,"Bit 0 is <font color=’red’>OFF</font>" CRLF );
}
soutpgm( sock,"<FORM action=>" CRLF );
soutpgm( sock,"<P> <INPUT type=\"radio\" name=\"status\" value=\"1\">ON" CRLF );
soutpgm( sock,"<P> <INPUT type=\"radio\" name=\"status\" value=\"0\">OFF" CRLF );
soutpgm( sock,"<P> <INPUT type=\"submit\" value=\"Submit\"> </FORM>" CRLF );
soutpgm( sock,"<P><HR>" CRLF );
soutpgm( sock, "<pre>" CRLF );
netPutFinalize( sock );
netClose( sock );
crec->type = CL_NONE;
}
main:
netIdle();
LCD_Set_Cursor(0,0);
if(Bit0_Status==1)
{
LCD_puts ("Bit = 1");
}
if(Bit0_Status==0)
{
LCD_puts ("Bit = 0");
}
Best Regards Sascha
6 years ago
Hi, this is an excellent job, I just want to ask you, if I use a 18f4550 pic do I will need to change other components?, thanks so much
Reply 6 years ago
As far as I know, basically the only difference between 18F4550 and 18F4553 is that the later has a 12-bit ADC. In fact, if I'm not mistaken they are so similar that a hex file compiled for one should also work for the other. So, to answer your question no you don't need to change anything, the same PCB design will work for both.
Reply 6 years ago
Thank you so much for your quick response, I´m going to try it to make it.
Reply 6 years ago
By the way, the datasheet for the PIC18F2458/2553/4458/4553 is only 46 pages compared to the one for PIC18F2455/2550/4455/4550 which is 430. And basically only thing it does is list the minor difference between the two.
6 years ago
Hello Magkopian,
Thank you for the great article. I must say it is very helpful.
I have few questions regarding the article,
1) In the circuit diagram given by you, you have connected + terminal of the capacitor to VSS (GND) and negative terminal to Vcap. Is it normal?
2) If its ok with you, can you please give me the idea about RJ45 connections made in PCB. I am using same RJ45 Magjack as you(the one you have listed) , yet i find it difficult to understand the numbering and the connections between RJ45 and ENC.
3) I am using the general purpose PCB and through hole components. Do you think that might affect the performance or the operation of PCB. Please suggest me the considerations to be made, if any in my case.
Thank you in advance for your help.
Reply 6 years ago
No, this is actually a mistake on the schematic. It has been corrected on the latest reversion but looks like I forgot to update the schematic for some reason, thanks for catching this up I will soon get it fixed.
If you got the same MagJack with me just follow the traces on the PCB design file and this is exactly how it should be connected to the ENC28J60. I also have labeled the pins of the connector on the schematic, so it should be pretty much straightforward.
No matter how crazy this sounds, I've actually built the very first prototype on a perfboard and it worked, so it is definitely possible. I had all sorts of issues with noise though, so this is something that I definitely not recommend doing if you can avoid it. If you are really interested in this project though, you can find pretty cheap PCB manufactures from China that will produce about 10 boards of this for as low as 20€. This what I actually did a few months after posting this instructable.
In case you are instead, I will upload the Gerber files of the latest revision so you can just send them to your favorite manufacturer and with almost no effort get your hands into some professional made PCBs.
7 years ago
Do you think that it should work if I download the hex code compiled for a 18F4553 in a 18F4550 chip? Because when I try to compile/build for a 18F4550 I am getting error messages!
Reply 7 years ago
It is possible to burn the hex file to an 18F4550 as its architecture is almost identical to 18F4553. The only difference between the two is basically that 18F4553 has a 12-bit ADC.
But, this will only be useful to you if you just need to test your board, you have no way to modify the code and play around with it if you don't manage to compile it. What version of MPLAB X and XC8 you have? Maybe the issue is related to the version of the compiler. Also, what kind of errors do you get?
7 years ago
can the webpage be changed to anything by simply editing the defount page or...
and its only html right
Reply 7 years ago
HTML, CSS, Javascript there is no difference for the server, they are all character strings for it. You can send the client (which most probably is a web browser) whatever output you want, then it is its own responsibility to parse it and display it on the screen properly. The output to the client is done inside the handleHTTP callback function which is on line 332 inside the main.c file. You can edit the calls to the soutpgm function and/or add your own, and this way send whatever you want to the client.
Reply 7 years ago
Ok gotcha. Il look more into the details.
Im interested in this thing u made and good work on spending the time to make these instructions.
With its current state i am able to just what u mentioned....
... Edit the default page with javascript or html and get something custom looking. I still gota learn javascript but il probavly just first edit the html page and get anything thats different than its defult page.
If i can do that with it in its current state il go ahead and build what you made.
Later when i get all that working il look into putting the web pages on external memory and see if the pages can be changed remotly without having to reprogram the thing.
Im still in the early stages of getting a good feel of pics but when looking a lityle in the future.. i see myself most likely trying this thing.
I wana see if with this thing u setup up i can store the data externally and historic data can be retreived remotly
Keep up the work its greatly appreciated.
7 years ago
This is amazing!
It works perfectly with a PIC18LF2550 and custom ENC28J60 development board, now, i'm trying to send JSONP packages to it, for Cross-domain requests, with the same basic program i send the "cmd" value as a response to the HTTP request, which is:
"http ://192.168.0.114/?callback=Cmd&q=do="6wfF5G2kno"+key="7rJ7HtbiVb"&format=json",
but it shows:
"GET /?callback=Cmd"
as cmd value
Any advice? Thank you!.
Reply 7 years ago
Hi, as I also mentioned on the last step of the instructable I'm not the original author of the web server code. I just made some small modifications to it in order to add support for the PIC18LF4553 microcontroller, which is the one I'm using on my board. I can help you with any hardware issue you might have regarding the board itself, but about the code I think it should be better to ask the original author directly on Microchip's forum.
But, I'll try to give you some pointers anyway. The HTTP request handling is happening in the main.c file, inside the handleHTTP callback function (line 332). On the third line of the function the HTTP request data (including the headers) is being read and dumped inside the cmd variable as a string. In case this is not a GET request no code is executed and the program returns immediately. If it is a GET request the PIC sends a response with some simple HTML code that includes the register values to the client.
No further parsing of the HTTP request is done, it only checks if the request starts with the characters "GET " and if it does it sends the response, otherwise it does nothing. Basically, you have to write your own code inside the handleHTTP function in order to parse the HTTP request and send the appropriate response to the client.
It doesn't know how to grab the arguments you are passing to it, you need to parse the string in the cmd variable to extract them and then you can do anything you want with them. I hope that helps.
Reply 7 years ago
Thanks for your answer!
I know I should have asked in the forum, and I did, but for some reason is not shown in the thread properly, I do not know why, I did it twice and is shown as a response (apart) or as a new post, I guess I'm doing something wrong.
Regarding the code, in the cmd variable request is saved, the problem is not to identify the data, but the cmd variable is limited in some way to 18 characters, I tried to change the types of associated variables, but should go changing more variables and the more variables changed, more errors. :\
Reply 7 years ago
The cmd variable just contains a pointer to gBuffers[ crec->buffer ].data. gBuffers is declared on line 51 of main.c and it is a type of Tbuffer struct. The declaration of Tbuffer is just above and as you can see the data field has a length of kBUFFERLEN. KBUFFERLEN is defined just above and its default size is 20. To have the ability to receive an HTTP request larger than 19 characters (the last character is always '\0') you will have to increase the size of kBUFFERLEN.
Of course, you will also have to take into account the amount of RAM memory your microcontroller has available. When you compile the code, MPLabX will tell how much of the RAM is in use. PIC18LF2550 has a total of just 2048 bytes of RAM, same situation with PIC18LF4553 which is the one I use on the board. Reducing the amount of buffers by modifying the value of kMAXBUFFERS will allow you to have a much larger length for the data field of the buffer.
In embedded systems where you have a very small amount of RAM available when writing a server in order to have the ability of receiving packages of any size and parse them, the only way is to read some amount of data, parse it, clear the buffer and repeat the same process. Unfortunately, this complicates a lot the application design and your code, but if the maximum size of the buffer you can have doesn't cover all the cases in your particular application there is really no other way. If your application is very complex you should consider going for a 32 bit PIC as they usually have much more RAM available. This of course means more complicated hardware design and larger hardware cost, the best solution depends on your particular application.
Reply 7 years ago
By the way, I got an email notification about the post you made on the thread on the Microchip's forum, but when I tried to reply you I couldn't because for some reason your post didn't seem to appear on the thread at all. And in fact it still doesn't, maybe it's a bug I don't know. Anyway, if you need to ask me anything else make sure to do it here on Instructables.
7 years ago
Nice work. I tried with PIC18F2550. Worked great first time. But then onward pinging times out. Kindly help. I reverted back to your program with the necessary changes as instructed by you, still wouldn't work. At times it pings once/twice out of four tries. Kindly help.
Reply 7 years ago
I have tested the code both with a PIC18F4553 and a PIC18F2550 and I didn't have any issues at all. If you used the exact same code I uploaded on the last step and you have that issue, the only thing I could suspect is that you have a hardware issue.
From the description of your problem the first think I would suspect would be some kind of power issue. So the very first thing to do is to measure the input voltage before and after the voltage regulator using a multimeter. Also, don't power the circuit with a 9V battery, it might work at first if the battery is brand new but after a short period of time the battery will die. As I mentioned on this instructable the ENC28J60 is very power hungry and it won't take long to drain your battery.
If you don't manage to find any power issues, the next thing you should do it to verify that there is a 25Mhz sine signal across the oscillator pins of the ENC28J60. As for the PIC18F2550 if you didn't change the fuses by default it uses its internal oscillator, so don't worry about that. Unfortunately, the only way to test this is by using an oscilloscope that has at least 25Mhz bandwidth.
Another thing you also need to make sure is to put an 100nF ceramic decoupling capacitor across every power pin pair of every IC, not just one 100nF for the whole PCB, you need 7 in total. Decoupling capacitors like these are used to filter noise from the power rails and they need to be as close to the power pins of the ICs as possible and they must be ceramic.
Lastly, make sure that the resistor values of the ENC28J60 (with only exception the 10K resistor on the reset pin) are as close to the value I used on the schematic as possible, their values are critical.
Reply 7 years ago
Sorry I visited your site after a long time. The problem was with our network, which was later sorted out. Thanks for your suggestions nevertheless. It might be of help later sometimes.