Analog In
Analog input pins read a continuous range of voltages instead of just high or low. Each input pin connects internally to an Analog-to-Digital Converter (ADC) that converts the voltage into a digital value.
Microcontrollers running on 3.3V can typically read voltages between 0V and 3.3V. The ADC's resolution determines accuracy:
- SC20xxx — 16-bit ADC (65,536 steps; ~50 µV per step over a 3.3V range)
- SC13xxx — 12-bit ADC (4,096 steps; ~0.8 mV per step over a 3.3V range)
Voltage changes smaller than one step are below the ADC's resolution and won't register.
NuGet packages: GHIElectronics.TinyCLR.Devices.Adc for the API, and GHIElectronics.TinyCLR.Pins for pin name constants.
Channel number ≠ pin number. Use the pin constants from GHIElectronics.TinyCLR.Pins to map a physical pin (like PA0) to its ADC channel — for example, SC20100.Adc.Controller1.PA0.
Reading a value
ReadRatio() returns a normalized double from 0.0 to 1.0; ReadValue() returns the raw integer (range depends on resolution).
using GHIElectronics.TinyCLR.Devices.Adc;
using GHIElectronics.TinyCLR.Pins;
using System.Diagnostics;
using System.Threading;
var adc = AdcController.FromName(FEZBit.Adc.Controller3.Id);
var analog = adc.OpenChannel(FEZBit.Adc.Controller3.P0);
while (true){
double ratio = analog.ReadRatio();
Debug.WriteLine("An-> " + ratio.ToString("N2"));
Thread.Sleep(100);
}
Sampling time
The ADC takes a small but non-zero amount of time to settle on each conversion. Longer sampling times improve accuracy on high-impedance signals at the cost of throughput. Default is 1 tick (one tick = 100 ns).
adcChannel.SamplingTime = TimeSpan.FromTicks(10); // ~1 µs
If the requested time falls between two supported values, the higher (slower) one is used.
SC20xxx (full or half speed):
| Ticks | Time |
|---|---|
| 0 | 23 ns |
| 1 | 132 ns |
| 2 | 257 ns |
| 5 | 507 ns |
| 10 | 1.0 µs |
| 60 | 6.1 µs |
| 126 | 12.7 µs |
SC13xxx (full speed):
| Ticks | Time |
|---|---|
| 0 | 81 ns |
| 1 | 156 ns |
| 3 | 306 ns |
| 5 | 593 ns |
| 11 | 1.2 µs |
| 30 | 3.1 µs |
| 80 | 8.0 µs |
SC13xxx (half speed):
| Ticks | Time |
|---|---|
| 1 | 162 ns |
| 3 | 312 ns |
| 6 | 612 ns |
| 11 | 1.2 µs |
| 23 | 2.3 µs |
| 60 | 6.2 µs |
| 160 | 16.0 µs |
Internal temperature sensor
SITCore chipsets include an internal temperature sensor on a dedicated ADC channel. Calibration values are stored in chip-specific memory regions and read with Marshal.ReadInt32.
using System;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
using GHIElectronics.TinyCLR.Devices.Adc;
using GHIElectronics.TinyCLR.Native;
using GHIElectronics.TinyCLR.Pins;
var sc20xxx = DeviceInformation.DeviceName.IndexOf("SC20") >= 0;
var ts_reg1 = sc20xxx ? (IntPtr)0x1FF1E820 : (IntPtr)0x1FFF75A8;
var ts_reg2 = sc20xxx ? (IntPtr)0x1FF1E840 : (IntPtr)0x1FFF75CA;
var enable_reg = sc20xxx
? (IntPtr)(0x40000000U + 0x18020000 + 0x6300 + 8)
: (IntPtr)(0x40000000U + 0x08000000U + 0x08040300U + 8);
var controller = sc20xxx
? AdcController.FromName(SC20100.Adc.Controller3.Id)
: AdcController.FromName(SC13048.Adc.Controller1.Id);
var channel = sc20xxx
? controller.OpenChannel(SC20100.Adc.Controller3.InternalTemperatureSensor)
: controller.OpenChannel(SC13048.Adc.Controller1.InternalTemperatureSensor);
var enable_val = Marshal.ReadInt32(enable_reg);
enable_val |= (1 << 23);
Marshal.WriteInt32(enable_reg, enable_val);
while (true) {
var v = channel.ReadValue() * 1.0;
var ts1 = Marshal.ReadInt32(ts_reg1);
var ts2 = Marshal.ReadInt32(ts_reg2);
if (!sc20xxx) {
ts1 &= 0xFFFF;
ts2 &= 0xFFFF;
v *= 1.1;
}
var t1 = (110 - 30) * 1.0;
var t2 = (ts2 - ts1) * 1.0;
var t3 = (v - ts1) * 1.0;
var temperature = t1 / t2 * t3 + 30;
Debug.WriteLine("T = " + temperature + " Celsius");
Thread.Sleep(1000);
}
API reference
| Namespace | Description |
|---|---|
| GHIElectronics.TinyCLR.Devices.Adc | ADC controller and channel classes |