3

I've got something pretty noddy to cross-fade the colour of an RGB led and I'm having problems getting the desired values.

I've stripped this example down to a bare minimum but Start, End and Steps will all be variable...

This should linearly increment R (UInt) from 0 to 255 in 100 steps. I'm not too worried about precision here so I don't really care if it rounds properly or just does a Floor/Ceiling

    Dim Start As UInteger = 0
    Dim [End] As UInteger = 255
    Dim Steps = 100

    For x = 1 To Steps
        Dim Temp = ([End] - Start) / Steps * x + Start
        Dim R = CUInt(Temp)

        Debug.Print(x.ToString & ": Temp: " & Temp.ToString & ", R:" & R.ToString)
        LedR.SetPulse(255, R)
        Threading.Thread.Sleep(20)
    Next

This Outputs:

1: Temp: 2.5500, R:196608
2: Temp: 5.1000, R:327680
3: Temp: 7.6500, R:524288
4: Temp: 10.2000, R:655360
5: Temp: 12.7499, R:851968
...
95: Temp: 242.2488, R:15859712
96: Temp: 244.7988, R:16056320
97: Temp: 247.3488, R:16187392
98: Temp: 249.8988, R:16384000
99: Temp: 252.4488, R:16515072
100: Temp: 254.9988, R:16711680

As you can see, the Temp variable is pretty-much correct, allowing for some slight imprecision but I can't see what the correlation is with R.

It's possible that CUint is simply reading the bits for Temp and treating the Double as a UInt - but if so, how do I get it to convert it correctly?

(Incidentally, this is running on a netduino), .Net Micro Framework 4.2

Edit: Tests requested below:

    Dim Test As Integer = 2
    Debug.Print(Test.ToString)
    Debug.Print(CInt(Test).ToString)
    Debug.Print(CUInt(Test).ToString)

    2
    2
    2

    Dim Test As Double = 2.5
    Debug.Print(Test.ToString)
    Debug.Print(CInt(Test).ToString)
    Debug.Print(CUInt(Test).ToString)

    2.5000
    131072
    131072

Using the following code...

    For x = 0 To Steps
        Dim Temp As Long = ([End] - Start) \ Steps * x + Start
        Dim R = CType(Temp, UInteger)

        Debug.Print(x.ToString & ": Temp: " & Temp.ToString & ", R:" & R.ToString)
        LedR.SetPulse(255, R)
        Threading.Thread.Sleep(20)
    Next

I get (on the Dim Temp line):

An unhandled exception of type 'System.Exception' occurred in Netduino_VBTest.exe

There's no inner exception but just above it in the output is a first chance exception which I'm guessing is the root cause:

A first chance exception of type 'System.NotImplementedException' occurred in Microsoft.SPOT.Native.dll
Basic
  • 26,321
  • 24
  • 115
  • 201

4 Answers4

2

Try using Convert.ToUInt32, outlined here: http://msdn.microsoft.com/en-us/library/y3569ft9.aspx

On my .Net 4.0(not Micro) on Windows 7 64bit I am not seeing what you are seeing with CInt/CUInt (mine converts properly). This may be an implementation error in netduino/the Micro Framework... If I had it I would test the above for you.

csauve
  • 5,904
  • 9
  • 40
  • 50
  • I don't believe that exists in the Micro Framework - unless it's buried in an odd namespace? I have a `Convert.ToUInt32` but it only has 1 overload with the parameter of type `String`. `Convert.ToUInt32(Temp.ToString)` results in `An unhandled exception of type 'System.Exception' occurred in mscorlib.dll` – Basic Jan 10 '12 at 15:45
  • It's not the netduino itself, if anything it's the .Net Micro Framework which is still very rough - I get the same if I use the emulator provided by the .NetMF. – Basic Jan 10 '12 at 15:47
  • Incidentally, I'm also Win7x64, .Net4, VS2010 – Basic Jan 10 '12 at 15:48
  • Sorry, I am not on Micro Framework. I have just installed it to allow me to investigate. – csauve Jan 10 '12 at 16:07
  • Hmmmm. I've just restarted VS and set it to emulator again - Now it works on the Emu but not the netduino?!? Perhaps you're right that it's a netduino issue. I've mentioned it on their forums... http://forums.netduino.com/index.php?/topic/3287-convert-double-to-integer/ I'd be interested to know what you get. – Basic Jan 10 '12 at 16:14
  • Well I can't quite get my Micro Framework working and I've gotta jet. How about Debug.Print(Test.ToString().Split("."c)(0)) – csauve Jan 10 '12 at 16:27
  • I added that as another answer. – csauve Jan 10 '12 at 16:29
  • After more digging, it seems that it's a bug in the current Micro Framework release. As such, this is the "correct" answer even though it doesn't work ATM. – Basic Jan 11 '12 at 19:33
