Tag Archives: c

C# USB HID Utility

Have you ever tried to write a program that connects to some device via USB? I have done so a few years ago and was shocked how much of a pain that is (at least on a Windows plattform). I always thought there should be a nice little library that wraps all those uggly DLL imports, marshalling and COM API calls and offers a nice and clean C# interface to the outside world.

Much to my surprise I found nothing that really did what I was looking for. Now I finally sat down and wrote my own. It’s on github.com under GNU GPLv3 license for anyone to modify and use.

My starting point was the Microchip PIC18F46J50 FS USB Demo Board. This nice little board comes pre-programmed as a HID (Human Interface Device) / MSD (Mass Storage Device) USB composite device and is a great starting point for anyone interested in building a USB device based on a PIC.

Once uppon a time, Microchip also wrote a WindowsForms application to showcase the USB functionality of their microcontrollers and that application (in various versions) can still be found here. It lets you read an analog voltage from the board, tells you if a pushbutton is pressed or not and lets you toggle an LED. Very simple but all you need to get started with your own device and application.

Unfortunately, that code no longer gets maintained and is quite outdated by now. It was created with VisualStudio2010 and .NET 2.0.  And all USB and WindowsForms code is mixed up in a single file which makes it difficult to re-use. It also lacks some functionality such as the ability to list available devices. Apart from that it works very well and stable so I used it as a starting point.

My solution is now based on VisualStudio Community 2015 (which is available for free) and .NET framework 4.6. So you can just download VisualStudio and open the HidUtilityDemo.sln file.

There are 3 projects inside the solution:

  • A WindowsForms application named HidDemoWindowsForms
  • A WPF application named HidDemoWpf
  • A console application named HidDemoConsole

All projects use a common file named hid.cs. This file is what this is all about. The applications mainly just show how to use it and give you a starting point for your own application.

hid.cs is not pretty. 900 something lines of DLL imports, COM object calls and marshalling. It’s C# but it doesn’t look and feel like C#. But it does all the heavy lifting for you and offers a nice, clean, truely C# interface for you to work with HID devices.

You add it to your namespace, create an instance of HidUtility, tell it what device to connect to  and subscribe to the events you are interested in:

// Get an instance of HidUtility
HidUtility HidUtil = new HidUtility();
// Connect to device with Vid=0x1234 and Pid=0x5678
HidUtil.SelectDevice(new hid.Device(0x1234, 0x5678));
// Subscribe to the events you care about
HidUtil.RaiseDeviceRemovedEvent += DeviceRemovedHandler;
HidUtil.RaiseDeviceAddedEvent += DeviceAddedHandler;
HidUtil.RaiseConnectionStatusChangedEvent += ConnectionStatusChangedHandler;
HidUtil.RaiseSendPacketEvent += SendPacketHandler;
HidUtil.RaisePacketSentEvent += PacketSentHandler;
HidUtil.RaiseReceivePacketEvent += ReceivePacketHandler;
HidUtil.RaisePacketReceivedEvent += PacketReceivedHandler;

You can also obtain a list of all available HID devices at any time:

foreach (Device dev in HidUtil.DeviceList)
{
Console.WriteLine(dev.ToString());
}

As the three projects demonstrate, the very same hid.cs file can be included in just about any C# project. There is not a single API call or anything in the remaining files.

Just register some event handlers and your application will be informed whenever a device has been added or removed, when a package of data has been received from the device, when the connection status has changed or whatever else.

So you don’t have to re-invent the wheel every time and can fully concentrate on the application you have in mind, not the details of USB communication.

A word of caution: I am by no means an expert C# programmer. I have tried the applications on 3 different PCs running Win7 and Win10, respectively. They seem to work reliably on any of these. Apart from that the code has not yet been productively deployed and there may well be some bugs and issues. If you find anything that doesn’t work, please let me know and I will do my best to get things fixed and updated on github. Also, please comment on this post if anything needs clarification.

