Just wanted to share some code that enables sending analog sensor data from the DigiSpark to a C# program interfaced via LibUsbDotNet (
http://sourceforge.net/projects/libusbdotnet/ or
http://libusbdotnet.sourceforge.net). The project was to read some analog data into a C# windows program at a relatively low rate (few samples per second is sufficient) in a launch-and-forget fashion.
Here is the DigiSpark code that simply writes some sensor data as a stream of numbers onto the serial port:
#include <DigiUSB.h>
void setup() {
DigiUSB.begin();
}
int get_sensor() {
return analogRead(0);
}
void loop() {
DigiUSB.println(get_sensor(),DEC);
DigiUSB.delay(10);
}
Here is the value receiver as a C# class (with associated example). DigiSparkValueReader implements a reader thread which constantly retrieves characters from the interface and parses them into a n integer number. Once the reader was started by a client program, the client can simply access a reader property to retrieve the latest read value.
namespace Examples
{
using System;
using System.Text;
using System.Threading;
using LibUsbDotNet;
using LibUsbDotNet.Main;
/// <summary>
/// Example program for the DigiSparkValueReader class.
/// </summary>
public class DigiSparkValueReaderExample
{
/// <summary>
/// Program's main entry point.
/// </summary>
/// <param name="args">Command line arguments</param>
public static void Main(string[] args)
{
DigiSparkValueReader digiSparkReader = new DigiSparkValueReader();
while (digiSparkReader.Reading)
{
Console.WriteLine("Press enter to retrieve current reader value.");
Console.ReadKey();
Console.WriteLine(digiSparkReader.Value);
}
digiSparkReader.Dispose();
}
}
/// <summary>
/// Reads integers from DigiSpark device.
/// </summary>
public class DigiSparkValueReader : IDisposable
{
/// <summary>
/// The DigiSpark USB device.
/// </summary>
private UsbDevice usbDevice = null;
/// <summary>
/// Standard packet to read data.
/// </summary>
private UsbSetupPacket readPacket = new UsbSetupPacket((byte)((0x01 << 5) | 0x80), 0x01, 0, 0, 1);
/// <summary>
/// Flag indicating if resource have been disposed already.
/// </summary>
private bool disposed = false;
/// <summary>
/// Thread that reads values.
/// </summary>
private Thread readerThread = null;
/// <summary>
/// Object to synchronize access to value.
/// </summary>
private object syncRoot = new object();
/// <summary>
/// Value read from DigiSpark
/// </summary>
private int value = 0;
/// <summary>
/// Creates an instance of the reader and starts the reading thread.
/// </summary>
public DigiSparkValueReader()
{
UsbDeviceFinder usbFinder = new UsbDeviceFinder(0x16C0, 0x05DF);
this.usbDevice = UsbDevice.OpenUsbDevice(usbFinder);
if (this.usbDevice == null)
{
throw new ApplicationException("DigiSpark device not found.");
}
this.readerThread = new Thread(this.ReadHandler);
readerThread.Start();
this.Reading = true;
}
/// <summary>
/// Gets a flag indicating wether the reader is still reading.
/// </summary>
public bool Reading
{
get;
private set;
}
/// <summary>
/// Get a flag with the most recent value read.
/// </summary>
public int Value
{
get
{
lock (syncRoot)
{
return this.value;
}
}
}
/// <summary>
/// Thread performing the read and value conversion operation.
/// </summary>
private void ReadHandler()
{
// String accumulator to hold largest integer string "-2147483648" (11 bytes)
StringBuilder currentLine = new StringBuilder(11);
byte[] ctrlData = new byte[1];
// Reading loop
while(this.Reading)
{
ctrlData[0] = 0;
while (ctrlData[0] != 4)
{
// Attempt to read one byte from device
ctrlData[0] = 4;
int transferred;
bool result = this.usbDevice.ControlTransfer(ref this.readPacket, ctrlData, 1, out transferred);
if (!result)
{
// Read error
this.Reading = false;
break;
}
// No data read
if (ctrlData[0] == 4)
{
break;
}
// Process read ASCII character
char currentCharacter = Convert.ToChar(ctrlData[0]);
if (((currentCharacter.Equals('\r') || currentCharacter.Equals('\n')) && currentLine.Length > 0) ||
(currentLine.Length == currentLine.Capacity))
{
// Line terminated or buffer full, parse line into number and reset line
int currentValue;
if (int.TryParse(currentLine.ToString(), out currentValue))
{
lock (this.syncRoot)
{
this.value = currentValue;
}
}
currentLine.Length = 0;
}
else if (char.IsDigit(currentCharacter) || currentCharacter.Equals('-'))
{
// Accumulate number in a buffer
currentLine.Append(currentCharacter);
}
}
// Pause reading thread
System.Threading.Thread.Sleep(10);
}
}
/// <summary>
/// Dispose resources
/// </summary>
/// <param name="disposing">Flag indicating if we are disposing</param>
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// Stop thread
if (this.readerThread != null)
{
this.readerThread.Abort();
}
// Close device
if (this.usbDevice != null)
{
if (this.usbDevice.IsOpen)
{
IUsbDevice wholeUsbDevice = usbDevice as IUsbDevice;
this.usbDevice.Close();
}
}
this.usbDevice = null;
UsbDevice.Exit();
}
this.disposed = true;
}
}
/// <summary>
/// Dispose resources
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}