Gadgeteering sure can be frustrating

A couple of years ago I created internet connected thermal controllers using the old CANXtra. I had started with the PandaII, but even after getting web requests to work reasonably reliably discovered that there just wasn’t enough memory to do networking really reliably. Since then, I killed on CANXtra and another one lost networking. Since they aren’t available anymore, I decided perhaps it was time to update. I had already purchased several G120HDRs (the original one) and then for Black Friday got some Gadgeteer stuff (including Cerberus).

I was able to get my Cerberus talking to the N18 display and that was fun and better that the display on the CANXtra (with more pixels and colors and only a little more complexity). Flush with success, I was ready for more. I did a quick perusal of the APIs to make sure I would have everything that I would need. I use DS18B20 sensors for temperature measurement. Here I ran into my first challenge. I had a nice set of objects to provide a higher level abstraction so I figured it would be easy to get it working on 4.2. Not so, the new API is different and has no documentation and non of the examples showed talking to specific devices or doing an actual discovery. So with some experimentation I was able to talk to the devices and even figured out how to implement the CRC (the fact the Maxim spreadsheet has the bytes reversed didn’t help :slight_smile: ).

Now I had the ability to measure temperature and display it. That was cool.

Now for the Internet. I read the warnings on the internet FW and decided that perhaps MIP would be a better solution, since I don’t need a high data rate. The MIP page said it worked fine with Gadgeteer, just don’t hook it up on in the picture. I was able to get it to work fine when it was the only thing in the project. But, when I added the N18 display (which also uses SPI) things stopped working. It seems that the Cerberus uses the same SPI port for both socket 5 and 6. MIP uses MultiSPI to allow use with multiple devices on SPI, but that is not compatible with Gadgeteer. I figured that the processor should have more than one SPI port and sure enough it does. But, it seems that the firmware does not support using more than one port.

Is this really true? Is there only one SPI port available on Cerberus?

With that avenue blocked, I figured how hard can it be to make a real Gadgeteer module for MIP. Looking at the code, it appeared like it had a decent abstraction and it would be possible. So, I downloaded all the stuff to make a module. I then discovered that Gadgeteer version of SPI did not have the same methods for WriteRead(). In particular one was missing that MIP uses. Since I had the source for all of Gadgeteer, it seemed like I should be able to easily add the missing overload. Sure enough I was able to do that and it even compiled without errors.

But using it was another story. Every time that I added the specific dll that I had created to a new project it would use the official one. I finally got it to use the one I wanted by changing the assembly version (the one it said not to change). But that led to my next problem, when I added my new module to another project it wanted to use the original version and my new stuff wanted to use the new version and it was unable to resolve it.

So, has anyone tried changing core Gadgeteer code and gotten it to work?

@ Frogmore - You have a LOT more patience than I do :smiley: :smiley:

you can fudge more spi connections if you want. remember, Cerberus is like an Arduino, original, it has only a number of pin combinations to use without doing things a little trickiily

If you have not read this https://www.ghielectronics.com/docs/122/gadgeteer-driver-modification, take a look. If that does not help, keep supplying details and questions here !!!

removed the comma from your link above so it would work…
cheers,

Thanks for the links, I had found the doc earlier and it was somewhat helpful. In case anybody else wants to follow me down the rabbit hole, here is what I figured out. Since I needed a new overload method for part of the Gadgeteer Core (the Gadgeteer SPI class does not have all the overloads that are in NETMF Core), I had to get the source for Gadgeteer Core and SPI and add the projects in addition to the new module driver I was trying to create for the ENC28J60 MIP driver.

It was not easy, but I got everything to compile finally. Of course, when I deployed the solution it got an error about not being able to find the reference to the new method that I had created. Luckily, I had run into this type of issue before and figured out that was because it was not deploying the new assembly (since it thought it already had a perfectly good one on the device). I used MFDeploy to erase the deployment and then I was able to get my solution to work. I could now do an HTTP PUT.