So once again, the code is available for download from github.com/soldernerd/HID_Utility.

Stand-alone Incuctance Meter Finished

If you’ve read my last post you’re already familiar with my Inductance Meter project: https://soldernerd.com/2015/01/14/stand-alone-inductance-meter/. At that time the hardware was ready but there was no software yet. That’s been corrected, the inductance meter is now fully functional.

_MG_1183

From a high-level point of view the new software is very similar to the Arduino sketch I wrote for the Inductance Meter Shield (https://soldernerd.com/2014/12/14/arduino-based-inductance-meter/). If you look a bit closer, you’ll notice some differences for several reasons:

  • This project uses an entirely different microcontroller: A PIC 16F1936* instead of the Atmel Atmega328
  • This code is written in C (for the MikroC for PIC compiler by Mikroelektronika), not Arduino-style C++
  • The display I’m using here comes with a I2C interface rather than the familiar Hitachi interface

*: In an earlier version I wrote 16F1932 instead of 1936. Thanks to Ralph Doncaster for pointing this out to me. By the way, Ralph has his own blog at http://nerdralph.blogspot.ca which I regularly enjoy reading.

_MG_1190

I’ve noticed that the MikroC compiler is not very popular among hobbyists but I like using it. It’s entirely free as long as your compiled code does not exceed a certain size. You can use any features, any library, just anything for free when you’re getting started. Yes, once your projects get bigger you’ll run into the limit and will have to buy a license but it was worth the price to me.

_MG_1193

As expected, the I2C display took me some time to get used to. It’s a MIDAS MCCOG21605B6W-BNMLWI (Farnell: 2063209). It seems to use a Hitachi-compatible controller with a I2C interface built on top of it. I like the concept and will probabely use one of these again. If there is a downside, it’s the data sheet. I had to do quite a bit of guessing and trial-and-error to get it working. I had used Hitachi-compatible MIDAS displays before so I had some idea what might work otherwise I might have given up. Examples?

  • No page numbering. Yes, this is a minor thing but have you ever seen a data sheet without page numbers?
  • There is a reset pin. As many reset pins, it’s active-low. But the data sheet never says so. Not explicitly, not with a bar accross the RST, not with a ~RST. Absolutely nothing.
  • It explains some of the Hitachi-functionality in great detail but does not really tell you that this functionality is not accessible over the I2C interface.
  • Like Hitachi-compatible types, this display needs some start-up time before you configure it. Otherwise it will just not work. But the data sheet doesn’t mention that with a single word.

_MG_1188

But it’s all working fine now. The PIC16F1936 has more than enough ROM, RAM and processing power for this meter so don’t expect the code to be optimized in any way. It was just not necessary. It does most of the math in floating-point which bloats the (compiled) code size and is dead-slow on this kind of architecture but it’s still more than fast enough and only uses around half of the available RAM and ROM.

_MG_1202

I think the code itself is quite readable but don’t hesitate to ask if you have any questions. Here’s the code as zip: LMeter _MG_1192

Arduino Ultrasonic Anemometer Part 7: Basic software

Today I’ll tell you how I got started with my software. If you’re new to my blog you might want to click here for an overview over my arduino-based wind meter project: https://soldernerd.com/arduino-ultrasonic-anemometer/

The first thing we’ll need to archive is to send a series of pulses at 40kHz which is the frequency the ultrasonic transducers work. They must be as precise and repeatable as possible since all our measurements depend on them. Any jitter and the like will affect our measurements. And the duty cycle should be 50%. So you really want to do them in hardware. The Atmega328 comes with a single 16-bit counter/timer (Timer/Counter1) as well as two 8-bit counters (Timer/Counter 0 and 2). We’ll need the 16-bit resolution so the choice is clear: Timer1.

Timer1_output
Sending pulses using timer/counter1

Well yes, you could easily use one of the 8-bit counters to generate your pulses but you’ll still need timer1 for measurement. I’ve decided to do everything with just one timer so it’s going to be timer1.

How many pulses we should send is not so clear. I’m working with 15 pulses which works quite well but I’m not claiming it’s an optimal choice. But it is short enough to make sure we’ve stopped transmitting before the first sound waves reach the opposite transducer, even with heavy tail wind.

Since we have such strict requirements for our pulses, we can’t rely on any of those convenient high-level functions to set up our timer but have to study the Atmega328 datasheet and do it ourselfs.

This is what I have done:

pinMode(10, OUTPUT);
TCCR1A = 0b00100011;
TCCR1B = 0b11011001;
OCR1AH = 0x01;
OCR1AL = 0x8F;
OCR1BH = 0x00;
OCR1BL = 0xC7;

This is a short explanation of what it does: Set pin 10 as an output. Arduino pin10 is pin16 of the Atmega328. And that’s the pin connected to the output B of timer1. That’s line 1.

I then set up counter1 in FastPWM mode running at the full system clock frequency of 16MHz. Output B (that’s our pin 10 on the arduino) is set high when the counter starts at zero. It will be cleared (i.e. set low) when the timer reaches the value in output compare register B (OCR1B). The counter will be reset when (i.e.it will start at zero again) when it reaches the value in couput compare register A (OCR1A). I also enable an interrupt for when the timer overflows. More on that later. That’s lines 2 and 3.

Then comes the part where I actually set duty cycle and pulse with. I do that by setting the output compare registers. OCR1AH and OCR1AB are the high and low bytes of register OCR1A. So the final value in that register is 0x018F which equals to 399. That means counter 1 will count from 0 up to 399 before it starts again. That’s 400 steps. And here’s the math: The timer runs at 16MHz, our counter will overflow every 400 cycles. 16000000 / 400 = 40000. That’s exactly the 40kHz we’re looking for. The duty cycle is set to half that time by setting OCR1B to 199 or 0x00C7.

That’s it. We have a perfect PWM signal at exactly 40kHz and 50% duty cycle. Look at the screenshot above to convince you that this is exactly what we are getting.

But so far, the pulses go on forever. What we need is a way to turn the output signal off after 15 (say) pulses. One way of doing that is to count the pulses and turn the output off once the 15 pulses have been sent. That’s what the interrupt at overflow is used for.

In that ISR (interrupt service routine) I increment the variable pulse_count. Once pulse_count reaches 15 I know that all the pulses have been sent and turn the output off: TCCR1A = 0b00000011; The timer/counter will continue to run but the PWM output has been turned off.

For debugging/monitoring purposes, I set pin A5 high at the beginning of the ISR and low at the end. So I can tell when (and how long) the ISR is running by monitoring pin A5. Here’s what I get:

Timer1_overflows
Pulses sent (yellow) and time spent in timer interrupts (blue)

The yellow signal is the PWM output (pin10) as before. The blue line shows the time spent handling the interrupt. I could then continue counting without sending any pulses and turn the output back on when I reach 80 for example. And at the very beginning that’s exactly what I did. But then the microcontroller has to handle an interrupt every 25us (microseconds) even when not sending pulses. That’s quite wasteful so I set a longer time period by increasing the OCR1A and OCR1B registers seen above.

Actually, I’m using this interrupt to do some other things as well such as setting Axis and Direction as well as the Mute signal and some other housekeeping. That wide blue pulse you see at the left side of the screenshot above does most of that, that’s why it is so wide.

TimerInterrupt
Time consumed handling a regular timer overflow interrupt

Speaking of time consumed handling interrupts. It’s quite significant as you can see here: About 5 microseconds for a normal (just counting) interrupt. That’s 20% of CPU time while sending pulses (5us every 25us). That’s muuuch more than I ever imagined it to be. That’s about 80 instructions. I’m writing in C so I’ll have to check the assember code produced by the compiler to see what’s going on.

Click here for the next post of this series: https://soldernerd.com/2014/11/23/arduino-ultrasonic-anemometer-part-8-more-software/