1

Whatever is happening I would advise you to avoid UInts as much as you can (I've been there). I would write the code like this:

Dim Start As Integer = 0
Dim [End] As Integer = 255
Dim Steps As Integer = 100

For x As Integer = 1 To Steps
    Dim Temp As Integer = ([End] - Start) \ Steps * x + Start
    LedR.SetPulse(255, CType(Temp,UInteger))
    Threading.Thread.Sleep(20)
Next

I cannot try it because I have not the Vb.Net compiler available and I've wrote the code directly on SO, please forgive me if there are any compilation errors.

Ignacio Soler Garcia
  • 21,122
  • 31
  • 128
  • 207
  • No worries, let me test it - I also don't particularly like UInts but it's what the hardware needs... Start is being read from hardware as a UInt, End is being provided by the user but it makes sense to write the same type as you read... – Basic Jan 10 '12 at 15:03
  • Using your conversion `CType(Temp, UInteger)` and storing the result in R, I get exactly the same result. I don't believe `Start` and `End` are the problem as `Temp` is being set correctly - it's simply converting _that_ into a `UInt` that's a little sticky – Basic Jan 10 '12 at 15:06
  • One of the things here is that Temp is not a double but an Integer. Can you write me an Int and its corresponding UInt conversion with CType? – Ignacio Soler Garcia Jan 10 '12 at 15:10
  • The code won't compile as the R.H.S of the Temp= formula results in a double. (I have Strict on - No implicit conversion from Double to Int). I'll edit in some test CInt()s in 2 secs... – Basic Jan 10 '12 at 15:30
  • ([End] - Start) \ Steps * x + Start must return an Integer. Note that I'm using the operator \ and not the operator /. – Ignacio Soler Garcia Jan 10 '12 at 15:38
  • Sorry, 1 further correction - the failed conversion was long to int not double to int using your code... I missed the `\\` – Basic Jan 10 '12 at 15:38
  • Argh. Looks like a hard problem. I'm tracking also the Netduino forum. May you post here the answer if they give you one? It's interesting. – Ignacio Soler Garcia Jan 10 '12 at 16:24
1

Another approach completely different. As the problem looks to be with doubles and conversions we could avoid doubles doing only subtracts:

Dim Start As Integer = 0
Dim [End] As Integer = 255
Dim Increment As Integer = 3
Dim Current as Integer = Start

While Current < End
    Current = Current + Increment
    LedR.SetPulse(255, CType(Current ,UInteger))
    Threading.Thread.Sleep(20)
End While

Quick & Dirty but it works.

Ignacio Soler Garcia
  • 21,122
  • 31
  • 128
  • 207
  • True - let me have a play. I'm not such a fan as I'd like this to all be variable and hard-coding increments is a problem (and I can't calc the increment as it'd be a double!) – Basic Jan 10 '12 at 17:12
1

How about

Debug.Print(Test.ToString().Split("."c)(0))

I have not worked out any edge-cases, but this worked on a couple of examples I tried. I would not recommend this solution if this will have to be performed in a loop as it will not perform well, but it might be a stop-gap until you can find something better.

csauve
  • 5,904
  • 9
  • 40
  • 50
  • This... `Debug.Print(UInteger.Parse(Test.ToString().Split("."c)(0)).ToString)` seems to work - I'll wrap it up in a function. Agreed it';s not performant but at least it works – Basic Jan 10 '12 at 17:16