I then added my N18 display to the project and while everything compiled fine, deployment was not so good. I got what seemed like a random error message about ChipSelectActive not being available/understood. Since I hadn’t changed anything with that and everything compiled fine it took me quit awhile to figure out that this was because the N18 was using the “official” version of Gadgeteer and that didn’t quite match what was actually deployed. The error message at deployment was totally unhelpful in figuring this out. So, the lesson I learned is, when you get strange errors at deployment, check the firmware and assemblies that are deployed (or present) match what the new code is expecting.

The solution was reasonably simple, I just needed to also add the N18 project to my solution and then everything was happy.

Since I was now able to use both the ENC28J60 and the N18 at the same time using the same SPI bus I was quite happy :clap: I even had about 40K Bytes of free memory.

So, with that working, I said, “what happens when the internet is not working well?” I removed the uplink cable on the network hub to simulate a broken connection to the internet with an active local connection. Since in Gadgeteer most things run in the same thread, I could tell that everything was stopped while the MIP stack was trying to make a connection that would never happen. When it timed out everything went back to normal.

But, after a couple of times of this, I got an out of memory exception. I traced this to the thread that was actually running Garbage Collection (every 10 s) and displaying the results. I believe it was probably caused by the Bitmap class allocating memory to render the text. This seemed strange to me, since I was using a static (pre-allocated) bitmap as the render surface.

I decided to solve that problem later and left the system running. It ran for several hours before it stopped working. Around this time, I decided that while I could probably figure this out too, I was probably never going to get a solution that would be really great, since there is a limited amount of memory in the Cerberus.

I was congratulating myself on the foresight to purchase G120HDR boards some months ago. After my experience with trying to get this solution working on the PandaII and Fez Connect, I was concerned that the Cerb family might have the same issue with limited memory (for network/HTTP connected applications).

After looking at the differences between the Cerberus and the G120HDR, I realized that my adventure of upgrading to NETMF 4.2 was not close to over, but just really beginning.

My first challenge was, do I go straight NETMF or use Gadgeteer? Since the N18 has Gadgeteer drivers and I had already created a “working” driver for the ENC28 (with MIP), I decided that was probably the easiest path (plus, I like the event/timer pattern that Gadgeteer enforces). Since I have a G120HDR, I needed to wire up sockets. The G120HDR is not a Gadgeteer board. The documentation for it is clear about that, but it does list a pin out for a SPI socket. The documentation for the Cobra II (which is a Gadgeteer board) doesn’t list the pin out for socket six (SPI socket) but it is in the schematic. I decided to go with the Cobra II specification, since it has definitions for SPI sockets, which I figured would be easier to use.

I was able to get the N18 working pretty easily. I noticed that it seemed much slower than on the Cerberus. Since the processor speed is 120MHz vs 168MHz this made some sense, plus the G120 has more memory so I figured its access time might be slower (which would impact NETMF significantly, since it is interpreted). I also then noticed that there was a lot more debug spew. It turns out that the G120 prints the extensive garbage collection, while the Cerberus does not. I’ll start a new thread for that issue.

Flush with success, I figured it would only take a few mins to get the ENC28 working (since it was working great on the Cerberus). Boy was I wrong. Everything compiled fine, but when I deployed and ran it, I got a system invalid operation exception when adding an event handler to and interrupt pin. This was in the enc28j60 module driver, inside MIP, inside my Gadgeteer MIP driver. This was code that worked perfectly well on the Cerberus. So, there are hardware differences, but surely the Cobra II would use an interrupt capable pin on the socket for the ENC. I found the little note that P0 and P2 ports are all interrupt capable, but it is easy to miss on the G120 data sheet. I tried using both P0_5 and P2_21. I then wrote a little program to run through all the pins and all of them were failing. I then searched for an example of an interrupt pin and I was able to find one that was close enough that I could modify it. It worked. It took me awhile, but I finally found the reason. The G120 does not support InterruptEdgeLevelLow. I think I finally found that documented somewhere. Since I didn’t write the ENC28 driver code, I didn’t know quite how it was using interrupts. So, I looked up the data sheet and saw that the interrupts are active low. I figured that InterruptEdgeLow would probably work. The documentation said that ClearInterrupt() should not be used, so I removed that from the code.

