SCM20XX: ADC Burst mode

Hello, any sample code anyone can point me to collect multi channel data
with
adcChannel.SamplingTime = TimeSpan.FromTicks(10);

Any ideas…

adcChannel.SamplingTime = TimeSpan.FromTicks(10); // Set to 1us (a tick is 100ns)

I want to use a accurate sample rate to collect data from the Analog IN
and how many bit is the ADC?

The system in not real time. There are few internal service and options to help with that. Can you tell us more? Like how important that the samples are exact 1us apart?

In serious commercial use cases where real time needs are a must, we can either add a built in feature to handle or add a sub $1 micro to do that timey real time task. A call with discussion resolves this quickly.

I am not thinking precise real time.

If I want to sample a channel at 10Khz i.e. 10us.
Can I do it with a timer
is there a helper function were I can give the ADC driver a buffer array and it will collect it for me.

How many bit is the ADC? it is not documented

Internally, we convert and round up user input sampling to cycles, not exactly the time user set.

It is different on each device (SC20xxx or SC13xxx), so there is property tell you the resolution.
But here it is:
SC20xxx: 16 bit
SC13xxx: 12 bit

would you be able to provide a couple of lines of code to read the resolution and collect ADC samples

or can I just put the ADC read in a loop like the DAC, it is blocked till the sample is taken?

if (sampleRate == 8000) {
    for (int i = dataIndex; i < size; i++) {
        analogOut.WriteValue(byteFile[i]);

        for (int timer = 0; timer < 58; timer++) {}
    }
}
else {
    Debug.WriteLine("Sorry, file does not have an 8 kHz sample rate.");
}

what device are you using? SC20260 or SC13xxx? what sampling time do you want?

Device: SC20260
Sampling: 10us
and if it can concurrently sample more channels it is even better

if you want 10us then just convert 10us = 100 ticks and set to sampling time, What we mean was, 10us and 15us may same cycles when we converted them to cycles internally.

I just check doc, everything is there but you may want this:

static void DoTestADC2()
        {

            var adc3 = AdcController.FromName(SC20260.Adc.Controller3.Id);

            var adcchannel1 = adc3.OpenChannel(SC20260.Adc.Controller3.PF10);
            var adcchannel2 = adc3.OpenChannel(SC20260.Adc.Controller3.PF8);

            adcchannel1.SamplingTime = TimeSpan.FromTicks(100);
            adcchannel2.SamplingTime = TimeSpan.FromTicks(100);

            Debug.WriteLine("Resolution " + adc3.ResolutionInBits); // show resolution in bit

            while (true)
            {
                var v1 = adcchannel1.ReadValue() * 3.3 / 0xFFFF; // 16 bits
                var v2 = adcchannel2.ReadValue() * 3.3 / 0xFFFF; // 16 bits

                Debug.WriteLine("v1 = " + v1);
                Debug.WriteLine("v2 = " + v2);
               
                Thread.Sleep(1000); // This sleep is not sampling time, just show message every one second

            }
        }

Thanks Dat_Tarn

The thing that is still not clear to me is the sampling time

adcchannel1.SamplingTime = TimeSpan.FromTicks(100);

How is it used?
I need to collect a bunch of samples in a buffer at 10us rate

No native builtin function to do that
Hope below will help.

 static void DoTestADC3()
        {
            var adc3 = AdcController.FromName(SC20260.Adc.Controller3.Id);

            var adcchannel1 = adc3.OpenChannel(SC20260.Adc.Controller3.PF10);

            adcchannel1.SamplingTime = TimeSpan.FromTicks(1);
            const int SAMPLE_COUNT = 100;
            var buff = new double[SAMPLE_COUNT];

            var end = DateTime.Now.Ticks + 100*100;            
            
            var cnt = 0;

            while (DateTime.Now.Ticks < end)
            {                
                buff[cnt++] = adcchannel1.ReadValue() * 3.3 / 0xFFFF; // 16 bits

                if (cnt == SAMPLE_COUNT)
                    break;
            }

            for (int i = 0; i < cnt; i++)
            {
                Debug.WriteLine(" " + buff[i]);
            }
        }

Thank you
ok…got it. I was expecting a native function.
But your sample is perfect.

Will this function “adcchannel1.ReadValue()” only return if it has a new sample?

Yes, of course
10us is very short in manage code, so don’t do too many things in the while loop.

Whatever tick I set the rate does not change, it is sampling at 1,455Hz for 1 channel and 760 for 2 channels

public class PMeter
{
public static Double[] Meter;

    static AdcController ADC;
    static AdcChannel ACH1;
    static AdcChannel ACH2;

    struct sADCRawVal
    {
        public double[] ADCVal;
    };

    static sADCRawVal[] ADCRawVal = new sADCRawVal[SQL_DBase.Channels];

    public PwrMeter()
    {
        Meter = new Double[SQL_DBase.Channels];

        ADC = AdcController.FromName(SC20100.Adc.Controller1.Id);
        ACH1 = ADC.OpenChannel(SC20100.Adc.Controller1.PA5); 
        ACH2 = ADC.OpenChannel(SC20100.Adc.Controller1.PA4); 

        //Tick is 100ns
        //0	    23ns
        //1	    132ns
        const int tk = 1;
        ACH1.SamplingTime = TimeSpan.FromTicks(tk);
        ACH2.SamplingTime = TimeSpan.FromTicks(tk);

        for (int i = 0; i < SQL_DBase.Channels; i++)
        {
            ADCRawVal[i].ADCVal = new double[100];
        }
    }

    static public void MeterRead()
    {

        {
            long ed, st;
            int buf_len = ADCRawVal[0].ADCVal.Length;
            st = DateTime.Now.Ticks;

            for (int cnt = 0; cnt < buf_len; cnt++)
            {
                //ADC Val = ACH1.ReadValue() * 3.3 / 0xFFFF; // 16 bits
                ADCRawVal[0].ADCVal[cnt] = ACH1.ReadValue();
                ADCRawVal[1].ADCVal[cnt] = ACH2.ReadValue();
            }

            ed = DateTime.Now.Ticks - st;

            Meter[0] = 1 / ((ed / buf_len) /1000000.0);    //Sampling  Frequency
            Meter[1] = ACH1.ReadRatio() * 100;

            Meter[3] = DeviceInformation.GetCpuUsageStatistic();       //cpuUsage from 0 to 100%
            Meter[4] = ACH2.ReadRatio() * 100;
        }
    }      
}

How did you know?

I am measuring the time to take the 100 samples

The maximun sampling rate is determined by how long it takes to take one sample. The chip manual should detail the necessary information to understand what are the capabilities of the chip as well as how to configure the ADC.

As a start, run your measurement code without actually accessing the ADC. This will show the maximum theoretical sampling rate you could achieve in managed code on the target chip. If this rate is not acceptable, then you will have to look to external hardware to meet your needs. Of course, you could have GHI do custom code.

It is how fast you can read adc per second, not sampling time. If your project has multiple threads running, it is even slower.

With TinyClr the maximum sample rate is determined by how fast you can read the ADC, but this is a managed code limitation not hardware.

The hardware maximum sampling rate far exceeds what TinyClr allows. A 10us (100,000 samples) is a challenge for TinyClr with an ADC read.

The M7@480Mhz has a maximum chip sampling rate of 3.6MSPS.