The Netduino forums have been replaced by new forums at community.wildernesslabs.co.
This site has been preserved for archival purposes only
and the ability to make new accounts or posts has been turned off.
Thanks to the efforts of .:oomlout:. and their Netduino Experimentation Kit, and our community member ItsDan on the Netduino Wiki, I was able to get the 74HC595 Shift Register example to work on my Netduino Go.
There were a couple of hurdles that made this a little more involved than adding references to the Netduino Go, the Shield Base and it's digital pins. More specifically it has to do with the way the current Shield Base realease and .NETMF 4.2 QFE1 are creating dependent objects out of order when trying to create them at the static class level. A quick solution is to pull those objects locally into the Main method however we lose global access to them. This is problematic for this example where in several of the methods found in this project require global access to those objects. A simple way to get around this problem was to pass the clock, data, and latch objects as arguments in the updateLEDs and changeLED methods. This isn't the prettiest solution but it works. Any other suggestions would be greatly welcomed. Hopefully the static declarations will be fixed in a future update.
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoGo;
using NetduinoGo;
namespace NetduinoGo_ShieldBaseShiftRegister
{
public class Program
{
static ShieldBase shieldBase = new ShieldBase(GoSockets.Socket5);
//As of .NetMF 4.2 QFE1 we cannot create these as static objects without throwing an error.
//static OutputPort data = new OutputPort(shieldBase.Pins.GPIO_PIN_D2, false); //Set pin 2 as an output and our data line
//static OutputPort clock = new OutputPort(shieldBase.Pins.GPIO_PIN_D3, false); //Set pin 3 as an output and our clock line
//static OutputPort latch = new OutputPort(shieldBase.Pins.GPIO_PIN_D4, false); //Set pin 4 as an output and our latch line
public static void Main()
{
OutputPort data = new OutputPort(shieldBase.Pins.GPIO_PIN_D2, false); //Set pin 2 as an output and our data line
OutputPort clock = new OutputPort(shieldBase.Pins.GPIO_PIN_D3, false); //Set pin 3 as an output and our clock line
OutputPort latch = new OutputPort(shieldBase.Pins.GPIO_PIN_D4, false); //Set pin 4 as an output and our latch line
int delayTime = 100; //the number of milliseconds to delay between LED updates
while (true)
{
for (int i = 0; i < 256; i++)
{
updateLEDs(i, data, clock, latch); //display the variable i on the LEDs in binary form
Thread.Sleep(delayTime); //wait delayTime milliseconds
}
//Uncomment this code, and comment out the previous for loop to cause the lights to light up one after another and then off
//for (int i = 0; i < 8; i++)
//{
// changeLED(i, true, data, clock, latch);
// Thread.Sleep(delayTime);
//}
//for (int i = 0; i < 8; i++)
//{
// changeLED(i, false, data, clock, latch);
// Thread.Sleep(delayTime);
//}
}
}
/// <summary>
/// sends the LED states set in value to the 74HC595 sequence
/// </summary>
/// <param name="value">the 8 bit number to be displayed in binary on the LEDs</param>
/// <param name="data">The OutputPort data </param>
/// <param name="clock">The OutputPort clock </param>
/// <param name="latch">The OutputPort latch </param>
static void updateLEDs(int value, OutputPort data, OutputPort clock, OutputPort latch)
{
latch.Write(false); //Pulls the chips latch low
for (int i = 0; i < 8; i++) //Will repeat 8 times (once for each bit)
{
int bit = value & 0x80; //We use a "bitmask" to select only the eighth
//bit in our number (the one we are addressing this time through
value = value << 1; //we move our number up one bit value so next time bit 7 will be
//bit 8 and we will do our math on it
if (bit == 128)
{
data.Write(true); //if bit 8 is set then set our data pin high
}
else
{
data.Write(false); //if bit 8 is unset then set the data pin low
}
clock.Write(true); //the next three lines pulse the clock pin
Thread.Sleep(1);
clock.Write(false);
}
latch.Write(true); //pulls the latch high shifting our data into being displayed
}
//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
static int[] bits = { 1, 2, 4, 8, 16, 32, 64, 128 };
static int[] masks = { 254, 253, 251, 247, 239, 223, 191, 127 };
static int ledState = 0;
///<summary>
/// changeLED(int led, int state) - changes an individual LED
/// <param name="led">the LED we are addressing</param>
/// <param name="state">whether that LED is to be on or off</param>
/// <param name="data">The OutputPort data </param>
/// <param name="clock">The OutputPort clock </param>
/// <param name="latch">The OutputPort latch </param>
///</summary>
public static void changeLED(int led, bool state, OutputPort data, OutputPort clock, OutputPort latch)
{
ledState = ledState & masks[led]; //clears ledState of the bit we are addressing
if (state) { ledState = ledState | bits[led]; } //if the bit is on we will add it to ledState
updateLEDs(ledState, data, clock, latch); //send the new LED state to the shift register
}
}
}
I handled the static initialization issue by by declaring the static objects at the class level but not initializing them. Thin my first lines in my main initialize them all.
public class program
{
static ShieldBase shieldBase = new ShieldBase(GoSockets.Socket5);
static OutputPort data;
static OutputPort clock;
static OutputPort latch;
public static void Main()
{
shieldBase = new ShieldBase(GoSockets.Socket5);
data = new OutputPort(shieldBase.Pins.GPIO_PIN_D2, false); //Set pin 2 as an output and our data line
clock = new OutputPort(shieldBase.Pins.GPIO_PIN_D3, false); //Set pin 3 as an output and our clock line
latch = new OutputPort(shieldBase.Pins.GPIO_PIN_D4, false); //Set pin 4 as an output and our latch line
}
}
The reason you're having problems is that .net doesn't guarantee the initialization order of static fields in a class. If you need them initialized in a particular way (eg they depend on each other), you have to write a static constructor for the class. This is just a method that has the same name as the class, just like a regular constructor, but has the 'static' qualifier in front of it. This static constructor will be called sometime between the module being loaded and the first time the class is used.
public class program
{
static ShieldBase shieldBase;
static OutputPort data;
static OutputPort clock;
static OutputPort latch;
static program()
{
shieldBase = new ShieldBase(GoSockets.Socket5);
data = new OutputPort(shieldBase.Pins.GPIO_PIN_D2, false); //Set pin 2 as an output and our data line
clock = new OutputPort(shieldBase.Pins.GPIO_PIN_D3, false); //Set pin 3 as an output and our clock line
latch = new OutputPort(shieldBase.Pins.GPIO_PIN_D4, false); //Set pin 4 as an output and our latch line
}
public static void Main()
{
// everything is already initialized when you enter this function
}
}
Very cool, Gutworks. Glad to see more and more samples running on Shield Base.
If you have a video, please let us know...we'd be happy to Tweet and help show it off for you.
BTW, Fabian--thanks for the notes on static constructors and initialization order. That is one of those behaviors in .NET (which is even more subtle in NETMF) that is good to understand.
Chris
BlackLamb and Fabien, thank you so much for the perfect explanations and code samples. That is awesome and the exact sort of thing I was wishing to see by posting this. I will post an update to the code later today once I get back to my office.
Chris, I would post a video if my web camera wasn't 10+ years old. I think my daughter's barbie cam has a better image. Hmmm, maybe...nevermind
The static constructor was new to me I'm going to switch all my programs to using that instead now. I like the idea of it being cleaner and separate from main.
The reason you're having problems is that .net doesn't guarantee the initialization order of static fields in a class. If you need them initialized in a particular way (eg they depend on each other), you have to write a static constructor for the class. This is just a method that has the same name as the class, just like a regular constructor, but has the 'static' qualifier in front of it. This static constructor will be called sometime between the module being loaded and the first time the class is used.
public class program
{
static ShieldBase shieldBase;
static OutputPort data;
static OutputPort clock;
static OutputPort latch;
static program()
{
shieldBase = new ShieldBase(GoSockets.Socket5);
data = new OutputPort(shieldBase.Pins.GPIO_PIN_D2, false); //Set pin 2 as an output and our data line
clock = new OutputPort(shieldBase.Pins.GPIO_PIN_D3, false); //Set pin 3 as an output and our clock line
latch = new OutputPort(shieldBase.Pins.GPIO_PIN_D4, false); //Set pin 4 as an output and our latch line
}
public static void Main()
{
// everything is already initialized when you enter this function
}
}
Hi Fabian,
I had a chance to try the example you have above and I am now getting the error:
An unhandled exception of type 'System.Exception' occurred in NetduinoGo.ShieldBase.dll
Any ideas what I may be doing wrong? I have also attached a screenshot of the error.
It is possible that the initialization is still a problem when it is in the static constructor. I'm betting it is being done before something in the NetduinoGO initialization has completed.
It may not be safe to call into any of the NetduinoGO runtime code until Man is called. Just a guess.
-Eric
Hi,
the static contructor is a solution but I prefer a diffrent approach. My main program always looks like this:
using System.Threading;
namespace Netduino.Extender
{
public class Program
{
private static ImportantController _ImportantController;
public static void Main()
{
_ImportantController = new ImportantController();
Thread.Sleep(Timeout.Infinite);
}
}
}
Now I'm done with all the static stuff. The real party starts in my "ImportantController" (in real life the class name is not "ImportantController" of course).
using ...;
namespace Netduino.Extender.Heating
{
public class ImportantController
{
private readonly Lcd _Lcd;
private readonly SwitchModule _SwitchModule;
public ImportantController()
{
ILcdTransferProvider lcdTransportProvider = new Shifter74Hc595LcdTransferProvider(...);
_Lcd = new Lcd(lcdTransportProvider, ...);
_SwitchModule = new SwitchModule(...);
_SwitchModule.ItemChanged += SwitchModuleItemChanged;
}
...
void SwitchModuleItemChanged()
{
_Lcd.Write();
...
}
}
}
In my opinion the advantage is that only one class (the "ImportantController") must be declared static. Inside this class you can decide if the objects should be instanciated more than once or if it should be static for some reason. Also if you want to refactor your code you don't have to remove all "static" modifiers. For example if you build a class with a field to count something and you need this class a second time the field shouldn't be static because your counter would count the "somethings" of all your instances.
Maybe the code in my example is a little bit desktop style programming but I don't know a reason against my approach. If there is one I would be happy to know it.
Sorry for the short and confused explanation but I've cought a cold and my brain is alread in bed sleeping :-)
Static objects are always tricky, especially if you don't own all the modules as is the case here. What is probably happening is that your static initializer is being called before those of the other classes you're calling. I think the best fix is to use gbreder's solution.
I finally had a breakthrough with all of your suggestions and ItsDan's suggestion of the Singleton method. I'm not sure if I'm following the exact guidelines but it seems to work. Any input would be greatly welcomed.
I would also add that these methodologies can temporarily inhibit the beginner folk, like myself, from using some of the basic Netduino samples. Hopefully this process can and will be updated in future revisions, and perhaps this code can help others.
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware.NetduinoGo;
using NetduinoGo;
namespace NetduinoGo_ShieldBaseShiftRegisterVer2
{
public class Program
{
static ShieldBaseController shieldBaseController;
public static void Main()
{
shieldBaseController = ShieldBaseController.GetInstance();
var data = shieldBaseController.Data;
int delayTime = 100; //the number of milliseconds to delay between LED updates
while (true)
{
for (int i = 0; i < 256; i++)
{
updateLEDs(i); //display the variable i on the LEDs in binary form
Thread.Sleep(delayTime); //wait delayTime milliseconds
}
//Uncomment this code, and comment out the previous for loop to cause the lights to light up one after another and then off
//for (int i = 0; i < 8; i++)
//{
// changeLED(i, true);
// Thread.Sleep(delayTime);
//}
//for (int i = 0; i < 8; i++)
//{
// changeLED(i, false, data, clock, latch);
// Thread.Sleep(delayTime);
//}
}
}
/// <summary>
/// sends the LED states set in value to the 74HC595 sequence
/// </summary>
/// <param name="value">the 8 bit number to be displayed in binary on the LEDs</param>
/// <param name="data">The OutputPort data </param>
/// <param name="clock">The OutputPort clock </param>
/// <param name="latch">The OutputPort latch </param>
static void updateLEDs(int value)
{
shieldBaseController.Latch.Write(false); //Pulls the chips latch low
for (int i = 0; i < 8; i++) //Will repeat 8 times (once for each bit)
{
int bit = value & 0x80; //We use a "bitmask" to select only the eighth
//bit in our number (the one we are addressing this time through
value = value << 1; //we move our number up one bit value so next time bit 7 will be
//bit 8 and we will do our math on it
if (bit == 128)
{
shieldBaseController.Data.Write(true); //if bit 8 is set then set our data pin high
}
else
{
shieldBaseController.Data.Write(false); //if bit 8 is unset then set the data pin low
}
shieldBaseController.Clock.Write(true); //the next three lines pulse the clock pin
Thread.Sleep(1);
shieldBaseController.Clock.Write(false);
}
shieldBaseController.Latch.Write(true); //pulls the latch high shifting our data into being displayed
}
//These are used in the bitwise math that we use to change individual LEDs
//For more details http://en.wikipedia.org/wiki/Bitwise_operation
static int[] bits = { 1, 2, 4, 8, 16, 32, 64, 128 };
static int[] masks = { 254, 253, 251, 247, 239, 223, 191, 127 };
static int ledState = 0;
///<summary>
/// changeLED(int led, int state) - changes an individual LED
/// <param name="led">the LED we are addressing</param>
/// <param name="state">whether that LED is to be on or off</param>
/// <param name="data">The OutputPort data </param>
/// <param name="clock">The OutputPort clock </param>
/// <param name="latch">The OutputPort latch </param>
///</summary>
public static void changeLED(int led, bool state)
{
ledState = ledState & masks[led]; //clears ledState of the bit we are addressing
if (state) { ledState = ledState | bits[led]; } //if the bit is on we will add it to ledState
updateLEDs(ledState); //send the new LED state to the shift register
}
///<summary>
/// ShieldBaseController - a 'Singelton' class http://msdn.microsoft.com/en-us/library/ff650316.aspx
///</summary>
public class ShieldBaseController
{
private static ShieldBaseController instance;
private static object syncRoot = new Object();
private ShieldBase shieldBase;
private OutputPort data;
private OutputPort clock;
private OutputPort latch;
private ShieldBaseController()
{
shieldBase = new ShieldBase(GoSockets.Socket5);
data = new OutputPort(shieldBase.Pins.GPIO_PIN_D2, false); //Set pin 2 as an output and our data line
clock = new OutputPort(shieldBase.Pins.GPIO_PIN_D3, false); //Set pin 3 as an output and our clock line
latch = new OutputPort(shieldBase.Pins.GPIO_PIN_D4, false); //Set pin 4 as an output and our latch line
}
public static ShieldBaseController GetInstance()
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new ShieldBaseController();
}
}
return instance;
}
public OutputPort Data
{
get { return data; }
}
public OutputPort Latch
{
get { return latch; }
}
public OutputPort Clock
{
get { return clock; }
}
}
}
}
Hi Gutworks,
a singleton can work until you add your second shield base. If you will never ever do this you code is fine.
A singelton if often used if the following is true:
Your class can only be instantiated once, there may not be a second instance of the class (like I2C bus on the classic Neduino).
Your class will be used in multiple other classes in your code.
You have no idea which code will call your class when. And so you have no idea who has to call the contructor.
Without the singleton pattern you would have to build the instance yourself (call the contructor) and give it to every class which may need it. This can get very ugly...
The use of an normal contructor (as stated in my earlier post) would suffice because your program calls "GetInstanc" once, your singleton will be used in only one class and you know when to call the constructor.
It isn't my intention to be rude and I'm absolutly thrilled that you have coded a beautiful singleton pattern. But simpler may be better.
It isn't my intention to be rude and I'm absolutly thrilled that you have coded a beautiful singleton pattern. But simpler may be better.
Guido, if your intention was to be rude, then you really would have done a poor job We Canadians have much thicker skin than that. In fact you have been quite the opposite. These responses have been great and are really forcing me to stretch my current, albeit, rusty developer skills.
I tried to follow your example but failed to get my code to work. In trying to research and find solutions it lead me to the Singleton method, which I thought closely resembled your example. My noobness really shines through when I say I don't really know the major differences between the two examples. In my reading I had missed the point about the Singleton only being able to be instantiated once, even though I had tried to make it thread safe.
So this is where I admit defeat, and ask for more help. Is is possible to provide some specific examples on how to alter my existing code so that it conforms to best practices? Again, I really appreciate all the help thus far from everyone and it has been a fantastic learning experience. I won't tell you how long it's taken me to get to this point out of sheer embarrassment
Hi,
I'm happy to help. I've mode some major and some minor changes. All major changes are listed below. The whole result was zipped and attached. But be aware that my Netduino GO hasn't arrived yet. So the code is completely untested.
The "controller" isn't nested anymore. A nested type is only used if it is related to its parent in some way.
The method "UpdateLeds" was moved inside "ShieldBaseController" because it was accessing only OutputPorts from it.
All output ports are now private.
The statement "bits[led]" and its "bits" array was replaced by a bit shift operation "1 << led".
The "mask[led]" was also expressed as (inverted) bit shift "~(1<<led)". For example 1<<4 would result in 16 (or 0x10) and the "~" will invert every bit in the byte so you will get 0xEF or 239. Less manual calculations and less code results in less errors :-)
Some minor renaming and other unimportant stuff
There is still room for improvement. You could change your SPI bit bang mode to native SPI from the Netduino. I've attached a class for the 74HC595 from my classic Netduino as example. You can also provide the parameter "GoSockets.Socket5" for your "new ShieldBase()" through the constructor of the class.
I'm happy to help. I've mode some major and some minor changes.
Guido, this is perfect. The code runs perfectly with the Netduino Go Shield Base. I'm taking some time today to go over the code and study the changes so that I can implicitly understand them. This is exactly what I was looking for and needed. Previously I got so stuck into the existing code and it's framework and I didn't think about pulling the other methods inside of the controller and creating new classes. After managing web developers for a few years, I'm having to learn this stuff all over again after placing my own coding skills on a shelve for too long.
You would put the second shift register also on SPI1 and define a different latch pin (aka slave select / device select).
If it is a 74HC595 shifter you can use something like this:
public class Shifter74Hc595Extender
{
public Shifter74Hc595Extender(SPI.SPI_module spiBus, Cpu.Pin latchPin)
{
var spiConfig = new SPI.Configuration(
latchPin, //latchPin (aka SlaveSelect),
false, // active state
0, // setup time
0, // hold time
false, // clock idle state
true, // clock edge
1000, // clock rate
spiBus);
_Spi = new SPI(spiConfig);
}
public void WriteData(byte data)
{
_WriteBuf[0] = data;
_Spi.Write(_WriteBuf);
}
}