Learning About Arduino and WIZ810MJ
(See also: Netduino)
Get the code
Ensure you have svn installed and then run this command:
$ svn checkout http://svn.mlalonde.net/cral/branches/follower
Then take a look at the README file. (Thanks Hyphenex :-) )
(See "Progress" below for progress I've made...)
- 2mm header pins
- (Unverified) Pins required for SPI: PWR, GND, CLK, MOSI, MISO, CS and (INT?) SPI_EN RESET
- "The W5100 operates as SPI Slave device and supports the most common modes - SPI Mode 0 and 3." (Datasheet)
- "In SPI Mode, W5100 operates in 'unit of 32-bit stream'. The unit of 32-bit stream is composed of 1 byte OP-Code Field, 2 bytes Address Field and 1 byte data Field." (Datasheet)
- "When you develop an application using W5100, you can use the interrupt-driven mode or polled mode." (Porting guide)
- W5100 Driver Source -- Note: This seems to be a complete Atmega128 driver. Although you'll need to grab the delay.c and delay.h files from this Application Note - DNS
- IDC Miniature Ribbon Sockets (2mm pitch) -- a local (for me) stockist for what I think are suitable connectors (for a cable to a breadboard) to the module. Possible PCB connector solution: CNHFND20 - 20 WAY 2mm FEMALE HEADER DIP DUAL ROW
- "Universally administered and locally administered addresses are distinguished by setting the second least significant bit of the most significant byte of the address. If the bit is 0, the address is universally administered. If it is 1, the address is locally administered. The bit is 0 in all OUIs. For example, 02-00-00-00-00-01. The most significant byte is 02h. The binary is 00000010 and the second least significant bit is 1. Therefore, it is a locally administered address." -- http://en.wikipedia.org/wiki/MAC_address Use this when setting the MAC address. (trivia)
- /INT not used for SPI -- assuming this is accurate it seems you can't have interrupt driven SPI.
- W5100E01-AVR WIZnet W5100 chip evaluation board -- includes sample Atmega128 code for Loopback, Webserver and Ping.
- Hardware note: "The 3.3V supply is only good for 50mA, which is 'not much.'" -- The same thread mentions the 3.3V supply comes from the FTDI chip.
- WIZ810 in a SPI environment -- Apparently the module doesn't play well with others on the SPI bus. (Confirmed by WIZnet PR Rep, a solution is
apparently forthcomingnow available or see W5100/WIZ810MJ SPI fix.)
- "Interrupt is not related to the interface mode. In any mode (SPI or BUS), you can use the interrupt signal."
Circuit Cellar Design Competition
- Write FLASH memory on ATmega128 Microcontroller architectures Bootloader Support Utilities (It seems SPM instructions have to be in the bootloader section—but the application can jump into the bootloader section (and then return?))
- "port can be specified as net:host:port. In this case, instead of trying to open a local device, a TCP network connection to (TCP) port on host is established."
Progress (chronological order)
- Connected the 3.3V from the Arduino to pin 24 (VCC) on the WIZ module and Gnd from the Arduino to pin 23 (GND) on the WIZ module. Initially the orange LED glowed but after a power disconnection (mis-wiring?) it ceased to glow. But after I plugged in a cable from the module to an Ethernet switch both the green link LED and orange LED glowed.
- The connector on the module is 2mm pitch—I used 2mm jumpers from a scrapped floppy drive and breadboard jumper wire to connect to the Arduino.
- When using no connections other than power, connecting an Ethernet cable to the module appears not to generate any traffic tethereal could detect.
- Connected cable to /RESET pin. By doing a "manual" reset (/RESET switched from HIGH to LOW to HIGH again by the sophisticated "move-wire" method) I seem to get both orange (ready?) and green (link) LEDs.
- I can read registers!! By connecting /RESET, SCLK, MOSI, MISO and SS (along with VCC & GND) I was able to successfully read register values. (SPI_EN was left unconnected.)
- Writing registers, configuration for networking and responding to pings work! Plan to upload code soon. Wireshark capture:
- Working on porting the W5100 driver source to work with Arduino. Have it compiled but need to change the pins used.
- I've also had word that xSmurf has successfully used the above code with a WIZ810MJ module on his PCB design to respond to a ping.
- I have ported enough of the W5100 driver source code (actually ended up using the code in the DNS appnote) to be able to use it to configure the network, create a socket, listen on a socket and detect a closed socket. Unfortunately I haven't managed to send/receive on a socket successfully yet. I can connect to the arduino using telnet but no data seems to be transferred. With some attempt to reduce the size of the library I have gotten the library+demo to under 10KB.
- A quick look with WireShark indicates DUP ACKs are being sent (from the module?) but I'm not sure if that's an/the issue.
- Code: Initial W5100 Arduino/Atmega168 driver port library with test code (Consider my changes released under LGPL.) (Note: Due to time constraints I don't have my edits to the driver source in this bundle apart from the headers, sorry! (I really released early. :-) ) After uploading it to your Arduino with WIZ810MJ attached telnet to the Arduino's IP, port 5555. The only thing you'll be able to do is disconnect, but the serial monitor should note it happened.
- I've discovered at least two issues that contributed to the lack of data transfer after the connection was established. A fairly major clue was I could access the module's receive buffer directly and read the data but not if I used the driver routines. Issue 1)--Even though it may only use the defaults you need to call sysinit otherwise the MCU-side buffer information isn't initialised and it uses bogus values to access the buffers. Issue 2) Thanks to some lovely copy-and-pase coding in the drivers, the "read/write a register" and "read/write a buffer" routines contain essentially exactly the same (IMO) poor SPI code that initialises and bit-twiddles on every call. When I changed the register handling code I neglected to notice the buffer handling code did exactly the same thing! So, much time was spent trying to fix the wrong thing... (The non-Windows AVR environment could stand some better debugging tools...)
- Unfortunately my receiving still isn't working correctly if I use the driver routine—the first character is ok but the rest is garbage. But the fact I can read the data from the module memory directly suggests it's just an issue with the driver—and at this time of morning it could easily be something simple. A work in progress...
- Binary: No code sorry, for the moment here's a binary you should be able to upload via the Arduino bootloader: semi-working echo server-type thing. Everything is hard-coded in this so it'll only work if you do: "telnet 192.168.2.105 5555" and then change your telnet client to use character mode if need be. (I realise this isn't an overly helpful state to provide things in but, hey, it's late/early.) You should be greeted by something like this:
bash-2.05a$ telnet 192.168.2.105 5555 Trying 192.168.2.105... Connected to 192.168.2.105. Escape character is '^]'. w00t>
- Code: Revised initial W5100 Arduino/Atmega168 driver port library with test code (Consider my changes released under LGPL.) Okay, so I couldn't leave you with only a binary. :-) Still sans driver source, sorry.
- A few minutes after I packed up I realised what the problem with receiving probably was. And sure enough, it was a quick fix. (Moral of the story: copying & pasting code to fix copy-and-pasted code will probably lead to errors.) Also, a SPI debugging hint (since it's the second time I've noticed it): If you can only received the first byte of an SPI transaction correctly it's possibly because you haven't completed the transaction properly, e.g. the chip select might have been left low.
- I haven't released a complete working archive but if you use the library files from here and the code from the previous release you should end up with a fully working echo server.
- Code: Current W5100 Arduino/Atmega168 driver port library with working echo server demo code The library binaries and echo server demo code in one archive release.
- Seems like
you canyou can't leave /RESET disconnected and just use the software reset. (Although the reset didn't seem to clear registers as I expected.) The good thing about not needing /RESET is we should be ablewould have been to connect with just a single header. (Hmmm, this doesn't work today, so seems like we do need to do something with /RESET, so no single connector cable...)
- Connecting a 2mm IDC ribbon socket connector to J1 doesn't seem to be entirely straight-forward because AFAICT the pin numbering doesn't match up to the standard order. i.e. J1:P1 --> Cable Wire 2, J1:P2 --> Cable Wire 1 and so on. It's not all bad though as it means the cable splits usefully into 3 contiguous groups: Group 1 (Power+Unused:Pins 2(/INT),1(Vcc),4,3,6,5,8(Gnd)), Group 2 (SPI:Pins 7,10,9,12) and Group 3 (Unused:Pins (the rest)).
- Okay, so I have things connected with a ribbon cable and one jumper (for /RESET)--not as tidy as I would have liked, but still tidier than it was before.
- I'm now putting the original driver into SVN and trying to do a "tidy" port now I know a little more how things are working. You can follow wiz810mj / w5100 SPI-only driver port for Arduino / Atmega168 progress here.
- If you are compiling with Os (optimise for reduced size) and you get the following message try compiling with fno-inline-functions as well: (Note: this will have a negative impact on size.)
delay.s: Assembler messages: delay.s:2249: Error: symbol `L_US' is already defined delay.s:2347: Error: symbol `L_US' is already defined
- A couple of notes for me:
Demo with old-style library: 9986 bytes Demo with in-progress (non-functional) library: 8442 (Actually, not SPI...) Demo with in-progress (untested) library: 9762 (SPI) Demo with in-progress (Arduino compiled SPI) library: 9782 avr-gcc -mmcu=atmega168 -Wall -Os -fsigned-char -combine -c socket.c w5100.c -o wiz810mj.o avr-strip --strip-debug --strip-unneeded wiz810mj.o # What did I use last time?
- The full ported driver code is now in the wiz810mj / w5100 SPI-only driver port for Arduino / Atmega168 SVN repository. You should be able to check out the source files and copy them into a directory in your Arduino library folder and have it compile. The very rough demo is also in the repo—not yet fully tidied up.
- I got bored tidying up the demo code so I spent some time to get the Arduino working as a web server. It works! (For certain limited values of "works". :-) ) The first successful HTML page served up had an attractive red background and the important content "foo!" on it.
- For a more interactive feel I hooked up an LED (and ever-present current-limiting resistor) to Arduino digital pin 2. After I added a rough and limited character-based request/URL parsing "state-machine" the Arduino can now respond to URLs of the form:
- In response to the above URL the LED will flash in the requested pattern (0=off, 1=on, with a 0.1s delay between state changes) and will return a page with the background colour dependent on the last digit of the URL (red=on,green=off). (The code for this demo is 'WizDemo2' in the 'demo' directory in the repository.)
- . December .
- I've just discovered a rather serious flaw in my understanding of how the socket part of the driver worked. I thought a call to socket return the socket number to the first parameter, but it turns out I was supposed to supply the socket number. Whoops! Oddly enough it took nearly two months before this mistake caused something to stop working (seemingly)--it seems nonsensical values didn't always cause failure. TODO: Investigate this further?
- I've just had two echo servers running on two different ports at the same time—thanks to a state machine based EchoServer class. Not yet committed the code.
- Now it's four simultaneous 'EchoServer' connections supported. I've also committed the code.
- I just successfully got the Arduino to connect to IRC and send a message:
__follower_ib (6:39:03AM): __follower_ib crosses his thumbs.... __follower_ib (6:39:11AM): wait for it... irc (6:39:34AM): Arduino has joined arduino arduino (6:39:35AM): Hello, world! buZz (6:39:41AM): hehe __follower_ib (6:39:46AM): wooo!!!!! __follower_ib (6:39:54AM): it actually worked! buZz (6:40:03AM): \o/ buZz (6:40:06AM): cool buZz (6:40:09AM): irc from arduino?
- . January .
- Programmed a bare bones board over ethernet.
- Prototype "Netduino" shield:
Some experiments in designing an API for a library: (Aiming to match Arduino HardwareSerial.cpp functionality..?)
Network.setup(ip,mask,gateway,mac); // Hmmm, how about 'NetworkInterface' class ===> 'Network' standard object. .setIP(ip) // default local-link? 169.254... http://www.ietf.org/rfc/rfc3927.txt .setMask(mask) // default 255.255....? .setGateway(gw) // default 0.0.0.0 .setMAC(mac) // default .... Network(ip,mask,gateway,mac); Network.listen(port); // Return 'Socket'? Clashes with library? 'Connection' instead? (Implies connected though?) 'ServerConnection'/'ClientConnection'? Which is which? Socket // + SocketStream? .connected() // Or .isConnected() .available() .read() // .readMatch(...)? or skipBytes(...)? .readUpTo(...)? .write() CommandServer EchoServer WebServer .requestAvailable() // Or just .available() .readRequest() // Or just .read()