Now things seemed to be working, no compile errors and no deployment errors. Later, I looked more closely and saw that while the packets were being sent, the code did not believe it was getting a response. Time for WireShark. Of course, when I looked at it, it looked fine (and the debug messages indicated the same). But a little while later the issue became more clear. WireShark showed that while the packets were being sent to the server fine and the server was responding correctly, some of the time the ENC28 would not hear the response and ask for it again. The server retried a few times and then gave up. I tried a few things to make this better, but it became clear this was not going to be easy.

So, I said perhaps I should use the standard libraries. Because of timeout (lack of really) issues with NETMF 4.1 WebRequest, I had been using NETMF.Toolbox HTTPRequest (which I had to modify to allow me to add the necessary header and PUT instead of just POST). Unfortunately, it seems that code still hasn’t been updated. I figured that this was going to take some time and perhaps I should start with a clean project to make sure I really had the wiring correct on the ENC28. I looked, but I had a hard time finding code for Cobra II using Gadgeteer networking. Since the APIs didn’t look too hard, I wrote a simple program. It got deployment errors (oops needed to wipe the deployment so it would deploy the official code). Once I got everything deployed, I would get events for unplugging and plugging the cable, but it said networking was not started.

I spent a lot of time trying to debug this but did not have much luck. Finally I found the CodeShare entry for the network stress test project. It used yet different pins for the connection, so I modified them to match my actual connection. Finally, I was able to get a network up and running. I then compared the setup code in the GHI ENC28 driver with what PhilM used and saw a big difference in SPI speed, but that didn’t seem to make any difference. I thought maybe that there was some weird interaction with the N18, like on the Cerberus (where it is impossible to use the N18 and the ENC28). But, this did not help. I finally gave up, because I was unable to get the ENC28 to work using the Gadgeteer library.

So, the question for today is has anyone gotten the ENC28 to work in a Gadgeteer project using the Gadgeter driver? I was able to get it to work by NOT adding the ENC28 to the Gadgeteer surface and using the base NETMF driver.

Please don’t get me wrong. Stuff is the way it is, but it sure is hard figuring out what that way is. The G120 page says that the ENC28 is supported, but it is not a Gadgeteer board. The Cobra II page shows using ENC28 with straight NETMF. This makes some sense since the ENC28 isn’t in a socket, but it means that the Gadgeteer networking classes can’t be used. The Cobra II (Eco) page says the ENC28 can be used to add networking, but does not give any examples (that I could find). The other thing is that the Gadgeteer driver for the ENC28 appears to require exclusive access to the SPI bus. While this probably makes the driver much easier, it does make it harder to have multiple SPI devices, since socket 6 uses the same SPI bus, so one would need to get the adapter and then use socket 9 to have two SPI devices. Since the N18 is significantly cheaper and smaller than the other displays, it seems likely to want to have both the N18 and ENC28.

Sorry for the long post, but I have spent many days getting to this point and want to help make things better, but I don’t really know the best way to do that. The Wiki is no more and CodeShare seems hard to navigate well and the search functions on the forum didn’t work well for me. What did work for me was to use bing and the site: option. It usually got me a reasonable number of hits that usually provided me with something to try. I usually got just enough of a payoff to continue working. At this point, I am going to switch to straight NETMF (and the G120, not Cerberus), since it seems that Gadgeteer is not going to make things easier (and Cerberus does not have enough RAM to do this project for long).

I’ll update my network logging class to work with the base NETMF networking, but I will add the extras I have to get it more resistant to bad connections so my code can run for (at least) weeks if not months without needing a reboot (my current NETMF 4.1 CANXtra code has run for months without hanging). I was really hoping that Gadgeteer would improve NETMF. While I can see a lot of promise, the reality is that it only helps with the wiring and then only if the thing you want to use has a Gadgeteer socket and your mainboard has enough of the right type with the right support.

I was also hoping that the STM/Cerb family would have enough memory to reliably do the job for Internet connected devices, but it seems the current software has too large of a memory footprint to do this reliably.

With time I expect the software side of things could get a lot better and it really would be simple to do what my project does (measure temperature, control heaters, display results locally, report results to an Internet logging site for aggregation and long distance viewing/analysis).