Paul Thomsen – Technology & Science

my thoughts on science and (mostly) computer-related technologies and technologies other than computer management

Using the U421 to read temperatures from a DS1822 via 1-Wire November 21, 2010

Filed under: sensors,U421 — Paul Thomsen @ 10:37 pm

Reading temperatures in your Windows C# program via a U421 USB interface is very easy if you’re using the DS1822 (or related) temperature sensor (which are digital and 1-Wire based).

The biggest challenge I had was orienting the pins correctly. The pin-out in the datasheet was from the bottom perspective but I was reading it from the top perspective and thus got it wrong. The bad news is that it gets VERY hot that way; the good news is that it doesn’t burn out (at least as long as you catch that issue within a few seconds).

My code (as follows, and poorly formatted, I know), gives the core details in C#. My previous posts on the U421 apply as well, of course. I haven’t confirmed the calibration (-1.0) beyond very limited testing, so be sure to do your own calibration.

// get the ROM details (at least to confirm the sensor is responding)
                buffer[0] = 0x06;                      // whichever port it’s on – see the U421 documentation for details
                USBm.USBm_Reset1Wire(Device, buffer);  // open it, essentially
                present = buffer[1]==0;                // 1=not present, 0=present
                USBm.USBm_Write1Wire(Device, 0x33);          // read ROM
                USBm.USBm_Read1Wire(Device, buffer);         // the first byte is the sensor type
                sensor_type = buffer[1];
                for (int i = 1; i < 7; i++)                  // then the ROM address
                {
                    USBm.USBm_Read1Wire(Device, buffer);
                    ROM = ROM + buffer[1].ToString(“X2”);
                }
                USBm.USBm_Read1Wire(Device, buffer);         // and the CRC, if you want to confirm everything was sent properly
                CRC = buffer[1];

                // get the temperature
                buffer[0] = 0x06; // the buffer is written to by the reset, so we have to set it back to the right port again, even if we were to use a separate buffer
                USBm.USBm_Reset1Wire(Device, buffer);
                USBm.USBm_Write1Wire(Device, 0xCC);  // i.e. use any 1-wire device (even though we do have the ROM number)
                USBm.USBm_Write1Wire(Device, 0x44);  // tell it to get the temperature

                // read the temperature
                buffer[0] = 0x06;
                USBm.USBm_Reset1Wire(Device, buffer);
                USBm.USBm_Write1Wire(Device, 0xCC); 
                USBm.USBm_Write1Wire(Device, 0xBE);  // read the temperature into the scratchpad – the first two bytes in particular
                USBm.USBm_Read1Wire(Device, buffer);
                byte1 = buffer[1];
                USBm.USBm_Read1Wire(Device, buffer);
                byte2 = (byte)((int)buffer[1] & 0x07);
            }
            celcius = Math.Round( ( (byte1 + (byte2 * 256)) / 16.0 ) – 1.0, 1);  // the “16.0” is dependent on the granularity – the 1.0 is based on calibration with physical thermometers (and feeling)
            farenheit = Math.Round( (celcius * 1.8) + 32, 1);          // the standard conversion algorithm

 

The importance of locking your U421 while using timed events November 15, 2010

Filed under: programming,U421 — Paul Thomsen @ 9:56 pm

My U421’s have been working well for me but as my solutions got more sophisticated they got less reliable. In particular, I was outputting to an LCD, outputting to an LED, and checking (inputting from) a switch at the same time (using multiple timers). But at seemingly random times my application would crash. It makes sense that I should only do one thing with the device at a time, but all my solutions failed.

I tried suspending the conflicting timers as operations were done, but that only partially helped. Setting a global variable didn’t help at all. Toggling only the relevant bits (“WriteABit”) didn’t help either.

Of course I didn’t expect I was the first person to hit such an issue so I did some research and found that the solution for C# (and similar languages, I assume) is to use locks – an old concept for anyone using database servers, clusters, or other complex systems.

In particular, I changed my code to create a generic object:

object U421_lock = new object();

and then later whenever doing anything U421 related I wrapped the code with:

lock( U421_lock )
{
       // do stuff
}

 

Getting started using LCD displays from a Windows PC using the U421 October 10, 2010

Filed under: electronics,programming,U421 — Paul Thomsen @ 10:30 pm

Full function monitors are admittedly cheap these days (roughly $100 on the low end), so using an LCD display from a PC has little value. But you can build an LCD solution for $60 and the information on it will be visible even when your screensaver is active or the machine is locked. They also allow you to more immediately focus on the information you display on them (as opposed to the multiple windows on your monitors).

Assuming you have a need to use an LCD display from your Windows PC, here’s a solution that will work:

The strength of the U421 in this case is that it has LCD APIs, so you don’t have to worry about the subtleties of timing the data transfer and coordinating RS, R/W, and E.

The wiring is fairly simple:

  • B data lines to the LCD data lines (i.e. B0 to DB0, B1 to DB1, etc.)
  • A data lines to the RS/Rw/E lines (A0 to Rw, A1 to Rs, A2 to E)
  • power lines as appropriate, except nothing to VDD (unless you want to set up a control for contrast)

Preparation for the coding is:

  • copy the USBMicro USBm.dll into the bin\debug folder of the application
  • add “using System.Runtime.InteropServices” to the ‘using’ part of your code
  • add the public class USBm from the USBMicro sample code to your application

The key code is:

result = USBm.USBm_FindDevices();
Device = 0; // assuming there’s only one device
USBm.USBm_DirectionA(Device, 0xFF, 0xFF); // output only
USBm.USBm_DirectionB(Device, 0xFF, 0xFF);
result =
USBm.USBm_InitLCD(Device, 0x01, 0x12); // A.0 is the RW line, A.1 is the RS line; data port B, A.2 is the E line
result = USBm.USBm_LCDCmd(Device, 0x30 + 8); // function set: 8 bit; 2 lines, font 0
result = USBm.USBm_LCDCmd(Device, 0x04); // entry mode – not incrementing, in either direction
result = USBm.USBm_LCDCmd(Device, 0x0C); // display on; no cursor, no blinking
result = USBm.USBm_LCDCmd(Device, 0x01); // clear display

output[0] = “initialized”;
for (int i = 0; i < output[0].Length; i++)
    result =
USBm.USBm_LCDData(Device, Convert.ToByte(output[0][i]));

p.s. There’s a key difference between the LCD-20x4Y (black on green) and LCD-20x4BW (black on white) displays – the second line starts at a different DDRAM address. Use 64 rather than 40.